From eb40ed78f348375efcd74b5a683bdc2380b3bd61 Mon Sep 17 00:00:00 2001 From: gmungoc Date: Tue, 21 Jul 2015 11:42:36 +0100 Subject: [PATCH] JAL-1807 Bob's first commit -- Applet loaded; needs image --- src/awt2swing/Button.java | 16 + src/awt2swing/Canvas.java | 6 + src/awt2swing/Checkbox.java | 23 + src/awt2swing/CheckboxMenuItem.java | 28 + src/awt2swing/Choice.java | 12 + src/awt2swing/Frame.java | 55 + src/awt2swing/Label.java | 24 + src/awt2swing/Menu.java | 17 + src/awt2swing/MenuBar.java | 7 + src/awt2swing/MenuItem.java | 15 + src/awt2swing/Panel.java | 18 + src/awt2swing/PopupMenu.java | 16 + src/awt2swing/ScrollPane.java | 7 + src/awt2swing/Scrollbar.java | 19 + src/awt2swing/TextArea.java | 15 + src/awt2swing/TextField.java | 46 + src/com/stevesoft/pat/BackRefRule.java | 2 +- src/com/stevesoft/pat/BasicStringBufferLike.java | 2 +- src/com/stevesoft/pat/CaseMgr.java | 8448 ++++++++++---------- src/com/stevesoft/pat/DirFileRegex.java | 30 +- src/com/stevesoft/pat/FileRegex.java | 510 +- src/com/stevesoft/pat/MessageManager.java | 21 + src/com/stevesoft/pat/NonDirFileRegex.java | 30 +- src/com/stevesoft/pat/Pattern.java | 6 +- src/com/stevesoft/pat/RegRes.java | 66 +- src/com/stevesoft/pat/Regex.java | 346 +- src/com/stevesoft/pat/RegexReader.java | 2 +- src/com/stevesoft/pat/RegexTokenizer.java | 8 +- src/com/stevesoft/pat/RegexWriter.java | 2 +- src/com/stevesoft/pat/ReplaceRule.java | 24 +- src/com/stevesoft/pat/Replacer.java | 10 +- src/com/stevesoft/pat/Skip.java | 10 +- src/com/stevesoft/pat/Skip2.java | 2 +- src/com/stevesoft/pat/SkipBMH.java | 20 +- src/com/stevesoft/pat/StringBufferLike.java | 12 +- src/com/stevesoft/pat/Transformer.java | 7 +- src/com/stevesoft/pat/Util.java | 13 + src/com/stevesoft/pat/Validator.java | 2 +- src/com/stevesoft/pat/oneChar.java | 6 +- src/com/stevesoft/pat/parsePerl.java | 10 +- .../stevesoft/pat/wrap/CharArrayBufferWrap.java | 2 +- .../stevesoft/pat/wrap/RandomAccessFileWrap.java | 313 +- src/com/stevesoft/pat/wrap/StringBufferWrap.java | 2 +- src/com/stevesoft/pat/wrap/WriterWrap.java | 2 +- src/fr/orsay/lri/varna/models/rna/RNA.java | 15 + src/jalview/analysis/AAFrequency.java | 8 +- src/jalview/analysis/AlignmentAnnotationUtils.java | 3 + src/jalview/analysis/AlignmentSorter.java | 6 +- src/jalview/analysis/Finder.java | 10 +- src/jalview/analysis/NJTree.java | 2 +- src/jalview/analysis/ParseProperties.java | 10 +- src/jalview/analysis/Rna.java | 13 +- src/jalview/analysis/StructureFrequency.java | 13 +- src/jalview/api/analysis/ViewBasedAnalysisI.java | 1 - src/jalview/appletgui/APopupMenu.java | 22 +- src/jalview/appletgui/AlignFrame.java | 310 +- src/jalview/appletgui/AlignViewport.java | 5 +- src/jalview/appletgui/AlignmentPanel.java | 13 +- src/jalview/appletgui/AnnotationColourChooser.java | 14 +- src/jalview/appletgui/AnnotationColumnChooser.java | 13 +- src/jalview/appletgui/AnnotationLabels.java | 14 +- src/jalview/appletgui/AnnotationPanel.java | 8 +- src/jalview/appletgui/AnnotationRowFilter.java | 14 +- src/jalview/appletgui/AppletJmol.java | 1223 +-- src/jalview/appletgui/AppletJmolBinding.java | 324 +- src/jalview/appletgui/CutAndPasteTransfer.java | 30 +- src/jalview/appletgui/EditNameDialog.java | 8 +- src/jalview/appletgui/EmbmenuFrame.java | 28 +- src/jalview/appletgui/ExtJmol.java | 357 +- src/jalview/appletgui/FeatureColourChooser.java | 14 +- src/jalview/appletgui/FeatureRenderer.java | 16 +- src/jalview/appletgui/FeatureSettings.java | 30 +- src/jalview/appletgui/Finder.java | 12 +- src/jalview/appletgui/FontChooser.java | 12 +- src/jalview/appletgui/IdCanvas.java | 4 +- src/jalview/appletgui/IdPanel.java | 2 +- src/jalview/appletgui/IdwidthAdjuster.java | 4 +- src/jalview/appletgui/JVDialog.java | 6 +- src/jalview/appletgui/OverviewPanel.java | 6 +- src/jalview/appletgui/PCAPanel.java | 18 +- src/jalview/appletgui/PairwiseAlignPanel.java | 8 +- src/jalview/appletgui/RedundancyPanel.java | 2 +- src/jalview/appletgui/RotatableCanvas.java | 4 +- src/jalview/appletgui/ScalePanel.java | 8 +- src/jalview/appletgui/SeqCanvas.java | 4 +- src/jalview/appletgui/SeqPanel.java | 2 +- src/jalview/appletgui/SliderPanel.java | 14 +- src/jalview/appletgui/SplitFrame.java | 10 +- src/jalview/appletgui/TitledPanel.java | 15 +- src/jalview/appletgui/Tooltip.java | 7 +- src/jalview/appletgui/TreeCanvas.java | 6 +- src/jalview/appletgui/TreePanel.java | 12 +- src/jalview/appletgui/UserDefinedColours.java | 40 +- src/jalview/bin/Cache.java | 966 +-- src/jalview/bin/JalviewLite.java | 107 +- src/jalview/commands/EditCommand.java | 110 +- src/jalview/datamodel/Alignment.java | 37 +- src/jalview/datamodel/AlignmentView.java | 2 +- src/jalview/datamodel/CigarBase.java | 2 +- src/jalview/datamodel/Sequence.java | 17 +- src/jalview/datamodel/SequenceI.java | 8 +- src/jalview/io/AlignmentProperties.java | 41 +- src/jalview/io/AnnotationFile.java | 10 +- src/jalview/io/AppletFormatAdapter.java | 129 +- src/jalview/io/FastaFile.java | 8 +- src/jalview/io/FeaturesFile.java | 3 +- src/jalview/io/FileParse.java | 201 +- src/jalview/io/IdentifyFile.java | 18 +- src/jalview/io/JnetAnnotationMaker.java | 6 +- src/jalview/io/ModellerDescription.java | 10 +- src/jalview/io/NewickFile.java | 714 +- src/jalview/javascript/JSFunctionExec.java | 2 +- src/jalview/javascript/JsSelectionSender.java | 2 + src/jalview/jsdev/Constants.java | 31 + src/jalview/jsdev/GenericFileAdapter.java | 130 + src/jalview/jsdev/JSRegex.java | 91 + src/jalview/jsdev/JavaScriptRegExp.java | 17 + src/jalview/jsdev/RegExp.java | 26 + src/jalview/jsdev/api/RegExpInterface.java | 37 + src/jalview/jsdev/api/VarnaRNA.java | 5 + src/jalview/math/Matrix.java | 3 +- src/jalview/math/RotatableMatrix.java | 3 +- src/jalview/renderer/AnnotationRenderer.java | 8 +- src/jalview/schemes/AnnotationColourGradient.java | 180 +- src/jalview/schemes/ResidueProperties.java | 13 + src/jalview/schemes/TCoffeeColourScheme.java | 8 +- .../structures/models/AAStructureBindingModel.java | 2 +- src/jalview/util/AWTConsole.java | 5 + src/jalview/util/Comparison.java | 2 +- src/jalview/util/DBRefUtils.java | 10 +- src/jalview/util/GroupUrlLink.java | 33 +- src/jalview/util/MessageManager.java | 10 +- src/jalview/util/QuickSort.java | 68 +- src/jalview/util/UrlLink.java | 40 +- .../seqfeatures/FeatureRendererModel.java | 5 +- src/jalview/workers/ConsensusThread.java | 1 + src/javajs/J2SIgnoreImport.java | 7 + src/javajs/J2SRequireImport.java | 7 + src/javajs/api/BytePoster.java | 7 + src/javajs/api/EigenInterface.java | 15 + src/javajs/api/EventManager.java | 16 + src/javajs/api/FontManager.java | 23 + src/javajs/api/GenericBinaryDocument.java | 53 + src/javajs/api/GenericCifDataParser.java | 45 + src/javajs/api/GenericColor.java | 19 + src/javajs/api/GenericFileInterface.java | 15 + src/javajs/api/GenericImageDialog.java | 9 + src/javajs/api/GenericImageEncoder.java | 12 + src/javajs/api/GenericLineReader.java | 5 + src/javajs/api/GenericMenuInterface.java | 18 + src/javajs/api/GenericMouseInterface.java | 13 + src/javajs/api/GenericPlatform.java | 141 + src/javajs/api/GenericZipInputStream.java | 13 + src/javajs/api/GenericZipTools.java | 45 + src/javajs/api/HTMLElement.java | 5 + src/javajs/api/HTMLWindowEvent.java | 10 + src/javajs/api/Interface.java | 40 + src/javajs/api/JSInterface.java | 30 + src/javajs/api/JSONEncodable.java | 7 + src/javajs/api/JmolObjectInterface.java | 12 + src/javajs/api/PlatformViewer.java | 7 + src/javajs/api/SC.java | 65 + src/javajs/api/SwingController.java | 136 + src/javajs/api/ZInputStream.java | 6 + src/javajs/awt/BorderLayout.java | 12 + src/javajs/awt/Color.java | 53 + src/javajs/awt/Component.java | 155 + src/javajs/awt/Container.java | 79 + src/javajs/awt/Dimension.java | 18 + src/javajs/awt/Font.java | 170 + src/javajs/awt/LayoutManager.java | 5 + src/javajs/awt/event/ActionEvent.java | 12 + src/javajs/awt/event/ActionListener.java | 8 + src/javajs/awt/event/Event.java | 59 + src/javajs/awt/event/ItemEvent.java | 6 + src/javajs/awt/event/WindowEvent.java | 6 + src/javajs/awt/event/WindowListener.java | 9 + src/javajs/export/PDFCreator.java | 364 + src/javajs/export/PDFObject.java | 152 + src/javajs/img/BMPDecoder.java | 208 + src/javajs/img/CRCEncoder.java | 110 + src/javajs/img/GifEncoder.java | 1132 +++ src/javajs/img/ImageEncoder.java | 124 + src/javajs/img/Jpg64Encoder.java | 64 + src/javajs/img/JpgEncoder.java | 1208 +++ src/javajs/img/PdfEncoder.java | 105 + src/javajs/img/PngEncoder.java | 453 ++ src/javajs/img/PpmEncoder.java | 60 + src/javajs/swing/AbstractButton.java | 118 + src/javajs/swing/AbstractTableModel.java | 13 + src/javajs/swing/ButtonGroup.java | 18 + src/javajs/swing/Cell.java | 25 + src/javajs/swing/ColumnSelectionModel.java | 9 + src/javajs/swing/Document.java | 7 + src/javajs/swing/FlowLayout.java | 7 + src/javajs/swing/Grid.java | 54 + src/javajs/swing/GridBagConstraints.java | 47 + src/javajs/swing/GridBagLayout.java | 7 + src/javajs/swing/Insets.java | 14 + src/javajs/swing/JButton.java | 16 + src/javajs/swing/JCheckBox.java | 19 + src/javajs/swing/JCheckBoxMenuItem.java | 10 + src/javajs/swing/JComboBox.java | 47 + src/javajs/swing/JComponent.java | 45 + src/javajs/swing/JComponentImp.java | 18 + src/javajs/swing/JContentPane.java | 23 + src/javajs/swing/JDialog.java | 126 + src/javajs/swing/JEditorPane.java | 26 + src/javajs/swing/JLabel.java | 22 + src/javajs/swing/JMenu.java | 28 + src/javajs/swing/JMenuItem.java | 46 + src/javajs/swing/JPanel.java | 67 + src/javajs/swing/JPopupMenu.java | 70 + src/javajs/swing/JRadioButtonMenuItem.java | 11 + src/javajs/swing/JScrollPane.java | 32 + src/javajs/swing/JSplitPane.java | 88 + src/javajs/swing/JTable.java | 83 + src/javajs/swing/JTextField.java | 21 + src/javajs/swing/JTextPane.java | 36 + src/javajs/swing/ListSelectionModel.java | 7 + src/javajs/swing/SwingConstants.java | 9 + src/javajs/swing/TableCellRenderer.java | 7 + src/javajs/swing/TableColumn.java | 7 + src/javajs/util/A4.java | 252 + src/javajs/util/AU.java | 655 ++ src/javajs/util/AjaxURLConnection.java | 89 + src/javajs/util/AjaxURLStreamHandler.java | 53 + src/javajs/util/AjaxURLStreamHandlerFactory.java | 27 + src/javajs/util/ArrayDataReader.java | 57 + src/javajs/util/BArray.java | 33 + src/javajs/util/BC.java | 163 + src/javajs/util/BS.java | 934 +++ src/javajs/util/Base64.java | 120 + src/javajs/util/BinaryDocument.java | 360 + src/javajs/util/CU.java | 550 ++ src/javajs/util/CifDataParser.java | 633 ++ src/javajs/util/CompoundDocDirEntry.java | 93 + src/javajs/util/CompoundDocHeader.java | 112 + src/javajs/util/CompoundDocument.java | 395 + src/javajs/util/DF.java | 161 + src/javajs/util/DataReader.java | 56 + src/javajs/util/Eigen.java | 1060 +++ src/javajs/util/Encoding.java | 30 + src/javajs/util/LimitedLineReader.java | 48 + src/javajs/util/ListDataReader.java | 57 + src/javajs/util/Lst.java | 88 + src/javajs/util/M3.java | 638 ++ src/javajs/util/M34.java | 416 + src/javajs/util/M4.java | 943 +++ src/javajs/util/Matrix.java | 457 ++ src/javajs/util/Measure.java | 733 ++ src/javajs/util/OC.java | 386 + src/javajs/util/P3.java | 65 + src/javajs/util/P3i.java | 43 + src/javajs/util/P4.java | 70 + src/javajs/util/PT.java | 1540 ++++ src/javajs/util/Quat.java | 815 ++ src/javajs/util/Rdr.java | 509 ++ src/javajs/util/SB.java | 342 + src/javajs/util/StringDataReader.java | 48 + src/javajs/util/T3.java | 341 + src/javajs/util/T3d.java | 225 + src/javajs/util/T3i.java | 151 + src/javajs/util/T4.java | 120 + src/javajs/util/V3.java | 77 + src/javajs/util/V3d.java | 93 + src/javajs/util/XmlUtil.java | 165 + src/javajs/util/ZipData.java | 76 + src/javajs/util/ZipTools.java | 432 + src/netscape/javascript/JSException.java | 5 + src/netscape/javascript/JSObject.java | 41 + src/org/exolab/castor/mapping/Mapping.java | 16 + src/org/exolab/castor/xml/Unmarshaller.java | 44 + src/org/jmol/viewer/Viewer.java | 5 + src/swingjs/JSEvent.java | 22 + src/swingjs/JSThread.java | 143 + src/swingjs/api/JSFunction.java | 5 + 277 files changed, 29524 insertions(+), 8077 deletions(-) create mode 100644 src/awt2swing/Button.java create mode 100644 src/awt2swing/Canvas.java create mode 100644 src/awt2swing/Checkbox.java create mode 100644 src/awt2swing/CheckboxMenuItem.java create mode 100644 src/awt2swing/Choice.java create mode 100644 src/awt2swing/Frame.java create mode 100644 src/awt2swing/Label.java create mode 100644 src/awt2swing/Menu.java create mode 100644 src/awt2swing/MenuBar.java create mode 100644 src/awt2swing/MenuItem.java create mode 100644 src/awt2swing/Panel.java create mode 100644 src/awt2swing/PopupMenu.java create mode 100644 src/awt2swing/ScrollPane.java create mode 100644 src/awt2swing/Scrollbar.java create mode 100644 src/awt2swing/TextArea.java create mode 100644 src/awt2swing/TextField.java create mode 100644 src/com/stevesoft/pat/MessageManager.java create mode 100644 src/com/stevesoft/pat/Util.java create mode 100644 src/fr/orsay/lri/varna/models/rna/RNA.java create mode 100644 src/jalview/jsdev/Constants.java create mode 100644 src/jalview/jsdev/GenericFileAdapter.java create mode 100644 src/jalview/jsdev/JSRegex.java create mode 100644 src/jalview/jsdev/JavaScriptRegExp.java create mode 100644 src/jalview/jsdev/RegExp.java create mode 100644 src/jalview/jsdev/api/RegExpInterface.java create mode 100644 src/jalview/jsdev/api/VarnaRNA.java create mode 100644 src/javajs/J2SIgnoreImport.java create mode 100644 src/javajs/J2SRequireImport.java create mode 100644 src/javajs/api/BytePoster.java create mode 100644 src/javajs/api/EigenInterface.java create mode 100644 src/javajs/api/EventManager.java create mode 100644 src/javajs/api/FontManager.java create mode 100644 src/javajs/api/GenericBinaryDocument.java create mode 100644 src/javajs/api/GenericCifDataParser.java create mode 100644 src/javajs/api/GenericColor.java create mode 100644 src/javajs/api/GenericFileInterface.java create mode 100644 src/javajs/api/GenericImageDialog.java create mode 100644 src/javajs/api/GenericImageEncoder.java create mode 100644 src/javajs/api/GenericLineReader.java create mode 100644 src/javajs/api/GenericMenuInterface.java create mode 100644 src/javajs/api/GenericMouseInterface.java create mode 100644 src/javajs/api/GenericPlatform.java create mode 100644 src/javajs/api/GenericZipInputStream.java create mode 100644 src/javajs/api/GenericZipTools.java create mode 100644 src/javajs/api/HTMLElement.java create mode 100644 src/javajs/api/HTMLWindowEvent.java create mode 100644 src/javajs/api/Interface.java create mode 100644 src/javajs/api/JSInterface.java create mode 100644 src/javajs/api/JSONEncodable.java create mode 100644 src/javajs/api/JmolObjectInterface.java create mode 100644 src/javajs/api/PlatformViewer.java create mode 100644 src/javajs/api/SC.java create mode 100644 src/javajs/api/SwingController.java create mode 100644 src/javajs/api/ZInputStream.java create mode 100644 src/javajs/awt/BorderLayout.java create mode 100644 src/javajs/awt/Color.java create mode 100644 src/javajs/awt/Component.java create mode 100644 src/javajs/awt/Container.java create mode 100644 src/javajs/awt/Dimension.java create mode 100644 src/javajs/awt/Font.java create mode 100644 src/javajs/awt/LayoutManager.java create mode 100644 src/javajs/awt/event/ActionEvent.java create mode 100644 src/javajs/awt/event/ActionListener.java create mode 100644 src/javajs/awt/event/Event.java create mode 100644 src/javajs/awt/event/ItemEvent.java create mode 100644 src/javajs/awt/event/WindowEvent.java create mode 100644 src/javajs/awt/event/WindowListener.java create mode 100644 src/javajs/export/PDFCreator.java create mode 100644 src/javajs/export/PDFObject.java create mode 100644 src/javajs/img/BMPDecoder.java create mode 100644 src/javajs/img/CRCEncoder.java create mode 100644 src/javajs/img/GifEncoder.java create mode 100644 src/javajs/img/ImageEncoder.java create mode 100644 src/javajs/img/Jpg64Encoder.java create mode 100644 src/javajs/img/JpgEncoder.java create mode 100644 src/javajs/img/PdfEncoder.java create mode 100644 src/javajs/img/PngEncoder.java create mode 100644 src/javajs/img/PpmEncoder.java create mode 100644 src/javajs/swing/AbstractButton.java create mode 100644 src/javajs/swing/AbstractTableModel.java create mode 100644 src/javajs/swing/ButtonGroup.java create mode 100644 src/javajs/swing/Cell.java create mode 100644 src/javajs/swing/ColumnSelectionModel.java create mode 100644 src/javajs/swing/Document.java create mode 100644 src/javajs/swing/FlowLayout.java create mode 100644 src/javajs/swing/Grid.java create mode 100644 src/javajs/swing/GridBagConstraints.java create mode 100644 src/javajs/swing/GridBagLayout.java create mode 100644 src/javajs/swing/Insets.java create mode 100644 src/javajs/swing/JButton.java create mode 100644 src/javajs/swing/JCheckBox.java create mode 100644 src/javajs/swing/JCheckBoxMenuItem.java create mode 100644 src/javajs/swing/JComboBox.java create mode 100644 src/javajs/swing/JComponent.java create mode 100644 src/javajs/swing/JComponentImp.java create mode 100644 src/javajs/swing/JContentPane.java create mode 100644 src/javajs/swing/JDialog.java create mode 100644 src/javajs/swing/JEditorPane.java create mode 100644 src/javajs/swing/JLabel.java create mode 100644 src/javajs/swing/JMenu.java create mode 100644 src/javajs/swing/JMenuItem.java create mode 100644 src/javajs/swing/JPanel.java create mode 100644 src/javajs/swing/JPopupMenu.java create mode 100644 src/javajs/swing/JRadioButtonMenuItem.java create mode 100644 src/javajs/swing/JScrollPane.java create mode 100644 src/javajs/swing/JSplitPane.java create mode 100644 src/javajs/swing/JTable.java create mode 100644 src/javajs/swing/JTextField.java create mode 100644 src/javajs/swing/JTextPane.java create mode 100644 src/javajs/swing/ListSelectionModel.java create mode 100644 src/javajs/swing/SwingConstants.java create mode 100644 src/javajs/swing/TableCellRenderer.java create mode 100644 src/javajs/swing/TableColumn.java create mode 100644 src/javajs/util/A4.java create mode 100644 src/javajs/util/AU.java create mode 100644 src/javajs/util/AjaxURLConnection.java create mode 100644 src/javajs/util/AjaxURLStreamHandler.java create mode 100644 src/javajs/util/AjaxURLStreamHandlerFactory.java create mode 100644 src/javajs/util/ArrayDataReader.java create mode 100644 src/javajs/util/BArray.java create mode 100644 src/javajs/util/BC.java create mode 100644 src/javajs/util/BS.java create mode 100644 src/javajs/util/Base64.java create mode 100644 src/javajs/util/BinaryDocument.java create mode 100644 src/javajs/util/CU.java create mode 100644 src/javajs/util/CifDataParser.java create mode 100644 src/javajs/util/CompoundDocDirEntry.java create mode 100644 src/javajs/util/CompoundDocHeader.java create mode 100644 src/javajs/util/CompoundDocument.java create mode 100644 src/javajs/util/DF.java create mode 100644 src/javajs/util/DataReader.java create mode 100644 src/javajs/util/Eigen.java create mode 100644 src/javajs/util/Encoding.java create mode 100644 src/javajs/util/LimitedLineReader.java create mode 100644 src/javajs/util/ListDataReader.java create mode 100644 src/javajs/util/Lst.java create mode 100644 src/javajs/util/M3.java create mode 100644 src/javajs/util/M34.java create mode 100644 src/javajs/util/M4.java create mode 100644 src/javajs/util/Matrix.java create mode 100644 src/javajs/util/Measure.java create mode 100644 src/javajs/util/OC.java create mode 100644 src/javajs/util/P3.java create mode 100644 src/javajs/util/P3i.java create mode 100644 src/javajs/util/P4.java create mode 100644 src/javajs/util/PT.java create mode 100644 src/javajs/util/Quat.java create mode 100644 src/javajs/util/Rdr.java create mode 100644 src/javajs/util/SB.java create mode 100644 src/javajs/util/StringDataReader.java create mode 100644 src/javajs/util/T3.java create mode 100644 src/javajs/util/T3d.java create mode 100644 src/javajs/util/T3i.java create mode 100644 src/javajs/util/T4.java create mode 100644 src/javajs/util/V3.java create mode 100644 src/javajs/util/V3d.java create mode 100644 src/javajs/util/XmlUtil.java create mode 100644 src/javajs/util/ZipData.java create mode 100644 src/javajs/util/ZipTools.java create mode 100644 src/netscape/javascript/JSException.java create mode 100644 src/netscape/javascript/JSObject.java create mode 100644 src/org/exolab/castor/mapping/Mapping.java create mode 100644 src/org/exolab/castor/xml/Unmarshaller.java create mode 100644 src/org/jmol/viewer/Viewer.java create mode 100644 src/swingjs/JSEvent.java create mode 100644 src/swingjs/JSThread.java create mode 100644 src/swingjs/api/JSFunction.java diff --git a/src/awt2swing/Button.java b/src/awt2swing/Button.java new file mode 100644 index 0000000..2e4b773 --- /dev/null +++ b/src/awt2swing/Button.java @@ -0,0 +1,16 @@ +package awt2swing; + +import javax.swing.JButton; + + +public class Button extends JButton { + + public Button() { + super(); + } + + public Button(String text) { + super(text); + } + +} diff --git a/src/awt2swing/Canvas.java b/src/awt2swing/Canvas.java new file mode 100644 index 0000000..73a6ce6 --- /dev/null +++ b/src/awt2swing/Canvas.java @@ -0,0 +1,6 @@ +package awt2swing; + + +public class Canvas extends Panel { + +} diff --git a/src/awt2swing/Checkbox.java b/src/awt2swing/Checkbox.java new file mode 100644 index 0000000..c320798 --- /dev/null +++ b/src/awt2swing/Checkbox.java @@ -0,0 +1,23 @@ +package awt2swing; + +import javax.swing.JCheckBox; + +public class Checkbox extends JCheckBox { + + public Checkbox(String string, boolean b) { + super(string, b); + } + + public Checkbox() { + super(); + } + + public boolean getState() { + return isSelected(); + } + + public void setState(boolean b) { + setSelected(b); + } + +} diff --git a/src/awt2swing/CheckboxMenuItem.java b/src/awt2swing/CheckboxMenuItem.java new file mode 100644 index 0000000..4be61dd --- /dev/null +++ b/src/awt2swing/CheckboxMenuItem.java @@ -0,0 +1,28 @@ +package awt2swing; + +import javax.swing.JCheckBoxMenuItem; + +public class CheckboxMenuItem extends JCheckBoxMenuItem { + + public CheckboxMenuItem(String string) { + super(string); + } + + public CheckboxMenuItem() { + } + + public CheckboxMenuItem(String string, boolean b) { + super(string, b); + } + + public boolean getState() { + return isSelected(); + } + + + public void setState(boolean tf) { + setSelected(tf); + } + + +} diff --git a/src/awt2swing/Choice.java b/src/awt2swing/Choice.java new file mode 100644 index 0000000..b9bda7c --- /dev/null +++ b/src/awt2swing/Choice.java @@ -0,0 +1,12 @@ +package awt2swing; + +import javax.swing.JComboBox; + + +public class Choice extends JComboBox { + + public void select(Object key) { + setSelectedItem(key); + } + +} diff --git a/src/awt2swing/Frame.java b/src/awt2swing/Frame.java new file mode 100644 index 0000000..2535321 --- /dev/null +++ b/src/awt2swing/Frame.java @@ -0,0 +1,55 @@ +package awt2swing; + +import javax.swing.JFrame; + +public class Frame extends JFrame { + + public Frame(String title) { + super(title); + /** + * @j2sNative + * + * xxxf = this; + */ + {} + } + + public Frame() { + super(); + /** + * @j2sNative + * + * xxxf = this; + */ + {} + } + + public void remove(int i) { + /** + * SwingJ has a somewhat reduced method set; we just use + * this interface to add ones we feel we need. + * + * @j2sNative + * + * this.removeInt(i); + * + */ + { + super.remove(i); + } + } + + public void setMenuBar(MenuBar m) { + setJMenuBar(m); + } + + public void unsetMenuBar() { + setJMenuBar(null); + } + + + public MenuBar getMenubar() { + return (MenuBar) getJMenuBar(); + } + +} diff --git a/src/awt2swing/Label.java b/src/awt2swing/Label.java new file mode 100644 index 0000000..2cfc18c --- /dev/null +++ b/src/awt2swing/Label.java @@ -0,0 +1,24 @@ +package awt2swing; + +import javax.swing.JLabel; + +public class Label extends JLabel { + + public Label() { + super(); + } + + public Label(String text) { + super(text); + } + + public Label(String text, int center) { + super(text, center); + } + + public void setAlignment(int alignment) { + setAlignmentX(alignment); + + } + +} diff --git a/src/awt2swing/Menu.java b/src/awt2swing/Menu.java new file mode 100644 index 0000000..ea4b672 --- /dev/null +++ b/src/awt2swing/Menu.java @@ -0,0 +1,17 @@ +package awt2swing; + +import javax.swing.JMenu; + +public class Menu extends JMenu { + + public Menu(String title) { + super(title); + title=null; + } + + public Menu() { + super(); + String s = null; + } + +} diff --git a/src/awt2swing/MenuBar.java b/src/awt2swing/MenuBar.java new file mode 100644 index 0000000..b5ca89b --- /dev/null +++ b/src/awt2swing/MenuBar.java @@ -0,0 +1,7 @@ +package awt2swing; + +import javax.swing.JMenuBar; + +public class MenuBar extends JMenuBar { + +} diff --git a/src/awt2swing/MenuItem.java b/src/awt2swing/MenuItem.java new file mode 100644 index 0000000..038db10 --- /dev/null +++ b/src/awt2swing/MenuItem.java @@ -0,0 +1,15 @@ +package awt2swing; + +import javax.swing.JMenuItem; + +public class MenuItem extends JMenuItem { + + public MenuItem(String string) { + super(string); + } + + public MenuItem() { + super(); + } + +} diff --git a/src/awt2swing/Panel.java b/src/awt2swing/Panel.java new file mode 100644 index 0000000..ac06a5b --- /dev/null +++ b/src/awt2swing/Panel.java @@ -0,0 +1,18 @@ +package awt2swing; + +import java.awt.Graphics; +import java.awt.LayoutManager; + +import javax.swing.JPanel; + +public class Panel extends JPanel { + + public Panel(LayoutManager layout) { + super(layout); + } + + public Panel() { + super(); + } + +} diff --git a/src/awt2swing/PopupMenu.java b/src/awt2swing/PopupMenu.java new file mode 100644 index 0000000..09cbdb3 --- /dev/null +++ b/src/awt2swing/PopupMenu.java @@ -0,0 +1,16 @@ +package awt2swing; + +import javax.swing.JPopupMenu; + +public class PopupMenu extends JPopupMenu { + + public PopupMenu() { + super(); + } + + public PopupMenu(String string) { + super(string); + } + + +} diff --git a/src/awt2swing/ScrollPane.java b/src/awt2swing/ScrollPane.java new file mode 100644 index 0000000..31da13c --- /dev/null +++ b/src/awt2swing/ScrollPane.java @@ -0,0 +1,7 @@ +package awt2swing; + +import javax.swing.JScrollPane; + +public class ScrollPane extends JScrollPane { + +} diff --git a/src/awt2swing/Scrollbar.java b/src/awt2swing/Scrollbar.java new file mode 100644 index 0000000..47783f9 --- /dev/null +++ b/src/awt2swing/Scrollbar.java @@ -0,0 +1,19 @@ +package awt2swing; + +import javax.swing.JScrollBar; + +public class Scrollbar extends JScrollBar { + + public Scrollbar(int direction) { + super(direction); + } + + public Scrollbar() { + super(); + } + + public Scrollbar(int orientation, int value, int extent, int min, int max) { + super(orientation, value, extent, min, max); + } + +} diff --git a/src/awt2swing/TextArea.java b/src/awt2swing/TextArea.java new file mode 100644 index 0000000..042016c --- /dev/null +++ b/src/awt2swing/TextArea.java @@ -0,0 +1,15 @@ +package awt2swing; + +import javax.swing.JTextArea; + +public class TextArea extends JTextArea { + + public TextArea(int rows, int cols) { + super(rows, cols); + } + + public TextArea() { + super(); + } + +} diff --git a/src/awt2swing/TextField.java b/src/awt2swing/TextField.java new file mode 100644 index 0000000..bfbfbfa --- /dev/null +++ b/src/awt2swing/TextField.java @@ -0,0 +1,46 @@ +package awt2swing; + +import jalview.structures.models.AAStructureBindingModel; + +import java.awt.event.TextEvent; +import java.awt.event.TextListener; + +import javax.swing.JTextField; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; + +public class TextField extends JTextField { + + public TextField(int width) { + super(width); + } + + public TextField() { + super(); + } + + public TextField(String text, int width) { + super(text, width); + } + + public void addTextListener(final TextListener textListener) { + getDocument().addDocumentListener(new DocumentListener() { + + @Override + public void insertUpdate(DocumentEvent e) { + } + + @Override + public void removeUpdate(DocumentEvent e) { + // TODO Auto-generated method stub + + } + + @Override + public void changedUpdate(DocumentEvent e) { + textListener.textValueChanged(new TextEvent(this, 0)); + } + }); + } + +} diff --git a/src/com/stevesoft/pat/BackRefRule.java b/src/com/stevesoft/pat/BackRefRule.java index daacbc1..e5c0778 100755 --- a/src/com/stevesoft/pat/BackRefRule.java +++ b/src/com/stevesoft/pat/BackRefRule.java @@ -24,7 +24,7 @@ public class BackRefRule extends ReplaceRule public void apply(StringBufferLike sb, RegRes res) { - String x = res.stringMatched(n); + String x = res.stringMatchedI(n); sb.append(x == null ? "" : x); } diff --git a/src/com/stevesoft/pat/BasicStringBufferLike.java b/src/com/stevesoft/pat/BasicStringBufferLike.java index adb10f1..89224e6 100755 --- a/src/com/stevesoft/pat/BasicStringBufferLike.java +++ b/src/com/stevesoft/pat/BasicStringBufferLike.java @@ -13,7 +13,7 @@ com.stevesoft.pat; */ public interface BasicStringBufferLike { - public void append(char c); + public void appendC(char c); public void append(String s); diff --git a/src/com/stevesoft/pat/CaseMgr.java b/src/com/stevesoft/pat/CaseMgr.java index 393dac9..077c795 100755 --- a/src/com/stevesoft/pat/CaseMgr.java +++ b/src/com/stevesoft/pat/CaseMgr.java @@ -22,4171 +22,4176 @@ final public class CaseMgr final static boolean java_1_0 = false; /** Convert a character to upper case . */ - public static char toUpperCase(char c) + public static char toUpperCaseC(char c) { - if (java_1_0) - { - int ret = (int) c; - switch (c) - { - case 97: - ret = 65; - break; - case 98: - ret = 66; - break; - case 99: - ret = 67; - break; - case 100: - ret = 68; - break; - case 101: - ret = 69; - break; - case 102: - ret = 70; - break; - case 103: - ret = 71; - break; - case 104: - ret = 72; - break; - case 105: - ret = 73; - break; - case 106: - ret = 74; - break; - case 107: - ret = 75; - break; - case 108: - ret = 76; - break; - case 109: - ret = 77; - break; - case 110: - ret = 78; - break; - case 111: - ret = 79; - break; - case 112: - ret = 80; - break; - case 113: - ret = 81; - break; - case 114: - ret = 82; - break; - case 115: - ret = 83; - break; - case 116: - ret = 84; - break; - case 117: - ret = 85; - break; - case 118: - ret = 86; - break; - case 119: - ret = 87; - break; - case 120: - ret = 88; - break; - case 121: - ret = 89; - break; - case 122: - ret = 90; - break; - case 224: - ret = 192; - break; - case 225: - ret = 193; - break; - case 226: - ret = 194; - break; - case 227: - ret = 195; - break; - case 228: - ret = 196; - break; - case 229: - ret = 197; - break; - case 230: - ret = 198; - break; - case 231: - ret = 199; - break; - case 232: - ret = 200; - break; - case 233: - ret = 201; - break; - case 234: - ret = 202; - break; - case 235: - ret = 203; - break; - case 236: - ret = 204; - break; - case 237: - ret = 205; - break; - case 238: - ret = 206; - break; - case 239: - ret = 207; - break; - case 240: - ret = 208; - break; - case 241: - ret = 209; - break; - case 242: - ret = 210; - break; - case 243: - ret = 211; - break; - case 244: - ret = 212; - break; - case 245: - ret = 213; - break; - case 246: - ret = 214; - break; - case 248: - ret = 216; - break; - case 249: - ret = 217; - break; - case 250: - ret = 218; - break; - case 251: - ret = 219; - break; - case 252: - ret = 220; - break; - case 253: - ret = 221; - break; - case 254: - ret = 222; - break; - case 255: - ret = 376; - break; - case 257: - ret = 256; - break; - case 259: - ret = 258; - break; - case 261: - ret = 260; - break; - case 263: - ret = 262; - break; - case 265: - ret = 264; - break; - case 267: - ret = 266; - break; - case 269: - ret = 268; - break; - case 271: - ret = 270; - break; - case 273: - ret = 272; - break; - case 275: - ret = 274; - break; - case 277: - ret = 276; - break; - case 279: - ret = 278; - break; - case 281: - ret = 280; - break; - case 283: - ret = 282; - break; - case 285: - ret = 284; - break; - case 287: - ret = 286; - break; - case 289: - ret = 288; - break; - case 291: - ret = 290; - break; - case 293: - ret = 292; - break; - case 295: - ret = 294; - break; - case 297: - ret = 296; - break; - case 299: - ret = 298; - break; - case 301: - ret = 300; - break; - case 303: - ret = 302; - break; - case 305: - ret = 73; - break; - case 307: - ret = 306; - break; - case 309: - ret = 308; - break; - case 311: - ret = 310; - break; - case 314: - ret = 313; - break; - case 316: - ret = 315; - break; - case 318: - ret = 317; - break; - case 320: - ret = 319; - break; - case 322: - ret = 321; - break; - case 324: - ret = 323; - break; - case 326: - ret = 325; - break; - case 328: - ret = 327; - break; - case 331: - ret = 330; - break; - case 333: - ret = 332; - break; - case 335: - ret = 334; - break; - case 337: - ret = 336; - break; - case 339: - ret = 338; - break; - case 341: - ret = 340; - break; - case 343: - ret = 342; - break; - case 345: - ret = 344; - break; - case 347: - ret = 346; - break; - case 349: - ret = 348; - break; - case 351: - ret = 350; - break; - case 353: - ret = 352; - break; - case 355: - ret = 354; - break; - case 357: - ret = 356; - break; - case 359: - ret = 358; - break; - case 361: - ret = 360; - break; - case 363: - ret = 362; - break; - case 365: - ret = 364; - break; - case 367: - ret = 366; - break; - case 369: - ret = 368; - break; - case 371: - ret = 370; - break; - case 373: - ret = 372; - break; - case 375: - ret = 374; - break; - case 378: - ret = 377; - break; - case 380: - ret = 379; - break; - case 382: - ret = 381; - break; - case 383: - ret = 83; - break; - case 387: - ret = 386; - break; - case 389: - ret = 388; - break; - case 392: - ret = 391; - break; - case 396: - ret = 395; - break; - case 402: - ret = 401; - break; - case 409: - ret = 408; - break; - case 417: - ret = 416; - break; - case 419: - ret = 418; - break; - case 421: - ret = 420; - break; - case 424: - ret = 423; - break; - case 429: - ret = 428; - break; - case 432: - ret = 431; - break; - case 436: - ret = 435; - break; - case 438: - ret = 437; - break; - case 441: - ret = 440; - break; - case 445: - ret = 444; - break; - case 453: - ret = 452; - break; - case 454: - ret = 452; - break; - case 456: - ret = 455; - break; - case 457: - ret = 455; - break; - case 459: - ret = 458; - break; - case 460: - ret = 458; - break; - case 462: - ret = 461; - break; - case 464: - ret = 463; - break; - case 466: - ret = 465; - break; - case 468: - ret = 467; - break; - case 470: - ret = 469; - break; - case 472: - ret = 471; - break; - case 474: - ret = 473; - break; - case 476: - ret = 475; - break; - case 479: - ret = 478; - break; - case 481: - ret = 480; - break; - case 483: - ret = 482; - break; - case 485: - ret = 484; - break; - case 487: - ret = 486; - break; - case 489: - ret = 488; - break; - case 491: - ret = 490; - break; - case 493: - ret = 492; - break; - case 495: - ret = 494; - break; - case 498: - ret = 497; - break; - case 499: - ret = 497; - break; - case 501: - ret = 500; - break; - case 507: - ret = 506; - break; - case 509: - ret = 508; - break; - case 511: - ret = 510; - break; - case 513: - ret = 512; - break; - case 515: - ret = 514; - break; - case 517: - ret = 516; - break; - case 519: - ret = 518; - break; - case 521: - ret = 520; - break; - case 523: - ret = 522; - break; - case 525: - ret = 524; - break; - case 527: - ret = 526; - break; - case 529: - ret = 528; - break; - case 531: - ret = 530; - break; - case 533: - ret = 532; - break; - case 535: - ret = 534; - break; - case 595: - ret = 385; - break; - case 596: - ret = 390; - break; - case 598: - ret = 393; - break; - case 599: - ret = 394; - break; - case 600: - ret = 398; - break; - case 601: - ret = 399; - break; - case 603: - ret = 400; - break; - case 608: - ret = 403; - break; - case 611: - ret = 404; - break; - case 616: - ret = 407; - break; - case 617: - ret = 406; - break; - case 623: - ret = 412; - break; - case 626: - ret = 413; - break; - case 643: - ret = 425; - break; - case 648: - ret = 430; - break; - case 650: - ret = 433; - break; - case 651: - ret = 434; - break; - case 658: - ret = 439; - break; - case 940: - ret = 902; - break; - case 941: - ret = 904; - break; - case 942: - ret = 905; - break; - case 943: - ret = 906; - break; - case 945: - ret = 913; - break; - case 946: - ret = 914; - break; - case 947: - ret = 915; - break; - case 948: - ret = 916; - break; - case 949: - ret = 917; - break; - case 950: - ret = 918; - break; - case 951: - ret = 919; - break; - case 952: - ret = 920; - break; - case 953: - ret = 921; - break; - case 954: - ret = 922; - break; - case 955: - ret = 923; - break; - case 956: - ret = 924; - break; - case 957: - ret = 925; - break; - case 958: - ret = 926; - break; - case 959: - ret = 927; - break; - case 960: - ret = 928; - break; - case 961: - ret = 929; - break; - case 963: - ret = 931; - break; - case 964: - ret = 932; - break; - case 965: - ret = 933; - break; - case 966: - ret = 934; - break; - case 967: - ret = 935; - break; - case 968: - ret = 936; - break; - case 969: - ret = 937; - break; - case 970: - ret = 938; - break; - case 971: - ret = 939; - break; - case 972: - ret = 908; - break; - case 973: - ret = 910; - break; - case 974: - ret = 911; - break; - case 976: - ret = 914; - break; - case 977: - ret = 920; - break; - case 981: - ret = 934; - break; - case 982: - ret = 928; - break; - case 995: - ret = 994; - break; - case 997: - ret = 996; - break; - case 999: - ret = 998; - break; - case 1001: - ret = 1000; - break; - case 1003: - ret = 1002; - break; - case 1005: - ret = 1004; - break; - case 1007: - ret = 1006; - break; - case 1008: - ret = 922; - break; - case 1009: - ret = 929; - break; - case 1072: - ret = 1040; - break; - case 1073: - ret = 1041; - break; - case 1074: - ret = 1042; - break; - case 1075: - ret = 1043; - break; - case 1076: - ret = 1044; - break; - case 1077: - ret = 1045; - break; - case 1078: - ret = 1046; - break; - case 1079: - ret = 1047; - break; - case 1080: - ret = 1048; - break; - case 1081: - ret = 1049; - break; - case 1082: - ret = 1050; - break; - case 1083: - ret = 1051; - break; - case 1084: - ret = 1052; - break; - case 1085: - ret = 1053; - break; - case 1086: - ret = 1054; - break; - case 1087: - ret = 1055; - break; - case 1088: - ret = 1056; - break; - case 1089: - ret = 1057; - break; - case 1090: - ret = 1058; - break; - case 1091: - ret = 1059; - break; - case 1092: - ret = 1060; - break; - case 1093: - ret = 1061; - break; - case 1094: - ret = 1062; - break; - case 1095: - ret = 1063; - break; - case 1096: - ret = 1064; - break; - case 1097: - ret = 1065; - break; - case 1098: - ret = 1066; - break; - case 1099: - ret = 1067; - break; - case 1100: - ret = 1068; - break; - case 1101: - ret = 1069; - break; - case 1102: - ret = 1070; - break; - case 1103: - ret = 1071; - break; - case 1105: - ret = 1025; - break; - case 1106: - ret = 1026; - break; - case 1107: - ret = 1027; - break; - case 1108: - ret = 1028; - break; - case 1109: - ret = 1029; - break; - case 1110: - ret = 1030; - break; - case 1111: - ret = 1031; - break; - case 1112: - ret = 1032; - break; - case 1113: - ret = 1033; - break; - case 1114: - ret = 1034; - break; - case 1115: - ret = 1035; - break; - case 1116: - ret = 1036; - break; - case 1118: - ret = 1038; - break; - case 1119: - ret = 1039; - break; - case 1121: - ret = 1120; - break; - case 1123: - ret = 1122; - break; - case 1125: - ret = 1124; - break; - case 1127: - ret = 1126; - break; - case 1129: - ret = 1128; - break; - case 1131: - ret = 1130; - break; - case 1133: - ret = 1132; - break; - case 1135: - ret = 1134; - break; - case 1137: - ret = 1136; - break; - case 1139: - ret = 1138; - break; - case 1141: - ret = 1140; - break; - case 1143: - ret = 1142; - break; - case 1145: - ret = 1144; - break; - case 1147: - ret = 1146; - break; - case 1149: - ret = 1148; - break; - case 1151: - ret = 1150; - break; - case 1153: - ret = 1152; - break; - case 1169: - ret = 1168; - break; - case 1171: - ret = 1170; - break; - case 1173: - ret = 1172; - break; - case 1175: - ret = 1174; - break; - case 1177: - ret = 1176; - break; - case 1179: - ret = 1178; - break; - case 1181: - ret = 1180; - break; - case 1183: - ret = 1182; - break; - case 1185: - ret = 1184; - break; - case 1187: - ret = 1186; - break; - case 1189: - ret = 1188; - break; - case 1191: - ret = 1190; - break; - case 1193: - ret = 1192; - break; - case 1195: - ret = 1194; - break; - case 1197: - ret = 1196; - break; - case 1199: - ret = 1198; - break; - case 1201: - ret = 1200; - break; - case 1203: - ret = 1202; - break; - case 1205: - ret = 1204; - break; - case 1207: - ret = 1206; - break; - case 1209: - ret = 1208; - break; - case 1211: - ret = 1210; - break; - case 1213: - ret = 1212; - break; - case 1215: - ret = 1214; - break; - case 1218: - ret = 1217; - break; - case 1220: - ret = 1219; - break; - case 1224: - ret = 1223; - break; - case 1228: - ret = 1227; - break; - case 1233: - ret = 1232; - break; - case 1235: - ret = 1234; - break; - case 1237: - ret = 1236; - break; - case 1239: - ret = 1238; - break; - case 1241: - ret = 1240; - break; - case 1243: - ret = 1242; - break; - case 1245: - ret = 1244; - break; - case 1247: - ret = 1246; - break; - case 1249: - ret = 1248; - break; - case 1251: - ret = 1250; - break; - case 1253: - ret = 1252; - break; - case 1255: - ret = 1254; - break; - case 1257: - ret = 1256; - break; - case 1259: - ret = 1258; - break; - case 1263: - ret = 1262; - break; - case 1265: - ret = 1264; - break; - case 1267: - ret = 1266; - break; - case 1269: - ret = 1268; - break; - case 1273: - ret = 1272; - break; - case 1377: - ret = 1329; - break; - case 1378: - ret = 1330; - break; - case 1379: - ret = 1331; - break; - case 1380: - ret = 1332; - break; - case 1381: - ret = 1333; - break; - case 1382: - ret = 1334; - break; - case 1383: - ret = 1335; - break; - case 1384: - ret = 1336; - break; - case 1385: - ret = 1337; - break; - case 1386: - ret = 1338; - break; - case 1387: - ret = 1339; - break; - case 1388: - ret = 1340; - break; - case 1389: - ret = 1341; - break; - case 1390: - ret = 1342; - break; - case 1391: - ret = 1343; - break; - case 1392: - ret = 1344; - break; - case 1393: - ret = 1345; - break; - case 1394: - ret = 1346; - break; - case 1395: - ret = 1347; - break; - case 1396: - ret = 1348; - break; - case 1397: - ret = 1349; - break; - case 1398: - ret = 1350; - break; - case 1399: - ret = 1351; - break; - case 1400: - ret = 1352; - break; - case 1401: - ret = 1353; - break; - case 1402: - ret = 1354; - break; - case 1403: - ret = 1355; - break; - case 1404: - ret = 1356; - break; - case 1405: - ret = 1357; - break; - case 1406: - ret = 1358; - break; - case 1407: - ret = 1359; - break; - case 1408: - ret = 1360; - break; - case 1409: - ret = 1361; - break; - case 1410: - ret = 1362; - break; - case 1411: - ret = 1363; - break; - case 1412: - ret = 1364; - break; - case 1413: - ret = 1365; - break; - case 1414: - ret = 1366; - break; - case 7681: - ret = 7680; - break; - case 7683: - ret = 7682; - break; - case 7685: - ret = 7684; - break; - case 7687: - ret = 7686; - break; - case 7689: - ret = 7688; - break; - case 7691: - ret = 7690; - break; - case 7693: - ret = 7692; - break; - case 7695: - ret = 7694; - break; - case 7697: - ret = 7696; - break; - case 7699: - ret = 7698; - break; - case 7701: - ret = 7700; - break; - case 7703: - ret = 7702; - break; - case 7705: - ret = 7704; - break; - case 7707: - ret = 7706; - break; - case 7709: - ret = 7708; - break; - case 7711: - ret = 7710; - break; - case 7713: - ret = 7712; - break; - case 7715: - ret = 7714; - break; - case 7717: - ret = 7716; - break; - case 7719: - ret = 7718; - break; - case 7721: - ret = 7720; - break; - case 7723: - ret = 7722; - break; - case 7725: - ret = 7724; - break; - case 7727: - ret = 7726; - break; - case 7729: - ret = 7728; - break; - case 7731: - ret = 7730; - break; - case 7733: - ret = 7732; - break; - case 7735: - ret = 7734; - break; - case 7737: - ret = 7736; - break; - case 7739: - ret = 7738; - break; - case 7741: - ret = 7740; - break; - case 7743: - ret = 7742; - break; - case 7745: - ret = 7744; - break; - case 7747: - ret = 7746; - break; - case 7749: - ret = 7748; - break; - case 7751: - ret = 7750; - break; - case 7753: - ret = 7752; - break; - case 7755: - ret = 7754; - break; - case 7757: - ret = 7756; - break; - case 7759: - ret = 7758; - break; - case 7761: - ret = 7760; - break; - case 7763: - ret = 7762; - break; - case 7765: - ret = 7764; - break; - case 7767: - ret = 7766; - break; - case 7769: - ret = 7768; - break; - case 7771: - ret = 7770; - break; - case 7773: - ret = 7772; - break; - case 7775: - ret = 7774; - break; - case 7777: - ret = 7776; - break; - case 7779: - ret = 7778; - break; - case 7781: - ret = 7780; - break; - case 7783: - ret = 7782; - break; - case 7785: - ret = 7784; - break; - case 7787: - ret = 7786; - break; - case 7789: - ret = 7788; - break; - case 7791: - ret = 7790; - break; - case 7793: - ret = 7792; - break; - case 7795: - ret = 7794; - break; - case 7797: - ret = 7796; - break; - case 7799: - ret = 7798; - break; - case 7801: - ret = 7800; - break; - case 7803: - ret = 7802; - break; - case 7805: - ret = 7804; - break; - case 7807: - ret = 7806; - break; - case 7809: - ret = 7808; - break; - case 7811: - ret = 7810; - break; - case 7813: - ret = 7812; - break; - case 7815: - ret = 7814; - break; - case 7817: - ret = 7816; - break; - case 7819: - ret = 7818; - break; - case 7821: - ret = 7820; - break; - case 7823: - ret = 7822; - break; - case 7825: - ret = 7824; - break; - case 7827: - ret = 7826; - break; - case 7829: - ret = 7828; - break; - case 7841: - ret = 7840; - break; - case 7843: - ret = 7842; - break; - case 7845: - ret = 7844; - break; - case 7847: - ret = 7846; - break; - case 7849: - ret = 7848; - break; - case 7851: - ret = 7850; - break; - case 7853: - ret = 7852; - break; - case 7855: - ret = 7854; - break; - case 7857: - ret = 7856; - break; - case 7859: - ret = 7858; - break; - case 7861: - ret = 7860; - break; - case 7863: - ret = 7862; - break; - case 7865: - ret = 7864; - break; - case 7867: - ret = 7866; - break; - case 7869: - ret = 7868; - break; - case 7871: - ret = 7870; - break; - case 7873: - ret = 7872; - break; - case 7875: - ret = 7874; - break; - case 7877: - ret = 7876; - break; - case 7879: - ret = 7878; - break; - case 7881: - ret = 7880; - break; - case 7883: - ret = 7882; - break; - case 7885: - ret = 7884; - break; - case 7887: - ret = 7886; - break; - case 7889: - ret = 7888; - break; - case 7891: - ret = 7890; - break; - case 7893: - ret = 7892; - break; - case 7895: - ret = 7894; - break; - case 7897: - ret = 7896; - break; - case 7899: - ret = 7898; - break; - case 7901: - ret = 7900; - break; - case 7903: - ret = 7902; - break; - case 7905: - ret = 7904; - break; - case 7907: - ret = 7906; - break; - case 7909: - ret = 7908; - break; - case 7911: - ret = 7910; - break; - case 7913: - ret = 7912; - break; - case 7915: - ret = 7914; - break; - case 7917: - ret = 7916; - break; - case 7919: - ret = 7918; - break; - case 7921: - ret = 7920; - break; - case 7923: - ret = 7922; - break; - case 7925: - ret = 7924; - break; - case 7927: - ret = 7926; - break; - case 7929: - ret = 7928; - break; - case 7936: - ret = 7944; - break; - case 7937: - ret = 7945; - break; - case 7938: - ret = 7946; - break; - case 7939: - ret = 7947; - break; - case 7940: - ret = 7948; - break; - case 7941: - ret = 7949; - break; - case 7942: - ret = 7950; - break; - case 7943: - ret = 7951; - break; - case 7952: - ret = 7960; - break; - case 7953: - ret = 7961; - break; - case 7954: - ret = 7962; - break; - case 7955: - ret = 7963; - break; - case 7956: - ret = 7964; - break; - case 7957: - ret = 7965; - break; - case 7968: - ret = 7976; - break; - case 7969: - ret = 7977; - break; - case 7970: - ret = 7978; - break; - case 7971: - ret = 7979; - break; - case 7972: - ret = 7980; - break; - case 7973: - ret = 7981; - break; - case 7974: - ret = 7982; - break; - case 7975: - ret = 7983; - break; - case 7984: - ret = 7992; - break; - case 7985: - ret = 7993; - break; - case 7986: - ret = 7994; - break; - case 7987: - ret = 7995; - break; - case 7988: - ret = 7996; - break; - case 7989: - ret = 7997; - break; - case 7990: - ret = 7998; - break; - case 7991: - ret = 7999; - break; - case 8000: - ret = 8008; - break; - case 8001: - ret = 8009; - break; - case 8002: - ret = 8010; - break; - case 8003: - ret = 8011; - break; - case 8004: - ret = 8012; - break; - case 8005: - ret = 8013; - break; - case 8017: - ret = 8025; - break; - case 8019: - ret = 8027; - break; - case 8021: - ret = 8029; - break; - case 8023: - ret = 8031; - break; - case 8032: - ret = 8040; - break; - case 8033: - ret = 8041; - break; - case 8034: - ret = 8042; - break; - case 8035: - ret = 8043; - break; - case 8036: - ret = 8044; - break; - case 8037: - ret = 8045; - break; - case 8038: - ret = 8046; - break; - case 8039: - ret = 8047; - break; - case 8048: - ret = 8122; - break; - case 8049: - ret = 8123; - break; - case 8050: - ret = 8136; - break; - case 8051: - ret = 8137; - break; - case 8052: - ret = 8138; - break; - case 8053: - ret = 8139; - break; - case 8054: - ret = 8154; - break; - case 8055: - ret = 8155; - break; - case 8056: - ret = 8184; - break; - case 8057: - ret = 8185; - break; - case 8058: - ret = 8170; - break; - case 8059: - ret = 8171; - break; - case 8060: - ret = 8186; - break; - case 8061: - ret = 8187; - break; - case 8064: - ret = 8072; - break; - case 8065: - ret = 8073; - break; - case 8066: - ret = 8074; - break; - case 8067: - ret = 8075; - break; - case 8068: - ret = 8076; - break; - case 8069: - ret = 8077; - break; - case 8070: - ret = 8078; - break; - case 8071: - ret = 8079; - break; - case 8080: - ret = 8088; - break; - case 8081: - ret = 8089; - break; - case 8082: - ret = 8090; - break; - case 8083: - ret = 8091; - break; - case 8084: - ret = 8092; - break; - case 8085: - ret = 8093; - break; - case 8086: - ret = 8094; - break; - case 8087: - ret = 8095; - break; - case 8096: - ret = 8104; - break; - case 8097: - ret = 8105; - break; - case 8098: - ret = 8106; - break; - case 8099: - ret = 8107; - break; - case 8100: - ret = 8108; - break; - case 8101: - ret = 8109; - break; - case 8102: - ret = 8110; - break; - case 8103: - ret = 8111; - break; - case 8112: - ret = 8120; - break; - case 8113: - ret = 8121; - break; - case 8115: - ret = 8124; - break; - case 8131: - ret = 8140; - break; - case 8144: - ret = 8152; - break; - case 8145: - ret = 8153; - break; - case 8160: - ret = 8168; - break; - case 8161: - ret = 8169; - break; - case 8165: - ret = 8172; - break; - case 8179: - ret = 8188; - break; - case 8560: - ret = 8544; - break; - case 8561: - ret = 8545; - break; - case 8562: - ret = 8546; - break; - case 8563: - ret = 8547; - break; - case 8564: - ret = 8548; - break; - case 8565: - ret = 8549; - break; - case 8566: - ret = 8550; - break; - case 8567: - ret = 8551; - break; - case 8568: - ret = 8552; - break; - case 8569: - ret = 8553; - break; - case 8570: - ret = 8554; - break; - case 8571: - ret = 8555; - break; - case 8572: - ret = 8556; - break; - case 8573: - ret = 8557; - break; - case 8574: - ret = 8558; - break; - case 8575: - ret = 8559; - break; - case 9424: - ret = 9398; - break; - case 9425: - ret = 9399; - break; - case 9426: - ret = 9400; - break; - case 9427: - ret = 9401; - break; - case 9428: - ret = 9402; - break; - case 9429: - ret = 9403; - break; - case 9430: - ret = 9404; - break; - case 9431: - ret = 9405; - break; - case 9432: - ret = 9406; - break; - case 9433: - ret = 9407; - break; - case 9434: - ret = 9408; - break; - case 9435: - ret = 9409; - break; - case 9436: - ret = 9410; - break; - case 9437: - ret = 9411; - break; - case 9438: - ret = 9412; - break; - case 9439: - ret = 9413; - break; - case 9440: - ret = 9414; - break; - case 9441: - ret = 9415; - break; - case 9442: - ret = 9416; - break; - case 9443: - ret = 9417; - break; - case 9444: - ret = 9418; - break; - case 9445: - ret = 9419; - break; - case 9446: - ret = 9420; - break; - case 9447: - ret = 9421; - break; - case 9448: - ret = 9422; - break; - case 9449: - ret = 9423; - break; - case 65345: - ret = 65313; - break; - case 65346: - ret = 65314; - break; - case 65347: - ret = 65315; - break; - case 65348: - ret = 65316; - break; - case 65349: - ret = 65317; - break; - case 65350: - ret = 65318; - break; - case 65351: - ret = 65319; - break; - case 65352: - ret = 65320; - break; - case 65353: - ret = 65321; - break; - case 65354: - ret = 65322; - break; - case 65355: - ret = 65323; - break; - case 65356: - ret = 65324; - break; - case 65357: - ret = 65325; - break; - case 65358: - ret = 65326; - break; - case 65359: - ret = 65327; - break; - case 65360: - ret = 65328; - break; - case 65361: - ret = 65329; - break; - case 65362: - ret = 65330; - break; - case 65363: - ret = 65331; - break; - case 65364: - ret = 65332; - break; - case 65365: - ret = 65333; - break; - case 65366: - ret = 65334; - break; - case 65367: - ret = 65335; - break; - case 65368: - ret = 65336; - break; - case 65369: - ret = 65337; - break; - case 65370: - ret = 65338; - break; - } - return (char) ret; - } +// if (java_1_0) +// { +// int ret = (int) c; +// switch (c) +// { +// case 97: +// ret = 65; +// break; +// case 98: +// ret = 66; +// break; +// case 99: +// ret = 67; +// break; +// case 100: +// ret = 68; +// break; +// case 101: +// ret = 69; +// break; +// case 102: +// ret = 70; +// break; +// case 103: +// ret = 71; +// break; +// case 104: +// ret = 72; +// break; +// case 105: +// ret = 73; +// break; +// case 106: +// ret = 74; +// break; +// case 107: +// ret = 75; +// break; +// case 108: +// ret = 76; +// break; +// case 109: +// ret = 77; +// break; +// case 110: +// ret = 78; +// break; +// case 111: +// ret = 79; +// break; +// case 112: +// ret = 80; +// break; +// case 113: +// ret = 81; +// break; +// case 114: +// ret = 82; +// break; +// case 115: +// ret = 83; +// break; +// case 116: +// ret = 84; +// break; +// case 117: +// ret = 85; +// break; +// case 118: +// ret = 86; +// break; +// case 119: +// ret = 87; +// break; +// case 120: +// ret = 88; +// break; +// case 121: +// ret = 89; +// break; +// case 122: +// ret = 90; +// break; +// case 224: +// ret = 192; +// break; +// case 225: +// ret = 193; +// break; +// case 226: +// ret = 194; +// break; +// case 227: +// ret = 195; +// break; +// case 228: +// ret = 196; +// break; +// case 229: +// ret = 197; +// break; +// case 230: +// ret = 198; +// break; +// case 231: +// ret = 199; +// break; +// case 232: +// ret = 200; +// break; +// case 233: +// ret = 201; +// break; +// case 234: +// ret = 202; +// break; +// case 235: +// ret = 203; +// break; +// case 236: +// ret = 204; +// break; +// case 237: +// ret = 205; +// break; +// case 238: +// ret = 206; +// break; +// case 239: +// ret = 207; +// break; +// case 240: +// ret = 208; +// break; +// case 241: +// ret = 209; +// break; +// case 242: +// ret = 210; +// break; +// case 243: +// ret = 211; +// break; +// case 244: +// ret = 212; +// break; +// case 245: +// ret = 213; +// break; +// case 246: +// ret = 214; +// break; +// case 248: +// ret = 216; +// break; +// case 249: +// ret = 217; +// break; +// case 250: +// ret = 218; +// break; +// case 251: +// ret = 219; +// break; +// case 252: +// ret = 220; +// break; +// case 253: +// ret = 221; +// break; +// case 254: +// ret = 222; +// break; +// case 255: +// ret = 376; +// break; +// case 257: +// ret = 256; +// break; +// case 259: +// ret = 258; +// break; +// case 261: +// ret = 260; +// break; +// case 263: +// ret = 262; +// break; +// case 265: +// ret = 264; +// break; +// case 267: +// ret = 266; +// break; +// case 269: +// ret = 268; +// break; +// case 271: +// ret = 270; +// break; +// case 273: +// ret = 272; +// break; +// case 275: +// ret = 274; +// break; +// case 277: +// ret = 276; +// break; +// case 279: +// ret = 278; +// break; +// case 281: +// ret = 280; +// break; +// case 283: +// ret = 282; +// break; +// case 285: +// ret = 284; +// break; +// case 287: +// ret = 286; +// break; +// case 289: +// ret = 288; +// break; +// case 291: +// ret = 290; +// break; +// case 293: +// ret = 292; +// break; +// case 295: +// ret = 294; +// break; +// case 297: +// ret = 296; +// break; +// case 299: +// ret = 298; +// break; +// case 301: +// ret = 300; +// break; +// case 303: +// ret = 302; +// break; +// case 305: +// ret = 73; +// break; +// case 307: +// ret = 306; +// break; +// case 309: +// ret = 308; +// break; +// case 311: +// ret = 310; +// break; +// case 314: +// ret = 313; +// break; +// case 316: +// ret = 315; +// break; +// case 318: +// ret = 317; +// break; +// case 320: +// ret = 319; +// break; +// case 322: +// ret = 321; +// break; +// case 324: +// ret = 323; +// break; +// case 326: +// ret = 325; +// break; +// case 328: +// ret = 327; +// break; +// case 331: +// ret = 330; +// break; +// case 333: +// ret = 332; +// break; +// case 335: +// ret = 334; +// break; +// case 337: +// ret = 336; +// break; +// case 339: +// ret = 338; +// break; +// case 341: +// ret = 340; +// break; +// case 343: +// ret = 342; +// break; +// case 345: +// ret = 344; +// break; +// case 347: +// ret = 346; +// break; +// case 349: +// ret = 348; +// break; +// case 351: +// ret = 350; +// break; +// case 353: +// ret = 352; +// break; +// case 355: +// ret = 354; +// break; +// case 357: +// ret = 356; +// break; +// case 359: +// ret = 358; +// break; +// case 361: +// ret = 360; +// break; +// case 363: +// ret = 362; +// break; +// case 365: +// ret = 364; +// break; +// case 367: +// ret = 366; +// break; +// case 369: +// ret = 368; +// break; +// case 371: +// ret = 370; +// break; +// case 373: +// ret = 372; +// break; +// case 375: +// ret = 374; +// break; +// case 378: +// ret = 377; +// break; +// case 380: +// ret = 379; +// break; +// case 382: +// ret = 381; +// break; +// case 383: +// ret = 83; +// break; +// case 387: +// ret = 386; +// break; +// case 389: +// ret = 388; +// break; +// case 392: +// ret = 391; +// break; +// case 396: +// ret = 395; +// break; +// case 402: +// ret = 401; +// break; +// case 409: +// ret = 408; +// break; +// case 417: +// ret = 416; +// break; +// case 419: +// ret = 418; +// break; +// case 421: +// ret = 420; +// break; +// case 424: +// ret = 423; +// break; +// case 429: +// ret = 428; +// break; +// case 432: +// ret = 431; +// break; +// case 436: +// ret = 435; +// break; +// case 438: +// ret = 437; +// break; +// case 441: +// ret = 440; +// break; +// case 445: +// ret = 444; +// break; +// case 453: +// ret = 452; +// break; +// case 454: +// ret = 452; +// break; +// case 456: +// ret = 455; +// break; +// case 457: +// ret = 455; +// break; +// case 459: +// ret = 458; +// break; +// case 460: +// ret = 458; +// break; +// case 462: +// ret = 461; +// break; +// case 464: +// ret = 463; +// break; +// case 466: +// ret = 465; +// break; +// case 468: +// ret = 467; +// break; +// case 470: +// ret = 469; +// break; +// case 472: +// ret = 471; +// break; +// case 474: +// ret = 473; +// break; +// case 476: +// ret = 475; +// break; +// case 479: +// ret = 478; +// break; +// case 481: +// ret = 480; +// break; +// case 483: +// ret = 482; +// break; +// case 485: +// ret = 484; +// break; +// case 487: +// ret = 486; +// break; +// case 489: +// ret = 488; +// break; +// case 491: +// ret = 490; +// break; +// case 493: +// ret = 492; +// break; +// case 495: +// ret = 494; +// break; +// case 498: +// ret = 497; +// break; +// case 499: +// ret = 497; +// break; +// case 501: +// ret = 500; +// break; +// case 507: +// ret = 506; +// break; +// case 509: +// ret = 508; +// break; +// case 511: +// ret = 510; +// break; +// case 513: +// ret = 512; +// break; +// case 515: +// ret = 514; +// break; +// case 517: +// ret = 516; +// break; +// case 519: +// ret = 518; +// break; +// case 521: +// ret = 520; +// break; +// case 523: +// ret = 522; +// break; +// case 525: +// ret = 524; +// break; +// case 527: +// ret = 526; +// break; +// case 529: +// ret = 528; +// break; +// case 531: +// ret = 530; +// break; +// case 533: +// ret = 532; +// break; +// case 535: +// ret = 534; +// break; +// case 595: +// ret = 385; +// break; +// case 596: +// ret = 390; +// break; +// case 598: +// ret = 393; +// break; +// case 599: +// ret = 394; +// break; +// case 600: +// ret = 398; +// break; +// case 601: +// ret = 399; +// break; +// case 603: +// ret = 400; +// break; +// case 608: +// ret = 403; +// break; +// case 611: +// ret = 404; +// break; +// case 616: +// ret = 407; +// break; +// case 617: +// ret = 406; +// break; +// case 623: +// ret = 412; +// break; +// case 626: +// ret = 413; +// break; +// case 643: +// ret = 425; +// break; +// case 648: +// ret = 430; +// break; +// case 650: +// ret = 433; +// break; +// case 651: +// ret = 434; +// break; +// case 658: +// ret = 439; +// break; +// case 940: +// ret = 902; +// break; +// case 941: +// ret = 904; +// break; +// case 942: +// ret = 905; +// break; +// case 943: +// ret = 906; +// break; +// case 945: +// ret = 913; +// break; +// case 946: +// ret = 914; +// break; +// case 947: +// ret = 915; +// break; +// case 948: +// ret = 916; +// break; +// case 949: +// ret = 917; +// break; +// case 950: +// ret = 918; +// break; +// case 951: +// ret = 919; +// break; +// case 952: +// ret = 920; +// break; +// case 953: +// ret = 921; +// break; +// case 954: +// ret = 922; +// break; +// case 955: +// ret = 923; +// break; +// case 956: +// ret = 924; +// break; +// case 957: +// ret = 925; +// break; +// case 958: +// ret = 926; +// break; +// case 959: +// ret = 927; +// break; +// case 960: +// ret = 928; +// break; +// case 961: +// ret = 929; +// break; +// case 963: +// ret = 931; +// break; +// case 964: +// ret = 932; +// break; +// case 965: +// ret = 933; +// break; +// case 966: +// ret = 934; +// break; +// case 967: +// ret = 935; +// break; +// case 968: +// ret = 936; +// break; +// case 969: +// ret = 937; +// break; +// case 970: +// ret = 938; +// break; +// case 971: +// ret = 939; +// break; +// case 972: +// ret = 908; +// break; +// case 973: +// ret = 910; +// break; +// case 974: +// ret = 911; +// break; +// case 976: +// ret = 914; +// break; +// case 977: +// ret = 920; +// break; +// case 981: +// ret = 934; +// break; +// case 982: +// ret = 928; +// break; +// case 995: +// ret = 994; +// break; +// case 997: +// ret = 996; +// break; +// case 999: +// ret = 998; +// break; +// case 1001: +// ret = 1000; +// break; +// case 1003: +// ret = 1002; +// break; +// case 1005: +// ret = 1004; +// break; +// case 1007: +// ret = 1006; +// break; +// case 1008: +// ret = 922; +// break; +// case 1009: +// ret = 929; +// break; +// case 1072: +// ret = 1040; +// break; +// case 1073: +// ret = 1041; +// break; +// case 1074: +// ret = 1042; +// break; +// case 1075: +// ret = 1043; +// break; +// case 1076: +// ret = 1044; +// break; +// case 1077: +// ret = 1045; +// break; +// case 1078: +// ret = 1046; +// break; +// case 1079: +// ret = 1047; +// break; +// case 1080: +// ret = 1048; +// break; +// case 1081: +// ret = 1049; +// break; +// case 1082: +// ret = 1050; +// break; +// case 1083: +// ret = 1051; +// break; +// case 1084: +// ret = 1052; +// break; +// case 1085: +// ret = 1053; +// break; +// case 1086: +// ret = 1054; +// break; +// case 1087: +// ret = 1055; +// break; +// case 1088: +// ret = 1056; +// break; +// case 1089: +// ret = 1057; +// break; +// case 1090: +// ret = 1058; +// break; +// case 1091: +// ret = 1059; +// break; +// case 1092: +// ret = 1060; +// break; +// case 1093: +// ret = 1061; +// break; +// case 1094: +// ret = 1062; +// break; +// case 1095: +// ret = 1063; +// break; +// case 1096: +// ret = 1064; +// break; +// case 1097: +// ret = 1065; +// break; +// case 1098: +// ret = 1066; +// break; +// case 1099: +// ret = 1067; +// break; +// case 1100: +// ret = 1068; +// break; +// case 1101: +// ret = 1069; +// break; +// case 1102: +// ret = 1070; +// break; +// case 1103: +// ret = 1071; +// break; +// case 1105: +// ret = 1025; +// break; +// case 1106: +// ret = 1026; +// break; +// case 1107: +// ret = 1027; +// break; +// case 1108: +// ret = 1028; +// break; +// case 1109: +// ret = 1029; +// break; +// case 1110: +// ret = 1030; +// break; +// case 1111: +// ret = 1031; +// break; +// case 1112: +// ret = 1032; +// break; +// case 1113: +// ret = 1033; +// break; +// case 1114: +// ret = 1034; +// break; +// case 1115: +// ret = 1035; +// break; +// case 1116: +// ret = 1036; +// break; +// case 1118: +// ret = 1038; +// break; +// case 1119: +// ret = 1039; +// break; +// case 1121: +// ret = 1120; +// break; +// case 1123: +// ret = 1122; +// break; +// case 1125: +// ret = 1124; +// break; +// case 1127: +// ret = 1126; +// break; +// case 1129: +// ret = 1128; +// break; +// case 1131: +// ret = 1130; +// break; +// case 1133: +// ret = 1132; +// break; +// case 1135: +// ret = 1134; +// break; +// case 1137: +// ret = 1136; +// break; +// case 1139: +// ret = 1138; +// break; +// case 1141: +// ret = 1140; +// break; +// case 1143: +// ret = 1142; +// break; +// case 1145: +// ret = 1144; +// break; +// case 1147: +// ret = 1146; +// break; +// case 1149: +// ret = 1148; +// break; +// case 1151: +// ret = 1150; +// break; +// case 1153: +// ret = 1152; +// break; +// case 1169: +// ret = 1168; +// break; +// case 1171: +// ret = 1170; +// break; +// case 1173: +// ret = 1172; +// break; +// case 1175: +// ret = 1174; +// break; +// case 1177: +// ret = 1176; +// break; +// case 1179: +// ret = 1178; +// break; +// case 1181: +// ret = 1180; +// break; +// case 1183: +// ret = 1182; +// break; +// case 1185: +// ret = 1184; +// break; +// case 1187: +// ret = 1186; +// break; +// case 1189: +// ret = 1188; +// break; +// case 1191: +// ret = 1190; +// break; +// case 1193: +// ret = 1192; +// break; +// case 1195: +// ret = 1194; +// break; +// case 1197: +// ret = 1196; +// break; +// case 1199: +// ret = 1198; +// break; +// case 1201: +// ret = 1200; +// break; +// case 1203: +// ret = 1202; +// break; +// case 1205: +// ret = 1204; +// break; +// case 1207: +// ret = 1206; +// break; +// case 1209: +// ret = 1208; +// break; +// case 1211: +// ret = 1210; +// break; +// case 1213: +// ret = 1212; +// break; +// case 1215: +// ret = 1214; +// break; +// case 1218: +// ret = 1217; +// break; +// case 1220: +// ret = 1219; +// break; +// case 1224: +// ret = 1223; +// break; +// case 1228: +// ret = 1227; +// break; +// case 1233: +// ret = 1232; +// break; +// case 1235: +// ret = 1234; +// break; +// case 1237: +// ret = 1236; +// break; +// case 1239: +// ret = 1238; +// break; +// case 1241: +// ret = 1240; +// break; +// case 1243: +// ret = 1242; +// break; +// case 1245: +// ret = 1244; +// break; +// case 1247: +// ret = 1246; +// break; +// case 1249: +// ret = 1248; +// break; +// case 1251: +// ret = 1250; +// break; +// case 1253: +// ret = 1252; +// break; +// case 1255: +// ret = 1254; +// break; +// case 1257: +// ret = 1256; +// break; +// case 1259: +// ret = 1258; +// break; +// case 1263: +// ret = 1262; +// break; +// case 1265: +// ret = 1264; +// break; +// case 1267: +// ret = 1266; +// break; +// case 1269: +// ret = 1268; +// break; +// case 1273: +// ret = 1272; +// break; +// case 1377: +// ret = 1329; +// break; +// case 1378: +// ret = 1330; +// break; +// case 1379: +// ret = 1331; +// break; +// case 1380: +// ret = 1332; +// break; +// case 1381: +// ret = 1333; +// break; +// case 1382: +// ret = 1334; +// break; +// case 1383: +// ret = 1335; +// break; +// case 1384: +// ret = 1336; +// break; +// case 1385: +// ret = 1337; +// break; +// case 1386: +// ret = 1338; +// break; +// case 1387: +// ret = 1339; +// break; +// case 1388: +// ret = 1340; +// break; +// case 1389: +// ret = 1341; +// break; +// case 1390: +// ret = 1342; +// break; +// case 1391: +// ret = 1343; +// break; +// case 1392: +// ret = 1344; +// break; +// case 1393: +// ret = 1345; +// break; +// case 1394: +// ret = 1346; +// break; +// case 1395: +// ret = 1347; +// break; +// case 1396: +// ret = 1348; +// break; +// case 1397: +// ret = 1349; +// break; +// case 1398: +// ret = 1350; +// break; +// case 1399: +// ret = 1351; +// break; +// case 1400: +// ret = 1352; +// break; +// case 1401: +// ret = 1353; +// break; +// case 1402: +// ret = 1354; +// break; +// case 1403: +// ret = 1355; +// break; +// case 1404: +// ret = 1356; +// break; +// case 1405: +// ret = 1357; +// break; +// case 1406: +// ret = 1358; +// break; +// case 1407: +// ret = 1359; +// break; +// case 1408: +// ret = 1360; +// break; +// case 1409: +// ret = 1361; +// break; +// case 1410: +// ret = 1362; +// break; +// case 1411: +// ret = 1363; +// break; +// case 1412: +// ret = 1364; +// break; +// case 1413: +// ret = 1365; +// break; +// case 1414: +// ret = 1366; +// break; +// case 7681: +// ret = 7680; +// break; +// case 7683: +// ret = 7682; +// break; +// case 7685: +// ret = 7684; +// break; +// case 7687: +// ret = 7686; +// break; +// case 7689: +// ret = 7688; +// break; +// case 7691: +// ret = 7690; +// break; +// case 7693: +// ret = 7692; +// break; +// case 7695: +// ret = 7694; +// break; +// case 7697: +// ret = 7696; +// break; +// case 7699: +// ret = 7698; +// break; +// case 7701: +// ret = 7700; +// break; +// case 7703: +// ret = 7702; +// break; +// case 7705: +// ret = 7704; +// break; +// case 7707: +// ret = 7706; +// break; +// case 7709: +// ret = 7708; +// break; +// case 7711: +// ret = 7710; +// break; +// case 7713: +// ret = 7712; +// break; +// case 7715: +// ret = 7714; +// break; +// case 7717: +// ret = 7716; +// break; +// case 7719: +// ret = 7718; +// break; +// case 7721: +// ret = 7720; +// break; +// case 7723: +// ret = 7722; +// break; +// case 7725: +// ret = 7724; +// break; +// case 7727: +// ret = 7726; +// break; +// case 7729: +// ret = 7728; +// break; +// case 7731: +// ret = 7730; +// break; +// case 7733: +// ret = 7732; +// break; +// case 7735: +// ret = 7734; +// break; +// case 7737: +// ret = 7736; +// break; +// case 7739: +// ret = 7738; +// break; +// case 7741: +// ret = 7740; +// break; +// case 7743: +// ret = 7742; +// break; +// case 7745: +// ret = 7744; +// break; +// case 7747: +// ret = 7746; +// break; +// case 7749: +// ret = 7748; +// break; +// case 7751: +// ret = 7750; +// break; +// case 7753: +// ret = 7752; +// break; +// case 7755: +// ret = 7754; +// break; +// case 7757: +// ret = 7756; +// break; +// case 7759: +// ret = 7758; +// break; +// case 7761: +// ret = 7760; +// break; +// case 7763: +// ret = 7762; +// break; +// case 7765: +// ret = 7764; +// break; +// case 7767: +// ret = 7766; +// break; +// case 7769: +// ret = 7768; +// break; +// case 7771: +// ret = 7770; +// break; +// case 7773: +// ret = 7772; +// break; +// case 7775: +// ret = 7774; +// break; +// case 7777: +// ret = 7776; +// break; +// case 7779: +// ret = 7778; +// break; +// case 7781: +// ret = 7780; +// break; +// case 7783: +// ret = 7782; +// break; +// case 7785: +// ret = 7784; +// break; +// case 7787: +// ret = 7786; +// break; +// case 7789: +// ret = 7788; +// break; +// case 7791: +// ret = 7790; +// break; +// case 7793: +// ret = 7792; +// break; +// case 7795: +// ret = 7794; +// break; +// case 7797: +// ret = 7796; +// break; +// case 7799: +// ret = 7798; +// break; +// case 7801: +// ret = 7800; +// break; +// case 7803: +// ret = 7802; +// break; +// case 7805: +// ret = 7804; +// break; +// case 7807: +// ret = 7806; +// break; +// case 7809: +// ret = 7808; +// break; +// case 7811: +// ret = 7810; +// break; +// case 7813: +// ret = 7812; +// break; +// case 7815: +// ret = 7814; +// break; +// case 7817: +// ret = 7816; +// break; +// case 7819: +// ret = 7818; +// break; +// case 7821: +// ret = 7820; +// break; +// case 7823: +// ret = 7822; +// break; +// case 7825: +// ret = 7824; +// break; +// case 7827: +// ret = 7826; +// break; +// case 7829: +// ret = 7828; +// break; +// case 7841: +// ret = 7840; +// break; +// case 7843: +// ret = 7842; +// break; +// case 7845: +// ret = 7844; +// break; +// case 7847: +// ret = 7846; +// break; +// case 7849: +// ret = 7848; +// break; +// case 7851: +// ret = 7850; +// break; +// case 7853: +// ret = 7852; +// break; +// case 7855: +// ret = 7854; +// break; +// case 7857: +// ret = 7856; +// break; +// case 7859: +// ret = 7858; +// break; +// case 7861: +// ret = 7860; +// break; +// case 7863: +// ret = 7862; +// break; +// case 7865: +// ret = 7864; +// break; +// case 7867: +// ret = 7866; +// break; +// case 7869: +// ret = 7868; +// break; +// case 7871: +// ret = 7870; +// break; +// case 7873: +// ret = 7872; +// break; +// case 7875: +// ret = 7874; +// break; +// case 7877: +// ret = 7876; +// break; +// case 7879: +// ret = 7878; +// break; +// case 7881: +// ret = 7880; +// break; +// case 7883: +// ret = 7882; +// break; +// case 7885: +// ret = 7884; +// break; +// case 7887: +// ret = 7886; +// break; +// case 7889: +// ret = 7888; +// break; +// case 7891: +// ret = 7890; +// break; +// case 7893: +// ret = 7892; +// break; +// case 7895: +// ret = 7894; +// break; +// case 7897: +// ret = 7896; +// break; +// case 7899: +// ret = 7898; +// break; +// case 7901: +// ret = 7900; +// break; +// case 7903: +// ret = 7902; +// break; +// case 7905: +// ret = 7904; +// break; +// case 7907: +// ret = 7906; +// break; +// case 7909: +// ret = 7908; +// break; +// case 7911: +// ret = 7910; +// break; +// case 7913: +// ret = 7912; +// break; +// case 7915: +// ret = 7914; +// break; +// case 7917: +// ret = 7916; +// break; +// case 7919: +// ret = 7918; +// break; +// case 7921: +// ret = 7920; +// break; +// case 7923: +// ret = 7922; +// break; +// case 7925: +// ret = 7924; +// break; +// case 7927: +// ret = 7926; +// break; +// case 7929: +// ret = 7928; +// break; +// case 7936: +// ret = 7944; +// break; +// case 7937: +// ret = 7945; +// break; +// case 7938: +// ret = 7946; +// break; +// case 7939: +// ret = 7947; +// break; +// case 7940: +// ret = 7948; +// break; +// case 7941: +// ret = 7949; +// break; +// case 7942: +// ret = 7950; +// break; +// case 7943: +// ret = 7951; +// break; +// case 7952: +// ret = 7960; +// break; +// case 7953: +// ret = 7961; +// break; +// case 7954: +// ret = 7962; +// break; +// case 7955: +// ret = 7963; +// break; +// case 7956: +// ret = 7964; +// break; +// case 7957: +// ret = 7965; +// break; +// case 7968: +// ret = 7976; +// break; +// case 7969: +// ret = 7977; +// break; +// case 7970: +// ret = 7978; +// break; +// case 7971: +// ret = 7979; +// break; +// case 7972: +// ret = 7980; +// break; +// case 7973: +// ret = 7981; +// break; +// case 7974: +// ret = 7982; +// break; +// case 7975: +// ret = 7983; +// break; +// case 7984: +// ret = 7992; +// break; +// case 7985: +// ret = 7993; +// break; +// case 7986: +// ret = 7994; +// break; +// case 7987: +// ret = 7995; +// break; +// case 7988: +// ret = 7996; +// break; +// case 7989: +// ret = 7997; +// break; +// case 7990: +// ret = 7998; +// break; +// case 7991: +// ret = 7999; +// break; +// case 8000: +// ret = 8008; +// break; +// case 8001: +// ret = 8009; +// break; +// case 8002: +// ret = 8010; +// break; +// case 8003: +// ret = 8011; +// break; +// case 8004: +// ret = 8012; +// break; +// case 8005: +// ret = 8013; +// break; +// case 8017: +// ret = 8025; +// break; +// case 8019: +// ret = 8027; +// break; +// case 8021: +// ret = 8029; +// break; +// case 8023: +// ret = 8031; +// break; +// case 8032: +// ret = 8040; +// break; +// case 8033: +// ret = 8041; +// break; +// case 8034: +// ret = 8042; +// break; +// case 8035: +// ret = 8043; +// break; +// case 8036: +// ret = 8044; +// break; +// case 8037: +// ret = 8045; +// break; +// case 8038: +// ret = 8046; +// break; +// case 8039: +// ret = 8047; +// break; +// case 8048: +// ret = 8122; +// break; +// case 8049: +// ret = 8123; +// break; +// case 8050: +// ret = 8136; +// break; +// case 8051: +// ret = 8137; +// break; +// case 8052: +// ret = 8138; +// break; +// case 8053: +// ret = 8139; +// break; +// case 8054: +// ret = 8154; +// break; +// case 8055: +// ret = 8155; +// break; +// case 8056: +// ret = 8184; +// break; +// case 8057: +// ret = 8185; +// break; +// case 8058: +// ret = 8170; +// break; +// case 8059: +// ret = 8171; +// break; +// case 8060: +// ret = 8186; +// break; +// case 8061: +// ret = 8187; +// break; +// case 8064: +// ret = 8072; +// break; +// case 8065: +// ret = 8073; +// break; +// case 8066: +// ret = 8074; +// break; +// case 8067: +// ret = 8075; +// break; +// case 8068: +// ret = 8076; +// break; +// case 8069: +// ret = 8077; +// break; +// case 8070: +// ret = 8078; +// break; +// case 8071: +// ret = 8079; +// break; +// case 8080: +// ret = 8088; +// break; +// case 8081: +// ret = 8089; +// break; +// case 8082: +// ret = 8090; +// break; +// case 8083: +// ret = 8091; +// break; +// case 8084: +// ret = 8092; +// break; +// case 8085: +// ret = 8093; +// break; +// case 8086: +// ret = 8094; +// break; +// case 8087: +// ret = 8095; +// break; +// case 8096: +// ret = 8104; +// break; +// case 8097: +// ret = 8105; +// break; +// case 8098: +// ret = 8106; +// break; +// case 8099: +// ret = 8107; +// break; +// case 8100: +// ret = 8108; +// break; +// case 8101: +// ret = 8109; +// break; +// case 8102: +// ret = 8110; +// break; +// case 8103: +// ret = 8111; +// break; +// case 8112: +// ret = 8120; +// break; +// case 8113: +// ret = 8121; +// break; +// case 8115: +// ret = 8124; +// break; +// case 8131: +// ret = 8140; +// break; +// case 8144: +// ret = 8152; +// break; +// case 8145: +// ret = 8153; +// break; +// case 8160: +// ret = 8168; +// break; +// case 8161: +// ret = 8169; +// break; +// case 8165: +// ret = 8172; +// break; +// case 8179: +// ret = 8188; +// break; +// case 8560: +// ret = 8544; +// break; +// case 8561: +// ret = 8545; +// break; +// case 8562: +// ret = 8546; +// break; +// case 8563: +// ret = 8547; +// break; +// case 8564: +// ret = 8548; +// break; +// case 8565: +// ret = 8549; +// break; +// case 8566: +// ret = 8550; +// break; +// case 8567: +// ret = 8551; +// break; +// case 8568: +// ret = 8552; +// break; +// case 8569: +// ret = 8553; +// break; +// case 8570: +// ret = 8554; +// break; +// case 8571: +// ret = 8555; +// break; +// case 8572: +// ret = 8556; +// break; +// case 8573: +// ret = 8557; +// break; +// case 8574: +// ret = 8558; +// break; +// case 8575: +// ret = 8559; +// break; +// case 9424: +// ret = 9398; +// break; +// case 9425: +// ret = 9399; +// break; +// case 9426: +// ret = 9400; +// break; +// case 9427: +// ret = 9401; +// break; +// case 9428: +// ret = 9402; +// break; +// case 9429: +// ret = 9403; +// break; +// case 9430: +// ret = 9404; +// break; +// case 9431: +// ret = 9405; +// break; +// case 9432: +// ret = 9406; +// break; +// case 9433: +// ret = 9407; +// break; +// case 9434: +// ret = 9408; +// break; +// case 9435: +// ret = 9409; +// break; +// case 9436: +// ret = 9410; +// break; +// case 9437: +// ret = 9411; +// break; +// case 9438: +// ret = 9412; +// break; +// case 9439: +// ret = 9413; +// break; +// case 9440: +// ret = 9414; +// break; +// case 9441: +// ret = 9415; +// break; +// case 9442: +// ret = 9416; +// break; +// case 9443: +// ret = 9417; +// break; +// case 9444: +// ret = 9418; +// break; +// case 9445: +// ret = 9419; +// break; +// case 9446: +// ret = 9420; +// break; +// case 9447: +// ret = 9421; +// break; +// case 9448: +// ret = 9422; +// break; +// case 9449: +// ret = 9423; +// break; +// case 65345: +// ret = 65313; +// break; +// case 65346: +// ret = 65314; +// break; +// case 65347: +// ret = 65315; +// break; +// case 65348: +// ret = 65316; +// break; +// case 65349: +// ret = 65317; +// break; +// case 65350: +// ret = 65318; +// break; +// case 65351: +// ret = 65319; +// break; +// case 65352: +// ret = 65320; +// break; +// case 65353: +// ret = 65321; +// break; +// case 65354: +// ret = 65322; +// break; +// case 65355: +// ret = 65323; +// break; +// case 65356: +// ret = 65324; +// break; +// case 65357: +// ret = 65325; +// break; +// case 65358: +// ret = 65326; +// break; +// case 65359: +// ret = 65327; +// break; +// case 65360: +// ret = 65328; +// break; +// case 65361: +// ret = 65329; +// break; +// case 65362: +// ret = 65330; +// break; +// case 65363: +// ret = 65331; +// break; +// case 65364: +// ret = 65332; +// break; +// case 65365: +// ret = 65333; +// break; +// case 65366: +// ret = 65334; +// break; +// case 65367: +// ret = 65335; +// break; +// case 65368: +// ret = 65336; +// break; +// case 65369: +// ret = 65337; +// break; +// case 65370: +// ret = 65338; +// break; +// } +// return (char) ret; +// } return Character.toUpperCase(c); } /** Convert a character to lower case. */ - public static char toLowerCase(char c) + public static char toLowerCaseC(char c) { - if (java_1_0) - { - int ret = (int) c; - switch (c) - { - case 65: - ret = 97; - break; - case 66: - ret = 98; - break; - case 67: - ret = 99; - break; - case 68: - ret = 100; - break; - case 69: - ret = 101; - break; - case 70: - ret = 102; - break; - case 71: - ret = 103; - break; - case 72: - ret = 104; - break; - case 73: - ret = 105; - break; - case 74: - ret = 106; - break; - case 75: - ret = 107; - break; - case 76: - ret = 108; - break; - case 77: - ret = 109; - break; - case 78: - ret = 110; - break; - case 79: - ret = 111; - break; - case 80: - ret = 112; - break; - case 81: - ret = 113; - break; - case 82: - ret = 114; - break; - case 83: - ret = 115; - break; - case 84: - ret = 116; - break; - case 85: - ret = 117; - break; - case 86: - ret = 118; - break; - case 87: - ret = 119; - break; - case 88: - ret = 120; - break; - case 89: - ret = 121; - break; - case 90: - ret = 122; - break; - case 192: - ret = 224; - break; - case 193: - ret = 225; - break; - case 194: - ret = 226; - break; - case 195: - ret = 227; - break; - case 196: - ret = 228; - break; - case 197: - ret = 229; - break; - case 198: - ret = 230; - break; - case 199: - ret = 231; - break; - case 200: - ret = 232; - break; - case 201: - ret = 233; - break; - case 202: - ret = 234; - break; - case 203: - ret = 235; - break; - case 204: - ret = 236; - break; - case 205: - ret = 237; - break; - case 206: - ret = 238; - break; - case 207: - ret = 239; - break; - case 208: - ret = 240; - break; - case 209: - ret = 241; - break; - case 210: - ret = 242; - break; - case 211: - ret = 243; - break; - case 212: - ret = 244; - break; - case 213: - ret = 245; - break; - case 214: - ret = 246; - break; - case 216: - ret = 248; - break; - case 217: - ret = 249; - break; - case 218: - ret = 250; - break; - case 219: - ret = 251; - break; - case 220: - ret = 252; - break; - case 221: - ret = 253; - break; - case 222: - ret = 254; - break; - case 256: - ret = 257; - break; - case 258: - ret = 259; - break; - case 260: - ret = 261; - break; - case 262: - ret = 263; - break; - case 264: - ret = 265; - break; - case 266: - ret = 267; - break; - case 268: - ret = 269; - break; - case 270: - ret = 271; - break; - case 272: - ret = 273; - break; - case 274: - ret = 275; - break; - case 276: - ret = 277; - break; - case 278: - ret = 279; - break; - case 280: - ret = 281; - break; - case 282: - ret = 283; - break; - case 284: - ret = 285; - break; - case 286: - ret = 287; - break; - case 288: - ret = 289; - break; - case 290: - ret = 291; - break; - case 292: - ret = 293; - break; - case 294: - ret = 295; - break; - case 296: - ret = 297; - break; - case 298: - ret = 299; - break; - case 300: - ret = 301; - break; - case 302: - ret = 303; - break; - case 304: - ret = 105; - break; - case 306: - ret = 307; - break; - case 308: - ret = 309; - break; - case 310: - ret = 311; - break; - case 313: - ret = 314; - break; - case 315: - ret = 316; - break; - case 317: - ret = 318; - break; - case 319: - ret = 320; - break; - case 321: - ret = 322; - break; - case 323: - ret = 324; - break; - case 325: - ret = 326; - break; - case 327: - ret = 328; - break; - case 330: - ret = 331; - break; - case 332: - ret = 333; - break; - case 334: - ret = 335; - break; - case 336: - ret = 337; - break; - case 338: - ret = 339; - break; - case 340: - ret = 341; - break; - case 342: - ret = 343; - break; - case 344: - ret = 345; - break; - case 346: - ret = 347; - break; - case 348: - ret = 349; - break; - case 350: - ret = 351; - break; - case 352: - ret = 353; - break; - case 354: - ret = 355; - break; - case 356: - ret = 357; - break; - case 358: - ret = 359; - break; - case 360: - ret = 361; - break; - case 362: - ret = 363; - break; - case 364: - ret = 365; - break; - case 366: - ret = 367; - break; - case 368: - ret = 369; - break; - case 370: - ret = 371; - break; - case 372: - ret = 373; - break; - case 374: - ret = 375; - break; - case 376: - ret = 255; - break; - case 377: - ret = 378; - break; - case 379: - ret = 380; - break; - case 381: - ret = 382; - break; - case 385: - ret = 595; - break; - case 386: - ret = 387; - break; - case 388: - ret = 389; - break; - case 390: - ret = 596; - break; - case 391: - ret = 392; - break; - case 393: - ret = 598; - break; - case 394: - ret = 599; - break; - case 395: - ret = 396; - break; - case 398: - ret = 600; - break; - case 399: - ret = 601; - break; - case 400: - ret = 603; - break; - case 401: - ret = 402; - break; - case 403: - ret = 608; - break; - case 404: - ret = 611; - break; - case 406: - ret = 617; - break; - case 407: - ret = 616; - break; - case 408: - ret = 409; - break; - case 412: - ret = 623; - break; - case 413: - ret = 626; - break; - case 416: - ret = 417; - break; - case 418: - ret = 419; - break; - case 420: - ret = 421; - break; - case 423: - ret = 424; - break; - case 425: - ret = 643; - break; - case 428: - ret = 429; - break; - case 430: - ret = 648; - break; - case 431: - ret = 432; - break; - case 433: - ret = 650; - break; - case 434: - ret = 651; - break; - case 435: - ret = 436; - break; - case 437: - ret = 438; - break; - case 439: - ret = 658; - break; - case 440: - ret = 441; - break; - case 444: - ret = 445; - break; - case 452: - ret = 454; - break; - case 453: - ret = 454; - break; - case 455: - ret = 457; - break; - case 456: - ret = 457; - break; - case 458: - ret = 460; - break; - case 459: - ret = 460; - break; - case 461: - ret = 462; - break; - case 463: - ret = 464; - break; - case 465: - ret = 466; - break; - case 467: - ret = 468; - break; - case 469: - ret = 470; - break; - case 471: - ret = 472; - break; - case 473: - ret = 474; - break; - case 475: - ret = 476; - break; - case 478: - ret = 479; - break; - case 480: - ret = 481; - break; - case 482: - ret = 483; - break; - case 484: - ret = 485; - break; - case 486: - ret = 487; - break; - case 488: - ret = 489; - break; - case 490: - ret = 491; - break; - case 492: - ret = 493; - break; - case 494: - ret = 495; - break; - case 497: - ret = 499; - break; - case 498: - ret = 499; - break; - case 500: - ret = 501; - break; - case 506: - ret = 507; - break; - case 508: - ret = 509; - break; - case 510: - ret = 511; - break; - case 512: - ret = 513; - break; - case 514: - ret = 515; - break; - case 516: - ret = 517; - break; - case 518: - ret = 519; - break; - case 520: - ret = 521; - break; - case 522: - ret = 523; - break; - case 524: - ret = 525; - break; - case 526: - ret = 527; - break; - case 528: - ret = 529; - break; - case 530: - ret = 531; - break; - case 532: - ret = 533; - break; - case 534: - ret = 535; - break; - case 902: - ret = 940; - break; - case 904: - ret = 941; - break; - case 905: - ret = 942; - break; - case 906: - ret = 943; - break; - case 908: - ret = 972; - break; - case 910: - ret = 973; - break; - case 911: - ret = 974; - break; - case 913: - ret = 945; - break; - case 914: - ret = 946; - break; - case 915: - ret = 947; - break; - case 916: - ret = 948; - break; - case 917: - ret = 949; - break; - case 918: - ret = 950; - break; - case 919: - ret = 951; - break; - case 920: - ret = 952; - break; - case 921: - ret = 953; - break; - case 922: - ret = 954; - break; - case 923: - ret = 955; - break; - case 924: - ret = 956; - break; - case 925: - ret = 957; - break; - case 926: - ret = 958; - break; - case 927: - ret = 959; - break; - case 928: - ret = 960; - break; - case 929: - ret = 961; - break; - case 931: - ret = 963; - break; - case 932: - ret = 964; - break; - case 933: - ret = 965; - break; - case 934: - ret = 966; - break; - case 935: - ret = 967; - break; - case 936: - ret = 968; - break; - case 937: - ret = 969; - break; - case 938: - ret = 970; - break; - case 939: - ret = 971; - break; - case 994: - ret = 995; - break; - case 996: - ret = 997; - break; - case 998: - ret = 999; - break; - case 1000: - ret = 1001; - break; - case 1002: - ret = 1003; - break; - case 1004: - ret = 1005; - break; - case 1006: - ret = 1007; - break; - case 1025: - ret = 1105; - break; - case 1026: - ret = 1106; - break; - case 1027: - ret = 1107; - break; - case 1028: - ret = 1108; - break; - case 1029: - ret = 1109; - break; - case 1030: - ret = 1110; - break; - case 1031: - ret = 1111; - break; - case 1032: - ret = 1112; - break; - case 1033: - ret = 1113; - break; - case 1034: - ret = 1114; - break; - case 1035: - ret = 1115; - break; - case 1036: - ret = 1116; - break; - case 1038: - ret = 1118; - break; - case 1039: - ret = 1119; - break; - case 1040: - ret = 1072; - break; - case 1041: - ret = 1073; - break; - case 1042: - ret = 1074; - break; - case 1043: - ret = 1075; - break; - case 1044: - ret = 1076; - break; - case 1045: - ret = 1077; - break; - case 1046: - ret = 1078; - break; - case 1047: - ret = 1079; - break; - case 1048: - ret = 1080; - break; - case 1049: - ret = 1081; - break; - case 1050: - ret = 1082; - break; - case 1051: - ret = 1083; - break; - case 1052: - ret = 1084; - break; - case 1053: - ret = 1085; - break; - case 1054: - ret = 1086; - break; - case 1055: - ret = 1087; - break; - case 1056: - ret = 1088; - break; - case 1057: - ret = 1089; - break; - case 1058: - ret = 1090; - break; - case 1059: - ret = 1091; - break; - case 1060: - ret = 1092; - break; - case 1061: - ret = 1093; - break; - case 1062: - ret = 1094; - break; - case 1063: - ret = 1095; - break; - case 1064: - ret = 1096; - break; - case 1065: - ret = 1097; - break; - case 1066: - ret = 1098; - break; - case 1067: - ret = 1099; - break; - case 1068: - ret = 1100; - break; - case 1069: - ret = 1101; - break; - case 1070: - ret = 1102; - break; - case 1071: - ret = 1103; - break; - case 1120: - ret = 1121; - break; - case 1122: - ret = 1123; - break; - case 1124: - ret = 1125; - break; - case 1126: - ret = 1127; - break; - case 1128: - ret = 1129; - break; - case 1130: - ret = 1131; - break; - case 1132: - ret = 1133; - break; - case 1134: - ret = 1135; - break; - case 1136: - ret = 1137; - break; - case 1138: - ret = 1139; - break; - case 1140: - ret = 1141; - break; - case 1142: - ret = 1143; - break; - case 1144: - ret = 1145; - break; - case 1146: - ret = 1147; - break; - case 1148: - ret = 1149; - break; - case 1150: - ret = 1151; - break; - case 1152: - ret = 1153; - break; - case 1168: - ret = 1169; - break; - case 1170: - ret = 1171; - break; - case 1172: - ret = 1173; - break; - case 1174: - ret = 1175; - break; - case 1176: - ret = 1177; - break; - case 1178: - ret = 1179; - break; - case 1180: - ret = 1181; - break; - case 1182: - ret = 1183; - break; - case 1184: - ret = 1185; - break; - case 1186: - ret = 1187; - break; - case 1188: - ret = 1189; - break; - case 1190: - ret = 1191; - break; - case 1192: - ret = 1193; - break; - case 1194: - ret = 1195; - break; - case 1196: - ret = 1197; - break; - case 1198: - ret = 1199; - break; - case 1200: - ret = 1201; - break; - case 1202: - ret = 1203; - break; - case 1204: - ret = 1205; - break; - case 1206: - ret = 1207; - break; - case 1208: - ret = 1209; - break; - case 1210: - ret = 1211; - break; - case 1212: - ret = 1213; - break; - case 1214: - ret = 1215; - break; - case 1217: - ret = 1218; - break; - case 1219: - ret = 1220; - break; - case 1223: - ret = 1224; - break; - case 1227: - ret = 1228; - break; - case 1232: - ret = 1233; - break; - case 1234: - ret = 1235; - break; - case 1236: - ret = 1237; - break; - case 1238: - ret = 1239; - break; - case 1240: - ret = 1241; - break; - case 1242: - ret = 1243; - break; - case 1244: - ret = 1245; - break; - case 1246: - ret = 1247; - break; - case 1248: - ret = 1249; - break; - case 1250: - ret = 1251; - break; - case 1252: - ret = 1253; - break; - case 1254: - ret = 1255; - break; - case 1256: - ret = 1257; - break; - case 1258: - ret = 1259; - break; - case 1262: - ret = 1263; - break; - case 1264: - ret = 1265; - break; - case 1266: - ret = 1267; - break; - case 1268: - ret = 1269; - break; - case 1272: - ret = 1273; - break; - case 1329: - ret = 1377; - break; - case 1330: - ret = 1378; - break; - case 1331: - ret = 1379; - break; - case 1332: - ret = 1380; - break; - case 1333: - ret = 1381; - break; - case 1334: - ret = 1382; - break; - case 1335: - ret = 1383; - break; - case 1336: - ret = 1384; - break; - case 1337: - ret = 1385; - break; - case 1338: - ret = 1386; - break; - case 1339: - ret = 1387; - break; - case 1340: - ret = 1388; - break; - case 1341: - ret = 1389; - break; - case 1342: - ret = 1390; - break; - case 1343: - ret = 1391; - break; - case 1344: - ret = 1392; - break; - case 1345: - ret = 1393; - break; - case 1346: - ret = 1394; - break; - case 1347: - ret = 1395; - break; - case 1348: - ret = 1396; - break; - case 1349: - ret = 1397; - break; - case 1350: - ret = 1398; - break; - case 1351: - ret = 1399; - break; - case 1352: - ret = 1400; - break; - case 1353: - ret = 1401; - break; - case 1354: - ret = 1402; - break; - case 1355: - ret = 1403; - break; - case 1356: - ret = 1404; - break; - case 1357: - ret = 1405; - break; - case 1358: - ret = 1406; - break; - case 1359: - ret = 1407; - break; - case 1360: - ret = 1408; - break; - case 1361: - ret = 1409; - break; - case 1362: - ret = 1410; - break; - case 1363: - ret = 1411; - break; - case 1364: - ret = 1412; - break; - case 1365: - ret = 1413; - break; - case 1366: - ret = 1414; - break; - case 4256: - ret = 4304; - break; - case 4257: - ret = 4305; - break; - case 4258: - ret = 4306; - break; - case 4259: - ret = 4307; - break; - case 4260: - ret = 4308; - break; - case 4261: - ret = 4309; - break; - case 4262: - ret = 4310; - break; - case 4263: - ret = 4311; - break; - case 4264: - ret = 4312; - break; - case 4265: - ret = 4313; - break; - case 4266: - ret = 4314; - break; - case 4267: - ret = 4315; - break; - case 4268: - ret = 4316; - break; - case 4269: - ret = 4317; - break; - case 4270: - ret = 4318; - break; - case 4271: - ret = 4319; - break; - case 4272: - ret = 4320; - break; - case 4273: - ret = 4321; - break; - case 4274: - ret = 4322; - break; - case 4275: - ret = 4323; - break; - case 4276: - ret = 4324; - break; - case 4277: - ret = 4325; - break; - case 4278: - ret = 4326; - break; - case 4279: - ret = 4327; - break; - case 4280: - ret = 4328; - break; - case 4281: - ret = 4329; - break; - case 4282: - ret = 4330; - break; - case 4283: - ret = 4331; - break; - case 4284: - ret = 4332; - break; - case 4285: - ret = 4333; - break; - case 4286: - ret = 4334; - break; - case 4287: - ret = 4335; - break; - case 4288: - ret = 4336; - break; - case 4289: - ret = 4337; - break; - case 4290: - ret = 4338; - break; - case 4291: - ret = 4339; - break; - case 4292: - ret = 4340; - break; - case 4293: - ret = 4341; - break; - case 7680: - ret = 7681; - break; - case 7682: - ret = 7683; - break; - case 7684: - ret = 7685; - break; - case 7686: - ret = 7687; - break; - case 7688: - ret = 7689; - break; - case 7690: - ret = 7691; - break; - case 7692: - ret = 7693; - break; - case 7694: - ret = 7695; - break; - case 7696: - ret = 7697; - break; - case 7698: - ret = 7699; - break; - case 7700: - ret = 7701; - break; - case 7702: - ret = 7703; - break; - case 7704: - ret = 7705; - break; - case 7706: - ret = 7707; - break; - case 7708: - ret = 7709; - break; - case 7710: - ret = 7711; - break; - case 7712: - ret = 7713; - break; - case 7714: - ret = 7715; - break; - case 7716: - ret = 7717; - break; - case 7718: - ret = 7719; - break; - case 7720: - ret = 7721; - break; - case 7722: - ret = 7723; - break; - case 7724: - ret = 7725; - break; - case 7726: - ret = 7727; - break; - case 7728: - ret = 7729; - break; - case 7730: - ret = 7731; - break; - case 7732: - ret = 7733; - break; - case 7734: - ret = 7735; - break; - case 7736: - ret = 7737; - break; - case 7738: - ret = 7739; - break; - case 7740: - ret = 7741; - break; - case 7742: - ret = 7743; - break; - case 7744: - ret = 7745; - break; - case 7746: - ret = 7747; - break; - case 7748: - ret = 7749; - break; - case 7750: - ret = 7751; - break; - case 7752: - ret = 7753; - break; - case 7754: - ret = 7755; - break; - case 7756: - ret = 7757; - break; - case 7758: - ret = 7759; - break; - case 7760: - ret = 7761; - break; - case 7762: - ret = 7763; - break; - case 7764: - ret = 7765; - break; - case 7766: - ret = 7767; - break; - case 7768: - ret = 7769; - break; - case 7770: - ret = 7771; - break; - case 7772: - ret = 7773; - break; - case 7774: - ret = 7775; - break; - case 7776: - ret = 7777; - break; - case 7778: - ret = 7779; - break; - case 7780: - ret = 7781; - break; - case 7782: - ret = 7783; - break; - case 7784: - ret = 7785; - break; - case 7786: - ret = 7787; - break; - case 7788: - ret = 7789; - break; - case 7790: - ret = 7791; - break; - case 7792: - ret = 7793; - break; - case 7794: - ret = 7795; - break; - case 7796: - ret = 7797; - break; - case 7798: - ret = 7799; - break; - case 7800: - ret = 7801; - break; - case 7802: - ret = 7803; - break; - case 7804: - ret = 7805; - break; - case 7806: - ret = 7807; - break; - case 7808: - ret = 7809; - break; - case 7810: - ret = 7811; - break; - case 7812: - ret = 7813; - break; - case 7814: - ret = 7815; - break; - case 7816: - ret = 7817; - break; - case 7818: - ret = 7819; - break; - case 7820: - ret = 7821; - break; - case 7822: - ret = 7823; - break; - case 7824: - ret = 7825; - break; - case 7826: - ret = 7827; - break; - case 7828: - ret = 7829; - break; - case 7840: - ret = 7841; - break; - case 7842: - ret = 7843; - break; - case 7844: - ret = 7845; - break; - case 7846: - ret = 7847; - break; - case 7848: - ret = 7849; - break; - case 7850: - ret = 7851; - break; - case 7852: - ret = 7853; - break; - case 7854: - ret = 7855; - break; - case 7856: - ret = 7857; - break; - case 7858: - ret = 7859; - break; - case 7860: - ret = 7861; - break; - case 7862: - ret = 7863; - break; - case 7864: - ret = 7865; - break; - case 7866: - ret = 7867; - break; - case 7868: - ret = 7869; - break; - case 7870: - ret = 7871; - break; - case 7872: - ret = 7873; - break; - case 7874: - ret = 7875; - break; - case 7876: - ret = 7877; - break; - case 7878: - ret = 7879; - break; - case 7880: - ret = 7881; - break; - case 7882: - ret = 7883; - break; - case 7884: - ret = 7885; - break; - case 7886: - ret = 7887; - break; - case 7888: - ret = 7889; - break; - case 7890: - ret = 7891; - break; - case 7892: - ret = 7893; - break; - case 7894: - ret = 7895; - break; - case 7896: - ret = 7897; - break; - case 7898: - ret = 7899; - break; - case 7900: - ret = 7901; - break; - case 7902: - ret = 7903; - break; - case 7904: - ret = 7905; - break; - case 7906: - ret = 7907; - break; - case 7908: - ret = 7909; - break; - case 7910: - ret = 7911; - break; - case 7912: - ret = 7913; - break; - case 7914: - ret = 7915; - break; - case 7916: - ret = 7917; - break; - case 7918: - ret = 7919; - break; - case 7920: - ret = 7921; - break; - case 7922: - ret = 7923; - break; - case 7924: - ret = 7925; - break; - case 7926: - ret = 7927; - break; - case 7928: - ret = 7929; - break; - case 7944: - ret = 7936; - break; - case 7945: - ret = 7937; - break; - case 7946: - ret = 7938; - break; - case 7947: - ret = 7939; - break; - case 7948: - ret = 7940; - break; - case 7949: - ret = 7941; - break; - case 7950: - ret = 7942; - break; - case 7951: - ret = 7943; - break; - case 7960: - ret = 7952; - break; - case 7961: - ret = 7953; - break; - case 7962: - ret = 7954; - break; - case 7963: - ret = 7955; - break; - case 7964: - ret = 7956; - break; - case 7965: - ret = 7957; - break; - case 7976: - ret = 7968; - break; - case 7977: - ret = 7969; - break; - case 7978: - ret = 7970; - break; - case 7979: - ret = 7971; - break; - case 7980: - ret = 7972; - break; - case 7981: - ret = 7973; - break; - case 7982: - ret = 7974; - break; - case 7983: - ret = 7975; - break; - case 7992: - ret = 7984; - break; - case 7993: - ret = 7985; - break; - case 7994: - ret = 7986; - break; - case 7995: - ret = 7987; - break; - case 7996: - ret = 7988; - break; - case 7997: - ret = 7989; - break; - case 7998: - ret = 7990; - break; - case 7999: - ret = 7991; - break; - case 8008: - ret = 8000; - break; - case 8009: - ret = 8001; - break; - case 8010: - ret = 8002; - break; - case 8011: - ret = 8003; - break; - case 8012: - ret = 8004; - break; - case 8013: - ret = 8005; - break; - case 8025: - ret = 8017; - break; - case 8027: - ret = 8019; - break; - case 8029: - ret = 8021; - break; - case 8031: - ret = 8023; - break; - case 8040: - ret = 8032; - break; - case 8041: - ret = 8033; - break; - case 8042: - ret = 8034; - break; - case 8043: - ret = 8035; - break; - case 8044: - ret = 8036; - break; - case 8045: - ret = 8037; - break; - case 8046: - ret = 8038; - break; - case 8047: - ret = 8039; - break; - case 8072: - ret = 8064; - break; - case 8073: - ret = 8065; - break; - case 8074: - ret = 8066; - break; - case 8075: - ret = 8067; - break; - case 8076: - ret = 8068; - break; - case 8077: - ret = 8069; - break; - case 8078: - ret = 8070; - break; - case 8079: - ret = 8071; - break; - case 8088: - ret = 8080; - break; - case 8089: - ret = 8081; - break; - case 8090: - ret = 8082; - break; - case 8091: - ret = 8083; - break; - case 8092: - ret = 8084; - break; - case 8093: - ret = 8085; - break; - case 8094: - ret = 8086; - break; - case 8095: - ret = 8087; - break; - case 8104: - ret = 8096; - break; - case 8105: - ret = 8097; - break; - case 8106: - ret = 8098; - break; - case 8107: - ret = 8099; - break; - case 8108: - ret = 8100; - break; - case 8109: - ret = 8101; - break; - case 8110: - ret = 8102; - break; - case 8111: - ret = 8103; - break; - case 8120: - ret = 8112; - break; - case 8121: - ret = 8113; - break; - case 8122: - ret = 8048; - break; - case 8123: - ret = 8049; - break; - case 8124: - ret = 8115; - break; - case 8136: - ret = 8050; - break; - case 8137: - ret = 8051; - break; - case 8138: - ret = 8052; - break; - case 8139: - ret = 8053; - break; - case 8140: - ret = 8131; - break; - case 8152: - ret = 8144; - break; - case 8153: - ret = 8145; - break; - case 8154: - ret = 8054; - break; - case 8155: - ret = 8055; - break; - case 8168: - ret = 8160; - break; - case 8169: - ret = 8161; - break; - case 8170: - ret = 8058; - break; - case 8171: - ret = 8059; - break; - case 8172: - ret = 8165; - break; - case 8184: - ret = 8056; - break; - case 8185: - ret = 8057; - break; - case 8186: - ret = 8060; - break; - case 8187: - ret = 8061; - break; - case 8188: - ret = 8179; - break; - case 8544: - ret = 8560; - break; - case 8545: - ret = 8561; - break; - case 8546: - ret = 8562; - break; - case 8547: - ret = 8563; - break; - case 8548: - ret = 8564; - break; - case 8549: - ret = 8565; - break; - case 8550: - ret = 8566; - break; - case 8551: - ret = 8567; - break; - case 8552: - ret = 8568; - break; - case 8553: - ret = 8569; - break; - case 8554: - ret = 8570; - break; - case 8555: - ret = 8571; - break; - case 8556: - ret = 8572; - break; - case 8557: - ret = 8573; - break; - case 8558: - ret = 8574; - break; - case 8559: - ret = 8575; - break; - case 9398: - ret = 9424; - break; - case 9399: - ret = 9425; - break; - case 9400: - ret = 9426; - break; - case 9401: - ret = 9427; - break; - case 9402: - ret = 9428; - break; - case 9403: - ret = 9429; - break; - case 9404: - ret = 9430; - break; - case 9405: - ret = 9431; - break; - case 9406: - ret = 9432; - break; - case 9407: - ret = 9433; - break; - case 9408: - ret = 9434; - break; - case 9409: - ret = 9435; - break; - case 9410: - ret = 9436; - break; - case 9411: - ret = 9437; - break; - case 9412: - ret = 9438; - break; - case 9413: - ret = 9439; - break; - case 9414: - ret = 9440; - break; - case 9415: - ret = 9441; - break; - case 9416: - ret = 9442; - break; - case 9417: - ret = 9443; - break; - case 9418: - ret = 9444; - break; - case 9419: - ret = 9445; - break; - case 9420: - ret = 9446; - break; - case 9421: - ret = 9447; - break; - case 9422: - ret = 9448; - break; - case 9423: - ret = 9449; - break; - case 65313: - ret = 65345; - break; - case 65314: - ret = 65346; - break; - case 65315: - ret = 65347; - break; - case 65316: - ret = 65348; - break; - case 65317: - ret = 65349; - break; - case 65318: - ret = 65350; - break; - case 65319: - ret = 65351; - break; - case 65320: - ret = 65352; - break; - case 65321: - ret = 65353; - break; - case 65322: - ret = 65354; - break; - case 65323: - ret = 65355; - break; - case 65324: - ret = 65356; - break; - case 65325: - ret = 65357; - break; - case 65326: - ret = 65358; - break; - case 65327: - ret = 65359; - break; - case 65328: - ret = 65360; - break; - case 65329: - ret = 65361; - break; - case 65330: - ret = 65362; - break; - case 65331: - ret = 65363; - break; - case 65332: - ret = 65364; - break; - case 65333: - ret = 65365; - break; - case 65334: - ret = 65366; - break; - case 65335: - ret = 65367; - break; - case 65336: - ret = 65368; - break; - case 65337: - ret = 65369; - break; - case 65338: - ret = 65370; - break; - } - return (char) ret; - } +// if (java_1_0) +// { +// int ret = (int) c; +// switch (c) +// { +// case 65: +// ret = 97; +// break; +// case 66: +// ret = 98; +// break; +// case 67: +// ret = 99; +// break; +// case 68: +// ret = 100; +// break; +// case 69: +// ret = 101; +// break; +// case 70: +// ret = 102; +// break; +// case 71: +// ret = 103; +// break; +// case 72: +// ret = 104; +// break; +// case 73: +// ret = 105; +// break; +// case 74: +// ret = 106; +// break; +// case 75: +// ret = 107; +// break; +// case 76: +// ret = 108; +// break; +// case 77: +// ret = 109; +// break; +// case 78: +// ret = 110; +// break; +// case 79: +// ret = 111; +// break; +// case 80: +// ret = 112; +// break; +// case 81: +// ret = 113; +// break; +// case 82: +// ret = 114; +// break; +// case 83: +// ret = 115; +// break; +// case 84: +// ret = 116; +// break; +// case 85: +// ret = 117; +// break; +// case 86: +// ret = 118; +// break; +// case 87: +// ret = 119; +// break; +// case 88: +// ret = 120; +// break; +// case 89: +// ret = 121; +// break; +// case 90: +// ret = 122; +// break; +// case 192: +// ret = 224; +// break; +// case 193: +// ret = 225; +// break; +// case 194: +// ret = 226; +// break; +// case 195: +// ret = 227; +// break; +// case 196: +// ret = 228; +// break; +// case 197: +// ret = 229; +// break; +// case 198: +// ret = 230; +// break; +// case 199: +// ret = 231; +// break; +// case 200: +// ret = 232; +// break; +// case 201: +// ret = 233; +// break; +// case 202: +// ret = 234; +// break; +// case 203: +// ret = 235; +// break; +// case 204: +// ret = 236; +// break; +// case 205: +// ret = 237; +// break; +// case 206: +// ret = 238; +// break; +// case 207: +// ret = 239; +// break; +// case 208: +// ret = 240; +// break; +// case 209: +// ret = 241; +// break; +// case 210: +// ret = 242; +// break; +// case 211: +// ret = 243; +// break; +// case 212: +// ret = 244; +// break; +// case 213: +// ret = 245; +// break; +// case 214: +// ret = 246; +// break; +// case 216: +// ret = 248; +// break; +// case 217: +// ret = 249; +// break; +// case 218: +// ret = 250; +// break; +// case 219: +// ret = 251; +// break; +// case 220: +// ret = 252; +// break; +// case 221: +// ret = 253; +// break; +// case 222: +// ret = 254; +// break; +// case 256: +// ret = 257; +// break; +// case 258: +// ret = 259; +// break; +// case 260: +// ret = 261; +// break; +// case 262: +// ret = 263; +// break; +// case 264: +// ret = 265; +// break; +// case 266: +// ret = 267; +// break; +// case 268: +// ret = 269; +// break; +// case 270: +// ret = 271; +// break; +// case 272: +// ret = 273; +// break; +// case 274: +// ret = 275; +// break; +// case 276: +// ret = 277; +// break; +// case 278: +// ret = 279; +// break; +// case 280: +// ret = 281; +// break; +// case 282: +// ret = 283; +// break; +// case 284: +// ret = 285; +// break; +// case 286: +// ret = 287; +// break; +// case 288: +// ret = 289; +// break; +// case 290: +// ret = 291; +// break; +// case 292: +// ret = 293; +// break; +// case 294: +// ret = 295; +// break; +// case 296: +// ret = 297; +// break; +// case 298: +// ret = 299; +// break; +// case 300: +// ret = 301; +// break; +// case 302: +// ret = 303; +// break; +// case 304: +// ret = 105; +// break; +// case 306: +// ret = 307; +// break; +// case 308: +// ret = 309; +// break; +// case 310: +// ret = 311; +// break; +// case 313: +// ret = 314; +// break; +// case 315: +// ret = 316; +// break; +// case 317: +// ret = 318; +// break; +// case 319: +// ret = 320; +// break; +// case 321: +// ret = 322; +// break; +// case 323: +// ret = 324; +// break; +// case 325: +// ret = 326; +// break; +// case 327: +// ret = 328; +// break; +// case 330: +// ret = 331; +// break; +// case 332: +// ret = 333; +// break; +// case 334: +// ret = 335; +// break; +// case 336: +// ret = 337; +// break; +// case 338: +// ret = 339; +// break; +// case 340: +// ret = 341; +// break; +// case 342: +// ret = 343; +// break; +// case 344: +// ret = 345; +// break; +// case 346: +// ret = 347; +// break; +// case 348: +// ret = 349; +// break; +// case 350: +// ret = 351; +// break; +// case 352: +// ret = 353; +// break; +// case 354: +// ret = 355; +// break; +// case 356: +// ret = 357; +// break; +// case 358: +// ret = 359; +// break; +// case 360: +// ret = 361; +// break; +// case 362: +// ret = 363; +// break; +// case 364: +// ret = 365; +// break; +// case 366: +// ret = 367; +// break; +// case 368: +// ret = 369; +// break; +// case 370: +// ret = 371; +// break; +// case 372: +// ret = 373; +// break; +// case 374: +// ret = 375; +// break; +// case 376: +// ret = 255; +// break; +// case 377: +// ret = 378; +// break; +// case 379: +// ret = 380; +// break; +// case 381: +// ret = 382; +// break; +// case 385: +// ret = 595; +// break; +// case 386: +// ret = 387; +// break; +// case 388: +// ret = 389; +// break; +// case 390: +// ret = 596; +// break; +// case 391: +// ret = 392; +// break; +// case 393: +// ret = 598; +// break; +// case 394: +// ret = 599; +// break; +// case 395: +// ret = 396; +// break; +// case 398: +// ret = 600; +// break; +// case 399: +// ret = 601; +// break; +// case 400: +// ret = 603; +// break; +// case 401: +// ret = 402; +// break; +// case 403: +// ret = 608; +// break; +// case 404: +// ret = 611; +// break; +// case 406: +// ret = 617; +// break; +// case 407: +// ret = 616; +// break; +// case 408: +// ret = 409; +// break; +// case 412: +// ret = 623; +// break; +// case 413: +// ret = 626; +// break; +// case 416: +// ret = 417; +// break; +// case 418: +// ret = 419; +// break; +// case 420: +// ret = 421; +// break; +// case 423: +// ret = 424; +// break; +// case 425: +// ret = 643; +// break; +// case 428: +// ret = 429; +// break; +// case 430: +// ret = 648; +// break; +// case 431: +// ret = 432; +// break; +// case 433: +// ret = 650; +// break; +// case 434: +// ret = 651; +// break; +// case 435: +// ret = 436; +// break; +// case 437: +// ret = 438; +// break; +// case 439: +// ret = 658; +// break; +// case 440: +// ret = 441; +// break; +// case 444: +// ret = 445; +// break; +// case 452: +// ret = 454; +// break; +// case 453: +// ret = 454; +// break; +// case 455: +// ret = 457; +// break; +// case 456: +// ret = 457; +// break; +// case 458: +// ret = 460; +// break; +// case 459: +// ret = 460; +// break; +// case 461: +// ret = 462; +// break; +// case 463: +// ret = 464; +// break; +// case 465: +// ret = 466; +// break; +// case 467: +// ret = 468; +// break; +// case 469: +// ret = 470; +// break; +// case 471: +// ret = 472; +// break; +// case 473: +// ret = 474; +// break; +// case 475: +// ret = 476; +// break; +// case 478: +// ret = 479; +// break; +// case 480: +// ret = 481; +// break; +// case 482: +// ret = 483; +// break; +// case 484: +// ret = 485; +// break; +// case 486: +// ret = 487; +// break; +// case 488: +// ret = 489; +// break; +// case 490: +// ret = 491; +// break; +// case 492: +// ret = 493; +// break; +// case 494: +// ret = 495; +// break; +// case 497: +// ret = 499; +// break; +// case 498: +// ret = 499; +// break; +// case 500: +// ret = 501; +// break; +// case 506: +// ret = 507; +// break; +// case 508: +// ret = 509; +// break; +// case 510: +// ret = 511; +// break; +// case 512: +// ret = 513; +// break; +// case 514: +// ret = 515; +// break; +// case 516: +// ret = 517; +// break; +// case 518: +// ret = 519; +// break; +// case 520: +// ret = 521; +// break; +// case 522: +// ret = 523; +// break; +// case 524: +// ret = 525; +// break; +// case 526: +// ret = 527; +// break; +// case 528: +// ret = 529; +// break; +// case 530: +// ret = 531; +// break; +// case 532: +// ret = 533; +// break; +// case 534: +// ret = 535; +// break; +// case 902: +// ret = 940; +// break; +// case 904: +// ret = 941; +// break; +// case 905: +// ret = 942; +// break; +// case 906: +// ret = 943; +// break; +// case 908: +// ret = 972; +// break; +// case 910: +// ret = 973; +// break; +// case 911: +// ret = 974; +// break; +// case 913: +// ret = 945; +// break; +// case 914: +// ret = 946; +// break; +// case 915: +// ret = 947; +// break; +// case 916: +// ret = 948; +// break; +// case 917: +// ret = 949; +// break; +// case 918: +// ret = 950; +// break; +// case 919: +// ret = 951; +// break; +// case 920: +// ret = 952; +// break; +// case 921: +// ret = 953; +// break; +// case 922: +// ret = 954; +// break; +// case 923: +// ret = 955; +// break; +// case 924: +// ret = 956; +// break; +// case 925: +// ret = 957; +// break; +// case 926: +// ret = 958; +// break; +// case 927: +// ret = 959; +// break; +// case 928: +// ret = 960; +// break; +// case 929: +// ret = 961; +// break; +// case 931: +// ret = 963; +// break; +// case 932: +// ret = 964; +// break; +// case 933: +// ret = 965; +// break; +// case 934: +// ret = 966; +// break; +// case 935: +// ret = 967; +// break; +// case 936: +// ret = 968; +// break; +// case 937: +// ret = 969; +// break; +// case 938: +// ret = 970; +// break; +// case 939: +// ret = 971; +// break; +// case 994: +// ret = 995; +// break; +// case 996: +// ret = 997; +// break; +// case 998: +// ret = 999; +// break; +// case 1000: +// ret = 1001; +// break; +// case 1002: +// ret = 1003; +// break; +// case 1004: +// ret = 1005; +// break; +// case 1006: +// ret = 1007; +// break; +// case 1025: +// ret = 1105; +// break; +// case 1026: +// ret = 1106; +// break; +// case 1027: +// ret = 1107; +// break; +// case 1028: +// ret = 1108; +// break; +// case 1029: +// ret = 1109; +// break; +// case 1030: +// ret = 1110; +// break; +// case 1031: +// ret = 1111; +// break; +// case 1032: +// ret = 1112; +// break; +// case 1033: +// ret = 1113; +// break; +// case 1034: +// ret = 1114; +// break; +// case 1035: +// ret = 1115; +// break; +// case 1036: +// ret = 1116; +// break; +// case 1038: +// ret = 1118; +// break; +// case 1039: +// ret = 1119; +// break; +// case 1040: +// ret = 1072; +// break; +// case 1041: +// ret = 1073; +// break; +// case 1042: +// ret = 1074; +// break; +// case 1043: +// ret = 1075; +// break; +// case 1044: +// ret = 1076; +// break; +// case 1045: +// ret = 1077; +// break; +// case 1046: +// ret = 1078; +// break; +// case 1047: +// ret = 1079; +// break; +// case 1048: +// ret = 1080; +// break; +// case 1049: +// ret = 1081; +// break; +// case 1050: +// ret = 1082; +// break; +// case 1051: +// ret = 1083; +// break; +// case 1052: +// ret = 1084; +// break; +// case 1053: +// ret = 1085; +// break; +// case 1054: +// ret = 1086; +// break; +// case 1055: +// ret = 1087; +// break; +// case 1056: +// ret = 1088; +// break; +// case 1057: +// ret = 1089; +// break; +// case 1058: +// ret = 1090; +// break; +// case 1059: +// ret = 1091; +// break; +// case 1060: +// ret = 1092; +// break; +// case 1061: +// ret = 1093; +// break; +// case 1062: +// ret = 1094; +// break; +// case 1063: +// ret = 1095; +// break; +// case 1064: +// ret = 1096; +// break; +// case 1065: +// ret = 1097; +// break; +// case 1066: +// ret = 1098; +// break; +// case 1067: +// ret = 1099; +// break; +// case 1068: +// ret = 1100; +// break; +// case 1069: +// ret = 1101; +// break; +// case 1070: +// ret = 1102; +// break; +// case 1071: +// ret = 1103; +// break; +// case 1120: +// ret = 1121; +// break; +// case 1122: +// ret = 1123; +// break; +// case 1124: +// ret = 1125; +// break; +// case 1126: +// ret = 1127; +// break; +// case 1128: +// ret = 1129; +// break; +// case 1130: +// ret = 1131; +// break; +// case 1132: +// ret = 1133; +// break; +// case 1134: +// ret = 1135; +// break; +// case 1136: +// ret = 1137; +// break; +// case 1138: +// ret = 1139; +// break; +// case 1140: +// ret = 1141; +// break; +// case 1142: +// ret = 1143; +// break; +// case 1144: +// ret = 1145; +// break; +// case 1146: +// ret = 1147; +// break; +// case 1148: +// ret = 1149; +// break; +// case 1150: +// ret = 1151; +// break; +// case 1152: +// ret = 1153; +// break; +// case 1168: +// ret = 1169; +// break; +// case 1170: +// ret = 1171; +// break; +// case 1172: +// ret = 1173; +// break; +// case 1174: +// ret = 1175; +// break; +// case 1176: +// ret = 1177; +// break; +// case 1178: +// ret = 1179; +// break; +// case 1180: +// ret = 1181; +// break; +// case 1182: +// ret = 1183; +// break; +// case 1184: +// ret = 1185; +// break; +// case 1186: +// ret = 1187; +// break; +// case 1188: +// ret = 1189; +// break; +// case 1190: +// ret = 1191; +// break; +// case 1192: +// ret = 1193; +// break; +// case 1194: +// ret = 1195; +// break; +// case 1196: +// ret = 1197; +// break; +// case 1198: +// ret = 1199; +// break; +// case 1200: +// ret = 1201; +// break; +// case 1202: +// ret = 1203; +// break; +// case 1204: +// ret = 1205; +// break; +// case 1206: +// ret = 1207; +// break; +// case 1208: +// ret = 1209; +// break; +// case 1210: +// ret = 1211; +// break; +// case 1212: +// ret = 1213; +// break; +// case 1214: +// ret = 1215; +// break; +// case 1217: +// ret = 1218; +// break; +// case 1219: +// ret = 1220; +// break; +// case 1223: +// ret = 1224; +// break; +// case 1227: +// ret = 1228; +// break; +// case 1232: +// ret = 1233; +// break; +// case 1234: +// ret = 1235; +// break; +// case 1236: +// ret = 1237; +// break; +// case 1238: +// ret = 1239; +// break; +// case 1240: +// ret = 1241; +// break; +// case 1242: +// ret = 1243; +// break; +// case 1244: +// ret = 1245; +// break; +// case 1246: +// ret = 1247; +// break; +// case 1248: +// ret = 1249; +// break; +// case 1250: +// ret = 1251; +// break; +// case 1252: +// ret = 1253; +// break; +// case 1254: +// ret = 1255; +// break; +// case 1256: +// ret = 1257; +// break; +// case 1258: +// ret = 1259; +// break; +// case 1262: +// ret = 1263; +// break; +// case 1264: +// ret = 1265; +// break; +// case 1266: +// ret = 1267; +// break; +// case 1268: +// ret = 1269; +// break; +// case 1272: +// ret = 1273; +// break; +// case 1329: +// ret = 1377; +// break; +// case 1330: +// ret = 1378; +// break; +// case 1331: +// ret = 1379; +// break; +// case 1332: +// ret = 1380; +// break; +// case 1333: +// ret = 1381; +// break; +// case 1334: +// ret = 1382; +// break; +// case 1335: +// ret = 1383; +// break; +// case 1336: +// ret = 1384; +// break; +// case 1337: +// ret = 1385; +// break; +// case 1338: +// ret = 1386; +// break; +// case 1339: +// ret = 1387; +// break; +// case 1340: +// ret = 1388; +// break; +// case 1341: +// ret = 1389; +// break; +// case 1342: +// ret = 1390; +// break; +// case 1343: +// ret = 1391; +// break; +// case 1344: +// ret = 1392; +// break; +// case 1345: +// ret = 1393; +// break; +// case 1346: +// ret = 1394; +// break; +// case 1347: +// ret = 1395; +// break; +// case 1348: +// ret = 1396; +// break; +// case 1349: +// ret = 1397; +// break; +// case 1350: +// ret = 1398; +// break; +// case 1351: +// ret = 1399; +// break; +// case 1352: +// ret = 1400; +// break; +// case 1353: +// ret = 1401; +// break; +// case 1354: +// ret = 1402; +// break; +// case 1355: +// ret = 1403; +// break; +// case 1356: +// ret = 1404; +// break; +// case 1357: +// ret = 1405; +// break; +// case 1358: +// ret = 1406; +// break; +// case 1359: +// ret = 1407; +// break; +// case 1360: +// ret = 1408; +// break; +// case 1361: +// ret = 1409; +// break; +// case 1362: +// ret = 1410; +// break; +// case 1363: +// ret = 1411; +// break; +// case 1364: +// ret = 1412; +// break; +// case 1365: +// ret = 1413; +// break; +// case 1366: +// ret = 1414; +// break; +// case 4256: +// ret = 4304; +// break; +// case 4257: +// ret = 4305; +// break; +// case 4258: +// ret = 4306; +// break; +// case 4259: +// ret = 4307; +// break; +// case 4260: +// ret = 4308; +// break; +// case 4261: +// ret = 4309; +// break; +// case 4262: +// ret = 4310; +// break; +// case 4263: +// ret = 4311; +// break; +// case 4264: +// ret = 4312; +// break; +// case 4265: +// ret = 4313; +// break; +// case 4266: +// ret = 4314; +// break; +// case 4267: +// ret = 4315; +// break; +// case 4268: +// ret = 4316; +// break; +// case 4269: +// ret = 4317; +// break; +// case 4270: +// ret = 4318; +// break; +// case 4271: +// ret = 4319; +// break; +// case 4272: +// ret = 4320; +// break; +// case 4273: +// ret = 4321; +// break; +// case 4274: +// ret = 4322; +// break; +// case 4275: +// ret = 4323; +// break; +// case 4276: +// ret = 4324; +// break; +// case 4277: +// ret = 4325; +// break; +// case 4278: +// ret = 4326; +// break; +// case 4279: +// ret = 4327; +// break; +// case 4280: +// ret = 4328; +// break; +// case 4281: +// ret = 4329; +// break; +// case 4282: +// ret = 4330; +// break; +// case 4283: +// ret = 4331; +// break; +// case 4284: +// ret = 4332; +// break; +// case 4285: +// ret = 4333; +// break; +// case 4286: +// ret = 4334; +// break; +// case 4287: +// ret = 4335; +// break; +// case 4288: +// ret = 4336; +// break; +// case 4289: +// ret = 4337; +// break; +// case 4290: +// ret = 4338; +// break; +// case 4291: +// ret = 4339; +// break; +// case 4292: +// ret = 4340; +// break; +// case 4293: +// ret = 4341; +// break; +// case 7680: +// ret = 7681; +// break; +// case 7682: +// ret = 7683; +// break; +// case 7684: +// ret = 7685; +// break; +// case 7686: +// ret = 7687; +// break; +// case 7688: +// ret = 7689; +// break; +// case 7690: +// ret = 7691; +// break; +// case 7692: +// ret = 7693; +// break; +// case 7694: +// ret = 7695; +// break; +// case 7696: +// ret = 7697; +// break; +// case 7698: +// ret = 7699; +// break; +// case 7700: +// ret = 7701; +// break; +// case 7702: +// ret = 7703; +// break; +// case 7704: +// ret = 7705; +// break; +// case 7706: +// ret = 7707; +// break; +// case 7708: +// ret = 7709; +// break; +// case 7710: +// ret = 7711; +// break; +// case 7712: +// ret = 7713; +// break; +// case 7714: +// ret = 7715; +// break; +// case 7716: +// ret = 7717; +// break; +// case 7718: +// ret = 7719; +// break; +// case 7720: +// ret = 7721; +// break; +// case 7722: +// ret = 7723; +// break; +// case 7724: +// ret = 7725; +// break; +// case 7726: +// ret = 7727; +// break; +// case 7728: +// ret = 7729; +// break; +// case 7730: +// ret = 7731; +// break; +// case 7732: +// ret = 7733; +// break; +// case 7734: +// ret = 7735; +// break; +// case 7736: +// ret = 7737; +// break; +// case 7738: +// ret = 7739; +// break; +// case 7740: +// ret = 7741; +// break; +// case 7742: +// ret = 7743; +// break; +// case 7744: +// ret = 7745; +// break; +// case 7746: +// ret = 7747; +// break; +// case 7748: +// ret = 7749; +// break; +// case 7750: +// ret = 7751; +// break; +// case 7752: +// ret = 7753; +// break; +// case 7754: +// ret = 7755; +// break; +// case 7756: +// ret = 7757; +// break; +// case 7758: +// ret = 7759; +// break; +// case 7760: +// ret = 7761; +// break; +// case 7762: +// ret = 7763; +// break; +// case 7764: +// ret = 7765; +// break; +// case 7766: +// ret = 7767; +// break; +// case 7768: +// ret = 7769; +// break; +// case 7770: +// ret = 7771; +// break; +// case 7772: +// ret = 7773; +// break; +// case 7774: +// ret = 7775; +// break; +// case 7776: +// ret = 7777; +// break; +// case 7778: +// ret = 7779; +// break; +// case 7780: +// ret = 7781; +// break; +// case 7782: +// ret = 7783; +// break; +// case 7784: +// ret = 7785; +// break; +// case 7786: +// ret = 7787; +// break; +// case 7788: +// ret = 7789; +// break; +// case 7790: +// ret = 7791; +// break; +// case 7792: +// ret = 7793; +// break; +// case 7794: +// ret = 7795; +// break; +// case 7796: +// ret = 7797; +// break; +// case 7798: +// ret = 7799; +// break; +// case 7800: +// ret = 7801; +// break; +// case 7802: +// ret = 7803; +// break; +// case 7804: +// ret = 7805; +// break; +// case 7806: +// ret = 7807; +// break; +// case 7808: +// ret = 7809; +// break; +// case 7810: +// ret = 7811; +// break; +// case 7812: +// ret = 7813; +// break; +// case 7814: +// ret = 7815; +// break; +// case 7816: +// ret = 7817; +// break; +// case 7818: +// ret = 7819; +// break; +// case 7820: +// ret = 7821; +// break; +// case 7822: +// ret = 7823; +// break; +// case 7824: +// ret = 7825; +// break; +// case 7826: +// ret = 7827; +// break; +// case 7828: +// ret = 7829; +// break; +// case 7840: +// ret = 7841; +// break; +// case 7842: +// ret = 7843; +// break; +// case 7844: +// ret = 7845; +// break; +// case 7846: +// ret = 7847; +// break; +// case 7848: +// ret = 7849; +// break; +// case 7850: +// ret = 7851; +// break; +// case 7852: +// ret = 7853; +// break; +// case 7854: +// ret = 7855; +// break; +// case 7856: +// ret = 7857; +// break; +// case 7858: +// ret = 7859; +// break; +// case 7860: +// ret = 7861; +// break; +// case 7862: +// ret = 7863; +// break; +// case 7864: +// ret = 7865; +// break; +// case 7866: +// ret = 7867; +// break; +// case 7868: +// ret = 7869; +// break; +// case 7870: +// ret = 7871; +// break; +// case 7872: +// ret = 7873; +// break; +// case 7874: +// ret = 7875; +// break; +// case 7876: +// ret = 7877; +// break; +// case 7878: +// ret = 7879; +// break; +// case 7880: +// ret = 7881; +// break; +// case 7882: +// ret = 7883; +// break; +// case 7884: +// ret = 7885; +// break; +// case 7886: +// ret = 7887; +// break; +// case 7888: +// ret = 7889; +// break; +// case 7890: +// ret = 7891; +// break; +// case 7892: +// ret = 7893; +// break; +// case 7894: +// ret = 7895; +// break; +// case 7896: +// ret = 7897; +// break; +// case 7898: +// ret = 7899; +// break; +// case 7900: +// ret = 7901; +// break; +// case 7902: +// ret = 7903; +// break; +// case 7904: +// ret = 7905; +// break; +// case 7906: +// ret = 7907; +// break; +// case 7908: +// ret = 7909; +// break; +// case 7910: +// ret = 7911; +// break; +// case 7912: +// ret = 7913; +// break; +// case 7914: +// ret = 7915; +// break; +// case 7916: +// ret = 7917; +// break; +// case 7918: +// ret = 7919; +// break; +// case 7920: +// ret = 7921; +// break; +// case 7922: +// ret = 7923; +// break; +// case 7924: +// ret = 7925; +// break; +// case 7926: +// ret = 7927; +// break; +// case 7928: +// ret = 7929; +// break; +// case 7944: +// ret = 7936; +// break; +// case 7945: +// ret = 7937; +// break; +// case 7946: +// ret = 7938; +// break; +// case 7947: +// ret = 7939; +// break; +// case 7948: +// ret = 7940; +// break; +// case 7949: +// ret = 7941; +// break; +// case 7950: +// ret = 7942; +// break; +// case 7951: +// ret = 7943; +// break; +// case 7960: +// ret = 7952; +// break; +// case 7961: +// ret = 7953; +// break; +// case 7962: +// ret = 7954; +// break; +// case 7963: +// ret = 7955; +// break; +// case 7964: +// ret = 7956; +// break; +// case 7965: +// ret = 7957; +// break; +// case 7976: +// ret = 7968; +// break; +// case 7977: +// ret = 7969; +// break; +// case 7978: +// ret = 7970; +// break; +// case 7979: +// ret = 7971; +// break; +// case 7980: +// ret = 7972; +// break; +// case 7981: +// ret = 7973; +// break; +// case 7982: +// ret = 7974; +// break; +// case 7983: +// ret = 7975; +// break; +// case 7992: +// ret = 7984; +// break; +// case 7993: +// ret = 7985; +// break; +// case 7994: +// ret = 7986; +// break; +// case 7995: +// ret = 7987; +// break; +// case 7996: +// ret = 7988; +// break; +// case 7997: +// ret = 7989; +// break; +// case 7998: +// ret = 7990; +// break; +// case 7999: +// ret = 7991; +// break; +// case 8008: +// ret = 8000; +// break; +// case 8009: +// ret = 8001; +// break; +// case 8010: +// ret = 8002; +// break; +// case 8011: +// ret = 8003; +// break; +// case 8012: +// ret = 8004; +// break; +// case 8013: +// ret = 8005; +// break; +// case 8025: +// ret = 8017; +// break; +// case 8027: +// ret = 8019; +// break; +// case 8029: +// ret = 8021; +// break; +// case 8031: +// ret = 8023; +// break; +// case 8040: +// ret = 8032; +// break; +// case 8041: +// ret = 8033; +// break; +// case 8042: +// ret = 8034; +// break; +// case 8043: +// ret = 8035; +// break; +// case 8044: +// ret = 8036; +// break; +// case 8045: +// ret = 8037; +// break; +// case 8046: +// ret = 8038; +// break; +// case 8047: +// ret = 8039; +// break; +// case 8072: +// ret = 8064; +// break; +// case 8073: +// ret = 8065; +// break; +// case 8074: +// ret = 8066; +// break; +// case 8075: +// ret = 8067; +// break; +// case 8076: +// ret = 8068; +// break; +// case 8077: +// ret = 8069; +// break; +// case 8078: +// ret = 8070; +// break; +// case 8079: +// ret = 8071; +// break; +// case 8088: +// ret = 8080; +// break; +// case 8089: +// ret = 8081; +// break; +// case 8090: +// ret = 8082; +// break; +// case 8091: +// ret = 8083; +// break; +// case 8092: +// ret = 8084; +// break; +// case 8093: +// ret = 8085; +// break; +// case 8094: +// ret = 8086; +// break; +// case 8095: +// ret = 8087; +// break; +// case 8104: +// ret = 8096; +// break; +// case 8105: +// ret = 8097; +// break; +// case 8106: +// ret = 8098; +// break; +// case 8107: +// ret = 8099; +// break; +// case 8108: +// ret = 8100; +// break; +// case 8109: +// ret = 8101; +// break; +// case 8110: +// ret = 8102; +// break; +// case 8111: +// ret = 8103; +// break; +// case 8120: +// ret = 8112; +// break; +// case 8121: +// ret = 8113; +// break; +// case 8122: +// ret = 8048; +// break; +// case 8123: +// ret = 8049; +// break; +// case 8124: +// ret = 8115; +// break; +// case 8136: +// ret = 8050; +// break; +// case 8137: +// ret = 8051; +// break; +// case 8138: +// ret = 8052; +// break; +// case 8139: +// ret = 8053; +// break; +// case 8140: +// ret = 8131; +// break; +// case 8152: +// ret = 8144; +// break; +// case 8153: +// ret = 8145; +// break; +// case 8154: +// ret = 8054; +// break; +// case 8155: +// ret = 8055; +// break; +// case 8168: +// ret = 8160; +// break; +// case 8169: +// ret = 8161; +// break; +// case 8170: +// ret = 8058; +// break; +// case 8171: +// ret = 8059; +// break; +// case 8172: +// ret = 8165; +// break; +// case 8184: +// ret = 8056; +// break; +// case 8185: +// ret = 8057; +// break; +// case 8186: +// ret = 8060; +// break; +// case 8187: +// ret = 8061; +// break; +// case 8188: +// ret = 8179; +// break; +// case 8544: +// ret = 8560; +// break; +// case 8545: +// ret = 8561; +// break; +// case 8546: +// ret = 8562; +// break; +// case 8547: +// ret = 8563; +// break; +// case 8548: +// ret = 8564; +// break; +// case 8549: +// ret = 8565; +// break; +// case 8550: +// ret = 8566; +// break; +// case 8551: +// ret = 8567; +// break; +// case 8552: +// ret = 8568; +// break; +// case 8553: +// ret = 8569; +// break; +// case 8554: +// ret = 8570; +// break; +// case 8555: +// ret = 8571; +// break; +// case 8556: +// ret = 8572; +// break; +// case 8557: +// ret = 8573; +// break; +// case 8558: +// ret = 8574; +// break; +// case 8559: +// ret = 8575; +// break; +// case 9398: +// ret = 9424; +// break; +// case 9399: +// ret = 9425; +// break; +// case 9400: +// ret = 9426; +// break; +// case 9401: +// ret = 9427; +// break; +// case 9402: +// ret = 9428; +// break; +// case 9403: +// ret = 9429; +// break; +// case 9404: +// ret = 9430; +// break; +// case 9405: +// ret = 9431; +// break; +// case 9406: +// ret = 9432; +// break; +// case 9407: +// ret = 9433; +// break; +// case 9408: +// ret = 9434; +// break; +// case 9409: +// ret = 9435; +// break; +// case 9410: +// ret = 9436; +// break; +// case 9411: +// ret = 9437; +// break; +// case 9412: +// ret = 9438; +// break; +// case 9413: +// ret = 9439; +// break; +// case 9414: +// ret = 9440; +// break; +// case 9415: +// ret = 9441; +// break; +// case 9416: +// ret = 9442; +// break; +// case 9417: +// ret = 9443; +// break; +// case 9418: +// ret = 9444; +// break; +// case 9419: +// ret = 9445; +// break; +// case 9420: +// ret = 9446; +// break; +// case 9421: +// ret = 9447; +// break; +// case 9422: +// ret = 9448; +// break; +// case 9423: +// ret = 9449; +// break; +// case 65313: +// ret = 65345; +// break; +// case 65314: +// ret = 65346; +// break; +// case 65315: +// ret = 65347; +// break; +// case 65316: +// ret = 65348; +// break; +// case 65317: +// ret = 65349; +// break; +// case 65318: +// ret = 65350; +// break; +// case 65319: +// ret = 65351; +// break; +// case 65320: +// ret = 65352; +// break; +// case 65321: +// ret = 65353; +// break; +// case 65322: +// ret = 65354; +// break; +// case 65323: +// ret = 65355; +// break; +// case 65324: +// ret = 65356; +// break; +// case 65325: +// ret = 65357; +// break; +// case 65326: +// ret = 65358; +// break; +// case 65327: +// ret = 65359; +// break; +// case 65328: +// ret = 65360; +// break; +// case 65329: +// ret = 65361; +// break; +// case 65330: +// ret = 65362; +// break; +// case 65331: +// ret = 65363; +// break; +// case 65332: +// ret = 65364; +// break; +// case 65333: +// ret = 65365; +// break; +// case 65334: +// ret = 65366; +// break; +// case 65335: +// ret = 65367; +// break; +// case 65336: +// ret = 65368; +// break; +// case 65337: +// ret = 65369; +// break; +// case 65338: +// ret = 65370; +// break; +// } +// return (char) ret; +// } return Character.toLowerCase(c); } - /** Convert a String to title case. */ + /** Convert a String to title case. + * + * @j2sIgnore + * + * + */ public static String toTitleCase(String s) { - StringBuffer sb = new StringBuffer(); + StringBuffer sb = new StringBuffer(); for (int i = 0; i < s.length(); i++) { - sb.append(CaseMgr.toTitleCase(s.charAt(i))); + sb.append(CaseMgr.toTitleCaseC(s.charAt(i))); } return sb.toString(); } @@ -4194,73 +4199,80 @@ final public class CaseMgr /** Convert a String to upper case. */ public static String toUpperCase(String s) { - StringBuffer sb = new StringBuffer(); - for (int i = 0; i < s.length(); i++) - { - sb.append(CaseMgr.toUpperCase(s.charAt(i))); - } - return sb.toString(); + return s.toUpperCase(); +// StringBuffer sb = new StringBuffer(); +// for (int i = 0; i < s.length(); i++) +// { +// sb.append(CaseMgr.toUpperCaseC(s.charAt(i))); +// } +// return sb.toString(); } /** Convert a String to lower case. */ public static String toLowerCase(String s) { - StringBuffer sb = new StringBuffer(); - for (int i = 0; i < s.length(); i++) - { - sb.append(CaseMgr.toLowerCase(s.charAt(i))); - } - return sb.toString(); + return s.toLowerCase(); +// StringBuffer sb = new StringBuffer(); +// for (int i = 0; i < s.length(); i++) +// { +// sb.append(CaseMgr.toLowerCaseC(s.charAt(i))); +// } +// return sb.toString(); } - /** Convert a character to title case. */ - public static char toTitleCase(char c) + /** Convert a character to title case. + * + * SwingJS -- BH -- ignoring title case. + * + * */ + public static char toTitleCaseC(char c) { - if (java_1_0) - { - int ret = (int) toUpperCase(c); - switch (c) - { - case 452: - ret = 453; - break; - case 453: - ret = 453; - break; - case 454: - ret = 453; - break; - case 455: - ret = 456; - break; - case 456: - ret = 456; - break; - case 457: - ret = 456; - break; - case 458: - ret = 459; - break; - case 459: - ret = 459; - break; - case 460: - ret = 459; - break; - case 497: - ret = 498; - break; - case 498: - ret = 498; - break; - case 499: - ret = 498; - break; - } - return (char) ret; - } - return Character.toTitleCase(c); + return Character.toUpperCase(c); +// if (java_1_0) +// { +// int ret = (int) toUpperCaseC(c); +// switch (c) +// { +// case 452: +// ret = 453; +// break; +// case 453: +// ret = 453; +// break; +// case 454: +// ret = 453; +// break; +// case 455: +// ret = 456; +// break; +// case 456: +// ret = 456; +// break; +// case 457: +// ret = 456; +// break; +// case 458: +// ret = 459; +// break; +// case 459: +// ret = 459; +// break; +// case 460: +// ret = 459; +// break; +// case 497: +// ret = 498; +// break; +// case 498: +// ret = 498; +// break; +// case 499: +// ret = 498; +// break; +// } +// return (char) ret; +// } +// return Character.toTitleCase(c); } /** @@ -4268,7 +4280,7 @@ final public class CaseMgr * definitions of upper, lower, and title case in this class when ignoreCase * is set. */ - public static boolean regionMatches(StringLike s1, boolean ign, int i1, + public static boolean regionMatchesLike(StringLike s1, boolean ign, int i1, StringLike s2, int i2, int i3) { int itot = i2 + i3; @@ -4290,7 +4302,7 @@ final public class CaseMgr { for (int i = i2; i < itot; i++) { - if (toLowerCase(s2.charAt(i)) != toLowerCase(s1.charAt(i1++))) + if (toLowerCaseC(s2.charAt(i)) != toLowerCaseC(s1.charAt(i1++))) { return false; } @@ -4326,7 +4338,7 @@ final public class CaseMgr { for (int i = i2; i < itot; i++) { - if (toLowerCase(s2.charAt(i)) != toLowerCase(s1.charAt(i1++))) + if (toLowerCaseC(s2.charAt(i)) != toLowerCaseC(s1.charAt(i1++))) { return false; } @@ -4340,7 +4352,7 @@ final public class CaseMgr * definitions of upper, lower, and title case in this class when ignoreCase * is set. */ - public static boolean regionMatches(StringLike s1, boolean ign, int i1, + public static boolean regionMatchesLike2(StringLike s1, boolean ign, int i1, String s2, int i2, int i3) { int itot = i2 + i3; @@ -4362,7 +4374,7 @@ final public class CaseMgr { for (int i = i2; i < itot; i++) { - if (toLowerCase(s2.charAt(i)) != toLowerCase(s1.charAt(i1++))) + if (toLowerCaseC(s2.charAt(i)) != toLowerCaseC(s1.charAt(i1++))) { return false; } @@ -4376,7 +4388,7 @@ final public class CaseMgr * definitions of upper, lower, and title case in this class when ignoreCase * is set. */ - public static boolean regionMatches(String s1, boolean ign, int i1, + public static boolean regionMatches2(String s1, boolean ign, int i1, String s2, int i2, int i3) { int itot = i2 + i3; @@ -4398,7 +4410,7 @@ final public class CaseMgr { for (int i = i2; i < itot; i++) { - if (toLowerCase(s2.charAt(i)) != toLowerCase(s1.charAt(i1++))) + if (toLowerCaseC(s2.charAt(i)) != toLowerCaseC(s1.charAt(i1++))) { return false; } diff --git a/src/com/stevesoft/pat/DirFileRegex.java b/src/com/stevesoft/pat/DirFileRegex.java index bc62910..64a50fc 100755 --- a/src/com/stevesoft/pat/DirFileRegex.java +++ b/src/com/stevesoft/pat/DirFileRegex.java @@ -13,19 +13,19 @@ package com.stevesoft.pat; */ public class DirFileRegex extends FileRegex { - public DirFileRegex() - { - dirflag = DIR; - } - - public DirFileRegex(String fp) - { - super(fp); - dirflag = DIR; - } - - public static String[] list(String f) - { - return list(f, DIR); - } +// public DirFileRegex() +// { +// dirflag = DIR; +// } +// +// public DirFileRegex(String fp) +// { +// super(fp); +// dirflag = DIR; +// } +// +// public static String[] list(String f) +// { +// return list(f, DIR); +// } } diff --git a/src/com/stevesoft/pat/FileRegex.java b/src/com/stevesoft/pat/FileRegex.java index 342d41c..263a005 100755 --- a/src/com/stevesoft/pat/FileRegex.java +++ b/src/com/stevesoft/pat/FileRegex.java @@ -65,259 +65,259 @@ import java.util.*; */ public class FileRegex extends Regex { - /** Build an unitialized FileRegex. */ - public FileRegex() - { - dirflag = EITHER; - } - - /** Build a FileRegex form String s. */ - public FileRegex(String s) - { - super(s); - dirflag = EITHER; - } - - /** - * Compile a new pattern. Throws - * - * @exception com.stevesoft.pat.RegSyntax - * for nonsensical patterns like "[9-0]+" just as Regex - * does. - * @see com.stevesoft.pat#compile(java.lang.String) - */ - public void compile(String s) throws RegSyntax - { - String npat = toFileRegex(s); - super.compile(npat); - if (File.separatorChar == '\\') // MS-DOS - { - ignoreCase = true; - } - } - - /** - * This is the method required by FileNameFilter. To get a listing of files in - * the current directory ending in .java, do this: - * - *
-   * File dot = new File(".");
-   * 
-   * FileRegex java_files = new FileRegex("*.java");
-   * 
-   * String[] file_list = dot.list(java_files);
-   * 
- */ - public boolean accept(File dir, String s) - { - if (dirflag != EITHER) - { - File f = new File(s); - if (f.isDirectory() && dirflag == NONDIR) - { - return false; - } - if (!f.isDirectory() && dirflag == DIR) - { - return false; - } - } - return matchAt(s, 0); - } - - int dirflag = 0; - - final static int EITHER = 0, DIR = 1, NONDIR = 2; - - /** - * Provides an alternative to File.list -- this separates its argument - * according to File.pathSeparator. To each path, it splits off a directory -- - * all characters up to and including the first instance of File.separator -- - * and a file pattern -- the part that comes after the directory. It then - * produces a list of all the pattern matches on all the paths. Thus - * "*.java:../*.java" would produce a list of all the java files in this - * directory and in the ".." directory on a Unix machine. "*.java;..\\*.java" - * would do the same thing on a Dos machine. - */ - public static String[] list(String f) - { - return list(f, EITHER); - } - - static String[] list(String f, int df) - { - // return list_(f,new FileRegex()); - StringTokenizer st = new StringTokenizer(f, File.pathSeparator); - Vector v = new Vector(); - while (st.hasMoreTokens()) - { - String path = st.nextToken(); - list1(path, v, df, true); - } - String[] sa = new String[v.size()]; - v.copyInto(sa); - return sa; - } - - final static Regex root = new Regex(File.separatorChar == '/' ? "/$" - : "(?:.:|)\\\\$"); - - static void list1(String path, Vector v, int df, boolean rec) - { - // if path looks like a/b/c/ or d:\ then add . - if (root.matchAt(path, 0)) - { - v.addElement(path + "."); - return; - } - File f = new File(path); - if (f.getParent() != null && rec) - { - Vector v2 = new Vector(); - list1(f.getParent(), v2, DIR, true); - for (int i = 0; i < v2.size(); i++) - { - String path2 = ((String) v2.elementAt(i)) + File.separator - + f.getName(); - list1(path2, v, df, false); - } - } - else - { - File base = new File(path); - - String dir_s = base.getParent(); - if (dir_s == null) - { - dir_s = "."; - } - File dir = new File(dir_s); - - FileRegex fr = new FileRegex(base.getName()); - if (fr.isLiteral()) - { - v.addElement(dir_s + File.separator + base.getName()); - return; - } - fr.dirflag = df; - String[] sa = dir.list(fr); - if (sa == null) - { - return; - } - for (int i = 0; i < sa.length; i++) - { - v.addElement(dir_s + File.separator + sa[i]); - } - } - } - - /** - * This method takes a file regular expression, and translates it into the - * type of pattern used by a normal Regex. - */ - public static String toFileRegex(String s) - { - StrPos sp = new StrPos(s, 0); - StringBuffer sb = new StringBuffer(); - if (sp.incMatch("{?e=")) - { - char e = sp.thisChar(); - sp.inc(); - if (sp.incMatch("}")) - { - sb.append("(?e=" + e + ")^"); - } - else - { - sb.append("^(?e="); - } - sp.esc = e; - } - int ParenLvl = 0; - while (!sp.eos()) - { - if (File.separatorChar == '\\') - { - if (sp.escaped()) - { - sb.append("\\\\"); - } - sp.dontMatch = false; - } - if (sp.incMatch("?")) - { - sb.append("."); - } - else if (sp.incMatch(".")) - { - sb.append(sp.esc); - sb.append('.'); - } - else if (sp.incMatch("{??")) - { - sb.append("(??"); - ParenLvl++; - // allow negative lookahead to work - } - else if (sp.incMatch("{?!")) - { - sb.append("(?!"); - ParenLvl++; - // allow positive lookahead to work - } - else if (sp.incMatch("{?=")) - { - sb.append("(?="); - ParenLvl++; - } - else if (sp.incMatch("{")) - { - sb.append("(?:"); - ParenLvl++; - } - else if (sp.incMatch("}")) - { - sb.append(')'); - ParenLvl--; - } - else if (ParenLvl != 0 && sp.incMatch(",")) - { - sb.append('|'); - } - else if (sp.incMatch("*")) - { - sb.append(".*"); - } - else - { - sb.append(sp.thisChar()); - sp.inc(); - } - } - sb.append("$"); - return sb.toString(); - } - - public boolean isLiteral() - { - Pattern x = thePattern; - while (x != null && !(x instanceof End)) - { - if (x instanceof oneChar) - { - ; - } - else if (x instanceof Skipped) - { - ; - } - else - { - return false; - } - x = x.next; - } - return true; - } +// /** Build an unitialized FileRegex. */ +// public FileRegex() +// { +// dirflag = EITHER; +// } +// +// /** Build a FileRegex form String s. */ +// public FileRegex(String s) +// { +// super(s); +// dirflag = EITHER; +// } +// +// /** +// * Compile a new pattern. Throws +// * +// * @exception com.stevesoft.pat.RegSyntax +// * for nonsensical patterns like "[9-0]+" just as Regex +// * does. +// * @see com.stevesoft.pat#compile(java.lang.String) +// */ +// public void compile(String s) throws RegSyntax +// { +// String npat = toFileRegex(s); +// super.compile(npat); +// if (File.separatorChar == '\\') // MS-DOS +// { +// ignoreCase = true; +// } +// } +// +// /** +// * This is the method required by FileNameFilter. To get a listing of files in +// * the current directory ending in .java, do this: +// * +// *
+//   * File dot = new File(".");
+//   * 
+//   * FileRegex java_files = new FileRegex("*.java");
+//   * 
+//   * String[] file_list = dot.list(java_files);
+//   * 
+// */ +// public boolean accept(File dir, String s) +// { +// if (dirflag != EITHER) +// { +// File f = new File(s); +// if (f.isDirectory() && dirflag == NONDIR) +// { +// return false; +// } +// if (!f.isDirectory() && dirflag == DIR) +// { +// return false; +// } +// } +// return matchAt(s, 0); +// } +// +// int dirflag = 0; +// +// final static int EITHER = 0, DIR = 1, NONDIR = 2; +// +// /** +// * Provides an alternative to File.list -- this separates its argument +// * according to File.pathSeparator. To each path, it splits off a directory -- +// * all characters up to and including the first instance of File.separator -- +// * and a file pattern -- the part that comes after the directory. It then +// * produces a list of all the pattern matches on all the paths. Thus +// * "*.java:../*.java" would produce a list of all the java files in this +// * directory and in the ".." directory on a Unix machine. "*.java;..\\*.java" +// * would do the same thing on a Dos machine. +// */ +// public static String[] list(String f) +// { +// return list(f, EITHER); +// } +// +// static String[] list(String f, int df) +// { +// // return list_(f,new FileRegex()); +// StringTokenizer st = new StringTokenizer(f, File.pathSeparator); +// Vector v = new Vector(); +// while (st.hasMoreTokens()) +// { +// String path = st.nextToken(); +// list1(path, v, df, true); +// } +// String[] sa = new String[v.size()]; +// v.copyInto(sa); +// return sa; +// } +// +// final static Regex root = new Regex(File.separatorChar == '/' ? "/$" +// : "(?:.:|)\\\\$"); +// +// static void list1(String path, Vector v, int df, boolean rec) +// { +// // if path looks like a/b/c/ or d:\ then add . +// if (root.matchAt(path, 0)) +// { +// v.addElement(path + "."); +// return; +// } +// File f = new File(path); +// if (f.getParent() != null && rec) +// { +// Vector v2 = new Vector(); +// list1(f.getParent(), v2, DIR, true); +// for (int i = 0; i < v2.size(); i++) +// { +// String path2 = ((String) v2.elementAt(i)) + File.separator +// + f.getName(); +// list1(path2, v, df, false); +// } +// } +// else +// { +// File base = new File(path); +// +// String dir_s = base.getParent(); +// if (dir_s == null) +// { +// dir_s = "."; +// } +// File dir = new File(dir_s); +// +// FileRegex fr = new FileRegex(base.getName()); +// if (fr.isLiteral()) +// { +// v.addElement(dir_s + File.separator + base.getName()); +// return; +// } +// fr.dirflag = df; +// String[] sa = dir.list(fr); +// if (sa == null) +// { +// return; +// } +// for (int i = 0; i < sa.length; i++) +// { +// v.addElement(dir_s + File.separator + sa[i]); +// } +// } +// } +// +// /** +// * This method takes a file regular expression, and translates it into the +// * type of pattern used by a normal Regex. +// */ +// public static String toFileRegex(String s) +// { +// StrPos sp = new StrPos(s, 0); +// StringBuffer sb = new StringBuffer(); +// if (sp.incMatch("{?e=")) +// { +// char e = sp.thisChar(); +// sp.inc(); +// if (sp.incMatch("}")) +// { +// sb.append("(?e=" + e + ")^"); +// } +// else +// { +// sb.append("^(?e="); +// } +// sp.esc = e; +// } +// int ParenLvl = 0; +// while (!sp.eos()) +// { +// if (File.separatorChar == '\\') +// { +// if (sp.escaped()) +// { +// sb.append("\\\\"); +// } +// sp.dontMatch = false; +// } +// if (sp.incMatch("?")) +// { +// sb.append("."); +// } +// else if (sp.incMatch(".")) +// { +// sb.append(sp.esc); +// sb.append('.'); +// } +// else if (sp.incMatch("{??")) +// { +// sb.append("(??"); +// ParenLvl++; +// // allow negative lookahead to work +// } +// else if (sp.incMatch("{?!")) +// { +// sb.append("(?!"); +// ParenLvl++; +// // allow positive lookahead to work +// } +// else if (sp.incMatch("{?=")) +// { +// sb.append("(?="); +// ParenLvl++; +// } +// else if (sp.incMatch("{")) +// { +// sb.append("(?:"); +// ParenLvl++; +// } +// else if (sp.incMatch("}")) +// { +// sb.append(')'); +// ParenLvl--; +// } +// else if (ParenLvl != 0 && sp.incMatch(",")) +// { +// sb.append('|'); +// } +// else if (sp.incMatch("*")) +// { +// sb.append(".*"); +// } +// else +// { +// sb.append(sp.thisChar()); +// sp.inc(); +// } +// } +// sb.append("$"); +// return sb.toString(); +// } +// +// public boolean isLiteral() +// { +// Pattern x = thePattern; +// while (x != null && !(x instanceof End)) +// { +// if (x instanceof oneChar) +// { +// ; +// } +// else if (x instanceof Skipped) +// { +// ; +// } +// else +// { +// return false; +// } +// x = x.next; +// } +// return true; +// } } diff --git a/src/com/stevesoft/pat/MessageManager.java b/src/com/stevesoft/pat/MessageManager.java new file mode 100644 index 0000000..d752bba --- /dev/null +++ b/src/com/stevesoft/pat/MessageManager.java @@ -0,0 +1,21 @@ +package com.stevesoft.pat; + +/** + * just a temporary implementation to avoid cross-referencing to jalview. + * @author Bob Hanson + * + */ +public class MessageManager { + + public static String getString(String string) { + return string; + } + + public static String formatMessage(String s, String...fields) { + // just a super super simple implementation to get us rolling + for (int i = 0; i < fields.length; i++) + s += " " + fields[i]; + return s; + } + +} diff --git a/src/com/stevesoft/pat/NonDirFileRegex.java b/src/com/stevesoft/pat/NonDirFileRegex.java index 864243c..a2e1a3e 100755 --- a/src/com/stevesoft/pat/NonDirFileRegex.java +++ b/src/com/stevesoft/pat/NonDirFileRegex.java @@ -13,19 +13,19 @@ package com.stevesoft.pat; */ public class NonDirFileRegex extends FileRegex { - public NonDirFileRegex() - { - dirflag = NONDIR; - } - - public NonDirFileRegex(String fp) - { - super(fp); - dirflag = NONDIR; - } - - public static String[] list(String f) - { - return list(f, NONDIR); - } +// public NonDirFileRegex() +// { +// dirflag = NONDIR; +// } +// +// public NonDirFileRegex(String fp) +// { +// super(fp); +// dirflag = NONDIR; +// } +// +// public static String[] list(String f) +// { +// return list(f, NONDIR); +// } } diff --git a/src/com/stevesoft/pat/Pattern.java b/src/com/stevesoft/pat/Pattern.java index 3a3462c..0ea3f2e 100755 --- a/src/com/stevesoft/pat/Pattern.java +++ b/src/com/stevesoft/pat/Pattern.java @@ -7,7 +7,7 @@ // package com.stevesoft.pat; -import jalview.util.MessageManager; +import com.stevesoft.pat.MessageManager; import java.util.*; @@ -259,12 +259,12 @@ public abstract class Pattern /** * Clones this pattern elements without cloning others in the linked list. */ - Pattern clone1(Hashtable h) + Pattern clone1(Hashtable h) { throw new Error(MessageManager.formatMessage("error.no_such_method_as_clone1_for", new String[]{getClass().getName()})); } - Pattern clone(Hashtable h) + Pattern clone(Hashtable h) { Pattern p = (Pattern) h.get(this); if (p != null) diff --git a/src/com/stevesoft/pat/RegRes.java b/src/com/stevesoft/pat/RegRes.java index a204c47..83a6c62 100755 --- a/src/com/stevesoft/pat/RegRes.java +++ b/src/com/stevesoft/pat/RegRes.java @@ -14,7 +14,7 @@ package com.stevesoft.pat; /** * This class is used to store a result from Regex */ -public class RegRes implements Cloneable +public class RegRes { protected int[] marks = null; @@ -48,20 +48,20 @@ public class RegRes implements Cloneable { int n = i + 1; sb - .append(" sub(" + n + ")=" + matchedFrom(n) + ":" - + charsMatched(n)); + .append(" sub(" + n + ")=" + matchedFromI(n) + ":" + + charsMatchedI(n)); } return sb.toString(); } - public RegRes() - { - } - - public RegRes(RegRes r) - { - copyOutOf(r); - } +// public RegRes() +// { +// } +// +// public RegRes(RegRes r) +// { +// copyOutOf(r); +// } public void copyOutOf(RegRes r) { @@ -91,11 +91,11 @@ public class RegRes implements Cloneable numSubs_ = r.numSubs_; } - public Object clone() - { - return new RegRes(this); - } - +// public Object clone() +// { +// return new RegRes(this); +// } +// public boolean equals(RegRes r) { if (charsMatched_ != r.charsMatched_ || matchFrom_ != r.matchFrom_ @@ -114,11 +114,11 @@ public class RegRes implements Cloneable } for (int i = 1; i <= numSubs_; i++) { - if (matchedFrom(i) != r.matchedFrom(i)) + if (matchedFromI(i) != r.matchedFromI(i)) { return false; } - else if (charsMatched(i) != r.charsMatched(i)) + else if (charsMatchedI(i) != r.charsMatchedI(i)) { return false; } @@ -138,7 +138,7 @@ public class RegRes implements Cloneable * Obtains the position backreference number i begins to match, or -1 if * backreference i was not matched. */ - public int matchedFrom(int i) + public int matchedFromI(int i) { if (marks == null || i > numSubs_) { @@ -153,7 +153,7 @@ public class RegRes implements Cloneable * Obtains the number of characters matched by backreference i, or -1 if * backreference i was not matched. */ - public int charsMatched(int i) + public int charsMatchedI(int i) { if (marks == null || i > numSubs_ || !didMatch_) { @@ -161,15 +161,15 @@ public class RegRes implements Cloneable } // Integer in = (Integer)marks.get("right"+i); // int i2 = in==null ? -1 : in.intValue(); - int mf = matchedFrom(i); - return mf < 0 ? -1 : marks[i + numSubs_] - matchedFrom(i); + int mf = matchedFromI(i); + return mf < 0 ? -1 : marks[i + numSubs_] - matchedFromI(i); } /** * This is either equal to matchedFrom(i)+charsMatched(i) if the match was * successful, or -1 if it was not. */ - public int matchedTo(int i) + public int matchedToI(int i) { if (marks == null || i > numSubs_ || !didMatch_) { @@ -182,9 +182,9 @@ public class RegRes implements Cloneable * Obtains a substring matching the nth set of parenthesis from the pattern. * See numSubs(void), or null if the nth backrefence did not match. */ - public String stringMatched(int i) + public String stringMatchedI(int i) { - int mf = matchedFrom(i), cm = charsMatched(i); + int mf = matchedFromI(i), cm = charsMatchedI(i); return !didMatch_ || mf < 0 || cm < 0 ? null : src.substring(mf, mf + cm); } @@ -203,9 +203,9 @@ public class RegRes implements Cloneable * This returns the part of the string that follows the ith backreference, or * null if the backreference did not match. */ - public String left(int i) + public String leftI(int i) { - int mf = matchedFrom(i); + int mf = matchedFromI(i); return !didMatch_ || (mf < 0) ? null : src.substring(0, mf); } @@ -224,9 +224,9 @@ public class RegRes implements Cloneable * This returns the string to the right of the ith backreference, or null if * the backreference did not match. */ - public String right(int i) + public String rightI(int i) { - int mf = matchedFrom(i), cm = charsMatched(i); + int mf = matchedFromI(i), cm = charsMatchedI(i); return !didMatch_ || mf < 0 || cm < 0 ? null : src.substring(mf + cm, src.length()); } @@ -286,14 +286,14 @@ public class RegRes implements Cloneable } /** An older name for matchedFrom. */ - public int matchFrom(int i) + public int matchFromI(int i) { - return matchedFrom(i); + return matchedFromI(i); } /** An older name for stringMatched. */ - public String substring(int i) + public String substringI(int i) { - return stringMatched(i); + return stringMatchedI(i); } } diff --git a/src/com/stevesoft/pat/Regex.java b/src/com/stevesoft/pat/Regex.java index 861c33b..5b788f2 100755 --- a/src/com/stevesoft/pat/Regex.java +++ b/src/com/stevesoft/pat/Regex.java @@ -7,12 +7,15 @@ // package com.stevesoft.pat; -import jalview.util.MessageManager; +import com.stevesoft.pat.MessageManager; -import java.io.*; -import java.util.*; +import jalview.jsdev.api.RegExpInterface; -import com.stevesoft.pat.wrap.*; +import java.io.File; +import java.util.BitSet; +import java.util.Hashtable; + +import com.stevesoft.pat.wrap.StringWrap; /** Matches a Unicode punctuation character. */ class UnicodePunct extends UniValidator @@ -169,7 +172,7 @@ class UnicodeUpper extends UniValidator final boolean isUpper(char c) { - return c == CaseMgr.toUpperCase(c) && c != CaseMgr.toLowerCase(c); + return c == CaseMgr.toUpperCaseC(c) && c != CaseMgr.toLowerCaseC(c); } } @@ -183,7 +186,7 @@ class UnicodeLower extends UniValidator final boolean isLower(char c) { - return c != CaseMgr.toUpperCase(c) && c == CaseMgr.toLowerCase(c); + return c != CaseMgr.toUpperCaseC(c) && c == CaseMgr.toLowerCaseC(c); } } @@ -284,7 +287,7 @@ class UnicodeLower extends UniValidator * @version package com.stevesoft.pat, release 1.5.3 * @see Pattern */ -public class Regex extends RegRes implements FilenameFilter +public class Regex extends RegRes implements RegExpInterface, Cloneable //implements FilenameFilter { /** * BackRefOffset gives the identity number of the first pattern. Version 1.0 @@ -298,25 +301,132 @@ public class Regex extends RegRes implements FilenameFilter patInt minMatch = new patInt(0); - static Hashtable validators = new Hashtable(); + static Hashtable validators = new Hashtable(); static { - define("p", "(?>1)", new UnicodePunct()); - define("P", "(?>1)", new NUnicodePunct()); - define("s", "(?>1)", new UnicodeWhite()); - define("S", "(?>1)", new NUnicodeWhite()); - define("w", "(?>1)", new UnicodeW()); - define("W", "(?>1)", new NUnicodeW()); - define("d", "(?>1)", new UnicodeDigit()); - define("D", "(?>1)", new NUnicodeDigit()); - define("m", "(?>1)", new UnicodeMath()); - define("M", "(?>1)", new NUnicodeMath()); - define("c", "(?>1)", new UnicodeCurrency()); - define("C", "(?>1)", new NUnicodeCurrency()); - define("a", "(?>1)", new UnicodeAlpha()); - define("A", "(?>1)", new NUnicodeAlpha()); - define("uc", "(?>1)", new UnicodeUpper()); - define("lc", "(?>1)", new UnicodeLower()); + defineV("p", "(?>1)", new UnicodePunct()); + defineV("P", "(?>1)", new NUnicodePunct()); + defineV("s", "(?>1)", new UnicodeWhite()); + defineV("S", "(?>1)", new NUnicodeWhite()); + defineV("w", "(?>1)", new UnicodeW()); + defineV("W", "(?>1)", new NUnicodeW()); + defineV("d", "(?>1)", new UnicodeDigit()); + defineV("D", "(?>1)", new NUnicodeDigit()); + defineV("m", "(?>1)", new UnicodeMath()); + defineV("M", "(?>1)", new NUnicodeMath()); + defineV("c", "(?>1)", new UnicodeCurrency()); + defineV("C", "(?>1)", new NUnicodeCurrency()); + defineV("a", "(?>1)", new UnicodeAlpha()); + defineV("A", "(?>1)", new NUnicodeAlpha()); + defineV("uc", "(?>1)", new UnicodeUpper()); + defineV("lc", "(?>1)", new UnicodeLower()); + } + + ReplaceRule rep = null; + + + /** + * Initializes the object without a Pattern. To supply a Pattern use + * compile(String s). + * + * @j2sIgnore + * + * @see com.stevesoft.pat.Regex#compile(java.lang.String) + */ + @Deprecated + public Regex() + { + } + + /** + * Create and compile both a Regex and a ReplaceRule. + * + * @see com.stevesoft.pat.ReplaceRule + * @see com.stevesoft.pat.Regex#compile(java.lang.String) + */ + public Regex(String s, String strRp) + { + try + { + if (s != null) + compile(s); + if (strRp.length() > 0) + rep = ReplaceRule.perlCode(strRp); + } catch (RegSyntax rs) + { + } + } + + /** + * Create and compile a Regex, but give it the ReplaceRule specified. This + * allows the user finer control of the Replacement process, if that is + * desired. + * + * @j2sIgnore + * + * @see com.stevesoft.pat.ReplaceRule + * @see com.stevesoft.pat.Regex#compile(java.lang.String) + */ + public Regex(String s, ReplaceRule rp) + { + this(s, ""); + rep = rp; + } + + /** + * Create and compile a Regex, but do not throw any exceptions. If you wish to + * have exceptions thrown for syntax errors, you must use the Regex(void) + * constructor to create the Regex object, and then call the compile method. + * Therefore, you should only call this method when you know your pattern is + * right. I will probably become more like + * + * @j2sIgnore + * + * @see com.stevesoft.pat.Regex#search(java.lang.String) + * @see com.stevesoft.pat.Regex#compile(java.lang.String) + */ + @Deprecated + public Regex(String s) + { + this(s, ""); + } + + /** A clone by any other name would smell as sweet. */ + public Object clone() + { + return new Regex(null, "").cloneFrom(this); + } + +// /** Return a clone of the underlying RegRes object. */ +// public RegRes result() +// { +// return (RegRes) super.clone(); +// } + + /** Essentially clones the Regex object */ + public Regex cloneFrom(Regex r) + { + copyOutOf(r); +// super((RegRes) r); + dontMatchInQuotes = r.dontMatchInQuotes; + esc = r.esc; + ignoreCase = r.ignoreCase; + gFlag = r.gFlag; + if (r.rep == null) + { + rep = null; + } + else + { + rep = (ReplaceRule) r.rep.clone(); + } + /* + * try { compile(r.toString()); } catch(RegSyntax r_) {} + */ + thePattern = r.thePattern.clone(new Hashtable()); + minMatch = r.minMatch; + skipper = r.skipper; + return this; } /** Set the dontMatch in quotes flag. */ @@ -374,68 +484,10 @@ public class Regex extends RegRes implements FilenameFilter } /** - * Initializes the object without a Pattern. To supply a Pattern use - * compile(String s). - * - * @see com.stevesoft.pat.Regex#compile(java.lang.String) - */ - public Regex() - { - } - - /** - * Create and compile a Regex, but do not throw any exceptions. If you wish to - * have exceptions thrown for syntax errors, you must use the Regex(void) - * constructor to create the Regex object, and then call the compile method. - * Therefore, you should only call this method when you know your pattern is - * right. I will probably become more like - * - * @see com.stevesoft.pat.Regex#search(java.lang.String) - * @see com.stevesoft.pat.Regex#compile(java.lang.String) - */ - public Regex(String s) - { - try - { - compile(s); - } catch (RegSyntax rs) - { - } - } - - ReplaceRule rep = null; - - /** - * Create and compile both a Regex and a ReplaceRule. - * - * @see com.stevesoft.pat.ReplaceRule - * @see com.stevesoft.pat.Regex#compile(java.lang.String) - */ - public Regex(String s, String rp) - { - this(s); - rep = ReplaceRule.perlCode(rp); - } - - /** - * Create and compile a Regex, but give it the ReplaceRule specified. This - * allows the user finer control of the Replacement process, if that is - * desired. - * - * @see com.stevesoft.pat.ReplaceRule - * @see com.stevesoft.pat.Regex#compile(java.lang.String) - */ - public Regex(String s, ReplaceRule rp) - { - this(s); - rep = rp; - } - - /** * Change the ReplaceRule of this Regex by compiling a new one using String * rp. */ - public void setReplaceRule(String rp) + public void setReplaceRuleStr(String rp) { rep = ReplaceRule.perlCode(rp); repr = null; // Clear Replacer history @@ -450,7 +502,7 @@ public class Regex extends RegRes implements FilenameFilter /** * Test to see if a custom defined rule exists. * - * @see com.stevesoft.pat#define(java.lang.String,java.lang.String,Validator) + * @see com.stevesoft.pat#defineV(java.lang.String,java.lang.String,Validator) */ public static boolean isDefined(String nm) { @@ -460,7 +512,7 @@ public class Regex extends RegRes implements FilenameFilter /** * Removes a custom defined rule. * - * @see com.stevesoft.pat#define(java.lang.String,java.lang.String,Validator) + * @see com.stevesoft.pat#defineV(java.lang.String,java.lang.String,Validator) */ public static void undefine(String nm) { @@ -471,7 +523,7 @@ public class Regex extends RegRes implements FilenameFilter * Defines a method to create a new rule. See test/deriv2.java and * test/deriv3.java for examples of how to use it. */ - public static void define(String nm, String pat, Validator v) + public static void defineV(String nm, String pat, Validator v) { v.pattern = pat; validators.put(nm, v); @@ -562,7 +614,7 @@ public class Regex extends RegRes implements FilenameFilter .toString(); } - public StringLike replaceAll(StringLike s) + public StringLike replaceAllLike(StringLike s) { return _getReplacer().replaceAllRegion(s, this, 0, s.length()); } @@ -592,30 +644,6 @@ public class Regex extends RegRes implements FilenameFilter return _getReplacer().replaceAllRegion(s, this, start, end).toString(); } - /** Essentially clones the Regex object */ - public Regex(Regex r) - { - super((RegRes) r); - dontMatchInQuotes = r.dontMatchInQuotes; - esc = r.esc; - ignoreCase = r.ignoreCase; - gFlag = r.gFlag; - if (r.rep == null) - { - rep = null; - } - else - { - rep = (ReplaceRule) r.rep.clone(); - } - /* - * try { compile(r.toString()); } catch(RegSyntax r_) {} - */ - thePattern = r.thePattern.clone(new Hashtable()); - minMatch = r.minMatch; - skipper = r.skipper; - } - /** * By default, the escape character is the backslash, but you can make it * anything you want by setting this variable. @@ -690,18 +718,6 @@ public class Regex extends RegRes implements FilenameFilter } } - /** A clone by any other name would smell as sweet. */ - public Object clone() - { - return new Regex(this); - } - - /** Return a clone of the underlying RegRes object. */ - public RegRes result() - { - return (RegRes) super.clone(); - } - // prep sets global variables of class // Pattern so that it can access them // during an attempt at a match @@ -762,9 +778,9 @@ public class Regex extends RegRes implements FilenameFilter * * @see com.stevesoft.pat.Regex#search */ - public boolean matchAt(StringLike s, int start_pos) + public boolean matchAtLike(StringLike s, int start_pos) { - return _search(s, start_pos, start_pos); + return _searchLike(s, start_pos, start_pos); } /** @@ -782,13 +798,13 @@ public class Regex extends RegRes implements FilenameFilter return _search(s, 0, s.length()); } - public boolean search(StringLike sl) + public boolean searchLike(StringLike sl) { if (sl == null) { throw new NullPointerException(MessageManager.getString("exception.null_string_like_given_to_regex_search")); } - return _search(sl, 0, sl.length()); + return _searchLike(sl, 0, sl.length()); } public boolean reverseSearch(String s) @@ -800,13 +816,13 @@ public class Regex extends RegRes implements FilenameFilter return _reverseSearch(s, 0, s.length()); } - public boolean reverseSearch(StringLike sl) + public boolean reverseSearchLike(StringLike sl) { if (sl == null) { throw new NullPointerException(MessageManager.getString("exception.null_string_like_given_to_regex_reverse_search")); } - return _reverseSearch(sl, 0, sl.length()); + return _reverseSearchLike(sl, 0, sl.length()); } /** @@ -826,13 +842,13 @@ public class Regex extends RegRes implements FilenameFilter return _search(s, start, s.length()); } - public boolean searchFrom(StringLike s, int start) + public boolean searchFromLike(StringLike s, int start) { if (s == null) { throw new NullPointerException(MessageManager.getString("exception.null_string_like_given_to_regex_search_from")); } - return _search(s, start, s.length()); + return _searchLike(s, start, s.length()); } /** @@ -889,10 +905,10 @@ public class Regex extends RegRes implements FilenameFilter final boolean _search(String s, int start, int end) { - return _search(new StringWrap(s), start, end); + return _searchLike(new StringWrap(s), start, end); } - final boolean _search(StringLike s, int start, int end) + final boolean _searchLike(StringLike s, int start, int end) { if (gFlag && gFlagto > 0 && gFlags != null && s.unwrap() == gFlags.unwrap()) @@ -974,10 +990,10 @@ public class Regex extends RegRes implements FilenameFilter boolean _reverseSearch(String s, int start, int end) { - return _reverseSearch(new StringWrap(s), start, end); + return _reverseSearchLike(new StringWrap(s), start, end); } - boolean _reverseSearch(StringLike s, int start, int end) + boolean _reverseSearchLike(StringLike s, int start, int end) { if (gFlag && gFlagto > 0 && s.unwrap() == gFlags.unwrap()) { @@ -1054,21 +1070,21 @@ public class Regex extends RegRes implements FilenameFilter lasts = s; } - // Wanted user to over-ride this in alpha version, - // but it wasn't really necessary because of this trick: - Regex newRegex() - { - try - { - return (Regex) getClass().newInstance(); - } catch (InstantiationException ie) - { - return null; - } catch (IllegalAccessException iae) - { - return null; - } - } +// // Wanted user to over-ride this in alpha version, +// // but it wasn't really necessary because of this trick: +// Regex newRegex() +// { +// try +// { +// return (Regex) getClass().newInstance(); +// } catch (InstantiationException ie) +// { +// return null; +// } catch (IllegalAccessException iae) +// { +// return null; +// } +// } /** * Only needed for creating your own extensions of Regex. This method adds the @@ -1100,7 +1116,7 @@ public class Regex extends RegRes implements FilenameFilter * is thrown when a nonsensensical pattern is supplied. For * example, a pattern beginning with *. */ - protected void compile1(StrPos sp, Rthings mk) throws RegSyntax + protected void compileSP(StrPos sp, Rthings mk) throws RegSyntax { if (sp.match('[')) { @@ -1235,7 +1251,7 @@ public class Regex extends RegRes implements FilenameFilter } else if (sp.dontMatch && sp.c == 'B') { - Regex r = new Regex(); + Regex r = new Regex(null, ""); r._compile("(?!" + back_slash + "b)", mk); add(r.thePattern); } @@ -1306,7 +1322,7 @@ public class Regex extends RegRes implements FilenameFilter if (validators.get(sbs) instanceof String) { String pat = (String) validators.get(sbs); - Regex r = newRegex(); + Regex r = new Regex(null, ""); Rthings rth = new Rthings(this); rth.noBackRefs = true; r._compile(pat, rth); @@ -1325,7 +1341,7 @@ public class Regex extends RegRes implements FilenameFilter cm.v = v2; v2.pattern = p; } - Regex r = newRegex(); + Regex r = new Regex(null, ""); Rthings rth = new Rthings(this); rth.noBackRefs = true; r._compile(cm.v.pattern, rth); @@ -1339,7 +1355,7 @@ public class Regex extends RegRes implements FilenameFilter else if (sp.match('(')) { mk.parenLevel++; - Regex r = newRegex(); + Regex r = new Regex(null, ""); // r.or = new Or(); sp.inc(); if (sp.incMatch("?:")) @@ -1398,7 +1414,7 @@ public class Regex extends RegRes implements FilenameFilter } if (r != null) { - add(r._compile(sp, mk)); + add(r._compileSP(sp, mk)); } } else if (sp.match('^')) @@ -1534,7 +1550,7 @@ public class Regex extends RegRes implements FilenameFilter minMatch = null; sFlag = mFlag = ignoreCase = gFlag = false; StrPos sp = new StrPos(pat, 0); - thePattern = _compile(sp, mk); + thePattern = _compileSP(sp, mk); pt.marks = null; return thePattern; } @@ -1543,11 +1559,11 @@ public class Regex extends RegRes implements FilenameFilter Or or = null; - Pattern _compile(StrPos sp, Rthings mk) throws RegSyntax + Pattern _compileSP(StrPos sp, Rthings mk) throws RegSyntax { while (!(sp.eos || (or != null && sp.match(')')))) { - compile1(sp, mk); + compileSP(sp, mk); sp.inc(); } if (sp.match(')')) @@ -1786,11 +1802,11 @@ public class Regex extends RegRes implements FilenameFilter */ public String toString() { - if (false && thePattern == null) - { - return ""; - } - else +// if (false && thePattern == null) +// { +// return ""; +// } +// else { StringBuffer sb = new StringBuffer(); if (esc != Pattern.ESC) @@ -1927,7 +1943,7 @@ public class Regex extends RegRes implements FilenameFilter } minMatch = new patInt(0); // thePattern.countMinChars(); thePattern = RegOpt.opt(thePattern, ignoreCase, dontMatchInQuotes); - skipper = Skip.findSkip(this); + skipper = Skip.findSkipRegex(this); // RegOpt.setParents(this); return; } diff --git a/src/com/stevesoft/pat/RegexReader.java b/src/com/stevesoft/pat/RegexReader.java index 2e10f16..c89139a 100755 --- a/src/com/stevesoft/pat/RegexReader.java +++ b/src/com/stevesoft/pat/RegexReader.java @@ -95,7 +95,7 @@ public class RegexReader extends Reader { readData(); } - else if (rp.getRegex().matchAt(wrap, rb.epos)) + else if (rp.getRegex().matchAtLike(wrap, rb.epos)) { if (wrap.overRun) { diff --git a/src/com/stevesoft/pat/RegexTokenizer.java b/src/com/stevesoft/pat/RegexTokenizer.java index 0378f3a..1913124 100755 --- a/src/com/stevesoft/pat/RegexTokenizer.java +++ b/src/com/stevesoft/pat/RegexTokenizer.java @@ -47,9 +47,9 @@ public class RegexTokenizer implements Enumeration { if (r.substring() != null) { - v.addElement(r.substring(i + offset)); - vi.addElement(new Integer(r.matchFrom(i + offset) - + r.charsMatched(i + offset))); + v.addElement(r.substringI(i + offset)); + vi.addElement(new Integer(r.matchFromI(i + offset) + + r.charsMatchedI(i + offset))); } } pos = r.matchFrom() + r.charsMatched(); @@ -64,7 +64,7 @@ public class RegexTokenizer implements Enumeration public RegexTokenizer(String txt, String ptrn) { toParse = txt; - r = new Regex(ptrn); + r = new Regex(ptrn, ""); offset = Regex.BackRefOffset; getMore(); } diff --git a/src/com/stevesoft/pat/RegexWriter.java b/src/com/stevesoft/pat/RegexWriter.java index 61bcdf6..6f23545 100755 --- a/src/com/stevesoft/pat/RegexWriter.java +++ b/src/com/stevesoft/pat/RegexWriter.java @@ -123,7 +123,7 @@ public class RegexWriter extends Writer { Regex rex = repr.getRegex(); int eposOld = epos; - if (rex.matchAt(wrap, epos) && !wrap.overRun) + if (rex.matchAtLike(wrap, epos) && !wrap.overRun) { while (pos < epos) { diff --git a/src/com/stevesoft/pat/ReplaceRule.java b/src/com/stevesoft/pat/ReplaceRule.java index bf56143..4805ed4 100755 --- a/src/com/stevesoft/pat/ReplaceRule.java +++ b/src/com/stevesoft/pat/ReplaceRule.java @@ -93,7 +93,7 @@ public abstract class ReplaceRule static Regex getvar = null; - final static Regex getv() + private static Regex getv() { // Thanks to Michael Jimenez for pointing out the need // to clone getvar rather than simply returning it. @@ -113,7 +113,7 @@ public abstract class ReplaceRule "\\\\c([\u0000-\uFFFF])|" + // ref 8 "\\\\x([A-Fa-f0-9]{2})|" + // ref 9 "\\\\([\u0000-\uFFFF])" + // ref 10 - ")"); + ")", ""); getvar.optimize(); return getvar; } @@ -142,9 +142,9 @@ public abstract class ReplaceRule head = add(head, new StringRule(s.substring(mt, mf))); } String var = null; - if ((var = gv.stringMatched(1 + off)) != null - || (var = gv.stringMatched(2 + off)) != null - || (var = gv.stringMatched(5 + off)) != null) + if ((var = gv.stringMatchedI(1 + off)) != null + || (var = gv.stringMatchedI(2 + off)) != null + || (var = gv.stringMatchedI(5 + off)) != null) { int d = 0; for (int i = 0; i < var.length(); i++) @@ -160,7 +160,7 @@ public abstract class ReplaceRule head = new StringRule("" + (char) d); } } - else if ((var = gv.stringMatched(10 + off)) != null) + else if ((var = gv.stringMatchedI(10 + off)) != null) { if ("QELlUu".indexOf(var) >= 0) { @@ -171,9 +171,9 @@ public abstract class ReplaceRule head = add(head, new StringRule(var)); } } - else if ((var = gv.stringMatched(3 + off)) != null - || (var = gv.stringMatched(4 + off)) != null - || (var = gv.stringMatched(6 + off)) != null) + else if ((var = gv.stringMatchedI(3 + off)) != null + || (var = gv.stringMatchedI(4 + off)) != null + || (var = gv.stringMatchedI(6 + off)) != null) { String arg = ""; int pc; @@ -255,7 +255,7 @@ public abstract class ReplaceRule head = add(head, new StringRule("${" + var + "}")); } } - else if ((var = gv.stringMatched(7 + off)) != null) + else if ((var = gv.stringMatchedI(7 + off)) != null) { char c = var.charAt(0); if (c == 'n') @@ -287,7 +287,7 @@ public abstract class ReplaceRule head = add(head, new StringRule("" + (char) 12)); } } - else if ((var = gv.stringMatched(8 + off)) != null) + else if ((var = gv.stringMatchedI(8 + off)) != null) { char c = var.charAt(0); if (c < Ctrl.cmap.length) @@ -296,7 +296,7 @@ public abstract class ReplaceRule } head = add(head, new StringRule("" + c)); } - else if ((var = gv.stringMatched(9 + off)) != null) + else if ((var = gv.stringMatchedI(9 + off)) != null) { int d = 16 * getHexDigit(var.charAt(0)) + getHexDigit(var.charAt(1)); diff --git a/src/com/stevesoft/pat/Replacer.java b/src/com/stevesoft/pat/Replacer.java index b886f6a..ce512a5 100755 --- a/src/com/stevesoft/pat/Replacer.java +++ b/src/com/stevesoft/pat/Replacer.java @@ -7,7 +7,7 @@ // package com.stevesoft.pat; -import jalview.util.MessageManager; +import com.stevesoft.pat.MessageManager; import com.stevesoft.pat.wrap.*; @@ -182,7 +182,7 @@ public class Replacer { throw new NullPointerException(MessageManager.getString("exception.replace_null_regex_pointer")); } - if (rh.me._search(s, start, end)) + if (rh.me._searchLike(s, start, end)) { int rmn = rh.me.matchedTo(); if (rh.me.charsMatched() == 0 && !isSpecial(rh.me.getReplaceRule())) @@ -193,7 +193,7 @@ public class Replacer apply(rh.me); if (!first) { - for (int i = rmn; !want_more_text && rh.me._search(s, i, end); i = rmn) + for (int i = rmn; !want_more_text && rh.me._searchLike(s, i, end); i = rmn) { rmn = rh.me.matchedTo(); if (rh.me.charsMatched() == 0) @@ -245,7 +245,7 @@ public class Replacer int rmf = r.matchedFrom(); for (int ii = pos; ii < rmf; ii++) { - sb.append(src.charAt(ii)); + sb.appendC(src.charAt(ii)); } for (ReplaceRule x = rp; x != null; x = x.next) @@ -315,7 +315,7 @@ public class Replacer int s_end = src.length(); for (int ii = pos; ii < s_end; ii++) { - sb.append(src.charAt(ii)); + sb.appendC(src.charAt(ii)); } src = null; lastMatchedTo = pos; diff --git a/src/com/stevesoft/pat/Skip.java b/src/com/stevesoft/pat/Skip.java index d3f3822..c3e05f8 100755 --- a/src/com/stevesoft/pat/Skip.java +++ b/src/com/stevesoft/pat/Skip.java @@ -20,8 +20,8 @@ public class Skip static int mkmask(int c) { char x = (char) c; - return ~(CaseMgr.toUpperCase(x) | CaseMgr.toLowerCase(x) | CaseMgr - .toTitleCase(x)); + return ~(CaseMgr.toUpperCaseC(x) | CaseMgr.toLowerCaseC(x) | CaseMgr + .toTitleCaseC(x)); } String src; @@ -102,7 +102,7 @@ public class Skip if (0 == (s.charAt(i) & mask)) { // if(m1||s.regionMatches(ign,i,src,0,src.length()) ) - if (m1 || CaseMgr.regionMatches(s, ign, i, src, 0, src.length())) + if (m1 || CaseMgr.regionMatchesLike2(s, ign, i, src, 0, src.length())) { return i - offset; } @@ -116,7 +116,7 @@ public class Skip if (c == s.charAt(i)) { // if(m1||s.regionMatches(ign,i,src,0,src.length()) ) - if (m1 || CaseMgr.regionMatches(s, ign, i, src, 0, src.length())) + if (m1 || CaseMgr.regionMatchesLike2(s, ign, i, src, 0, src.length())) { return i - offset; } @@ -126,7 +126,7 @@ public class Skip return -1; } - static Skip findSkip(Regex r) + static Skip findSkipRegex(Regex r) { return findSkip(r.thePattern, r.ignoreCase, !r.dontMatchInQuotes); } diff --git a/src/com/stevesoft/pat/Skip2.java b/src/com/stevesoft/pat/Skip2.java index 5f6bb5a..b498a3e 100755 --- a/src/com/stevesoft/pat/Skip2.java +++ b/src/com/stevesoft/pat/Skip2.java @@ -46,7 +46,7 @@ public class Skip2 extends Skip if (0 == (s.charAt(i) & mask) && 0 == (s.charAt(i + 1) & mask1)) { // if(m1||s.regionMatches(ign,i,src,0,src.length()) ) - if (m1 || CaseMgr.regionMatches(s, ign, i, src, 0, src.length())) + if (m1 || CaseMgr.regionMatchesLike2(s, ign, i, src, 0, src.length())) { return i - offset; } diff --git a/src/com/stevesoft/pat/SkipBMH.java b/src/com/stevesoft/pat/SkipBMH.java index 1397b90..8529fdb 100755 --- a/src/com/stevesoft/pat/SkipBMH.java +++ b/src/com/stevesoft/pat/SkipBMH.java @@ -67,9 +67,9 @@ public class SkipBMH extends Skip sm1 = src.length() - 1; x = src.charAt(sm1); - uc = CaseMgr.toUpperCase(x); - lc = CaseMgr.toLowerCase(x); - tc = CaseMgr.toTitleCase(x); + uc = CaseMgr.toUpperCaseC(x); + lc = CaseMgr.toLowerCaseC(x); + tc = CaseMgr.toTitleCaseC(x); // We don't really want 65536 long arrays in skip[], // so we mask of the higher bits. This can be combined @@ -80,9 +80,9 @@ public class SkipBMH extends Skip char x_ = src.charAt(k); if (ign) { - char uc_ = CaseMgr.toUpperCase(x_); - char lc_ = CaseMgr.toLowerCase(x_); - char tc_ = CaseMgr.toTitleCase(x_); + char uc_ = CaseMgr.toUpperCaseC(x_); + char lc_ = CaseMgr.toLowerCaseC(x_); + char tc_ = CaseMgr.toTitleCaseC(x_); skip[uc_ & (MAX_CHAR - 1)] = (char) (src.length() - k - 1); skip[lc_ & (MAX_CHAR - 1)] = (char) (src.length() - k - 1); skip[tc_ & (MAX_CHAR - 1)] = (char) (src.length() - k - 1); @@ -139,7 +139,7 @@ public class SkipBMH extends Skip // table look-up is expensive, avoid it if possible if (anyc(s.charAt(k))) { - if (CaseMgr.regionMatches(src, ign, 0, s, k - sm1, sm1)) + if (CaseMgr.regionMatches2(src, ign, 0, s, k - sm1, sm1)) { return k - sm1 - offset; } @@ -151,7 +151,7 @@ public class SkipBMH extends Skip // table look-up is expensive, avoid it if possible if (anyc(s.charAt(k))) { - if (CaseMgr.regionMatches(src, ign, 0, s, k - sm1, sm1)) + if (CaseMgr.regionMatches2(src, ign, 0, s, k - sm1, sm1)) { return k - sm1 - offset; } @@ -171,7 +171,7 @@ public class SkipBMH extends Skip if (x == s.charAt(k)) { // if(src.regionMatches(0,s,k-sm1,sm1)) - if (CaseMgr.regionMatches(src, false, 0, s, k - sm1, sm1)) + if (CaseMgr.regionMatches2(src, false, 0, s, k - sm1, sm1)) { return k - sm1 - offset; } @@ -184,7 +184,7 @@ public class SkipBMH extends Skip if (x == s.charAt(k)) { // if(src.regionMatches(0,s,k-sm1,sm1)) - if (CaseMgr.regionMatches(src, false, 0, s, k - sm1, sm1)) + if (CaseMgr.regionMatches2(src, false, 0, s, k - sm1, sm1)) { return k - sm1 - offset; } diff --git a/src/com/stevesoft/pat/StringBufferLike.java b/src/com/stevesoft/pat/StringBufferLike.java index d125758..b4bada8 100755 --- a/src/com/stevesoft/pat/StringBufferLike.java +++ b/src/com/stevesoft/pat/StringBufferLike.java @@ -32,7 +32,7 @@ public class StringBufferLike implements BasicStringBufferLike return sbl.toString(); } - public void append(char c) + public void appendC(char c) { switch (mode) @@ -41,13 +41,13 @@ public class StringBufferLike implements BasicStringBufferLike mode = altMode; altMode = ' '; case 'U': - sbl.append(CaseMgr.toUpperCase(c)); + sbl.appendC(CaseMgr.toUpperCaseC(c)); break; case 'l': mode = altMode; altMode = ' '; case 'L': - sbl.append(CaseMgr.toLowerCase(c)); + sbl.appendC(CaseMgr.toLowerCaseC(c)); break; case 'Q': if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') @@ -57,10 +57,10 @@ public class StringBufferLike implements BasicStringBufferLike } else { - sbl.append('\\'); + sbl.appendC('\\'); } default: - sbl.append(c); + sbl.appendC(c); break; } } @@ -69,7 +69,7 @@ public class StringBufferLike implements BasicStringBufferLike { for (int i = 0; i < s.length(); i++) { - append(s.charAt(i)); + appendC(s.charAt(i)); } } diff --git a/src/com/stevesoft/pat/Transformer.java b/src/com/stevesoft/pat/Transformer.java index 84a3a46..b041aac 100755 --- a/src/com/stevesoft/pat/Transformer.java +++ b/src/com/stevesoft/pat/Transformer.java @@ -7,9 +7,7 @@ // package com.stevesoft.pat; -import jalview.util.MessageManager; - -import com.stevesoft.pat.wrap.*; +import com.stevesoft.pat.wrap.StringWrap; /** * Replacement rule used by the Transformer. @@ -64,7 +62,7 @@ public class Transformer { TransPat tp; - Regex rp = new Regex(); + Regex rp; boolean auto_optimize; @@ -81,6 +79,7 @@ public class Transformer /** Instantiate a new Transformer object. */ public Transformer(boolean auto) { + rp = new Regex(null, ""); auto_optimize = auto; tp = new TransPat(); rp.setReplaceRule(new TransRepRule(this)); diff --git a/src/com/stevesoft/pat/Util.java b/src/com/stevesoft/pat/Util.java new file mode 100644 index 0000000..88b01eb --- /dev/null +++ b/src/com/stevesoft/pat/Util.java @@ -0,0 +1,13 @@ +// +// This software is now distributed according to +// the Lesser Gnu Public License. Please see +// http://www.gnu.org/copyleft/lesser.txt for +// the details. +// -- Happy Computing! +// +package com.stevesoft.pat; + + +public abstract class Util +{ +} diff --git a/src/com/stevesoft/pat/Validator.java b/src/com/stevesoft/pat/Validator.java index dbedca5..de45f6c 100755 --- a/src/com/stevesoft/pat/Validator.java +++ b/src/com/stevesoft/pat/Validator.java @@ -31,7 +31,7 @@ public class Validator * * By default, this method just returns end and thus does nothing. * - * @see com.stevesoft.pat.Regex#define(java.lang.String,java.lang.String,com.stevesoft.pat.Validator) + * @see com.stevesoft.pat.Regex#defineV(java.lang.String,java.lang.String,com.stevesoft.pat.Validator) */ public int validate(StringLike src, int start, int end) { diff --git a/src/com/stevesoft/pat/oneChar.java b/src/com/stevesoft/pat/oneChar.java index ebbe991..d2ac38d 100755 --- a/src/com/stevesoft/pat/oneChar.java +++ b/src/com/stevesoft/pat/oneChar.java @@ -20,9 +20,9 @@ class oneChar extends Pattern { c = ci; char cu, cl, ct; - cu = CaseMgr.toUpperCase(c); - cl = CaseMgr.toLowerCase(c); - ct = CaseMgr.toTitleCase(c); + cu = CaseMgr.toUpperCaseC(c); + cl = CaseMgr.toLowerCaseC(c); + ct = CaseMgr.toTitleCaseC(c); if (c == cu) { altc = cl; diff --git a/src/com/stevesoft/pat/parsePerl.java b/src/com/stevesoft/pat/parsePerl.java index 0d1f14e..db842c3 100755 --- a/src/com/stevesoft/pat/parsePerl.java +++ b/src/com/stevesoft/pat/parsePerl.java @@ -45,10 +45,10 @@ class parsePerl final public static String codify(String s, boolean keepbs) { - return codify(s, 0, s.length(), keepbs); + return codifyRange(s, 0, s.length(), keepbs); } - final public static String codify(String s, int i0, int iN, boolean keepbs) + final public static String codifyRange(String s, int i0, int iN, boolean keepbs) { StringBuffer sb = new StringBuffer(); boolean ucmode = false, lcmode = false, litmode = false; @@ -133,12 +133,12 @@ class parsePerl final static char uc(char c) { - return CaseMgr.toUpperCase(c); + return CaseMgr.toUpperCaseC(c); } final static char lc(char c) { - return CaseMgr.toLowerCase(c); + return CaseMgr.toLowerCaseC(c); } final static boolean needbs(char c) @@ -303,7 +303,7 @@ class parsePerl return null; } } - Regex r = new Regex(); + Regex r = new Regex(null, ""); try { String pat = s1.toString(), reprul = s2.toString(); diff --git a/src/com/stevesoft/pat/wrap/CharArrayBufferWrap.java b/src/com/stevesoft/pat/wrap/CharArrayBufferWrap.java index c014a57..f82ccd2 100755 --- a/src/com/stevesoft/pat/wrap/CharArrayBufferWrap.java +++ b/src/com/stevesoft/pat/wrap/CharArrayBufferWrap.java @@ -17,7 +17,7 @@ public class CharArrayBufferWrap implements BasicStringBufferLike { StringBuffer sb = new StringBuffer(); - public void append(char c) + public void appendC(char c) { sb.append(c); } diff --git a/src/com/stevesoft/pat/wrap/RandomAccessFileWrap.java b/src/com/stevesoft/pat/wrap/RandomAccessFileWrap.java index f5b61ab..2ab5a95 100755 --- a/src/com/stevesoft/pat/wrap/RandomAccessFileWrap.java +++ b/src/com/stevesoft/pat/wrap/RandomAccessFileWrap.java @@ -7,169 +7,164 @@ // package com.stevesoft.pat.wrap; -import jalview.util.MessageManager; - -import java.io.*; - -import com.stevesoft.pat.*; /** * Provides a wrapper for a RandomAccessFile so that it can be searched by * Regex. */ -public class RandomAccessFileWrap implements StringLike +public class RandomAccessFileWrap //implements StringLike { - - long offset = 0; - - public void setOffset(long o) - { - offset = o; - i0 = iend = 0; - } - - public long getOffset() - { - return offset; - } - - RandomAccessFile raf; - - int i0 = 0, iend = 0; - - byte[] buf = new byte[1024]; - - public int getBufferSize() - { - return buf.length; - } - - public void setBufferSize(int bs) - { - buf = new byte[bs]; - i0 = iend = 0; - } - - public RandomAccessFileWrap(String file) throws IOException - { - this.raf = new RandomAccessFile(file, "r"); - } - - public RandomAccessFileWrap(RandomAccessFile raf) - { - this.raf = raf; - } - - public char charAt(int i) - { - if (i >= i0 && i < iend) - { - return (char) buf[i - i0]; - } - - try - { - i0 = i - 5; - // if(i0+offset<0) i0=(int)(-offset); - if (i0 < 0) - { - i0 = 0; - } - raf.seek(i0 + offset); - iend = i0 + raf.read(buf, 0, buf.length); - - if (i >= i0 && i < iend) - { - return (char) buf[i - i0]; - } - } catch (Throwable t) - { - } - - throw new ArrayIndexOutOfBoundsException(MessageManager.formatMessage("exception.out_of_bounds_for_file", new String[]{ - Integer.valueOf(i).toString(), - Integer.valueOf(i0).toString(), - Integer.valueOf(iend).toString() - })); - } - - public String toString() - { - throw new Error(MessageManager.getString("error.not_implemented")); - } - - public int length() - { - try - { - long len = raf.length() - offset; - if (len > Integer.MAX_VALUE) - { - return Integer.MAX_VALUE; - } - return (int) len; - } catch (IOException ioe) - { - return 0; - } - } - - public String substring(int i1, int i2) - { - StringBuffer sb = new StringBuffer(); - for (int i = i1; i < i2; i++) - { - sb.append(charAt(i)); - } - return sb.toString(); - } - - public Object unwrap() - { - return raf; - } - - public static void main(String[] files) throws IOException - { - for (int i = 0; i < files.length; i++) - { - RandomAccessFileWrap fw = new RandomAccessFileWrap( - new RandomAccessFile(files[i], "r")); - Regex r = new Regex("toString\\(\\) *(?@{})"); - r.setGFlag(true); - r.optimize(); - System.out.print(files[i] + " "); - int j = 0; - do - { - if (r.searchFrom(fw, j)) - { - System.out.println("Matched at index: " + r.matchedFrom()); - j = r.matchedTo(); - } - else - { - System.out.println("not found"); - } - System.out.println(r.stringMatched()); - } while (r.didMatch()); - } - } - - public BasicStringBufferLike newStringBufferLike() - { - return new StringBufferWrap(); - } - - public int indexOf(char c) - { - for (int i = 0; i < length(); i++) - { - if (charAt(i) == c) - { - return i; - } - } - return -1; - } +// +// long offset = 0; +// +// public void setOffset(long o) +// { +// offset = o; +// i0 = iend = 0; +// } +// +// public long getOffset() +// { +// return offset; +// } +// +// RandomAccessFile raf; +// +// int i0 = 0, iend = 0; +// +// byte[] buf = new byte[1024]; +// +// public int getBufferSize() +// { +// return buf.length; +// } +// +// public void setBufferSize(int bs) +// { +// buf = new byte[bs]; +// i0 = iend = 0; +// } +// +// public RandomAccessFileWrap(String file) throws IOException +// { +// this.raf = new RandomAccessFile(file, "r"); +// } +// +// public RandomAccessFileWrap(RandomAccessFile raf) +// { +// this.raf = raf; +// } +// +// public char charAt(int i) +// { +// if (i >= i0 && i < iend) +// { +// return (char) buf[i - i0]; +// } +// +// try +// { +// i0 = i - 5; +// // if(i0+offset<0) i0=(int)(-offset); +// if (i0 < 0) +// { +// i0 = 0; +// } +// raf.seek(i0 + offset); +// iend = i0 + raf.read(buf, 0, buf.length); +// +// if (i >= i0 && i < iend) +// { +// return (char) buf[i - i0]; +// } +// } catch (Throwable t) +// { +// } +// +// throw new ArrayIndexOutOfBoundsException(MessageManager.formatMessage("exception.out_of_bounds_for_file", new String[]{ +// Integer.valueOf(i).toString(), +// Integer.valueOf(i0).toString(), +// Integer.valueOf(iend).toString() +// })); +// } +// +// public String toString() +// { +// throw new Error(MessageManager.getString("error.not_implemented")); +// } +// +// public int length() +// { +// try +// { +// long len = raf.length() - offset; +// if (len > Integer.MAX_VALUE) +// { +// return Integer.MAX_VALUE; +// } +// return (int) len; +// } catch (IOException ioe) +// { +// return 0; +// } +// } +// +// public String substring(int i1, int i2) +// { +// StringBuffer sb = new StringBuffer(); +// for (int i = i1; i < i2; i++) +// { +// sb.append(charAt(i)); +// } +// return sb.toString(); +// } +// +// public Object unwrap() +// { +// return raf; +// } +// +// public static void main(String[] files) throws IOException +// { +// for (int i = 0; i < files.length; i++) +// { +// RandomAccessFileWrap fw = new RandomAccessFileWrap( +// new RandomAccessFile(files[i], "r")); +// Regex r = new Regex("toString\\(\\) *(?@{})"); +// r.setGFlag(true); +// r.optimize(); +// System.out.print(files[i] + " "); +// int j = 0; +// do +// { +// if (r.searchFromLike(fw, j)) +// { +// System.out.println("Matched at index: " + r.matchedFrom()); +// j = r.matchedTo(); +// } +// else +// { +// System.out.println("not found"); +// } +// System.out.println(r.stringMatched()); +// } while (r.didMatch()); +// } +// } +// +// public BasicStringBufferLike newStringBufferLike() +// { +// return new StringBufferWrap(); +// } +// +// public int indexOf(char c) +// { +// for (int i = 0; i < length(); i++) +// { +// if (charAt(i) == c) +// { +// return i; +// } +// } +// return -1; +// } } diff --git a/src/com/stevesoft/pat/wrap/StringBufferWrap.java b/src/com/stevesoft/pat/wrap/StringBufferWrap.java index d522461..53c27b2 100755 --- a/src/com/stevesoft/pat/wrap/StringBufferWrap.java +++ b/src/com/stevesoft/pat/wrap/StringBufferWrap.java @@ -17,7 +17,7 @@ public class StringBufferWrap implements BasicStringBufferLike { StringBuffer sb = new StringBuffer(); - public void append(char c) + public void appendC(char c) { sb.append(c); } diff --git a/src/com/stevesoft/pat/wrap/WriterWrap.java b/src/com/stevesoft/pat/wrap/WriterWrap.java index e72b5fa..a354639 100755 --- a/src/com/stevesoft/pat/wrap/WriterWrap.java +++ b/src/com/stevesoft/pat/wrap/WriterWrap.java @@ -28,7 +28,7 @@ public class WriterWrap implements BasicStringBufferLike this.w = w; } - public void append(char c) + public void appendC(char c) { try { diff --git a/src/fr/orsay/lri/varna/models/rna/RNA.java b/src/fr/orsay/lri/varna/models/rna/RNA.java new file mode 100644 index 0000000..ff63f83 --- /dev/null +++ b/src/fr/orsay/lri/varna/models/rna/RNA.java @@ -0,0 +1,15 @@ +package fr.orsay.lri.varna.models.rna; + +public class RNA { + + public int getSize() { + // TODO Auto-generated method stub + return 0; + } + + public String getStructDBN(boolean b) { + // TODO Auto-generated method stub + return null; + } + +} diff --git a/src/jalview/analysis/AAFrequency.java b/src/jalview/analysis/AAFrequency.java index 6dd3a97..278caa7 100755 --- a/src/jalview/analysis/AAFrequency.java +++ b/src/jalview/analysis/AAFrequency.java @@ -344,7 +344,7 @@ public class AAFrequency // { (char) c }; vl[c] = profile[0][c]; } - QuickSort.sortFloat(vl, ca); + QuickSort.sortFloatChar(vl, ca); for (int p = 0, c = ca.length - 1; profile[0][ca[c]] > 0; c--) { final char residue = ca[c]; @@ -425,7 +425,7 @@ public class AAFrequency ca[c] = (char) c; vl[c] = profile[0][c]; } - QuickSort.sortFloat(vl, ca); + QuickSort.sortFloatChar(vl, ca); int nextArrayPos = 2; int totalPercentage = 0; int distinctValuesCount = 0; @@ -480,7 +480,7 @@ public class AAFrequency { codons[i] = (char) i; } - QuickSort.sortInt(sortedCounts, codons); + QuickSort.sortIntChar(sortedCounts, codons); int totalPercentage = 0; int distinctValuesCount = 0; int j = 3; @@ -615,7 +615,7 @@ public class AAFrequency int[] sortedCodonCounts = new int[codonCounts.length - 2]; System.arraycopy(codonCounts, 2, sortedCodonCounts, 0, codonCounts.length - 2); - QuickSort.sortInt(sortedCodonCounts, codons); + QuickSort.sortIntChar(sortedCodonCounts, codons); int modalCodonEncoded = codons[codons.length - 1]; int modalCodonCount = sortedCodonCounts[codons.length - 1]; diff --git a/src/jalview/analysis/AlignmentAnnotationUtils.java b/src/jalview/analysis/AlignmentAnnotationUtils.java index e02aa9e..381d24a 100644 --- a/src/jalview/analysis/AlignmentAnnotationUtils.java +++ b/src/jalview/analysis/AlignmentAnnotationUtils.java @@ -8,10 +8,13 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import javajs.J2SIgnoreImport; + import jalview.datamodel.AlignmentAnnotation; import jalview.datamodel.SequenceI; import jalview.renderer.AnnotationRenderer; +@J2SIgnoreImport({jalview.renderer.AnnotationRenderer.class}) public class AlignmentAnnotationUtils { diff --git a/src/jalview/analysis/AlignmentSorter.java b/src/jalview/analysis/AlignmentSorter.java index e960e63..a41a1cc 100755 --- a/src/jalview/analysis/AlignmentSorter.java +++ b/src/jalview/analysis/AlignmentSorter.java @@ -129,7 +129,7 @@ public class AlignmentSorter seqs[i] = align.getSequenceAt(i); } - QuickSort.sortFloat(scores, seqs); + QuickSort.sortFloatObject(scores, seqs); setReverseOrder(align, seqs); } @@ -268,7 +268,7 @@ public class AlignmentSorter length[i] = (seqs[i].getEnd() - seqs[i].getStart()); } - QuickSort.sortFloat(length, seqs); + QuickSort.sortFloatObject(length, seqs); if (sortLengthAscending) { @@ -607,7 +607,7 @@ public class AlignmentSorter .floatValue(); } - QuickSort.sortFloat(ids, alignment); + QuickSort.sortFloatObject(ids, alignment); } /** diff --git a/src/jalview/analysis/Finder.java b/src/jalview/analysis/Finder.java index 3c72598..3562dee 100644 --- a/src/jalview/analysis/Finder.java +++ b/src/jalview/analysis/Finder.java @@ -24,11 +24,13 @@ import jalview.datamodel.AlignmentI; import jalview.datamodel.SearchResults; import jalview.datamodel.Sequence; import jalview.datamodel.SequenceGroup; +import jalview.jsdev.RegExp; +import jalview.jsdev.api.RegExpInterface; import jalview.util.Comparison; import java.util.Vector; -import com.stevesoft.pat.Regex; +//import com.stevesoft.pat.Regex; public class Finder { @@ -49,7 +51,7 @@ public class Finder boolean findAll = false; - Regex regex = null; + RegExpInterface regex = null; /** * hold's last-searched position between calles to find(false) @@ -86,7 +88,7 @@ public class Finder { searchString = searchString.toUpperCase(); } - regex = new Regex(searchString); + regex = RegExp.newRegex(searchString); regex.setIgnoreCase(!caseSensitive); searchResults = new SearchResults(); idMatch = new Vector(); @@ -333,7 +335,7 @@ public class Finder /** * @return the regex */ - public Regex getRegex() + public RegExpInterface getRegex() { return regex; } diff --git a/src/jalview/analysis/NJTree.java b/src/jalview/analysis/NJTree.java index 3674be1..16395c2 100644 --- a/src/jalview/analysis/NJTree.java +++ b/src/jalview/analysis/NJTree.java @@ -38,7 +38,7 @@ import java.util.List; import java.util.Vector; /** - * DOCUMENT ME! + * NeighborJoining tree * * @author $author$ * @version $Revision$ diff --git a/src/jalview/analysis/ParseProperties.java b/src/jalview/analysis/ParseProperties.java index 3347800..5fe7adb 100644 --- a/src/jalview/analysis/ParseProperties.java +++ b/src/jalview/analysis/ParseProperties.java @@ -20,11 +20,13 @@ */ package jalview.analysis; -import com.stevesoft.pat.Regex; +//import com.stevesoft.pat.Regex; import jalview.datamodel.AlignmentAnnotation; import jalview.datamodel.AlignmentI; import jalview.datamodel.SequenceI; +import jalview.jsdev.RegExp; +import jalview.jsdev.api.RegExpInterface; public class ParseProperties { @@ -80,7 +82,7 @@ public class ParseProperties * description for each numeric field in regex match * @param regex * Regular Expression string for passing to - * new com.stevesoft.patt.Regex(regex) + * new jalview.jsdevt.Regex(regex) * @param repeat * true means the regex will be applied multiple times along the * description string of each sequence @@ -91,7 +93,7 @@ public class ParseProperties boolean repeat) { int count = 0; - Regex pattern = new Regex(regex); + RegExpInterface pattern = RegExp.newRegex(regex); if (pattern.numSubs() > ScoreNames.length) { // Check that we have enough labels and descriptions for any parsed @@ -131,7 +133,7 @@ public class ParseProperties pos = pattern.matchedTo(); for (int cols = 0; cols < pattern.numSubs(); cols++) { - String sstring = pattern.stringMatched(cols + 1); + String sstring = pattern.stringMatchedI(cols + 1); double score = Double.NaN; try { diff --git a/src/jalview/analysis/Rna.java b/src/jalview/analysis/Rna.java index 1b89cd1..6b93dcb 100644 --- a/src/jalview/analysis/Rna.java +++ b/src/jalview/analysis/Rna.java @@ -58,17 +58,16 @@ public class Rna private static HashSet closingParsSet = new HashSet( Arrays.asList(closingPars)); - private static Hashtable closingToOpening = new Hashtable() - // Initializing final data structure - { - private static final long serialVersionUID = 1L; - { + private static Hashtable closingToOpening = new Hashtable(); + + + static { + // Initializing final data structure for (int i = 0; i < openingPars.length; i++) { // System.out.println(closingPars[i] + "->" + openingPars[i]); - put(closingPars[i], openingPars[i]); + closingToOpening.put(closingPars[i], openingPars[i]); } - } }; private static boolean isOpeningParenthesis(char c) diff --git a/src/jalview/analysis/StructureFrequency.java b/src/jalview/analysis/StructureFrequency.java index d7d07bc..d77c5ac 100644 --- a/src/jalview/analysis/StructureFrequency.java +++ b/src/jalview/analysis/StructureFrequency.java @@ -421,7 +421,7 @@ public class StructureFrequency * ((c == 0) ? "" : "; ") + alphabet[c] + " " + ((int) tval) + "%"; } } * else { */ - int[][] ca = new int[625][]; + int[][] ca = javajs.util.AU.newInt2(625);// BH new int[625][]; float[] vl = new float[625]; int x = 0; for (int c = 65; c < 90; c++) @@ -434,7 +434,7 @@ public class StructureFrequency x++; } } - QuickSort.sortFloat(vl, ca); + QuickSort.sortFloatObject(vl, ca); int p = 0; /* @@ -487,7 +487,7 @@ public class StructureFrequency // TODO fix the object length, also do it in completeConsensus // Object[] ca = new Object[625]; - int[][] ca = new int[625][]; + int[][] ca = javajs.util.AU.newInt2(625);// BH new int[625][]; float[] vl = new float[625]; int x = 0; for (int c = 65; c < 90; c++) @@ -500,7 +500,7 @@ public class StructureFrequency x++; } } - QuickSort.sortFloat(vl, ca); + QuickSort.sortFloatObject(vl, ca); int valuesCount = 0; rtnval[1] = 0; @@ -526,6 +526,11 @@ public class StructureFrequency return result; } + /** + * @j2sIgnore + * + * @param args + */ public static void main(String args[]) { // Short test to see if checkBpType works diff --git a/src/jalview/api/analysis/ViewBasedAnalysisI.java b/src/jalview/api/analysis/ViewBasedAnalysisI.java index 3404afc..2c171c5 100644 --- a/src/jalview/api/analysis/ViewBasedAnalysisI.java +++ b/src/jalview/api/analysis/ViewBasedAnalysisI.java @@ -1,6 +1,5 @@ package jalview.api.analysis; -import jalview.api.AlignViewportI; import jalview.api.AlignmentViewPanel; public interface ViewBasedAnalysisI diff --git a/src/jalview/appletgui/APopupMenu.java b/src/jalview/appletgui/APopupMenu.java index 1d59202..afa4c71 100644 --- a/src/jalview/appletgui/APopupMenu.java +++ b/src/jalview/appletgui/APopupMenu.java @@ -53,10 +53,10 @@ import jalview.util.DBRefUtils; import jalview.util.MessageManager; import jalview.util.UrlLink; -import java.awt.CheckboxMenuItem; -import java.awt.Frame; -import java.awt.Menu; -import java.awt.MenuItem; +import awt2swing.CheckboxMenuItem; +import awt2swing.Frame; +import awt2swing.Menu; +import awt2swing.MenuItem; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ItemEvent; @@ -69,7 +69,7 @@ import java.util.Map; import java.util.TreeMap; import java.util.Vector; -public class APopupMenu extends java.awt.PopupMenu implements +public class APopupMenu extends awt2swing.PopupMenu implements ActionListener, ItemListener { private static final String ALL_ANNOTATIONS = "All"; @@ -420,7 +420,7 @@ AppletFormatAdapter.WRITEABLE_FORMATS[i]); } } - /** + /** * Build menus for annotation types that may be shown or hidden, and for * 'reference annotations' that may be added to the alignment. */ @@ -906,11 +906,11 @@ AppletFormatAdapter.WRITEABLE_FORMATS[i]); new AppletJmol(entry, new SequenceI[] { seq }, null, ap, AppletFormatAdapter.URL); } - else - { - new MCview.AppletPDBViewer(entry, new SequenceI[] - { seq }, null, ap, AppletFormatAdapter.URL); - } +// else +// { +// new MCview.AppletPDBViewer(entry, new SequenceI[] +// { seq }, null, ap, AppletFormatAdapter.URL); +// } } else diff --git a/src/jalview/appletgui/AlignFrame.java b/src/jalview/appletgui/AlignFrame.java index 1fd4231..fd42e9d 100644 --- a/src/jalview/appletgui/AlignFrame.java +++ b/src/jalview/appletgui/AlignFrame.java @@ -52,7 +52,9 @@ import jalview.io.AnnotationFile; import jalview.io.AppletFormatAdapter; import jalview.io.FeaturesFile; import jalview.io.NewickFile; +import jalview.io.AlignFile; import jalview.io.TCoffeeScoreFile; +import jalview.jsdev.GenericFileAdapter; import jalview.schemes.Blosum62ColourScheme; import jalview.schemes.BuriedColourScheme; import jalview.schemes.ClustalxColourScheme; @@ -77,17 +79,10 @@ import jalview.util.MessageManager; import jalview.viewmodel.AlignmentViewport; import java.awt.BorderLayout; -import java.awt.Canvas; -import java.awt.CheckboxMenuItem; import java.awt.Color; import java.awt.Font; import java.awt.FontMetrics; -import java.awt.Frame; import java.awt.Graphics; -import java.awt.Label; -import java.awt.Menu; -import java.awt.MenuBar; -import java.awt.MenuItem; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.FocusEvent; @@ -110,7 +105,15 @@ import java.util.Map; import java.util.StringTokenizer; import java.util.Vector; -import org.jmol.viewer.Viewer; +import awt2swing.Canvas; +import awt2swing.CheckboxMenuItem; +import awt2swing.Frame; +import awt2swing.Label; +import awt2swing.Menu; +import awt2swing.MenuBar; +import awt2swing.MenuItem; + +//import org.jmol.viewer.Viewer; public class AlignFrame extends EmbmenuFrame implements ActionListener, ItemListener, KeyListener, AlignViewControllerGuiI @@ -2926,7 +2929,7 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener, } @Override - public void paint(Graphics g) + public void paintComponent(Graphics g) { g.setColor(Color.white); g.fillRect(0, 0, getSize().width, getSize().height); @@ -2934,7 +2937,7 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener, FontMetrics fm = g.getFontMetrics(); int fh = fm.getHeight(); int y = 5, x = 7; - g.setColor(Color.black); + g.setColor(Color.black); // TODO: update this text for each release or centrally store it for // lite and application g.setFont(new Font("Helvetica", Font.BOLD, 14)); @@ -3731,7 +3734,7 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener, this.add(statusBar, BorderLayout.SOUTH); } - public void setStatus(String string) + public void setStatus(String string) { statusBar.setText(string); }; @@ -3860,77 +3863,77 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener, theApplet.validate(); } - /** - * create a new binding between structures in an existing jmol viewer instance - * and an alignpanel with sequences that have existing PDBFile entries. Note, - * this does not open a new Jmol window, or modify the display of the - * structures in the original jmol window. Note This method doesn't work - * without an additional javascript library to exchange messages between the - * distinct applets. See http://issues.jalview.org/browse/JAL-621 - * - * @param viewer - * JmolViewer instance - * @param sequenceIds - * - sequence Ids to search for associations - */ - public SequenceStructureBinding addStructureViewInstance( - Object jmolviewer, String[] sequenceIds) - { - Viewer viewer = null; - try - { - viewer = (Viewer) jmolviewer; - } catch (ClassCastException ex) - { - System.err.println("Unsupported viewer object :" - + jmolviewer.getClass()); - } - if (viewer == null) - { - System.err.println("Can't use this object as a structure viewer:" - + jmolviewer.getClass()); - return null; - } - SequenceI[] seqs = null; - if (sequenceIds == null || sequenceIds.length == 0) - { - seqs = viewport.getAlignment().getSequencesArray(); - } - else - { - Vector sqi = new Vector(); - AlignmentI al = viewport.getAlignment(); - for (int sid = 0; sid < sequenceIds.length; sid++) - { - SequenceI sq = al.findName(sequenceIds[sid]); - if (sq != null) - { - sqi.addElement(sq); - } - } - if (sqi.size() > 0) - { - seqs = new SequenceI[sqi.size()]; - for (int sid = 0, sSize = sqi.size(); sid < sSize; sid++) - { - seqs[sid] = (SequenceI) sqi.elementAt(sid); - } - } - else - { - return null; - } - } - AAStructureBindingModel jmv = null; - // TODO: search for a jmv that involves viewer - if (jmv == null) - { // create a new viewer/jalview binding. - jmv = new ExtJmol(viewer, alignPanel, new SequenceI[][] - { seqs }); - } - return jmv; - - } + /** + * create a new binding between structures in an existing jmol viewer instance + * and an alignpanel with sequences that have existing PDBFile entries. Note, + * this does not open a new Jmol window, or modify the display of the + * structures in the original jmol window. Note This method doesn't work + * without an additional javascript library to exchange messages between the + * distinct applets. See http://issues.jalview.org/browse/JAL-621 + * + * @param viewer + * JmolViewer instance + * @param sequenceIds + * - sequence Ids to search for associations + */ + public SequenceStructureBinding addStructureViewInstance(Object jmolviewer, + String[] sequenceIds) { + return null; + // Viewer viewer = null; + // try + // { + // viewer = (Viewer) jmolviewer; + // } catch (ClassCastException ex) + // { + // System.err.println("Unsupported viewer object :" + // + jmolviewer.getClass()); + // } + // if (viewer == null) + // { + // System.err.println("Can't use this object as a structure viewer:" + // + jmolviewer.getClass()); + // return null; + // } + // SequenceI[] seqs = null; + // if (sequenceIds == null || sequenceIds.length == 0) + // { + // seqs = viewport.getAlignment().getSequencesArray(); + // } + // else + // { + // Vector sqi = new Vector(); + // AlignmentI al = viewport.getAlignment(); + // for (int sid = 0; sid < sequenceIds.length; sid++) + // { + // SequenceI sq = al.findName(sequenceIds[sid]); + // if (sq != null) + // { + // sqi.addElement(sq); + // } + // } + // if (sqi.size() > 0) + // { + // seqs = new SequenceI[sqi.size()]; + // for (int sid = 0, sSize = sqi.size(); sid < sSize; sid++) + // { + // seqs[sid] = (SequenceI) sqi.elementAt(sid); + // } + // } + // else + // { + // return null; + // } + // } + // AAStructureBindingModel jmv = null; + // // TODO: search for a jmv that involves viewer + // if (jmv == null) + // { // create a new viewer/jalview binding. + // jmv = new ExtJmol(viewer, alignPanel, new SequenceI[][] + // { seqs }); + // } + // return jmv; + // + } /** * bind a pdb file to a sequence in the current view @@ -4028,78 +4031,67 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener, } - public void newStructureView(JalviewLite applet, PDBEntry pdb, - SequenceI[] seqs, String[] chains, String protocol) - { - // Scrub any null sequences from the array - Object[] sqch = cleanSeqChainArrays(seqs, chains); - seqs = (SequenceI[]) sqch[0]; - chains = (String[]) sqch[1]; - if (seqs == null || seqs.length == 0) - { - System.err - .println("JalviewLite.AlignFrame:newStructureView: No sequence to bind structure to."); - } - if (protocol == null || protocol.trim().length() == 0 - || protocol.equals("null")) - { - protocol = (String) pdb.getProperty().get("protocol"); - if (protocol == null) - { - System.err.println("Couldn't work out protocol to open structure: " - + pdb.getId()); - return; - } - } - if (applet.useXtrnalSviewer) - { - // register the association(s) and quit, don't create any windows. - if (StructureSelectionManager.getStructureSelectionManager(applet) - .setMapping(seqs, chains, pdb.getFile(), protocol) == null) - { - System.err.println("Failed to map " + pdb.getFile() + " (" - + protocol + ") to any sequences"); - } - return; - } - if (applet.isAlignPdbStructures() && applet.jmolAvailable) - { - // can only do alignments with Jmol - // find the last jmol window assigned to this alignment - AppletJmol ajm = null, tajm; - Vector jmols = applet -.getAppletWindow(AppletJmol.class); - for (int i = 0, iSize = jmols.size(); i < iSize; i++) - { - tajm = (AppletJmol) jmols.elementAt(i); - if (tajm.ap.alignFrame == this) - { - ajm = tajm; - break; - } - } - if (ajm != null) - { - System.err - .println("Incremental adding and aligning structure to existing Jmol view not yet implemented."); - // try and add the pdb structure - // ajm.addS - ajm = null; - } - } - // otherwise, create a new window - if (applet.jmolAvailable) - { - new AppletJmol(pdb, seqs, chains, alignPanel, protocol); - applet.lastFrameX += 40; - applet.lastFrameY += 40; - } - else - { - new MCview.AppletPDBViewer(pdb, seqs, chains, alignPanel, protocol); - } - - } + public void newStructureView(JalviewLite applet, PDBEntry pdb, + SequenceI[] seqs, String[] chains, String protocol) { + // Scrub any null sequences from the array + Object[] sqch = cleanSeqChainArrays(seqs, chains); + seqs = (SequenceI[]) sqch[0]; + chains = (String[]) sqch[1]; + if (seqs == null || seqs.length == 0) { + System.err + .println("JalviewLite.AlignFrame:newStructureView: No sequence to bind structure to."); + } + if (protocol == null || protocol.trim().length() == 0 + || protocol.equals("null")) { + protocol = (String) pdb.getProperty().get("protocol"); + if (protocol == null) { + System.err.println("Couldn't work out protocol to open structure: " + + pdb.getId()); + return; + } + } + if (applet.useXtrnalSviewer) { + // register the association(s) and quit, don't create any windows. + if (StructureSelectionManager.getStructureSelectionManager(applet) + .setMapping(seqs, chains, pdb.getFile(), protocol) == null) { + System.err.println("Failed to map " + pdb.getFile() + " (" + protocol + + ") to any sequences"); + } + return; + } + if (applet.isAlignPdbStructures() && applet.jmolAvailable) { + // can only do alignments with Jmol + // find the last jmol window assigned to this alignment + AppletJmol ajm = null, tajm; + Vector jmols = applet.getAppletWindow(AppletJmol.class); + for (int i = 0, iSize = jmols.size(); i < iSize; i++) { + tajm = (AppletJmol) jmols.elementAt(i); + if (tajm.ap.alignFrame == this) { + ajm = tajm; + break; + } + } + if (ajm != null) { + System.err + .println("Incremental adding and aligning structure to existing Jmol view not yet implemented."); + // try and add the pdb structure + // ajm.addS + ajm = null; + } + } + // otherwise, create a new window + // if (applet.jmolAvailable) + // { + new AppletJmol(pdb, seqs, chains, alignPanel, protocol); + applet.lastFrameX += 40; + applet.lastFrameY += 40; + // } + // else + // { + // new MCview.AppletPDBViewer(pdb, seqs, chains, alignPanel, protocol); + // } + + } public void alignedStructureView(JalviewLite applet, PDBEntry[] pdb, SequenceI[][] seqs, String[][] chains, String[] protocols) @@ -4148,22 +4140,22 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener, /** * Load the (T-Coffee) score file from the specified url * - * @param source + * @param inFile * File/URL/T-COFFEE score file contents * @throws IOException * @return true if alignment was annotated with data from source */ - public boolean loadScoreFile(String source) throws IOException + public boolean loadScoreFile(String inFile) throws IOException { - TCoffeeScoreFile file = new TCoffeeScoreFile(source, - AppletFormatAdapter.checkProtocol(source)); + TCoffeeScoreFile file = (TCoffeeScoreFile) GenericFileAdapter.getFile("TCoffeeScoreFile", inFile, + AppletFormatAdapter.checkProtocol(inFile)); if (!file.isValid()) { // TODO: raise dialog for gui System.err.println("Problems parsing T-Coffee scores: " + file.getWarningMessage()); - System.err.println("Origin was:\n" + source); + System.err.println("Origin was:\n" + inFile); return false; } diff --git a/src/jalview/appletgui/AlignViewport.java b/src/jalview/appletgui/AlignViewport.java index 68d6c90..65d263a 100644 --- a/src/jalview/appletgui/AlignViewport.java +++ b/src/jalview/appletgui/AlignViewport.java @@ -257,7 +257,7 @@ public class AlignViewport extends AlignmentViewport implements return sq; } - java.awt.Frame nullFrame; + awt2swing.Frame nullFrame; protected FeatureSettings featureSettings = null; @@ -268,8 +268,9 @@ public class AlignViewport extends AlignmentViewport implements font = f; if (nullFrame == null) { - nullFrame = new java.awt.Frame(); + nullFrame = new awt2swing.Frame(); nullFrame.addNotify(); + nullFrame.setFont(font); } java.awt.FontMetrics fm = nullFrame.getGraphics().getFontMetrics(font); diff --git a/src/jalview/appletgui/AlignmentPanel.java b/src/jalview/appletgui/AlignmentPanel.java index d82b3c3..c7bd08a 100644 --- a/src/jalview/appletgui/AlignmentPanel.java +++ b/src/jalview/appletgui/AlignmentPanel.java @@ -33,10 +33,10 @@ import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.FontMetrics; -import java.awt.Frame; +import awt2swing.Frame; import java.awt.Graphics; -import java.awt.Panel; -import java.awt.Scrollbar; +import awt2swing.Panel; +import awt2swing.Scrollbar; import java.awt.event.AdjustmentEvent; import java.awt.event.AdjustmentListener; import java.awt.event.ComponentAdapter; @@ -240,10 +240,9 @@ public class AlignmentPanel extends Panel implements AdjustmentListener, { av.nullFrame = new Frame(); av.nullFrame.addNotify(); + av.nullFrame.setFont(av.font); } - Graphics g = av.nullFrame.getGraphics(); - FontMetrics fm = g.getFontMetrics(av.font); AlignmentI al = av.getAlignment(); @@ -768,6 +767,8 @@ public class AlignmentPanel extends Panel implements AdjustmentListener, public void adjustmentValueChanged(AdjustmentEvent evt) { + if (annotationPanel == null) + return; // BH in process of loading int oldX = av.getStartRes(); int oldY = av.getStartSeq(); @@ -968,7 +969,7 @@ public class AlignmentPanel extends Panel implements AdjustmentListener, paint(g); } - public void paint(Graphics g) + public void paintComponent(Graphics g) { invalidate(); Dimension d = idPanel.idCanvas.getSize(); diff --git a/src/jalview/appletgui/AnnotationColourChooser.java b/src/jalview/appletgui/AnnotationColourChooser.java index 3d79588..6bbbf0a 100644 --- a/src/jalview/appletgui/AnnotationColourChooser.java +++ b/src/jalview/appletgui/AnnotationColourChooser.java @@ -29,17 +29,17 @@ import jalview.schemes.ColourSchemeI; import jalview.util.MessageManager; import java.awt.BorderLayout; -import java.awt.Button; -import java.awt.Checkbox; -import java.awt.Choice; +import awt2swing.Button; +import awt2swing.Checkbox; +import awt2swing.Choice; import java.awt.Color; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.Font; -import java.awt.Frame; -import java.awt.Panel; -import java.awt.Scrollbar; -import java.awt.TextField; +import awt2swing.Frame; +import awt2swing.Panel; +import awt2swing.Scrollbar; +import awt2swing.TextField; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.AdjustmentEvent; diff --git a/src/jalview/appletgui/AnnotationColumnChooser.java b/src/jalview/appletgui/AnnotationColumnChooser.java index 07eef12..b7f4290 100644 --- a/src/jalview/appletgui/AnnotationColumnChooser.java +++ b/src/jalview/appletgui/AnnotationColumnChooser.java @@ -10,13 +10,13 @@ import jalview.viewmodel.annotationfilter.AnnotationFilterParameter; import java.awt.BorderLayout; import java.awt.CardLayout; -import java.awt.Checkbox; -import java.awt.Choice; +import awt2swing.Checkbox; +import awt2swing.Choice; import java.awt.Color; import java.awt.Dimension; -import java.awt.Frame; -import java.awt.Panel; -import java.awt.TextField; +import awt2swing.Frame; +import awt2swing.Panel; +import awt2swing.TextField; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.AdjustmentEvent; @@ -608,7 +608,7 @@ public class AnnotationColumnChooser extends AnnotationRowFilter implements public void itemStateChanged(ItemEvent e) { aColChooser.setCurrentFutherActionPanel(this); - if (furtherAction.getSelectedItem().equalsIgnoreCase("Select")) + if (furtherAction.getSelectedItem().toString().equalsIgnoreCase("Select")) // BH added "toString()" { setActionOption(ACTION_OPTION_SELECT); updateView(); @@ -780,7 +780,6 @@ public class AnnotationColumnChooser extends AnnotationRowFilter implements public void textValueChanged(TextEvent e) { searchStringAction(); - } }); diff --git a/src/jalview/appletgui/AnnotationLabels.java b/src/jalview/appletgui/AnnotationLabels.java index c490fba..c823113 100755 --- a/src/jalview/appletgui/AnnotationLabels.java +++ b/src/jalview/appletgui/AnnotationLabels.java @@ -29,18 +29,18 @@ import jalview.datamodel.SequenceI; import jalview.util.MessageManager; import jalview.util.ParseHtmlBodyAndLinks; -import java.awt.Checkbox; -import java.awt.CheckboxMenuItem; +import awt2swing.Checkbox; +import awt2swing.CheckboxMenuItem; import java.awt.Color; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.FontMetrics; -import java.awt.Frame; +import awt2swing.Frame; import java.awt.Graphics; import java.awt.Image; -import java.awt.MenuItem; -import java.awt.Panel; -import java.awt.PopupMenu; +import awt2swing.MenuItem; +import awt2swing.Panel; +import awt2swing.PopupMenu; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.InputEvent; @@ -788,7 +788,7 @@ public class AnnotationLabels extends Panel implements ActionListener, paint(g); } - public void paint(Graphics g) + public void paintComponent(Graphics g) { int w = getSize().width; int h = getSize().height; diff --git a/src/jalview/appletgui/AnnotationPanel.java b/src/jalview/appletgui/AnnotationPanel.java index 6f406a4..27e589f 100755 --- a/src/jalview/appletgui/AnnotationPanel.java +++ b/src/jalview/appletgui/AnnotationPanel.java @@ -33,9 +33,9 @@ import java.awt.Font; import java.awt.FontMetrics; import java.awt.Graphics; import java.awt.Image; -import java.awt.MenuItem; -import java.awt.Panel; -import java.awt.PopupMenu; +import awt2swing.MenuItem; +import awt2swing.Panel; +import awt2swing.PopupMenu; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.AdjustmentEvent; @@ -541,7 +541,7 @@ public class AnnotationPanel extends Panel implements AwtRenderPanelI, } @Override - public void paint(Graphics g) + public void paintComponent(Graphics g) { Dimension d = getSize(); imgWidth = d.width; diff --git a/src/jalview/appletgui/AnnotationRowFilter.java b/src/jalview/appletgui/AnnotationRowFilter.java index 1345503..bcc9013 100644 --- a/src/jalview/appletgui/AnnotationRowFilter.java +++ b/src/jalview/appletgui/AnnotationRowFilter.java @@ -4,13 +4,13 @@ import jalview.datamodel.AlignmentAnnotation; import jalview.schemes.AnnotationColourGradient; import jalview.util.MessageManager; -import java.awt.Button; -import java.awt.Checkbox; -import java.awt.Choice; -import java.awt.Frame; -import java.awt.Panel; -import java.awt.Scrollbar; -import java.awt.TextField; +import awt2swing.Button; +import awt2swing.Checkbox; +import awt2swing.Choice; +import awt2swing.Frame; +import awt2swing.Panel; +import awt2swing.Scrollbar; +import awt2swing.TextField; import java.awt.event.ActionEvent; import java.util.Vector; diff --git a/src/jalview/appletgui/AppletJmol.java b/src/jalview/appletgui/AppletJmol.java index c981104..aa18f5f 100644 --- a/src/jalview/appletgui/AppletJmol.java +++ b/src/jalview/appletgui/AppletJmol.java @@ -39,18 +39,18 @@ import jalview.structure.StructureSelectionManager; import jalview.util.MessageManager; import java.awt.BorderLayout; -import java.awt.CheckboxMenuItem; +import awt2swing.CheckboxMenuItem; import java.awt.Color; import java.awt.Dimension; import java.awt.Font; -import java.awt.Frame; +import awt2swing.Frame; import java.awt.Graphics; -import java.awt.Menu; -import java.awt.MenuBar; -import java.awt.MenuItem; -import java.awt.Panel; -import java.awt.TextArea; -import java.awt.TextField; +import awt2swing.Menu; +import awt2swing.MenuBar; +import awt2swing.MenuItem; +import awt2swing.Panel; +import awt2swing.TextArea; +import awt2swing.TextField; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ItemEvent; @@ -64,62 +64,10 @@ import java.util.Hashtable; import java.util.List; import java.util.Vector; -public class AppletJmol extends EmbmenuFrame implements -// StructureListener, - KeyListener, ActionListener, ItemListener +public class AppletJmol //extends EmbmenuFrame implements +// KeyListener, ActionListener, ItemListener { - Menu fileMenu = new Menu(MessageManager.getString("action.file")); - - Menu viewMenu = new Menu(MessageManager.getString("action.view")); - - Menu coloursMenu = new Menu(MessageManager.getString("action.colour")); - - Menu chainMenu = new Menu(MessageManager.getString("action.show_chain")); - - Menu helpMenu = new Menu(MessageManager.getString("action.help")); - - MenuItem mappingMenuItem = new MenuItem( - MessageManager.getString("label.view_mapping")); - - CheckboxMenuItem seqColour = new CheckboxMenuItem( - MessageManager.getString("action.by_sequence"), true); - - CheckboxMenuItem jmolColour = new CheckboxMenuItem( - MessageManager.getString("action.using_jmol"), false); - - MenuItem chain = new MenuItem(MessageManager.getString("action.by_chain")); - - MenuItem charge = new MenuItem( - MessageManager.getString("label.charge_cysteine")); - - MenuItem zappo = new MenuItem(MessageManager.getString("label.zappo")); - - MenuItem taylor = new MenuItem(MessageManager.getString("label.taylor")); - - MenuItem hydro = new MenuItem( - MessageManager.getString("label.hydrophobicity")); - - MenuItem helix = new MenuItem( - MessageManager.getString("label.helix_propensity")); - - MenuItem strand = new MenuItem( - MessageManager.getString("label.strand_propensity")); - - MenuItem turn = new MenuItem( - MessageManager.getString("label.turn_propensity")); - - MenuItem buried = new MenuItem( - MessageManager.getString("label.buried_index")); - - MenuItem purinepyrimidine = new MenuItem( - MessageManager.getString("label.purine_pyrimidine")); - - MenuItem user = new MenuItem( - MessageManager.getString("label.user_defined_colours")); - - MenuItem jmolHelp = new MenuItem( - MessageManager.getString("label.jmol_help")); Panel scriptWindow; @@ -144,500 +92,565 @@ public class AppletJmol extends EmbmenuFrame implements AppletJmolBinding jmb; - /** - * datasource protocol for access to PDBEntry - */ - String protocol = null; - - /** - * Load a bunch of pdb entries associated with sequences in the alignment and - * display them - aligning them if necessary. - * - * @param pdbentries - * each pdb file (at least one needed) - * @param boundseqs - * each set of sequences for each pdb file (must match number of pdb - * files) - * @param boundchains - * the target pdb chain corresponding with each sequence associated - * with each pdb file (may be null at any level) - * @param align - * true/false - * @param ap - * associated alignment - * @param protocol - * how to get pdb data - */ - public AppletJmol(PDBEntry[] pdbentries, SequenceI[][] boundseqs, - String[][] boundchains, boolean align, AlignmentPanel ap, - String protocol) - { - throw new Error(MessageManager.getString("error.not_yet_implemented")); - } - - public AppletJmol(PDBEntry pdbentry, SequenceI[] seq, String[] chains, - AlignmentPanel ap, String protocol) - { - this.ap = ap; - jmb = new AppletJmolBinding(this, ap.getStructureSelectionManager(), - new PDBEntry[] - { pdbentry }, new SequenceI[][] - { seq }, new String[][] - { chains }, protocol); - jmb.setColourBySequence(true); - if (pdbentry.getId() == null || pdbentry.getId().length() < 1) - { - if (protocol.equals(AppletFormatAdapter.PASTE)) - { - pdbentry.setId("PASTED PDB" - + (chains == null ? "_" : chains.toString())); - } - else - { - pdbentry.setId(pdbentry.getFile()); - } - } - - if (JalviewLite.debug) - { - System.err - .println("AppletJmol: PDB ID is '" + pdbentry.getId() + "'"); - } - - String alreadyMapped = StructureSelectionManager - .getStructureSelectionManager(ap.av.applet) - .alreadyMappedToFile(pdbentry.getId()); - MCview.PDBfile reader = null; - if (alreadyMapped != null) - { - reader = StructureSelectionManager.getStructureSelectionManager( - ap.av.applet).setMapping(seq, chains, pdbentry.getFile(), - protocol); - // PROMPT USER HERE TO ADD TO NEW OR EXISTING VIEW? - // FOR NOW, LETS JUST OPEN A NEW WINDOW - } - MenuBar menuBar = new MenuBar(); - menuBar.add(fileMenu); - fileMenu.add(mappingMenuItem); - menuBar.add(viewMenu); - mappingMenuItem.addActionListener(this); - viewMenu.add(chainMenu); - menuBar.add(coloursMenu); - menuBar.add(helpMenu); - - charge.addActionListener(this); - hydro.addActionListener(this); - chain.addActionListener(this); - seqColour.addItemListener(this); - jmolColour.addItemListener(this); - zappo.addActionListener(this); - taylor.addActionListener(this); - helix.addActionListener(this); - strand.addActionListener(this); - turn.addActionListener(this); - buried.addActionListener(this); - purinepyrimidine.addActionListener(this); - user.addActionListener(this); - - jmolHelp.addActionListener(this); - - coloursMenu.add(seqColour); - coloursMenu.add(chain); - coloursMenu.add(charge); - coloursMenu.add(zappo); - coloursMenu.add(taylor); - coloursMenu.add(hydro); - coloursMenu.add(helix); - coloursMenu.add(strand); - coloursMenu.add(turn); - coloursMenu.add(buried); - coloursMenu.add(purinepyrimidine); - coloursMenu.add(user); - coloursMenu.add(jmolColour); - helpMenu.add(jmolHelp); - this.setLayout(new BorderLayout()); - - setMenuBar(menuBar); - - renderPanel = new RenderPanel(); - embedMenuIfNeeded(renderPanel); - this.add(renderPanel, BorderLayout.CENTER); - scriptWindow = new Panel(); - scriptWindow.setVisible(false); - // this.add(scriptWindow, BorderLayout.SOUTH); - - try - { - jmb.allocateViewer(renderPanel, true, ap.av.applet.getName() - + "_jmol_", ap.av.applet.getDocumentBase(), - ap.av.applet.getCodeBase(), "-applet", scriptWindow, null); - } catch (Exception e) - { - System.err - .println("Couldn't create a jmol viewer. Args to allocate viewer were:\nDocumentBase=" - + ap.av.applet.getDocumentBase() - + "\nCodebase=" - + ap.av.applet.getCodeBase()); - e.printStackTrace(); - dispose(); - return; - } - // jmb.newJmolPopup(true, "Jmol", true); - - this.addWindowListener(new WindowAdapter() - { - public void windowClosing(WindowEvent evt) - { - closeViewer(); - } - }); - if (pdbentry.getProperty() == null) - { - pdbentry.setProperty(new Hashtable()); - pdbentry.getProperty().put("protocol", protocol); - } - if (pdbentry.getFile() != null) - { - // import structure data from pdbentry.getFile based on given protocol - if (protocol.equals(AppletFormatAdapter.PASTE)) - { - // TODO: JAL-623 : correctly record file contents for matching up later - // pdbentry.getProperty().put("pdbfilehash",""+pdbentry.getFile().hashCode()); - loadInline(pdbentry.getFile()); - } - else if (protocol.equals(AppletFormatAdapter.FILE) - || protocol.equals(AppletFormatAdapter.URL)) - { - jmb.viewer.openFile(pdbentry.getFile()); - } - else - { - // probably CLASSLOADER based datasource.. - // Try and get a reader on the datasource, and pass that to Jmol - try - { - java.io.Reader freader = null; - if (reader != null) - { - if (JalviewLite.debug) - { - System.err - .println("AppletJmol:Trying to reuse existing PDBfile IO parser."); - } - // re-use the one we opened earlier - freader = reader.getReader(); - } - if (freader == null) - { - if (JalviewLite.debug) - { - System.err - .println("AppletJmol:Creating new PDBfile IO parser."); - } - FileParse fp = new FileParse(pdbentry.getFile(), protocol); - fp.mark(); - // reader = new MCview.PDBfile(fp); - // could set ID, etc. - // if (!reader.isValid()) - // { - // throw new Exception("Invalid datasource. - // "+reader.getWarningMessage()); - // } - // fp.reset(); - freader = fp.getReader(); - } - if (freader == null) - { - throw new Exception(MessageManager.getString("exception.invalid_datasource_couldnt_obtain_reader")); - } - jmb.viewer.openReader(pdbentry.getFile(), pdbentry.getId(), - freader); - } catch (Exception e) - { - // give up! - System.err.println("Couldn't access pdbentry id=" - + pdbentry.getId() + " and file=" + pdbentry.getFile() - + " using protocol=" + protocol); - e.printStackTrace(); - } - } - } - - JalviewLite.addFrame(this, jmb.getViewerTitle(), 400, 400); - } - - public void loadInline(String string) - { - loadedInline = true; - jmb.loadInline(string); - } - - void setChainMenuItems(Vector chains) - { - chainMenu.removeAll(); - - MenuItem menuItem = new MenuItem(MessageManager.getString("label.all")); - menuItem.addActionListener(this); - - chainMenu.add(menuItem); - - CheckboxMenuItem menuItemCB; - for (String ch : chains) - { - menuItemCB = new CheckboxMenuItem(ch, true); - menuItemCB.addItemListener(this); - chainMenu.add(menuItemCB); - } - } - - boolean allChainsSelected = false; - - void centerViewer() - { - Vector toshow = new Vector(); - for (int i = 0; i < chainMenu.getItemCount(); i++) - { - if (chainMenu.getItem(i) instanceof CheckboxMenuItem) - { - CheckboxMenuItem item = (CheckboxMenuItem) chainMenu.getItem(i); - if (item.getState()) - { - toshow.addElement(item.getLabel()); - } - } - } - jmb.centerViewer(toshow); - } - - void closeViewer() - { - jmb.closeViewer(); - jmb = null; - this.setVisible(false); - } - - public void actionPerformed(ActionEvent evt) - { - if (evt.getSource() == mappingMenuItem) - { - CutAndPasteTransfer cap = new CutAndPasteTransfer( - false, null); - Frame frame = new Frame(); - frame.add(cap); - - StringBuffer sb = new StringBuffer(); - try - { - cap.setText(jmb.printMappings()); - } catch (OutOfMemoryError ex) - { - frame.dispose(); - System.err - .println("Out of memory when trying to create dialog box with sequence-structure mapping."); - return; - } - JalviewLite.addFrame(frame, - MessageManager.getString("label.pdb_sequence_mapping"), 550, - 600); - } - else if (evt.getSource() == charge) - { - setEnabled(charge); - jmb.colourByCharge(); - } - - else if (evt.getSource() == chain) - { - setEnabled(chain); - jmb.colourByChain(); - } - else if (evt.getSource() == zappo) - { - setEnabled(zappo); - jmb.setJalviewColourScheme(new ZappoColourScheme()); - } - else if (evt.getSource() == taylor) - { - setEnabled(taylor); - jmb.setJalviewColourScheme(new TaylorColourScheme()); - } - else if (evt.getSource() == hydro) - { - setEnabled(hydro); - jmb.setJalviewColourScheme(new HydrophobicColourScheme()); - } - else if (evt.getSource() == helix) - { - setEnabled(helix); - jmb.setJalviewColourScheme(new HelixColourScheme()); - } - else if (evt.getSource() == strand) - { - setEnabled(strand); - jmb.setJalviewColourScheme(new StrandColourScheme()); - } - else if (evt.getSource() == turn) - { - setEnabled(turn); - jmb.setJalviewColourScheme(new TurnColourScheme()); - } - else if (evt.getSource() == buried) - { - setEnabled(buried); - jmb.setJalviewColourScheme(new BuriedColourScheme()); - } - else if (evt.getSource() == purinepyrimidine) - { - jmb.setJalviewColourScheme(new PurinePyrimidineColourScheme()); - } - else if (evt.getSource() == user) - { - setEnabled(user); - new UserDefinedColours(this); - } - else if (evt.getSource() == jmolHelp) - { - try - { - ap.av.applet.getAppletContext().showDocument( - new java.net.URL( - "http://jmol.sourceforge.net/docs/JmolUserGuide/"), - "jmolHelp"); - } catch (java.net.MalformedURLException ex) - { - } - } - else - { - allChainsSelected = true; - for (int i = 0; i < chainMenu.getItemCount(); i++) - { - if (chainMenu.getItem(i) instanceof CheckboxMenuItem) - { - ((CheckboxMenuItem) chainMenu.getItem(i)).setState(true); - } - } - - centerViewer(); - allChainsSelected = false; - } - } - - /** - * tick or untick the seqColour menu entry or jmoColour entry depending upon - * if it was selected or not. - * - * @param itm - */ - private void setEnabled(MenuItem itm) - { - jmolColour.setState(itm == jmolColour); - seqColour.setState(itm == seqColour); - jmb.setColourBySequence(itm == seqColour); - } - - public void itemStateChanged(ItemEvent evt) - { - if (evt.getSource() == jmolColour) - { - setEnabled(jmolColour); - jmb.setColourBySequence(false); - } - else if (evt.getSource() == seqColour) - { - setEnabled(seqColour); - jmb.colourBySequence(ap); - } - else if (!allChainsSelected) - { - centerViewer(); - } - } - - public void keyPressed(KeyEvent evt) - { - if (evt.getKeyCode() == KeyEvent.VK_ENTER && scriptWindow.isVisible()) - { - jmb.eval(inputLine.getText()); - history.append("\n$ " + inputLine.getText()); - inputLine.setText(""); - } - - } - - public void keyTyped(KeyEvent evt) - { - } - - public void keyReleased(KeyEvent evt) - { - } - - public void updateColours(Object source) - { - AlignmentPanel panel = (AlignmentPanel) source; - jmb.colourBySequence(panel); - } - - public void updateTitleAndMenus() - { - if (jmb.fileLoadingError != null && jmb.fileLoadingError.length() > 0) - { - repaint(); - return; - } - setChainMenuItems(jmb.chainNames); - jmb.colourBySequence(ap); - - setTitle(jmb.getViewerTitle()); - } - - public void showUrl(String url) - { - try - { - ap.av.applet.getAppletContext().showDocument(new java.net.URL(url), - "jmolOutput"); - } catch (java.net.MalformedURLException ex) - { - } - } - - Panel splitPane = null; - - public void showConsole(boolean showConsole) - { - if (showConsole) - { - remove(renderPanel); - splitPane = new Panel(); - - splitPane.setLayout(new java.awt.GridLayout(2, 1)); - splitPane.add(renderPanel); - splitPane.add(scriptWindow); - scriptWindow.setVisible(true); - this.add(splitPane, BorderLayout.CENTER); - splitPane.setVisible(true); - splitPane.validate(); - } - else - { - scriptWindow.setVisible(false); - remove(splitPane); - add(renderPanel, BorderLayout.CENTER); - splitPane = null; - } - validate(); - } - - public float[][] functionXY(String functionName, int x, int y) - { - return null; - } - - // /End JmolStatusListener - // ///////////////////////////// + public AppletJmol(PDBEntry entry, SequenceI[] sequenceIs, Object object, + AlignmentPanel ap2, String uRL) { + // TODO Auto-generated constructor stub + } + + + public void setJalviewColourScheme(UserColourScheme ucs) { + // TODO Auto-generated method stub + + } + + + // Menu fileMenu = new Menu(MessageManager.getString("action.file")); +// +// Menu viewMenu = new Menu(MessageManager.getString("action.view")); +// +// Menu coloursMenu = new Menu(MessageManager.getString("action.colour")); +// +// Menu chainMenu = new Menu(MessageManager.getString("action.show_chain")); +// +// Menu helpMenu = new Menu(MessageManager.getString("action.help")); +// +// MenuItem mappingMenuItem = new MenuItem( +// MessageManager.getString("label.view_mapping")); +// +// CheckboxMenuItem seqColour = new CheckboxMenuItem( +// MessageManager.getString("action.by_sequence"), true); +// +// CheckboxMenuItem jmolColour = new CheckboxMenuItem( +// MessageManager.getString("action.using_jmol"), false); +// +// MenuItem chain = new MenuItem(MessageManager.getString("action.by_chain")); +// +// MenuItem charge = new MenuItem( +// MessageManager.getString("label.charge_cysteine")); +// +// MenuItem zappo = new MenuItem(MessageManager.getString("label.zappo")); +// +// MenuItem taylor = new MenuItem(MessageManager.getString("label.taylor")); +// +// MenuItem hydro = new MenuItem( +// MessageManager.getString("label.hydrophobicity")); +// +// MenuItem helix = new MenuItem( +// MessageManager.getString("label.helix_propensity")); +// +// MenuItem strand = new MenuItem( +// MessageManager.getString("label.strand_propensity")); +// +// MenuItem turn = new MenuItem( +// MessageManager.getString("label.turn_propensity")); +// +// MenuItem buried = new MenuItem( +// MessageManager.getString("label.buried_index")); +// +// MenuItem purinepyrimidine = new MenuItem( +// MessageManager.getString("label.purine_pyrimidine")); +// +// MenuItem user = new MenuItem( +// MessageManager.getString("label.user_defined_colours")); +// +// MenuItem jmolHelp = new MenuItem( +// MessageManager.getString("label.jmol_help")); +// +// /** +// * datasource protocol for access to PDBEntry +// */ +// String protocol = null; +// +// /** +// * Load a bunch of pdb entries associated with sequences in the alignment and +// * display them - aligning them if necessary. +// * +// * @param pdbentries +// * each pdb file (at least one needed) +// * @param boundseqs +// * each set of sequences for each pdb file (must match number of pdb +// * files) +// * @param boundchains +// * the target pdb chain corresponding with each sequence associated +// * with each pdb file (may be null at any level) +// * @param align +// * true/false +// * @param ap +// * associated alignment +// * @param protocol +// * how to get pdb data +// */ +// public AppletJmol(PDBEntry[] pdbentries, SequenceI[][] boundseqs, +// String[][] boundchains, boolean align, AlignmentPanel ap, +// String protocol) +// { +// throw new Error(MessageManager.getString("error.not_yet_implemented")); +// } +// +// public AppletJmol(PDBEntry pdbentry, SequenceI[] seq, String[] chains, +// AlignmentPanel ap, String protocol) +// { +// this.ap = ap; +// jmb = new AppletJmolBinding(this, ap.getStructureSelectionManager(), +// new PDBEntry[] +// { pdbentry }, new SequenceI[][] +// { seq }, new String[][] +// { chains }, protocol); +// jmb.setColourBySequence(true); +// if (pdbentry.getId() == null || pdbentry.getId().length() < 1) +// { +// if (protocol.equals(AppletFormatAdapter.PASTE)) +// { +// pdbentry.setId("PASTED PDB" +// + (chains == null ? "_" : chains.toString())); +// } +// else +// { +// pdbentry.setId(pdbentry.getFile()); +// } +// } +// +// if (JalviewLite.debug) +// { +// System.err +// .println("AppletJmol: PDB ID is '" + pdbentry.getId() + "'"); +// } +// +// String alreadyMapped = StructureSelectionManager +// .getStructureSelectionManager(ap.av.applet) +// .alreadyMappedToFile(pdbentry.getId()); +// MCview.PDBfile reader = null; +// if (alreadyMapped != null) +// { +// reader = StructureSelectionManager.getStructureSelectionManager( +// ap.av.applet).setMapping(seq, chains, pdbentry.getFile(), +// protocol); +// // PROMPT USER HERE TO ADD TO NEW OR EXISTING VIEW? +// // FOR NOW, LETS JUST OPEN A NEW WINDOW +// } +// MenuBar menuBar = new MenuBar(); +// menuBar.add(fileMenu); +// fileMenu.add(mappingMenuItem); +// menuBar.add(viewMenu); +// mappingMenuItem.addActionListener(this); +// viewMenu.add(chainMenu); +// menuBar.add(coloursMenu); +// menuBar.add(helpMenu); +// +// charge.addActionListener(this); +// hydro.addActionListener(this); +// chain.addActionListener(this); +// seqColour.addItemListener(this); +// jmolColour.addItemListener(this); +// zappo.addActionListener(this); +// taylor.addActionListener(this); +// helix.addActionListener(this); +// strand.addActionListener(this); +// turn.addActionListener(this); +// buried.addActionListener(this); +// purinepyrimidine.addActionListener(this); +// user.addActionListener(this); +// +// jmolHelp.addActionListener(this); +// +// coloursMenu.add(seqColour); +// coloursMenu.add(chain); +// coloursMenu.add(charge); +// coloursMenu.add(zappo); +// coloursMenu.add(taylor); +// coloursMenu.add(hydro); +// coloursMenu.add(helix); +// coloursMenu.add(strand); +// coloursMenu.add(turn); +// coloursMenu.add(buried); +// coloursMenu.add(purinepyrimidine); +// coloursMenu.add(user); +// coloursMenu.add(jmolColour); +// helpMenu.add(jmolHelp); +// this.setLayout(new BorderLayout()); +// +// setMenuBar(menuBar); +// +// renderPanel = new RenderPanel(); +// embedMenuIfNeeded(renderPanel); +// this.add(renderPanel, BorderLayout.CENTER); +// scriptWindow = new Panel(); +// scriptWindow.setVisible(false); +// // this.add(scriptWindow, BorderLayout.SOUTH); +// +// try +// { +// jmb.allocateViewer(renderPanel, true, ap.av.applet.getName() +// + "_jmol_", ap.av.applet.getDocumentBase(), +// ap.av.applet.getCodeBase(), "-applet", scriptWindow, null); +// } catch (Exception e) +// { +// System.err +// .println("Couldn't create a jmol viewer. Args to allocate viewer were:\nDocumentBase=" +// + ap.av.applet.getDocumentBase() +// + "\nCodebase=" +// + ap.av.applet.getCodeBase()); +// e.printStackTrace(); +// dispose(); +// return; +// } +// // jmb.newJmolPopup(true, "Jmol", true); +// +// this.addWindowListener(new WindowAdapter() +// { +// public void windowClosing(WindowEvent evt) +// { +// closeViewer(); +// } +// }); +// if (pdbentry.getProperty() == null) +// { +// pdbentry.setProperty(new Hashtable()); +// pdbentry.getProperty().put("protocol", protocol); +// } +// if (pdbentry.getFile() != null) +// { +// // import structure data from pdbentry.getFile based on given protocol +// if (protocol.equals(AppletFormatAdapter.PASTE)) +// { +// // TODO: JAL-623 : correctly record file contents for matching up later +// // pdbentry.getProperty().put("pdbfilehash",""+pdbentry.getFile().hashCode()); +// loadInline(pdbentry.getFile()); +// } +// else if (protocol.equals(AppletFormatAdapter.FILE) +// || protocol.equals(AppletFormatAdapter.URL)) +// { +// jmb.viewer.openFile(pdbentry.getFile()); +// } +// else +// { +// // probably CLASSLOADER based datasource.. +// // Try and get a reader on the datasource, and pass that to Jmol +// try +// { +// java.io.Reader freader = null; +// if (reader != null) +// { +// if (JalviewLite.debug) +// { +// System.err +// .println("AppletJmol:Trying to reuse existing PDBfile IO parser."); +// } +// // re-use the one we opened earlier +// freader = reader.getReader(); +// } +// if (freader == null) +// { +// if (JalviewLite.debug) +// { +// System.err +// .println("AppletJmol:Creating new PDBfile IO parser."); +// } +// FileParse fp = new FileParse(pdbentry.getFile(), protocol); +// fp.mark(); +// // reader = new MCview.PDBfile(fp); +// // could set ID, etc. +// // if (!reader.isValid()) +// // { +// // throw new Exception("Invalid datasource. +// // "+reader.getWarningMessage()); +// // } +// // fp.reset(); +// freader = fp.getReader(); +// } +// if (freader == null) +// { +// throw new Exception(MessageManager.getString("exception.invalid_datasource_couldnt_obtain_reader")); +// } +// jmb.viewer.openReader(pdbentry.getFile(), pdbentry.getId(), +// freader); +// } catch (Exception e) +// { +// // give up! +// System.err.println("Couldn't access pdbentry id=" +// + pdbentry.getId() + " and file=" + pdbentry.getFile() +// + " using protocol=" + protocol); +// e.printStackTrace(); +// } +// } +// } +// +// JalviewLite.addFrame(this, jmb.getViewerTitle(), 400, 400); +// } +// +// public void loadInline(String string) +// { +// loadedInline = true; +// jmb.loadInline(string); +// } +// +// void setChainMenuItems(Vector chains) +// { +// chainMenu.removeAll(); +// +// MenuItem menuItem = new MenuItem(MessageManager.getString("label.all")); +// menuItem.addActionListener(this); +// +// chainMenu.add(menuItem); +// +// CheckboxMenuItem menuItemCB; +// for (String ch : chains) +// { +// menuItemCB = new CheckboxMenuItem(ch, true); +// menuItemCB.addItemListener(this); +// chainMenu.add(menuItemCB); +// } +// } +// +// boolean allChainsSelected = false; +// +// void centerViewer() +// { +// Vector toshow = new Vector(); +// for (int i = 0; i < chainMenu.getItemCount(); i++) +// { +// if (chainMenu.getItem(i) instanceof CheckboxMenuItem) +// { +// CheckboxMenuItem item = (CheckboxMenuItem) chainMenu.getItem(i); +// if (item.getState()) +// { +// toshow.addElement(item.getLabel()); +// } +// } +// } +// jmb.centerViewer(toshow); +// } +// +// void closeViewer() +// { +// jmb.closeViewer(); +// jmb = null; +// this.setVisible(false); +// } +// +// public void actionPerformed(ActionEvent evt) +// { +// if (evt.getSource() == mappingMenuItem) +// { +// CutAndPasteTransfer cap = new CutAndPasteTransfer( +// false, null); +// Frame frame = new Frame(); +// frame.add(cap); +// +// StringBuffer sb = new StringBuffer(); +// try +// { +// cap.setText(jmb.printMappings()); +// } catch (OutOfMemoryError ex) +// { +// frame.dispose(); +// System.err +// .println("Out of memory when trying to create dialog box with sequence-structure mapping."); +// return; +// } +// JalviewLite.addFrame(frame, +// MessageManager.getString("label.pdb_sequence_mapping"), 550, +// 600); +// } +// else if (evt.getSource() == charge) +// { +// setEnabled(charge); +// jmb.colourByCharge(); +// } +// +// else if (evt.getSource() == chain) +// { +// setEnabled(chain); +// jmb.colourByChain(); +// } +// else if (evt.getSource() == zappo) +// { +// setEnabled(zappo); +// jmb.setJalviewColourScheme(new ZappoColourScheme()); +// } +// else if (evt.getSource() == taylor) +// { +// setEnabled(taylor); +// jmb.setJalviewColourScheme(new TaylorColourScheme()); +// } +// else if (evt.getSource() == hydro) +// { +// setEnabled(hydro); +// jmb.setJalviewColourScheme(new HydrophobicColourScheme()); +// } +// else if (evt.getSource() == helix) +// { +// setEnabled(helix); +// jmb.setJalviewColourScheme(new HelixColourScheme()); +// } +// else if (evt.getSource() == strand) +// { +// setEnabled(strand); +// jmb.setJalviewColourScheme(new StrandColourScheme()); +// } +// else if (evt.getSource() == turn) +// { +// setEnabled(turn); +// jmb.setJalviewColourScheme(new TurnColourScheme()); +// } +// else if (evt.getSource() == buried) +// { +// setEnabled(buried); +// jmb.setJalviewColourScheme(new BuriedColourScheme()); +// } +// else if (evt.getSource() == purinepyrimidine) +// { +// jmb.setJalviewColourScheme(new PurinePyrimidineColourScheme()); +// } +// else if (evt.getSource() == user) +// { +// setEnabled(user); +// new UserDefinedColours(this); +// } +// else if (evt.getSource() == jmolHelp) +// { +// try +// { +// ap.av.applet.getAppletContext().showDocument( +// new java.net.URL( +// "http://jmol.sourceforge.net/docs/JmolUserGuide/"), +// "jmolHelp"); +// } catch (java.net.MalformedURLException ex) +// { +// } +// } +// else +// { +// allChainsSelected = true; +// for (int i = 0; i < chainMenu.getItemCount(); i++) +// { +// if (chainMenu.getItem(i) instanceof CheckboxMenuItem) +// { +// ((CheckboxMenuItem) chainMenu.getItem(i)).setState(true); +// } +// } +// +// centerViewer(); +// allChainsSelected = false; +// } +// } +// +// /** +// * tick or untick the seqColour menu entry or jmoColour entry depending upon +// * if it was selected or not. +// * +// * @param itm +// */ +// private void setEnabled(Object itm) // BH MenuItem not superclass of CheckBoxMenuItem +// { +// jmolColour.setState(itm == jmolColour); +// seqColour.setState(itm == seqColour); +// jmb.setColourBySequence(itm == seqColour); +// } +// +// public void itemStateChanged(ItemEvent evt) +// { +// if (evt.getSource() == jmolColour) +// { +// setEnabled(jmolColour); +// jmb.setColourBySequence(false); +// } +// else if (evt.getSource() == seqColour) +// { +// setEnabled(seqColour); +// jmb.colourBySequence(ap); +// } +// else if (!allChainsSelected) +// { +// centerViewer(); +// } +// } +// +// public void keyPressed(KeyEvent evt) +// { +// if (evt.getKeyCode() == KeyEvent.VK_ENTER && scriptWindow.isVisible()) +// { +// jmb.eval(inputLine.getText()); +// history.append("\n$ " + inputLine.getText()); +// inputLine.setText(""); +// } +// +// } +// +// public void keyTyped(KeyEvent evt) +// { +// } +// +// public void keyReleased(KeyEvent evt) +// { +// } +// +// public void updateColours(Object source) +// { +// AlignmentPanel panel = (AlignmentPanel) source; +// jmb.colourBySequence(panel); +// } +// +// public void updateTitleAndMenus() +// { +// if (jmb.fileLoadingError != null && jmb.fileLoadingError.length() > 0) +// { +// repaint(); +// return; +// } +// setChainMenuItems(jmb.chainNames); +// jmb.colourBySequence(ap); +// +// setTitle(jmb.getViewerTitle()); +// } +// +// public void showUrl(String url) +// { +// try +// { +// ap.av.applet.getAppletContext().showDocument(new java.net.URL(url), +// "jmolOutput"); +// } catch (java.net.MalformedURLException ex) +// { +// } +// } +// +// Panel splitPane = null; +// +// public void showConsole(boolean showConsole) +// { +// if (showConsole) +// { +// remove(renderPanel); +// splitPane = new Panel(); +// +// splitPane.setLayout(new java.awt.GridLayout(2, 1)); +// splitPane.add(renderPanel); +// splitPane.add(scriptWindow); +// scriptWindow.setVisible(true); +// this.add(splitPane, BorderLayout.CENTER); +// splitPane.setVisible(true); +// splitPane.validate(); +// } +// else +// { +// scriptWindow.setVisible(false); +// remove(splitPane); +// add(renderPanel, BorderLayout.CENTER); +// splitPane = null; +// } +// validate(); +// } +// +// public float[][] functionXY(String functionName, int x, int y) +// { +// return null; +// } +// +// // /End JmolStatusListener +// // ///////////////////////////// +// class RenderPanel extends Panel { Dimension currentSize = new Dimension(); @@ -647,59 +660,59 @@ public class AppletJmol extends EmbmenuFrame implements paint(g); } - public void paint(Graphics g) + public void PaintComponent(Graphics g) { currentSize = this.getSize(); - if (jmb.viewer == null) - { - g.setColor(Color.black); - g.fillRect(0, 0, currentSize.width, currentSize.height); - g.setColor(Color.white); - g.setFont(new Font("Verdana", Font.BOLD, 14)); - g.drawString(MessageManager.getString("label.retrieving_pdb_data"), - 20, currentSize.height / 2); - } - else - { - jmb.viewer.renderScreenImage(g, currentSize.width, - currentSize.height); - } - } - } - - /* - * @Override public Color getColour(int atomIndex, int pdbResNum, String - * chain, String pdbId) { return jmb.getColour(atomIndex, pdbResNum, chain, - * pdbId); } - * - * @Override public String[] getPdbFile() { return jmb.getPdbFile(); } - * - * @Override public void highlightAtom(int atomIndex, int pdbResNum, String - * chain, String pdbId) { jmb.highlightAtom(atomIndex, pdbResNum, chain, - * pdbId); - * - * } - * - * @Override public void mouseOverStructure(int atomIndex, String strInfo) { - * jmb.mouseOverStructure(atomIndex, strInfo); - * - * } - */ - public void setJalviewColourScheme(UserColourScheme ucs) - { - jmb.setJalviewColourScheme(ucs); - } - - public AlignmentPanel getAlignmentPanelFor(AlignmentI alignment) - { - for (int i = 0; i < _aps.size(); i++) - { - if (_aps.get(i).av.getAlignment() == alignment) - { - return (_aps.get(i)); - } +// if (jmb.viewer == null) +// { +// g.setColor(Color.black); +// g.fillRect(0, 0, currentSize.width, currentSize.height); +// g.setColor(Color.white); +// g.setFont(new Font("Verdana", Font.BOLD, 14)); +// g.drawString(MessageManager.getString("label.retrieving_pdb_data"), +// 20, currentSize.height / 2); +// } +// else +// { +// jmb.viewer.renderScreenImage(g, currentSize.width, +// currentSize.height); +// } } - return ap; } +// +// /* +// * @Override public Color getColour(int atomIndex, int pdbResNum, String +// * chain, String pdbId) { return jmb.getColour(atomIndex, pdbResNum, chain, +// * pdbId); } +// * +// * @Override public String[] getPdbFile() { return jmb.getPdbFile(); } +// * +// * @Override public void highlightAtom(int atomIndex, int pdbResNum, String +// * chain, String pdbId) { jmb.highlightAtom(atomIndex, pdbResNum, chain, +// * pdbId); +// * +// * } +// * +// * @Override public void mouseOverStructure(int atomIndex, String strInfo) { +// * jmb.mouseOverStructure(atomIndex, strInfo); +// * +// * } +// */ +// public void setJalviewColourScheme(UserColourScheme ucs) +// { +// jmb.setJalviewColourScheme(ucs); +// } +// +// public AlignmentPanel getAlignmentPanelFor(AlignmentI alignment) +// { +// for (int i = 0; i < _aps.size(); i++) +// { +// if (_aps.get(i).av.getAlignment() == alignment) +// { +// return (_aps.get(i)); +// } +// } +// return ap; +// } } diff --git a/src/jalview/appletgui/AppletJmolBinding.java b/src/jalview/appletgui/AppletJmolBinding.java index 7035058..d23d164 100644 --- a/src/jalview/appletgui/AppletJmolBinding.java +++ b/src/jalview/appletgui/AppletJmolBinding.java @@ -23,7 +23,7 @@ package jalview.appletgui; import jalview.api.AlignmentViewPanel; import jalview.datamodel.PDBEntry; import jalview.datamodel.SequenceI; -import jalview.ext.jmol.JalviewJmolBinding; +//import jalview.ext.jmol.JalviewJmolBinding; import jalview.structure.StructureSelectionManager; import java.awt.Container; @@ -31,168 +31,168 @@ import java.util.Map; import javajs.awt.Dimension; -import org.jmol.api.JmolAppConsoleInterface; -import org.jmol.console.AppletConsole; -import org.jmol.java.BS; +//import org.jmol.api.JmolAppConsoleInterface; +//import org.jmol.console.AppletConsole; +//import org.jmol.java.BS; -class AppletJmolBinding extends JalviewJmolBinding +class AppletJmolBinding //extends JalviewJmolBinding { - /** - * Window that contains the bound Jmol instance - */ - private AppletJmol appletJmolBinding; - - public AppletJmolBinding(AppletJmol appletJmol, - StructureSelectionManager sSm, PDBEntry[] pdbentry, - SequenceI[][] seq, String[][] chains, String protocol) - { - super(sSm, pdbentry, seq, chains, protocol); - appletJmolBinding = appletJmol; - } - - @Override - public jalview.api.FeatureRenderer getFeatureRenderer( - AlignmentViewPanel alignment) - { - AlignmentPanel ap = (AlignmentPanel) alignment; - if (appletJmolBinding.ap.av.isShowSequenceFeatures()) - { - if (appletJmolBinding.fr == null) - { - appletJmolBinding.fr = new jalview.appletgui.FeatureRenderer( - appletJmolBinding.ap.av); - } - - appletJmolBinding.fr - .transferSettings(appletJmolBinding.ap.seqPanel.seqCanvas - .getFeatureRenderer()); - } - - return appletJmolBinding.fr; - } - - @Override - public jalview.api.SequenceRenderer getSequenceRenderer( - AlignmentViewPanel alignment) - { - return new SequenceRenderer(((AlignmentPanel) alignment).av); - } - - @Override - public void sendConsoleEcho(String strEcho) - { - if (appletJmolBinding.scriptWindow == null) - { - appletJmolBinding.showConsole(true); - } - - appletJmolBinding.history.append("\n" + strEcho); - } - - @Override - public void sendConsoleMessage(String strStatus) - { - if (appletJmolBinding.history != null && strStatus != null - && !strStatus.equals("Script completed")) - { - appletJmolBinding.history.append("\n" + strStatus); - } - } - - @Override - public void showUrl(String url, String target) - { - appletJmolBinding.ap.alignFrame.showURL(url, target); - - } - - @Override - public void refreshGUI() - { - appletJmolBinding.updateTitleAndMenus(); - } - - public void updateColours(Object source) - { - AlignmentPanel ap = (AlignmentPanel) source; - colourBySequence(ap); - } - - public void showUrl(String url) - { - try - { - appletJmolBinding.ap.av.applet.getAppletContext().showDocument( - new java.net.URL(url), "jmol"); - } catch (java.net.MalformedURLException ex) - { - } - } - - public void newJmolPopup(boolean translateLocale, String menuName, - boolean asPopup) - { - // jmolpopup = new JmolAwtPopup(); // is this used? - // jmolpopup.jpiInitialize((viewer), menuName); - } - - @Override - public void notifyScriptTermination(String strStatus, int msWalltime) - { - // do nothing. - } - - public void selectionChanged(BS arg0) - { - // TODO Auto-generated method stub - - } - - @Override - public void refreshPdbEntries() - { - // noop - } - - @Override - public void showConsole(boolean show) - { - appletJmolBinding.showConsole(show); - } - - @Override - protected JmolAppConsoleInterface createJmolConsole( - Container consolePanel, String buttonsToShow) - { - JmolAppConsoleInterface appc = new AppletConsole(); - appc.start(viewer); - return appc; - } - - @Override - protected void releaseUIResources() - { - appletJmolBinding = null; - closeConsole(); - } - - @Override - public void releaseReferences(Object svl) - { - } - - @Override - public Dimension resizeInnerPanel(String data) - { - // TODO Auto-generated method stub - return null; - } - - @Override - public Map getJSpecViewProperty(String arg0) - { - // TODO Auto-generated method stub - return null; - } +// /** +// * Window that contains the bound Jmol instance +// */ +// private AppletJmol appletJmolBinding; +// +// public AppletJmolBinding(AppletJmol appletJmol, +// StructureSelectionManager sSm, PDBEntry[] pdbentry, +// SequenceI[][] seq, String[][] chains, String protocol) +// { +// super(sSm, pdbentry, seq, chains, protocol); +// appletJmolBinding = appletJmol; +// } +// +// @Override +// public jalview.api.FeatureRenderer getFeatureRenderer( +// AlignmentViewPanel alignment) +// { +// AlignmentPanel ap = (AlignmentPanel) alignment; +// if (appletJmolBinding.ap.av.isShowSequenceFeatures()) +// { +// if (appletJmolBinding.fr == null) +// { +// appletJmolBinding.fr = new jalview.appletgui.FeatureRenderer( +// appletJmolBinding.ap.av); +// } +// +// appletJmolBinding.fr +// .transferSettings(appletJmolBinding.ap.seqPanel.seqCanvas +// .getFeatureRenderer()); +// } +// +// return appletJmolBinding.fr; +// } +// +// @Override +// public jalview.api.SequenceRenderer getSequenceRenderer( +// AlignmentViewPanel alignment) +// { +// return new SequenceRenderer(((AlignmentPanel) alignment).av); +// } +// +// @Override +// public void sendConsoleEcho(String strEcho) +// { +// if (appletJmolBinding.scriptWindow == null) +// { +// appletJmolBinding.showConsole(true); +// } +// +// appletJmolBinding.history.append("\n" + strEcho); +// } +// +// @Override +// public void sendConsoleMessage(String strStatus) +// { +// if (appletJmolBinding.history != null && strStatus != null +// && !strStatus.equals("Script completed")) +// { +// appletJmolBinding.history.append("\n" + strStatus); +// } +// } +// +// @Override +// public void showUrl(String url, String target) +// { +// appletJmolBinding.ap.alignFrame.showURL(url, target); +// +// } +// +// @Override +// public void refreshGUI() +// { +// appletJmolBinding.updateTitleAndMenus(); +// } +// +// public void updateColours(Object source) +// { +// AlignmentPanel ap = (AlignmentPanel) source; +// colourBySequence(ap); +// } +// +// public void showUrl(String url) +// { +// try +// { +// appletJmolBinding.ap.av.applet.getAppletContext().showDocument( +// new java.net.URL(url), "jmol"); +// } catch (java.net.MalformedURLException ex) +// { +// } +// } +// +// public void newJmolPopup(boolean translateLocale, String menuName, +// boolean asPopup) +// { +// // jmolpopup = new JmolAwtPopup(); // is this used? +// // jmolpopup.jpiInitialize((viewer), menuName); +// } +// +// @Override +// public void notifyScriptTermination(String strStatus, int msWalltime) +// { +// // do nothing. +// } +// +// public void selectionChanged(BS arg0) +// { +// // TODO Auto-generated method stub +// +// } +// +// @Override +// public void refreshPdbEntries() +// { +// // noop +// } +// +// @Override +// public void showConsole(boolean show) +// { +// appletJmolBinding.showConsole(show); +// } +// +// @Override +// protected JmolAppConsoleInterface createJmolConsole( +// Container consolePanel, String buttonsToShow) +// { +// JmolAppConsoleInterface appc = new AppletConsole(); +// appc.start(viewer); +// return appc; +// } +// +// @Override +// protected void releaseUIResources() +// { +// appletJmolBinding = null; +// closeConsole(); +// } +// +// @Override +// public void releaseReferences(Object svl) +// { +// } +// +// @Override +// public Dimension resizeInnerPanel(String data) +// { +// // TODO Auto-generated method stub +// return null; +// } +// +// @Override +// public Map getJSpecViewProperty(String arg0) +// { +// // TODO Auto-generated method stub +// return null; +// } } diff --git a/src/jalview/appletgui/CutAndPasteTransfer.java b/src/jalview/appletgui/CutAndPasteTransfer.java index 20f61b5..a286a44 100644 --- a/src/jalview/appletgui/CutAndPasteTransfer.java +++ b/src/jalview/appletgui/CutAndPasteTransfer.java @@ -32,19 +32,21 @@ import jalview.io.AppletFormatAdapter; import jalview.io.FileParse; import jalview.io.IdentifyFile; import jalview.io.NewickFile; +import jalview.io.AlignFile; import jalview.io.TCoffeeScoreFile; +import jalview.jsdev.GenericFileAdapter; import jalview.schemes.ColourSchemeI; import jalview.schemes.TCoffeeColourScheme; import jalview.util.MessageManager; import java.awt.BorderLayout; -import java.awt.Button; +import awt2swing.Button; import java.awt.Dialog; import java.awt.Font; -import java.awt.Frame; -import java.awt.Label; -import java.awt.Panel; -import java.awt.TextArea; +import awt2swing.Frame; +import awt2swing.Label; +import awt2swing.Panel; +import awt2swing.TextArea; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseEvent; @@ -357,7 +359,7 @@ public class CutAndPasteTransfer extends Panel implements ActionListener, TCoffeeScoreFile tcf = null; try { - tcf = new TCoffeeScoreFile(textarea.getText(), + tcf = (TCoffeeScoreFile) GenericFileAdapter.getFile("TCoffeeScoreFile", textarea.getText(), AppletFormatAdapter.PASTE); if (tcf.isValid()) { @@ -426,16 +428,16 @@ public class CutAndPasteTransfer extends Panel implements ActionListener, PDBEntry pdb = new PDBEntry(); pdb.setFile(text); - if (alignFrame.alignPanel.av.applet.jmolAvailable) - { +// if (alignFrame.alignPanel.av.applet.jmolAvailable) +// { new AppletJmol(pdb, new SequenceI[] { seq }, null, alignFrame.alignPanel, AppletFormatAdapter.PASTE); - } - else - { - new MCview.AppletPDBViewer(pdb, new SequenceI[] - { seq }, null, alignFrame.alignPanel, AppletFormatAdapter.PASTE); - } +// } +// else +// { +// new MCview.AppletPDBViewer(pdb, new SequenceI[] +// { seq }, null, alignFrame.alignPanel, AppletFormatAdapter.PASTE); +// } } protected void cancel() diff --git a/src/jalview/appletgui/EditNameDialog.java b/src/jalview/appletgui/EditNameDialog.java index 2f6469b..1e984be 100644 --- a/src/jalview/appletgui/EditNameDialog.java +++ b/src/jalview/appletgui/EditNameDialog.java @@ -22,10 +22,10 @@ package jalview.appletgui; import java.awt.BorderLayout; import java.awt.Font; -import java.awt.Frame; -import java.awt.Label; -import java.awt.Panel; -import java.awt.TextField; +import awt2swing.Frame; +import awt2swing.Label; +import awt2swing.Panel; +import awt2swing.TextField; public class EditNameDialog extends JVDialog { diff --git a/src/jalview/appletgui/EmbmenuFrame.java b/src/jalview/appletgui/EmbmenuFrame.java index a26202b..afb2c1e 100644 --- a/src/jalview/appletgui/EmbmenuFrame.java +++ b/src/jalview/appletgui/EmbmenuFrame.java @@ -26,18 +26,21 @@ import java.awt.BorderLayout; import java.awt.Color; import java.awt.FlowLayout; import java.awt.Font; -import java.awt.Frame; +import awt2swing.Frame; import java.awt.HeadlessException; -import java.awt.Label; -import java.awt.Menu; -import java.awt.MenuBar; -import java.awt.Panel; -import java.awt.PopupMenu; +import awt2swing.Label; +import awt2swing.Menu; +import awt2swing.MenuBar; +import awt2swing.MenuItem; +import awt2swing.Panel; +import awt2swing.PopupMenu; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.util.HashMap; import java.util.Map; +import javax.swing.JMenuItem; + /** * This class implements a pattern for embedding toolbars as a panel with popups * for situations where the system menu bar is either invisible or @@ -91,7 +94,7 @@ public class EmbmenuFrame extends Frame implements MouseListener */ protected boolean embedMenuIfNeeded(Panel tobeAdjusted) { - MenuBar topMenuBar = getMenuBar(); + MenuBar topMenuBar = (MenuBar) getJMenuBar(); if (topMenuBar == null) { return false; @@ -101,7 +104,7 @@ public class EmbmenuFrame extends Frame implements MouseListener { // Build the embedded menu panel, allowing override with system font embeddedMenu = makeEmbeddedPopupMenu(topMenuBar, true, false); - setMenuBar(null); + unsetMenuBar(); // add the components to the Panel area. add(embeddedMenu, BorderLayout.NORTH); tobeAdjusted.setSize(getSize().width, @@ -162,6 +165,7 @@ public class EmbmenuFrame extends Frame implements MouseListener Panel embeddedMenu, MouseListener clickHandler) { + if (overrideFonts) { Font mbf = menuBar.getFont(); @@ -180,7 +184,7 @@ public class EmbmenuFrame extends Frame implements MouseListener // loop thru for (int mbi = 0, nMbi = menuBar.getMenuCount(); mbi < nMbi; mbi++) { - Menu mi = menuBar.getMenu(mbi); + Menu mi = (Menu) menuBar.getMenu(mbi); Label elab = new Label(mi.getLabel()); elab.setFont(font); // add the menu entries @@ -188,7 +192,11 @@ public class EmbmenuFrame extends Frame implements MouseListener int m, mSize = mi.getItemCount(); for (m = 0; m < mSize; m++) { - popup.add(mi.getItem(m)); + // BH slight difference in Swing -- no actual item separator, just null + if (mi.getItem(m) == null) + popup.addSeparator(); + else + popup.add(mi.getItem(m)); mSize--; m--; } diff --git a/src/jalview/appletgui/ExtJmol.java b/src/jalview/appletgui/ExtJmol.java index c1035bd..3f5a436 100644 --- a/src/jalview/appletgui/ExtJmol.java +++ b/src/jalview/appletgui/ExtJmol.java @@ -25,7 +25,10 @@ import jalview.api.FeatureRenderer; import jalview.api.SequenceRenderer; import jalview.datamodel.PDBEntry; import jalview.datamodel.SequenceI; -import jalview.ext.jmol.JalviewJmolBinding; +//import jalview.ext.jmol.JalviewJmolBinding; +import jalview.structure.AtomSpec; +import jalview.structure.StructureSelectionManager; +import jalview.structures.models.AAStructureBindingModel; import java.awt.Container; import java.util.ArrayList; @@ -33,8 +36,8 @@ import java.util.List; import java.util.Map; import java.util.Vector; -import org.jmol.api.JmolAppConsoleInterface; -import org.jmol.java.BS; +//import org.jmol.api.JmolAppConsoleInterface; +//import org.jmol.java.BS; import org.jmol.viewer.Viewer; /** @@ -43,165 +46,195 @@ import org.jmol.viewer.Viewer; * @author JimP * */ -public class ExtJmol extends JalviewJmolBinding +public class ExtJmol extends AAStructureBindingModel //extends JalviewJmolBinding { - private AlignmentPanel ap; - - protected ExtJmol(jalview.appletgui.AlignFrame alframe, - PDBEntry[] pdbentry, SequenceI[][] seq, String[][] chains, - String protocol) - { - super(alframe.alignPanel.getStructureSelectionManager(), pdbentry, seq, - chains, protocol); - } - - public ExtJmol(Viewer viewer, AlignmentPanel alignPanel, - SequenceI[][] seqs) - { - super(alignPanel.getStructureSelectionManager(), seqs, viewer); - ap = alignPanel; - notifyFileLoaded(null, null, null, null, 0); - } - - public void updateColours(Object source) - { - - // TODO Auto-generated method stub - - } - - public void showUrl(String arg0) - { - showUrl(arg0, "jmol"); - } - - @Override - public FeatureRenderer getFeatureRenderer(AlignmentViewPanel alignment) - { - AlignmentPanel ap = (AlignmentPanel) alignment; - if (ap.av.isShowSequenceFeatures()) - { - return ap.getFeatureRenderer(); - } - else - { - return null; - } - } - - @Override - public SequenceRenderer getSequenceRenderer(AlignmentViewPanel alignment) - { - return ((AlignmentPanel) alignment).getSequenceRenderer(); - } - - @Override - public void notifyScriptTermination(String strStatus, int msWalltime) - { - // ignore - } - - @Override - public void sendConsoleEcho(String strEcho) - { - // ignore - } - - @Override - public void sendConsoleMessage(String strStatus) - { - // ignore - } - - @Override - public void showUrl(String url, String target) - { - ap.alignFrame.showURL(url, target); - } - - @Override - public void refreshGUI() - { - // ignore - } - - public void selectionChanged(BS arg0) - { - System.out.println(arg0); - } - - @Override - public void refreshPdbEntries() - { - List pdbe = new ArrayList(); - List fileids = new ArrayList(); - SequenceI[] sq = ap.av.getAlignment().getSequencesArray(); - for (int s = 0; s < sq.length; s++) - { - Vector pdbids = sq[s].getPDBId(); - if (pdbids != null) - { - for (int pe = 0, peSize = pdbids.size(); pe < peSize; pe++) - { - PDBEntry pentry = pdbids.elementAt(pe); - if (!fileids.contains(pentry.getId())) - { - pdbe.add(pentry); - } - else - { - fileids.add(pentry.getId()); - } - } - } - } - PDBEntry[] newEntries = new PDBEntry[pdbe.size()]; - for (int pe = 0; pe < pdbe.size(); pe++) - { - newEntries[pe] = pdbe.get(pe); - } - setPdbentry(newEntries); - } - - @Override - public void showConsole(boolean show) - { - // This never gets called because we haven't overriden the associated Jmol's - // console - System.err - .println("WARNING: unexpected call to ExtJmol's showConsole method. (showConsole=" - + show); - } - - @Override - protected JmolAppConsoleInterface createJmolConsole( - Container consolePanel, String buttonsToShow) - { - // TODO Auto-generated method stub - return null; - } - - @Override - protected void releaseUIResources() - { - ap = null; - closeConsole(); - - } - - @Override - public void releaseReferences(Object svl) - { - // TODO Auto-generated method stub - - } - - @Override - public Map getJSpecViewProperty(String arg0) - { - // TODO Auto-generated method stub - return null; - } - + public ExtJmol(StructureSelectionManager ssm, PDBEntry[] pdbentry, + SequenceI[][] sequenceIs, String[][] chains, String protocol) { + super(ssm, pdbentry, sequenceIs, chains, protocol); + // TODO Auto-generated constructor stub + } + + @Override + public String[] getPdbFile() { + // TODO Auto-generated method stub + return null; + } + + @Override + public void updateColours(Object source) { + // TODO Auto-generated method stub + + } + + @Override + public void releaseReferences(Object svl) { + // TODO Auto-generated method stub + + } + + @Override + public void highlightAtoms(List atoms) { + // TODO Auto-generated method stub + + } + +// private AlignmentPanel ap; +// +// protected ExtJmol(jalview.appletgui.AlignFrame alframe, +// PDBEntry[] pdbentry, SequenceI[][] seq, String[][] chains, +// String protocol) +// { +// super(alframe.alignPanel.getStructureSelectionManager(), pdbentry, seq, +// chains, protocol); +// } +// +// public ExtJmol(Viewer viewer, AlignmentPanel alignPanel, +// SequenceI[][] seqs) +// { +// super(alignPanel.getStructureSelectionManager(), seqs, viewer); +// ap = alignPanel; +// notifyFileLoaded(null, null, null, null, 0); +// } +// +// public void updateColours(Object source) +// { +// +// // TODO Auto-generated method stub +// +// } +// +// public void showUrl(String arg0) +// { +// showUrl(arg0, "jmol"); +// } +// +// @Override +// public FeatureRenderer getFeatureRenderer(AlignmentViewPanel alignment) +// { +// AlignmentPanel ap = (AlignmentPanel) alignment; +// if (ap.av.isShowSequenceFeatures()) +// { +// return ap.getFeatureRenderer(); +// } +// else +// { +// return null; +// } +// } +// +// @Override +// public SequenceRenderer getSequenceRenderer(AlignmentViewPanel alignment) +// { +// return ((AlignmentPanel) alignment).getSequenceRenderer(); +// } +// +// @Override +// public void notifyScriptTermination(String strStatus, int msWalltime) +// { +// // ignore +// } +// +// @Override +// public void sendConsoleEcho(String strEcho) +// { +// // ignore +// } +// +// @Override +// public void sendConsoleMessage(String strStatus) +// { +// // ignore +// } +// +// @Override +// public void showUrl(String url, String target) +// { +// ap.alignFrame.showURL(url, target); +// } +// +// @Override +// public void refreshGUI() +// { +// // ignore +// } +// +// public void selectionChanged(BS arg0) +// { +// System.out.println(arg0); +// } +// +// @Override +// public void refreshPdbEntries() +// { +// List pdbe = new ArrayList(); +// List fileids = new ArrayList(); +// SequenceI[] sq = ap.av.getAlignment().getSequencesArray(); +// for (int s = 0; s < sq.length; s++) +// { +// Vector pdbids = sq[s].getPDBId(); +// if (pdbids != null) +// { +// for (int pe = 0, peSize = pdbids.size(); pe < peSize; pe++) +// { +// PDBEntry pentry = pdbids.elementAt(pe); +// if (!fileids.contains(pentry.getId())) +// { +// pdbe.add(pentry); +// } +// else +// { +// fileids.add(pentry.getId()); +// } +// } +// } +// } +// PDBEntry[] newEntries = new PDBEntry[pdbe.size()]; +// for (int pe = 0; pe < pdbe.size(); pe++) +// { +// newEntries[pe] = pdbe.get(pe); +// } +// setPdbentry(newEntries); +// } +// +// @Override +// public void showConsole(boolean show) +// { +// // This never gets called because we haven't overriden the associated Jmol's +// // console +// System.err +// .println("WARNING: unexpected call to ExtJmol's showConsole method. (showConsole=" +// + show); +// } +// +// @Override +// protected JmolAppConsoleInterface createJmolConsole( +// Container consolePanel, String buttonsToShow) +// { +// // TODO Auto-generated method stub +// return null; +// } +// +// @Override +// protected void releaseUIResources() +// { +// ap = null; +// closeConsole(); +// +// } +// +// @Override +// public void releaseReferences(Object svl) +// { +// // TODO Auto-generated method stub +// +// } +// +// @Override +// public Map getJSpecViewProperty(String arg0) +// { +// // TODO Auto-generated method stub +// return null; +// } +// } diff --git a/src/jalview/appletgui/FeatureColourChooser.java b/src/jalview/appletgui/FeatureColourChooser.java index 915d27f..fbc47c3 100644 --- a/src/jalview/appletgui/FeatureColourChooser.java +++ b/src/jalview/appletgui/FeatureColourChooser.java @@ -25,18 +25,18 @@ import jalview.schemes.AnnotationColourGradient; import jalview.schemes.GraduatedColor; import jalview.util.MessageManager; -import java.awt.Checkbox; -import java.awt.Choice; +import awt2swing.Checkbox; +import awt2swing.Choice; import java.awt.Color; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.Font; -import java.awt.Frame; +import awt2swing.Frame; import java.awt.GridLayout; -import java.awt.Label; -import java.awt.Panel; -import java.awt.Scrollbar; -import java.awt.TextField; +import awt2swing.Label; +import awt2swing.Panel; +import awt2swing.Scrollbar; +import awt2swing.TextField; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.AdjustmentEvent; diff --git a/src/jalview/appletgui/FeatureRenderer.java b/src/jalview/appletgui/FeatureRenderer.java index 8a0e528..2d996c7 100644 --- a/src/jalview/appletgui/FeatureRenderer.java +++ b/src/jalview/appletgui/FeatureRenderer.java @@ -31,18 +31,18 @@ import jalview.util.MessageManager; import jalview.viewmodel.AlignmentViewport; import java.awt.BorderLayout; -import java.awt.Button; -import java.awt.Choice; +import awt2swing.Button; +import awt2swing.Choice; import java.awt.Color; import java.awt.Dimension; import java.awt.Font; import java.awt.Graphics; import java.awt.GridLayout; -import java.awt.Label; -import java.awt.Panel; -import java.awt.ScrollPane; -import java.awt.TextArea; -import java.awt.TextField; +import awt2swing.Label; +import awt2swing.Panel; +import awt2swing.ScrollPane; +import awt2swing.TextArea; +import awt2swing.TextField; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.Hashtable; @@ -156,7 +156,7 @@ public class FeatureRenderer extends super(null); } - public void paint(Graphics g) + public void PaintComponent(Graphics g) { Dimension d = getSize(); if (isGcol) diff --git a/src/jalview/appletgui/FeatureSettings.java b/src/jalview/appletgui/FeatureSettings.java index 8984390..d8a6140 100755 --- a/src/jalview/appletgui/FeatureSettings.java +++ b/src/jalview/appletgui/FeatureSettings.java @@ -29,23 +29,23 @@ import jalview.schemes.GraduatedColor; import jalview.util.MessageManager; import java.awt.BorderLayout; -import java.awt.Button; -import java.awt.Checkbox; +import awt2swing.Button; +import awt2swing.Checkbox; import java.awt.Color; import java.awt.Component; import java.awt.Dimension; import java.awt.Font; import java.awt.FontMetrics; -import java.awt.Frame; +import awt2swing.Frame; import java.awt.Graphics; import java.awt.GridLayout; import java.awt.Image; -import java.awt.Label; -import java.awt.MenuItem; -import java.awt.Panel; -import java.awt.PopupMenu; -import java.awt.ScrollPane; -import java.awt.Scrollbar; +import awt2swing.Label; +import awt2swing.MenuItem; +import awt2swing.Panel; +import awt2swing.PopupMenu; +import awt2swing.ScrollPane; +import awt2swing.Scrollbar; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.AdjustmentEvent; @@ -184,7 +184,7 @@ public class FeatureSettings extends Panel implements ItemListener, height); } - public void paint(Graphics g) + public void PaintComponent(Graphics g) { g.setColor(Color.black); g.drawString(MessageManager @@ -202,10 +202,10 @@ public class FeatureSettings extends Panel implements ItemListener, { final String type = check.type; final Object typeCol = fr.getFeatureStyle(type); - java.awt.PopupMenu men = new PopupMenu(MessageManager.formatMessage( + awt2swing.PopupMenu men = new PopupMenu(MessageManager.formatMessage( "label.settings_for_type", new String[] { type })); - java.awt.MenuItem scr = new MenuItem( + awt2swing.MenuItem scr = new MenuItem( MessageManager.getString("label.sort_by_score")); men.add(scr); final FeatureSettings me = this; @@ -236,8 +236,8 @@ public class FeatureSettings extends Panel implements ItemListener, { final Object typeMinMax = minmax.get(type); /* - * final java.awt.CheckboxMenuItem chb = new - * java.awt.CheckboxMenuItem("Vary Height"); // this is broken at the + * final awt2swing.CheckboxMenuItem chb = new + * awt2swing.CheckboxMenuItem("Vary Height"); // this is broken at the * moment chb.setState(minmax.get(type) != null); * chb.addActionListener(new ActionListener() { * @@ -756,7 +756,7 @@ public class FeatureSettings extends Panel implements ItemListener, updateColor(featureStyle); } - public void paint(Graphics g) + public void PaintComponent(Graphics g) { Dimension d = getSize(); if (gcol != null) diff --git a/src/jalview/appletgui/Finder.java b/src/jalview/appletgui/Finder.java index 7315eea..885f877 100644 --- a/src/jalview/appletgui/Finder.java +++ b/src/jalview/appletgui/Finder.java @@ -27,15 +27,15 @@ import jalview.datamodel.SequenceI; import jalview.util.MessageManager; import jalview.viewmodel.AlignmentViewport; -import java.awt.Button; -import java.awt.Checkbox; +import awt2swing.Button; +import awt2swing.Checkbox; import java.awt.Font; -import java.awt.Frame; +import awt2swing.Frame; import java.awt.GridLayout; -import java.awt.Label; -import java.awt.Panel; +import awt2swing.Label; +import awt2swing.Panel; import java.awt.Rectangle; -import java.awt.TextField; +import awt2swing.TextField; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; diff --git a/src/jalview/appletgui/FontChooser.java b/src/jalview/appletgui/FontChooser.java index 739eeb2..f867afa 100644 --- a/src/jalview/appletgui/FontChooser.java +++ b/src/jalview/appletgui/FontChooser.java @@ -25,16 +25,16 @@ import jalview.bin.JalviewLite; import jalview.util.MessageManager; import java.awt.BorderLayout; -import java.awt.Button; -import java.awt.Checkbox; -import java.awt.Choice; +import awt2swing.Button; +import awt2swing.Checkbox; +import awt2swing.Choice; import java.awt.Color; import java.awt.FlowLayout; import java.awt.Font; import java.awt.FontMetrics; -import java.awt.Frame; -import java.awt.Label; -import java.awt.Panel; +import awt2swing.Frame; +import awt2swing.Label; +import awt2swing.Panel; import java.awt.Toolkit; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; diff --git a/src/jalview/appletgui/IdCanvas.java b/src/jalview/appletgui/IdCanvas.java index 5204094..62cc3a0 100755 --- a/src/jalview/appletgui/IdCanvas.java +++ b/src/jalview/appletgui/IdCanvas.java @@ -26,7 +26,7 @@ import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.Image; -import java.awt.Panel; +import awt2swing.Panel; import java.util.List; public class IdCanvas extends Panel @@ -144,7 +144,7 @@ public class IdCanvas extends Panel paint(g); } - public void paint(Graphics g) + public void PaintComponent(Graphics g) { if (getSize().height < 0 || getSize().width < 0) { diff --git a/src/jalview/appletgui/IdPanel.java b/src/jalview/appletgui/IdPanel.java index c4b9651..ffd7f8e 100755 --- a/src/jalview/appletgui/IdPanel.java +++ b/src/jalview/appletgui/IdPanel.java @@ -28,7 +28,7 @@ import jalview.util.UrlLink; import jalview.viewmodel.AlignmentViewport; import java.awt.BorderLayout; -import java.awt.Panel; +import awt2swing.Panel; import java.awt.event.InputEvent; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; diff --git a/src/jalview/appletgui/IdwidthAdjuster.java b/src/jalview/appletgui/IdwidthAdjuster.java index b537112..c1b8198 100755 --- a/src/jalview/appletgui/IdwidthAdjuster.java +++ b/src/jalview/appletgui/IdwidthAdjuster.java @@ -24,7 +24,7 @@ import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Image; -import java.awt.Panel; +import awt2swing.Panel; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.event.MouseMotionListener; @@ -120,7 +120,7 @@ public class IdwidthAdjuster extends Panel implements MouseListener, { } - public void paint(Graphics g) + public void PaintComponent(Graphics g) { g.setColor(Color.white); g.fillRect(0, 0, getSize().width, getSize().height); diff --git a/src/jalview/appletgui/JVDialog.java b/src/jalview/appletgui/JVDialog.java index 58c4feb..fc71393 100644 --- a/src/jalview/appletgui/JVDialog.java +++ b/src/jalview/appletgui/JVDialog.java @@ -21,11 +21,11 @@ package jalview.appletgui; import java.awt.BorderLayout; -import java.awt.Button; +import awt2swing.Button; import java.awt.Dialog; import java.awt.FlowLayout; -import java.awt.Frame; -import java.awt.Panel; +import awt2swing.Frame; +import awt2swing.Panel; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; diff --git a/src/jalview/appletgui/OverviewPanel.java b/src/jalview/appletgui/OverviewPanel.java index 5c5ae84..8bc0da8 100755 --- a/src/jalview/appletgui/OverviewPanel.java +++ b/src/jalview/appletgui/OverviewPanel.java @@ -25,10 +25,10 @@ import jalview.datamodel.SequenceI; import java.awt.Color; import java.awt.Dimension; -import java.awt.Frame; +import awt2swing.Frame; import java.awt.Graphics; import java.awt.Image; -import java.awt.Panel; +import awt2swing.Panel; import java.awt.event.ComponentAdapter; import java.awt.event.ComponentEvent; import java.awt.event.MouseEvent; @@ -467,7 +467,7 @@ public class OverviewPanel extends Panel implements Runnable, } @Override - public void paint(Graphics g) + public void paintComponent(Graphics g) { Graphics og = offscreen.getGraphics(); if (miniMe != null) diff --git a/src/jalview/appletgui/PCAPanel.java b/src/jalview/appletgui/PCAPanel.java index 1746736..c7e9a69 100644 --- a/src/jalview/appletgui/PCAPanel.java +++ b/src/jalview/appletgui/PCAPanel.java @@ -30,17 +30,17 @@ import jalview.util.MessageManager; import jalview.viewmodel.PCAModel; import java.awt.BorderLayout; -import java.awt.Button; -import java.awt.CheckboxMenuItem; -import java.awt.Choice; +import awt2swing.Button; +import awt2swing.CheckboxMenuItem; +import awt2swing.Choice; import java.awt.Color; import java.awt.FlowLayout; -import java.awt.Frame; -import java.awt.Label; -import java.awt.Menu; -import java.awt.MenuBar; -import java.awt.MenuItem; -import java.awt.Panel; +import awt2swing.Frame; +import awt2swing.Label; +import awt2swing.Menu; +import awt2swing.MenuBar; +import awt2swing.MenuItem; +import awt2swing.Panel; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ItemEvent; diff --git a/src/jalview/appletgui/PairwiseAlignPanel.java b/src/jalview/appletgui/PairwiseAlignPanel.java index 5548795..4d6038f 100644 --- a/src/jalview/appletgui/PairwiseAlignPanel.java +++ b/src/jalview/appletgui/PairwiseAlignPanel.java @@ -28,10 +28,10 @@ import jalview.util.Format; import jalview.util.MessageManager; import java.awt.BorderLayout; -import java.awt.Button; -import java.awt.Panel; -import java.awt.ScrollPane; -import java.awt.TextArea; +import awt2swing.Button; +import awt2swing.Panel; +import awt2swing.ScrollPane; +import awt2swing.TextArea; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.Vector; diff --git a/src/jalview/appletgui/RedundancyPanel.java b/src/jalview/appletgui/RedundancyPanel.java index 9ce4f26..5611460 100644 --- a/src/jalview/appletgui/RedundancyPanel.java +++ b/src/jalview/appletgui/RedundancyPanel.java @@ -30,7 +30,7 @@ import jalview.datamodel.SequenceGroup; import jalview.datamodel.SequenceI; import jalview.util.MessageManager; -import java.awt.Frame; +import awt2swing.Frame; import java.awt.event.ActionEvent; import java.awt.event.AdjustmentEvent; import java.awt.event.AdjustmentListener; diff --git a/src/jalview/appletgui/RotatableCanvas.java b/src/jalview/appletgui/RotatableCanvas.java index 63dcde0..2602e89 100755 --- a/src/jalview/appletgui/RotatableCanvas.java +++ b/src/jalview/appletgui/RotatableCanvas.java @@ -34,7 +34,7 @@ import java.awt.Dimension; import java.awt.Font; import java.awt.Graphics; import java.awt.Image; -import java.awt.Panel; +import awt2swing.Panel; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.awt.event.MouseEvent; @@ -326,7 +326,7 @@ public class RotatableCanvas extends Panel implements MouseListener, paint(g); } - public void paint(Graphics g) + public void PaintComponent(Graphics g) { if (points == null) { diff --git a/src/jalview/appletgui/ScalePanel.java b/src/jalview/appletgui/ScalePanel.java index 3bb676f..4466238 100755 --- a/src/jalview/appletgui/ScalePanel.java +++ b/src/jalview/appletgui/ScalePanel.java @@ -27,9 +27,9 @@ import jalview.util.MessageManager; import java.awt.Color; import java.awt.FontMetrics; import java.awt.Graphics; -import java.awt.MenuItem; -import java.awt.Panel; -import java.awt.PopupMenu; +import awt2swing.MenuItem; +import awt2swing.Panel; +import awt2swing.PopupMenu; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.InputEvent; @@ -351,7 +351,7 @@ public class ScalePanel extends Panel implements MouseMotionListener, paint(g); } - public void paint(Graphics g) + public void PaintComponent(Graphics g) { drawScale(g, av.getStartRes(), av.getEndRes(), getSize().width, getSize().height); diff --git a/src/jalview/appletgui/SeqCanvas.java b/src/jalview/appletgui/SeqCanvas.java index 0057194..90f7745 100755 --- a/src/jalview/appletgui/SeqCanvas.java +++ b/src/jalview/appletgui/SeqCanvas.java @@ -31,7 +31,7 @@ import java.awt.Color; import java.awt.FontMetrics; import java.awt.Graphics; import java.awt.Image; -import java.awt.Panel; +import awt2swing.Panel; public class SeqCanvas extends Panel { @@ -283,7 +283,7 @@ public class SeqCanvas extends Panel } @Override - public void paint(Graphics g) + public void paintComponent(Graphics g) { if (img != null diff --git a/src/jalview/appletgui/SeqPanel.java b/src/jalview/appletgui/SeqPanel.java index 348a921..1ff723a 100644 --- a/src/jalview/appletgui/SeqPanel.java +++ b/src/jalview/appletgui/SeqPanel.java @@ -44,7 +44,7 @@ import jalview.viewmodel.AlignmentViewport; import java.awt.BorderLayout; import java.awt.Font; import java.awt.FontMetrics; -import java.awt.Panel; +import awt2swing.Panel; import java.awt.Point; import java.awt.event.InputEvent; import java.awt.event.MouseEvent; diff --git a/src/jalview/appletgui/SliderPanel.java b/src/jalview/appletgui/SliderPanel.java index b267678..dbc94e8 100644 --- a/src/jalview/appletgui/SliderPanel.java +++ b/src/jalview/appletgui/SliderPanel.java @@ -26,15 +26,15 @@ import jalview.schemes.ColourSchemeI; import jalview.util.MessageManager; import java.awt.BorderLayout; -import java.awt.Button; -import java.awt.Checkbox; +import awt2swing.Button; +import awt2swing.Checkbox; import java.awt.Color; import java.awt.FlowLayout; -import java.awt.Frame; -import java.awt.Label; -import java.awt.Panel; -import java.awt.Scrollbar; -import java.awt.TextField; +import awt2swing.Frame; +import awt2swing.Label; +import awt2swing.Panel; +import awt2swing.Scrollbar; +import awt2swing.TextField; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.AdjustmentEvent; diff --git a/src/jalview/appletgui/SplitFrame.java b/src/jalview/appletgui/SplitFrame.java index 3d30800..ceab348 100644 --- a/src/jalview/appletgui/SplitFrame.java +++ b/src/jalview/appletgui/SplitFrame.java @@ -11,7 +11,9 @@ import jalview.viewmodel.AlignmentViewport; import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.GridLayout; -import java.awt.Panel; + +import awt2swing.MenuBar; +import awt2swing.Panel; public class SplitFrame extends EmbmenuFrame { @@ -83,7 +85,7 @@ public class SplitFrame extends EmbmenuFrame */ protected void constructSplit() { - setMenuBar(null); + unsetMenuBar(); outermost = new Panel(new GridLayout(2, 1)); Panel topPanel = new Panel(); @@ -95,7 +97,7 @@ public class SplitFrame extends EmbmenuFrame addAlignFrameComponents(bottomFrame, bottomPanel); } - /** + /** * Make any adjustments to the layout */ protected void adjustLayout() @@ -150,7 +152,7 @@ public class SplitFrame extends EmbmenuFrame { panel.setLayout(new BorderLayout()); Panel menuPanel = af - .makeEmbeddedPopupMenu(af.getMenuBar(), true, false); + .makeEmbeddedPopupMenu((MenuBar) af.getJMenuBar(), true, false); panel.add(menuPanel, BorderLayout.NORTH); panel.add(af.statusBar, BorderLayout.SOUTH); panel.add(af.alignPanel, BorderLayout.CENTER); diff --git a/src/jalview/appletgui/TitledPanel.java b/src/jalview/appletgui/TitledPanel.java index 1ae36f4..4594ba2 100644 --- a/src/jalview/appletgui/TitledPanel.java +++ b/src/jalview/appletgui/TitledPanel.java @@ -1,10 +1,10 @@ package jalview.appletgui; -import java.awt.Frame; +import awt2swing.Frame; import java.awt.Graphics; import java.awt.Insets; -import java.awt.Label; -import java.awt.Panel; +import awt2swing.Label; +import awt2swing.Panel; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; @@ -30,9 +30,9 @@ public class TitledPanel extends Panel return insets; } - public void paint(Graphics g) + public void paintComponent(Graphics g) { - super.paint(g); + super.paintComponent(g); g.setColor(getForeground()); g.drawRect(5, 5, getWidth() - 10, getHeight() - 10); int width = g.getFontMetrics().stringWidth(getTitle()); @@ -42,6 +42,11 @@ public class TitledPanel extends Panel g.drawString(getTitle(), 10, 10); } + /** + * @j2sIgnore + * + * @param args + */ public static void main(String[] args) { Frame f = new Frame("TitledPanel Tester"); diff --git a/src/jalview/appletgui/Tooltip.java b/src/jalview/appletgui/Tooltip.java index 7a65ec3..50f90ff 100755 --- a/src/jalview/appletgui/Tooltip.java +++ b/src/jalview/appletgui/Tooltip.java @@ -21,12 +21,10 @@ package jalview.appletgui; import java.applet.Applet; -import java.awt.Canvas; import java.awt.Color; import java.awt.Component; import java.awt.Container; import java.awt.FontMetrics; -import java.awt.Frame; import java.awt.Graphics; import java.awt.Image; import java.awt.LayoutManager; @@ -35,6 +33,9 @@ import java.awt.event.MouseListener; import java.awt.event.MouseMotionListener; import java.util.StringTokenizer; +import awt2swing.Canvas; +import awt2swing.Frame; + public class Tooltip extends Canvas implements MouseListener, MouseMotionListener { @@ -76,7 +77,7 @@ public class Tooltip extends Canvas implements MouseListener, } } - public void paint(Graphics g) + public void PaintComponent(Graphics g) { int w = getSize().width; int h = getSize().height; diff --git a/src/jalview/appletgui/TreeCanvas.java b/src/jalview/appletgui/TreeCanvas.java index 64dd412..3f149d0 100755 --- a/src/jalview/appletgui/TreeCanvas.java +++ b/src/jalview/appletgui/TreeCanvas.java @@ -40,10 +40,10 @@ import java.awt.Dimension; import java.awt.Font; import java.awt.FontMetrics; import java.awt.Graphics; -import java.awt.Panel; +import awt2swing.Panel; import java.awt.Point; import java.awt.Rectangle; -import java.awt.ScrollPane; +import awt2swing.ScrollPane; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.event.MouseMotionListener; @@ -421,7 +421,7 @@ public class TreeCanvas extends Panel implements MouseListener, } @Override - public void paint(Graphics g) + public void paintComponent(Graphics g) { if (tree == null) { diff --git a/src/jalview/appletgui/TreePanel.java b/src/jalview/appletgui/TreePanel.java index e5971e5..4cc7fab 100644 --- a/src/jalview/appletgui/TreePanel.java +++ b/src/jalview/appletgui/TreePanel.java @@ -33,12 +33,12 @@ import jalview.schemes.ResidueProperties; import jalview.util.MessageManager; import java.awt.BorderLayout; -import java.awt.CheckboxMenuItem; +import awt2swing.CheckboxMenuItem; import java.awt.Color; -import java.awt.Menu; -import java.awt.MenuBar; -import java.awt.MenuItem; -import java.awt.ScrollPane; +import awt2swing.Menu; +import awt2swing.MenuBar; +import awt2swing.MenuItem; +import awt2swing.ScrollPane; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ItemEvent; @@ -334,7 +334,7 @@ public class TreePanel extends EmbmenuFrame implements ActionListener, String output = fout.print(false, true); CutAndPasteTransfer cap = new CutAndPasteTransfer(false, null); cap.setText(output); - java.awt.Frame frame = new java.awt.Frame(); + awt2swing.Frame frame = new awt2swing.Frame(); frame.add(cap); JalviewLite.addFrame(frame, type + " " + pwtype, 500, 100); } diff --git a/src/jalview/appletgui/UserDefinedColours.java b/src/jalview/appletgui/UserDefinedColours.java index afea10d..af8a155 100644 --- a/src/jalview/appletgui/UserDefinedColours.java +++ b/src/jalview/appletgui/UserDefinedColours.java @@ -28,19 +28,19 @@ import jalview.schemes.ResidueProperties; import jalview.schemes.UserColourScheme; import jalview.util.MessageManager; -import java.awt.Button; +import awt2swing.Button; import java.awt.Color; import java.awt.Component; import java.awt.Container; import java.awt.Dialog; import java.awt.Font; -import java.awt.Frame; +import awt2swing.Frame; import java.awt.GridLayout; -import java.awt.Label; -import java.awt.Panel; +import awt2swing.Label; +import awt2swing.Panel; import java.awt.Rectangle; -import java.awt.Scrollbar; -import java.awt.TextField; +import awt2swing.Scrollbar; +import awt2swing.TextField; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.AdjustmentEvent; @@ -66,7 +66,7 @@ public class UserDefinedColours extends Panel implements ActionListener, Frame frame; - MCview.AppletPDBCanvas pdbcanvas; +// MCview.AppletPDBCanvas pdbcanvas; AppletJmol jmol; @@ -103,11 +103,11 @@ public class UserDefinedColours extends Panel implements ActionListener, init(); } - public UserDefinedColours(MCview.AppletPDBCanvas pdb) - { - this.pdbcanvas = pdb; - init(); - } +// public UserDefinedColours(MCview.AppletPDBCanvas pdb) +// { +// this.pdbcanvas = pdb; +// init(); +// } public UserDefinedColours(AppletJmol jmol) { @@ -515,10 +515,10 @@ public class UserDefinedColours extends Panel implements ActionListener, { jmol.setJalviewColourScheme(ucs); } - else if (pdbcanvas != null) - { - pdbcanvas.setColours(ucs); - } +// else if (pdbcanvas != null) +// { +// pdbcanvas.setColours(ucs); +// } } protected void cancelButton_actionPerformed() @@ -596,10 +596,10 @@ public class UserDefinedColours extends Panel implements ActionListener, { jmol.setJalviewColourScheme(ucs); } - else if (pdbcanvas != null) - { - pdbcanvas.pdb.setColours(ucs); - } +// else if (pdbcanvas != null) +// { +// pdbcanvas.pdb.setColours(ucs); +// } frame.setVisible(false); } diff --git a/src/jalview/bin/Cache.java b/src/jalview/bin/Cache.java index 4ed6e1a..49bbf6c 100755 --- a/src/jalview/bin/Cache.java +++ b/src/jalview/bin/Cache.java @@ -1,947 +1,25 @@ -/* - * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$) - * Copyright (C) $$Year-Rel$$ The Jalview Authors - * - * This file is part of Jalview. - * - * Jalview is free software: you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation, either version 3 - * of the License, or (at your option) any later version. - * - * Jalview is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty - * of MERCHANTABILITY or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Jalview. If not, see . - * The Jalview Authors are detailed in the 'AUTHORS' file. - */ package jalview.bin; -import jalview.gui.UserDefinedColours; -import jalview.io.PIRFile; -import jalview.jbgui.GDesktop; -import jalview.schemes.ColourSchemeProperty; -import jalview.schemes.UserColourScheme; -import jalview.util.Format; -import jalview.ws.dbsources.das.api.DasSourceRegistryI; -import jalview.ws.dbsources.das.datamodel.DasSourceRegistry; - -import java.awt.Color; -import java.io.BufferedReader; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.Collections; -import java.util.Date; -import java.util.Enumeration; -import java.util.Properties; -import java.util.TreeSet; - -import org.apache.log4j.ConsoleAppender; -import org.apache.log4j.Level; -import org.apache.log4j.Logger; -import org.apache.log4j.SimpleLayout; - -/** - * Stores and retrieves Jalview Application Properties Lists and fields within - * list entries are separated by '|' symbols unless otherwise stated (|) clauses - * are alternative values for a tag.
- *
- * Current properties include: - *
    - *
    - * logs.Axis.Level - one of the stringified Levels for log4j controlling the - * logging level for axis (used for web services)
    - * - *
  • logs.Castor.Level - one of the stringified Levels for log4j controlling - * the logging level for castor (used for serialization)
    - *
  • - *
  • logs.Jalview.Level - Cache.log stringified level.
    - *
  • - *
  • SCREEN_WIDTH
  • - *
  • SCREEN_HEIGHT
  • - *
  • SCREEN_Y=285
  • - *
  • SCREEN_X=371
  • - *
  • SHOW_FULLSCREEN boolean
  • - *
  • FONT_NAME java font name for alignment text display
  • - *
  • FONT_SIZE size of displayed alignment text
  • - *
  • FONT_STYLE style of font displayed (sequence labels are always italic)
  • - *
  • GAP_SYMBOL character to treat as gap symbol (usually -,.,' ')
  • - *
  • LAST_DIRECTORY last directory for browsing alignment
  • - *
  • USER_DEFINED_COLOURS list of user defined colour scheme files
  • - *
  • SHOW_FULL_ID show id with '/start-end' numbers appended
  • - *
  • SHOW_IDENTITY show percentage identity annotation
  • - *
  • SHOW_QUALITY show alignment quality annotation
  • - *
  • SHOW_ANNOTATIONS show alignment annotation rows
  • - *
  • SHOW_CONSERVATION show alignment conservation annotation
  • - *
  • SORT_ANNOTATIONS currently either SEQUENCE_AND_LABEL or - * LABEL_AND_SEQUENCE
  • - *
  • SHOW_AUTOCALC_ABOVE true to show autocalculated annotations above - * sequence annotations
  • - *
  • CENTRE_COLUMN_LABELS centre the labels at each column in a displayed - * annotation row
  • - *
  • DEFAULT_COLOUR default colour scheme to apply for a new alignment
  • - *
  • DEFAULT_FILE_FORMAT file format used to save
  • - *
  • STARTUP_FILE file loaded on startup (may be a fully qualified url)
  • - *
  • SHOW_STARTUP_FILE flag to control loading of startup file
  • - *
  • VERSION the version of the jalview build
  • - *
  • BUILD_DATE date of this build
  • - *
  • LATEST_VERSION the latest jalview version advertised on the - * www.jalview.org
  • - *
  • PIR_MODELLER boolean indicating if PIR files are written with MODELLER - * descriptions
  • - *
  • (FASTA,MSF,PILEUP,CLUSTAL,BLC,PIR,PFAM)_JVSUFFIX boolean for adding jv - * suffix to file
  • - *
  • RECENT_URL list of recently retrieved URLs
  • - *
  • RECENT_FILE list of recently opened files
  • - *
  • USE_PROXY flag for whether a http proxy is to be used
  • - *
  • PROXY_SERVER the proxy
  • - *
  • PROXY_PORT
  • - *
  • NOQUESTIONNAIRES true to prevent jalview from checking the questionnaire - * service
  • - *
  • QUESTIONNAIRE last questionnaire:responder id string from questionnaire - * service
  • - *
  • USAGESTATS (false - user prompted) Enable google analytics tracker for - * collecting usage statistics
  • - *
  • DAS_LOCAL_SOURCE list of local das sources
  • - *
  • SHOW_OVERVIEW boolean for overview window display
  • - *
  • ANTI_ALIAS boolean for smooth fonts
  • - *
  • RIGHT_ALIGN_IDS boolean
  • - *
  • AUTO_CALC_CONSENSUS boolean for automatic recalculation of consensus
  • - *
  • PAD_GAPS boolean
  • - *
  • ID_ITALICS boolean
  • - *
  • SHOW_JV_SUFFIX
  • - *
  • WRAP_ALIGNMENT
  • - *
  • EPS_RENDERING (Prompt each time|Lineart|Text) default for EPS rendering - * style check
  • - *
  • SORT_ALIGNMENT (No sort|Id|Pairwise Identity)
  • - *
  • SEQUENCE_LINKS list of name|URL pairs for opening a url with - * $SEQUENCE_ID$
  • - *
  • GROUP_LINKS list of name|URL[|<separator>] tuples - see - * jalview.utils.GroupURLLink for more info
  • - *
  • DAS_REGISTRY_URL the registry to query
  • - *
  • DEFAULT_BROWSER for unix
  • - *
  • DAS_ACTIVE_SOURCE list of active sources
  • - *
  • SHOW_MEMUSAGE boolean show memory usage and warning indicator on desktop - * (false)
  • - *
  • VERSION_CHECK (true) check for the latest release version from - * www.jalview.org (or the alias given by the www.jalview.org property)
  • - *
  • SHOW_NPFEATS_TOOLTIP (true) show non-positional features in the Sequence - * ID tooltip
  • - *
  • SHOW_DBREFS_TOOLTIP (true) show Database Cross References in the Sequence - * ID tooltip
  • - *
  • SHOW_UNCONSERVED (false) only render unconserved residues - conserved - * displayed as '.'
  • - *
  • SORT_BY_TREE (false) sort the current alignment view according to the - * order of a newly displayed tree
  • - *
  • DBFETCH_USEPICR (false) use PICR to recover valid DB references from - * sequence ID strings before attempting retrieval from any datasource
  • - *
  • SHOW_GROUP_CONSENSUS (false) Show consensus annotation for groups in the - * alignment.
  • - *
  • SHOW_GROUP_CONSERVATION (false) Show conservation annotation for groups - * in the alignment.
  • - *
  • SHOW_CONSENSUS_HISTOGRAM (false) Show consensus annotation row's - * histogram.
  • - *
  • SHOW_CONSENSUS_LOGO (false) Show consensus annotation row's sequence - * logo.
  • - *
  • NORMALISE_CONSENSUS_LOGO (false) Show consensus annotation row's sequence - * logo normalised to row height rather than histogram height.
  • - *
  • FOLLOW_SELECTIONS (true) Controls whether a new alignment view should - * respond to selections made in other alignments containing the same sequences. - *
  • - *
  • JWS2HOSTURLS comma-separated list of URLs to try for JABAWS services
  • - *
  • SHOW_WSDISCOVERY_ERRORS (true) Controls if the web service URL discovery - * warning dialog box is displayed.
  • - *
  • ANNOTATIONCOLOUR_MIN (orange) Shade used for minimum value of annotation - * when shading by annotation
  • - *
  • ANNOTATIONCOLOUR_MAX (red) Shade used for maximum value of annotation - * when shading by annotation
  • - *
  • www.jalview.org (http://www.jalview.org) a property enabling all HTTP - * requests to be redirected to a mirror of http://www.jalview.org
  • - *
  • FIGURE_AUTOIDWIDTH (false) Expand the left hand column of an exported - * alignment figure to accommodate even the longest sequence ID or annotation - * label.
  • - *
  • FIGURE_FIXEDIDWIDTH Specifies the width to use for the left-hand column - * when exporting an alignment as a figure (setting FIGURE_AUTOIDWIDTH to true - * will override this).
  • - *
  • STRUCT_FROM_PDB (false) derive secondary structure annotation from PDB - * record
  • - *
  • USE_RNAVIEW (false) use RNAViewer to derive secondary structure
  • - *
  • ADD_SS_ANN (false) add secondary structure annotation to alignment - * display
  • - *
  • ADD_TEMPFACT_ANN (false) add Temperature Factor annotation to alignment - * display
  • - *
  • STRUCTURE_DISPLAY choose from JMOL (default) or CHIMERA for 3D structure - * display
  • - *
  • CHIMERA_PATH specify full path to Chimera program (if non-standard)
  • - * - *
- * Deprecated settings: - *
    - * * - *
  • DISCOVERY_START - Boolean - controls if discovery services are queried on - * startup (JWS1 services only)
  • - *
  • DISCOVERY_URLS - comma separated list of Discovery Service endpoints. - * (JWS1 services only)
  • - *
  • SHOW_JWS1_SERVICES (true) enable or disable the original Jalview 2 - * services in the desktop GUI
  • - *
  • ENABLE_RSBS_EDITOR (false for 2.7 release) enable or disable RSBS editing - * panel in web service preferences
  • - *
- * - * @author $author$ - * @version $Revision$ - */ -public class Cache -{ - /** - * property giving log4j level for CASTOR loggers - */ - public static final String CASTORLOGLEVEL = "logs.Castor.level"; - - /** - * property giving log4j level for AXIS loggers - */ - public static final String AXISLOGLEVEL = "logs.Axis.level"; - - /** - * property giving log4j level for Jalview Log - */ - public static final String JALVIEWLOGLEVEL = "logs.Jalview.level"; - - public static final String DAS_LOCAL_SOURCE = "DAS_LOCAL_SOURCE"; - - public static final String DAS_REGISTRY_URL = "DAS_REGISTRY_URL"; - - public static final String DAS_ACTIVE_SOURCE = "DAS_ACTIVE_SOURCE"; - - /** - * Initialises the Jalview Application Log - */ - public static Logger log; - - /** Jalview Properties */ - public static Properties applicationProperties = new Properties() { - // override results in properties output in alphabetical order - @Override - public synchronized Enumeration keys() { - return Collections.enumeration(new TreeSet(super.keySet())); - } - }; - - /** Default file is ~/.jalview_properties */ - static String propertiesFile; - - private static boolean propsAreReadOnly = false; - - public static void initLogger() - { - if (log != null) - { - return; - } - try - { - // TODO: redirect stdout and stderr here in order to grab the output of - // the log - - ConsoleAppender ap = new ConsoleAppender(new SimpleLayout(), - "System.err"); - ap.setName("JalviewLogger"); - org.apache.log4j.Logger.getRootLogger().addAppender(ap); // catch all for - // log output - Logger laxis = Logger.getLogger("org.apache.axis"); - Logger lcastor = Logger.getLogger("org.exolab.castor"); - Cache.log = Logger.getLogger("jalview.bin.Jalview"); - - laxis.setLevel(Level.toLevel(Cache.getDefault("logs.Axis.Level", - Level.INFO.toString()))); - lcastor.setLevel(Level.toLevel(Cache.getDefault("logs.Castor.Level", - Level.INFO.toString()))); - lcastor = Logger.getLogger("org.exolab.castor.xml"); - lcastor.setLevel(Level.toLevel(Cache.getDefault("logs.Castor.Level", - Level.INFO.toString()))); - // lcastor = Logger.getLogger("org.exolab.castor.xml.Marshaller"); - // lcastor.setLevel(Level.toLevel(Cache.getDefault("logs.Castor.Level", - // Level.INFO.toString()))); - Cache.log.setLevel(Level.toLevel(Cache.getDefault( - "logs.Jalview.level", Level.INFO.toString()))); - // laxis.addAppender(ap); - // lcastor.addAppender(ap); - // Cache.log.addAppender(ap); - // Tell the user that debug is enabled - Cache.log.debug("Jalview Debugging Output Follows."); - } catch (Exception ex) - { - System.err.println("Problems initializing the log4j system\n"); - ex.printStackTrace(System.err); - } - } - - /** Called when Jalview is started */ - public static void loadProperties(String propsFile) - { - propertiesFile = propsFile; - if (propsFile == null) - { - propertiesFile = System.getProperty("user.home") + File.separatorChar - + ".jalview_properties"; - } - else - { - // don't corrupt the file we've been given. - propsAreReadOnly = true; - } - - try - { - InputStream fis; - try - { - fis = new java.net.URL(propertiesFile).openStream(); - System.out.println("Loading jalview properties from : " - + propertiesFile); - System.out - .println("Disabling Jalview writing to user's local properties file."); - propsAreReadOnly = true; - - } catch (Exception ex) - { - fis = null; - } - if (fis == null) - { - fis = new FileInputStream(propertiesFile); - } - applicationProperties.load(fis); - - // remove any old build properties - - deleteBuildProperties(); - fis.close(); - } catch (Exception ex) - { - System.out.println("Error reading properties file: " + ex); - } - - if (getDefault("USE_PROXY", false)) - { - String proxyServer = getDefault("PROXY_SERVER", ""), proxyPort = getDefault( - "PROXY_PORT", "8080"); - - System.out.println("Using proxyServer: " + proxyServer - + " proxyPort: " + proxyPort); - - System.setProperty("http.proxyHost", proxyServer); - System.setProperty("http.proxyPort", proxyPort); - } - - // LOAD THE AUTHORS FROM THE authors.props file - try - { - String authorDetails = "jar:".concat(Cache.class - .getProtectionDomain().getCodeSource().getLocation() - .toString().concat("!/authors.props")); - - java.net.URL localJarFileURL = new java.net.URL(authorDetails); - - InputStream in = localJarFileURL.openStream(); - applicationProperties.load(in); - in.close(); - } catch (Exception ex) - { - System.out.println("Error reading author details: " + ex); - applicationProperties.remove("AUTHORS"); - applicationProperties.remove("AUTHORFNAMES"); - applicationProperties.remove("YEAR"); - } - - // FIND THE VERSION NUMBER AND BUILD DATE FROM jalview.jar - // MUST FOLLOW READING OF LOCAL PROPERTIES FILE AS THE - // VERSION MAY HAVE CHANGED SINCE LAST USING JALVIEW - try - { - String buildDetails = "jar:".concat(Cache.class.getProtectionDomain() - .getCodeSource().getLocation().toString() - .concat("!/.build_properties")); - - java.net.URL localJarFileURL = new java.net.URL(buildDetails); - - InputStream in = localJarFileURL.openStream(); - applicationProperties.load(in); - in.close(); - } catch (Exception ex) - { - System.out.println("Error reading build details: " + ex); - applicationProperties.remove("VERSION"); - } - - String jnlpVersion = System.getProperty("jalview.version"); - String codeVersion = getProperty("VERSION"); - String codeInstallation = getProperty("INSTALLATION"); - if (codeVersion == null) - { - // THIS SHOULD ONLY BE THE CASE WHEN TESTING!! - codeVersion = "Test"; - jnlpVersion = "Test"; - codeInstallation = ""; - } - else - { - codeInstallation = " (" + codeInstallation + ")"; - } - - System.out - .println("Jalview Version: " + codeVersion + codeInstallation); - - // jnlpVersion will be null if we're using InstallAnywhere - // Dont do this check if running in headless mode - if (jnlpVersion == null - && getDefault("VERSION_CHECK", true) - && (System.getProperty("java.awt.headless") == null || System - .getProperty("java.awt.headless").equals("false"))) - { - - class VersionChecker extends Thread - { - public void run() - { - String orgtimeout = System - .getProperty("sun.net.client.defaultConnectTimeout"); - if (orgtimeout == null) - { - orgtimeout = "30"; - System.out.println("# INFO: Setting default net timeout to " - + orgtimeout + " seconds."); - } - String jnlpVersion = null; - try - { - System.setProperty("sun.net.client.defaultConnectTimeout", - "5000"); - java.net.URL url = new java.net.URL(Cache.getDefault( - "www.jalview.org", "http://www.jalview.org") - + "/webstart/jalview.jnlp"); - BufferedReader in = new BufferedReader(new InputStreamReader( - url.openStream())); - String line = null; - while ((line = in.readLine()) != null) - { - if (line.indexOf("jalview.version") == -1) - { - continue; - } - - line = line.substring(line.indexOf("value=") + 7); - line = line.substring(0, line.lastIndexOf("\"")); - jnlpVersion = line; - break; - } - } catch (Exception ex) - { - System.out - .println("Non-fatal exceptions when checking version at www.jalview.org :"); - System.out.println(ex); - jnlpVersion = getProperty("VERSION"); - } - System.setProperty("sun.net.client.defaultConnectTimeout", - orgtimeout); - - setProperty("LATEST_VERSION", jnlpVersion); - } - } - - VersionChecker vc = new VersionChecker(); - vc.start(); - } - else - { - if (jnlpVersion != null) - { - setProperty("LATEST_VERSION", jnlpVersion); - } - else - { - applicationProperties.remove("LATEST_VERSION"); - } - } - - setProperty("VERSION", codeVersion); - - // LOAD USERDEFINED COLOURS - UserDefinedColours - .initUserColourSchemes(getProperty("USER_DEFINED_COLOURS")); - PIRFile.useModellerOutput = Cache.getDefault("PIR_MODELLER", - false); - } - - private static void deleteBuildProperties() - { - applicationProperties.remove("LATEST_VERSION"); - applicationProperties.remove("VERSION"); - applicationProperties.remove("AUTHORS"); - applicationProperties.remove("AUTHORFNAMES"); - applicationProperties.remove("YEAR"); - applicationProperties.remove("BUILD_DATE"); - applicationProperties.remove("INSTALLATION"); - } - - /** - * Gets Jalview application property of given key. Returns null if key not - * found - * - * @param key - * Name of property - * - * @return Property value - */ - public static String getProperty(String key) - { - return applicationProperties.getProperty(key); - } - - /** - * These methods are used when checking if the saved preference is different - * to the default setting - */ - - public static boolean getDefault(String property, boolean def) - { - String string = getProperty(property); - if (string != null) - { - def = Boolean.valueOf(string).booleanValue(); - } - - return def; - } - - /** - * These methods are used when checking if the saved preference is different - * to the default setting - */ - public static String getDefault(String property, String def) - { - String string = getProperty(property); - if (string != null) - { - return string; - } - - return def; - } - - /** - * Stores property in the file "HOME_DIR/.jalview_properties" - * - * @param key - * Name of object - * @param obj - * String value of property - * - * @return String value of property - */ - public static String setProperty(String key, String obj) - { - - try - { - applicationProperties.setProperty(key, obj); - if (!propsAreReadOnly) - { - FileOutputStream out = new FileOutputStream(propertiesFile); - applicationProperties.store(out, "---JalviewX Properties File---"); - out.close(); - } - } catch (Exception ex) - { - System.out.println("Error setting property: " + key + " " + obj - + "\n" + ex); - } - return obj; - } - - /** - * remove the specified property from the jalview properties file - * - * @param string - */ - public static void removeProperty(String string) - { - applicationProperties.remove(string); - saveProperties(); - } - - /** - * save the properties to the jalview properties path - */ - public static void saveProperties() - { - if (!propsAreReadOnly) - { - try - { - FileOutputStream out = new FileOutputStream(propertiesFile); - applicationProperties.store(out, "---JalviewX Properties File---"); - out.close(); - } catch (Exception ex) - { - System.out.println("Error saving properties: " + ex); - } - } - } - - /** - * internal vamsas class discovery state - */ - private static int vamsasJarsArePresent = -1; - - /** - * Searches for vamsas client classes on class path. - * - * @return true if vamsas client is present on classpath - */ - public static boolean vamsasJarsPresent() - { - if (vamsasJarsArePresent == -1) - { - try - { - if (GDesktop.class.getClassLoader().loadClass( - "uk.ac.vamsas.client.VorbaId") != null) - { - Cache.log - .debug("Found Vamsas Classes (uk.ac..vamsas.client.VorbaId can be loaded)"); - vamsasJarsArePresent = 1; - Logger lvclient = Logger.getLogger("uk.ac.vamsas"); - lvclient.setLevel(Level.toLevel(Cache.getDefault( - "logs.Vamsas.Level", Level.INFO.toString()))); - - lvclient.addAppender(log.getAppender("JalviewLogger")); - // Tell the user that debug is enabled - lvclient.debug("Jalview Vamsas Client Debugging Output Follows."); - } - } catch (Exception e) - { - vamsasJarsArePresent = 0; - Cache.log.debug("Vamsas Classes are not present"); - } - } - return (vamsasJarsArePresent > 0); - } - - /** - * internal vamsas class discovery state - */ - private static int groovyJarsArePresent = -1; - - /** - * Searches for vamsas client classes on class path. - * - * @return true if vamsas client is present on classpath - */ - public static boolean groovyJarsPresent() - { - if (groovyJarsArePresent == -1) - { - try - { - if (Cache.class.getClassLoader().loadClass( - "groovy.lang.GroovyObject") != null) - { - Cache.log - .debug("Found Groovy (groovy.lang.GroovyObject can be loaded)"); - groovyJarsArePresent = 1; - Logger lgclient = Logger.getLogger("groovy"); - lgclient.setLevel(Level.toLevel(Cache.getDefault( - "logs.Groovy.Level", Level.INFO.toString()))); - - lgclient.addAppender(log.getAppender("JalviewLogger")); - // Tell the user that debug is enabled - lgclient.debug("Jalview Groovy Client Debugging Output Follows."); - } - } catch (Error e) - { - groovyJarsArePresent = 0; - Cache.log.debug("Groovy Classes are not present", e); - } catch (Exception e) - { - groovyJarsArePresent = 0; - Cache.log.debug("Groovy Classes are not present"); - } - } - return (groovyJarsArePresent > 0); - } - - /** - * GA tracker object - actually JGoogleAnalyticsTracker null if tracking not - * enabled. - */ - protected static Object tracker = null; - - protected static Class trackerfocus = null; - - protected static Class jgoogleanalyticstracker = null; - - /** - * Initialise the google tracker if it is not done already. - */ - public static void initGoogleTracker() - { - if (tracker == null) - { - if (jgoogleanalyticstracker == null) - { - // try to get the tracker class - try - { - jgoogleanalyticstracker = Cache.class - .getClassLoader() - .loadClass( - "com.boxysystems.jgoogleanalytics.JGoogleAnalyticsTracker"); - trackerfocus = Cache.class.getClassLoader().loadClass( - "com.boxysystems.jgoogleanalytics.FocusPoint"); - } catch (Exception e) - { - log.debug("com.boxysystems.jgoogleanalytics package is not present - tracking not enabled."); - tracker = null; - jgoogleanalyticstracker = null; - trackerfocus = null; - return; - } - } - // now initialise tracker - Exception re = null, ex = null; - Error err = null; - String vrs = "No Version Accessible"; - try - { - // Google analytics tracking code for Library Finder - tracker = jgoogleanalyticstracker.getConstructor(new Class[] - { String.class, String.class, String.class }).newInstance( - new Object[] - { - "Jalview Desktop", - (vrs = Cache.getProperty("VERSION") - + "_" - + Cache.getDefault("BUILD_DATE", - "unknown")), "UA-9060947-1" }); - jgoogleanalyticstracker.getMethod("trackAsynchronously", - new Class[] - { trackerfocus }).invoke(tracker, new Object[] - { trackerfocus.getConstructor(new Class[] - { String.class }).newInstance(new Object[] - { "Application Started." }) }); - } catch (RuntimeException e) - { - re = e; - } catch (Exception e) - { - ex = e; - } catch (Error e) - { - err = e; - } - if (re != null || ex != null || err != null) - { - if (log != null) - { - if (re != null) - { - log.debug("Caught runtime exception in googletracker init:", re); - } - if (ex != null) - { - log.warn( - "Failed to initialise GoogleTracker for Jalview Desktop with version " - + vrs, ex); - } - if (err != null) - { - log.error( - "Whilst initing GoogleTracker for Jalview Desktop version " - + vrs, err); - } - } - else - { - if (re != null) - { - System.err - .println("Debug: Caught runtime exception in googletracker init:" - + vrs); - re.printStackTrace(); - } - if (ex != null) - { - System.err - .println("Warning: Failed to initialise GoogleTracker for Jalview Desktop with version " - + vrs); - ex.printStackTrace(); - } - - if (err != null) - { - System.err - .println("ERROR: Whilst initing GoogleTracker for Jalview Desktop version " - + vrs); - err.printStackTrace(); - } - } - } - else - { - log.debug("Successfully initialised tracker."); - } - } - } - - /** - * get the user's default colour if available - * - * @param property - * @param defcolour - * @return - */ - public static Color getDefaultColour(String property, Color defcolour) - { - String colprop = getProperty(property); - if (colprop == null) - { - return defcolour; - } - Color col = ColourSchemeProperty.getAWTColorFromName(colprop); - if (col == null) - { - try - { - col = new UserColourScheme(colprop).findColour('A'); - } catch (Exception ex) - { - log.warn("Couldn't parse '" + colprop + "' as a colour for " - + property); - col = null; - } - } - return (col == null) ? defcolour : col; - } - - /** - * store a colour as a Jalview user default property - * - * @param property - * @param colour - */ - public static void setColourProperty(String property, Color colour) - { - setProperty(property, Format.getHexString(colour)); - } - - public static final DateFormat date_format = SimpleDateFormat - .getDateTimeInstance(); - - /** - * store a date in a jalview property - * - * @param string - * @param time - */ - public static void setDateProperty(String property, Date time) - { - setProperty(property, date_format.format(time)); - } - - /** - * read a date stored in a jalview property - * - * @param property - * @return valid date as stored by setDateProperty, or null - * - */ - public static Date getDateProperty(String property) - { - String val = getProperty(property); - if (val != null) - { - try - { - return date_format.parse(val); - } catch (Exception ex) - { - System.err.println("Invalid or corrupt date in property '" - + property + "' : value was '" + val + "'"); - } - } - return null; - } - - /** - * get and parse a property as an integer. send any parsing problems to - * System.err - * - * @param property - * @return null or Integer - */ - public static Integer getIntegerProperty(String property) - { - String val = getProperty(property); - if (val != null && (val = val.trim()).length() > 0) - { - try - { - return Integer.valueOf(val); - } catch (NumberFormatException x) - { - System.err.println("Invalid integer in property '" + property - + "' (value was '" + val + "')"); - } - } - return null; - } - - private static DasSourceRegistryI sourceRegistry = null; - - /** - * initialise and .. - * - * @return instance of the das source registry - */ - public static DasSourceRegistryI getDasSourceRegistry() - { - if (sourceRegistry == null) - { - sourceRegistry = new DasSourceRegistry(); - } - return sourceRegistry; - } - - /** - * Set the specified value, or remove it if null or empty. Does not save the - * properties file. - * - * @param propName - * @param value - */ - public static void setOrRemove(String propName, String value) - { - if (propName == null) - { - return; - } - if (value == null || value.trim().length() < 1) - { - Cache.applicationProperties.remove(propName); - } - else - { - Cache.applicationProperties.setProperty(propName, value); - } - } +public class Cache { + public static final String CASTORLOGLEVEL = null; + public static Log log; + + public class Log { + + public void error(String string) { + // TODO Auto-generated method stub + + } + + public boolean isDebugEnabled() { + // TODO Auto-generated method stub + return false; + } + + } + + public static String getDefault(String string, String string2) { + // TODO Auto-generated method stub + return null; + } } diff --git a/src/jalview/bin/JalviewLite.java b/src/jalview/bin/JalviewLite.java index 5d1f0b0..3ec841a 100644 --- a/src/jalview/bin/JalviewLite.java +++ b/src/jalview/bin/JalviewLite.java @@ -27,6 +27,10 @@ import jalview.appletgui.AlignViewport; import jalview.appletgui.EmbmenuFrame; import jalview.appletgui.FeatureSettings; import jalview.appletgui.SplitFrame; +//import jalview.appletgui.AlignViewport; +//import jalview.appletgui.EmbmenuFrame; +//import jalview.appletgui.FeatureSettings; +//import jalview.appletgui.SplitFrame; import jalview.datamodel.Alignment; import jalview.datamodel.AlignmentI; import jalview.datamodel.AlignmentOrder; @@ -35,12 +39,14 @@ import jalview.datamodel.PDBEntry; import jalview.datamodel.Sequence; import jalview.datamodel.SequenceGroup; import jalview.datamodel.SequenceI; +import jalview.io.AlignFile; import jalview.io.AnnotationFile; import jalview.io.AppletFormatAdapter; import jalview.io.FileParse; import jalview.io.IdentifyFile; -import jalview.io.JPredFile; import jalview.io.JnetAnnotationMaker; +//import jalview.io.JPredFile; +//import jalview.io.JnetAnnotationMaker; import jalview.io.NewickFile; import jalview.javascript.JSFunctionExec; import jalview.javascript.JalviewLiteJsApi; @@ -48,19 +54,19 @@ import jalview.javascript.JsCallBack; import jalview.javascript.JsSelectionSender; import jalview.javascript.MouseOverListener; import jalview.javascript.MouseOverStructureListener; +import jalview.jsdev.GenericFileAdapter; +//import jalview.javascript.MouseOverListener; +//import jalview.javascript.MouseOverStructureListener; import jalview.schemes.ColourSchemeProperty; import jalview.schemes.UserColourScheme; import jalview.structure.SelectionListener; import jalview.structure.StructureSelectionManager; import jalview.util.MessageManager; -import java.applet.Applet; -import java.awt.Button; import java.awt.Color; import java.awt.Component; import java.awt.EventQueue; import java.awt.Font; -import java.awt.Frame; import java.awt.Graphics; import java.awt.event.ActionEvent; import java.awt.event.WindowAdapter; @@ -75,16 +81,21 @@ import java.util.List; import java.util.StringTokenizer; import java.util.Vector; -import netscape.javascript.JSException; +import javax.swing.JApplet; +import javax.swing.JButton; +import javax.swing.JFrame; + import netscape.javascript.JSObject; +//import netscape.javascript.JSObject; + /** * Jalview Applet. Runs in Java 1.18 runtime * * @author $author$ * @version $Revision: 1.92 $ */ -public class JalviewLite extends Applet implements +public class JalviewLite extends JApplet implements StructureSelectionManagerProvider, JalviewLiteJsApi { @@ -1213,7 +1224,7 @@ public class JalviewLite extends Applet implements public void scrollViewToColumnIn(final AlignFrame alf, final String leftHandColumn) { - java.awt.EventQueue.invokeLater(new Runnable() + EventQueue.invokeLater(new Runnable() { @Override @@ -1248,7 +1259,7 @@ public class JalviewLite extends Applet implements String file2 = null; - Button launcher = new Button( + JButton launcher = new JButton( MessageManager.getString("label.start_jalview")); /** @@ -1378,6 +1389,7 @@ public class JalviewLite extends Applet implements * turn on extra applet debugging */ debug = TRUE.equalsIgnoreCase(getParameter("debug")); + if (debug) { @@ -1472,7 +1484,14 @@ public class JalviewLite extends Applet implements if (embedded) { LoadingThread loader = new LoadingThread(file, file2, this); - loader.start(); + /** + * @j2sNative + * + * loader.run(); + */ + { + loader.start(); + } } else if (file != null) { @@ -1537,7 +1556,7 @@ public class JalviewLite extends Applet implements { notFailed = true; } - } catch (JSException jsex) + } catch (Exception jsex) { System.err.println("Attempt " + tries + " to access LiveConnect javascript failed."); @@ -1601,7 +1620,7 @@ public class JalviewLite extends Applet implements * @param height * height of new frame */ - public static void addFrame(final Frame frame, String title, int width, + public static void addFrame(final JFrame frame, String title, int width, int height) { frame.setLocation(lastFrameX, lastFrameY); @@ -1822,23 +1841,29 @@ public class JalviewLite extends Applet implements applet = _applet; } - public void run() - { - LoadJmolThread jmolchecker = new LoadJmolThread(); - jmolchecker.start(); - while (jmolchecker.notFinished()) - { - // wait around until the Jmol check is complete. - try - { - Thread.sleep(2); - } catch (Exception e) - { - } - } - startLoading(); - // applet.callInitCallback(); - } + public void run() { + /** + * + * @j2sNative + * + * + * System.out.println("BYPASSING JMOL LOADING FOR NOW. THIS WILL BE DONE ANOTHER WAY") + * + */ + { + LoadJmolThread jmolchecker = new LoadJmolThread(); + jmolchecker.start(); + while (jmolchecker.notFinished()) { + // wait around until the Jmol check is complete. + try { + Thread.sleep(2); + } catch (Exception e) { + } + } + } + startLoading(); + // applet.callInitCallback(); + } /** * Load the alignment and any related files as specified by applet @@ -2162,7 +2187,7 @@ public class JalviewLite extends Applet implements try { param = setProtocolState(param); - JPredFile predictions = new JPredFile(param, protocol); + AlignFile predictions = GenericFileAdapter.getFile("JPredFile", param, protocol); JnetAnnotationMaker.add_annotation(predictions, alignFrame.viewport.getAlignment(), 0, false); // false == do not add sequence profile from concise output @@ -2898,17 +2923,19 @@ public class JalviewLite extends Applet implements private String resolveUrlForLocalOrAbsolute(String url, URL localref) { String codebase = localref.toString(); - if (url.indexOf("/") == 0) - { - url = codebase.substring(0, codebase.length() - - localref.getFile().length()) - + url; - } - else - { - url = localref + url; - } - return url; + // BH removing file name and query + int pt = codebase.indexOf("?"); + if (pt < 0) + pt = codebase.length(); + codebase = codebase.substring(0, pt); + codebase = codebase.substring(0, codebase.lastIndexOf("/") + 1); + // codebase is now http://...xxx/ + if (url.indexOf("/") == 0 && !localref.getProtocol().equals("file")) + { // http:// https:// we do NOT allow going to the root file system directory! + pt = codebase.indexOf("/", 8); + return codebase.substring(0, pt) + url; + } + return codebase + url; } /** diff --git a/src/jalview/commands/EditCommand.java b/src/jalview/commands/EditCommand.java index e44068d..de80576 100644 --- a/src/jalview/commands/EditCommand.java +++ b/src/jalview/commands/EditCommand.java @@ -64,57 +64,79 @@ import java.util.Map; */ public class EditCommand implements CommandI { - public enum Action + public enum Action { INSERT_GAP - { - @Override - public Action getUndoAction() - { - return DELETE_GAP; - } - }, +// { +// @Override +// public Action getUndoAction() +// { +// return DELETE_GAP; +// } +// } + , DELETE_GAP - { - @Override - public Action getUndoAction() - { - return INSERT_GAP; - } - }, +// { +// @Override +// public Action getUndoAction() +// { +// return INSERT_GAP; +// } +// } + , CUT - { - @Override - public Action getUndoAction() - { - return PASTE; - } - }, +// { +// @Override +// public Action getUndoAction() +// { +// return PASTE; +// } +// } + , PASTE - { - @Override - public Action getUndoAction() - { - return CUT; - } - }, +// { +// @Override +// public Action getUndoAction() +// { +// return CUT; +// } +// } + , REPLACE - { - @Override - public Action getUndoAction() - { - return REPLACE; - } - }, +// { +// @Override +// public Action getUndoAction() +// { +// return REPLACE; +// } +// } + , INSERT_NUC - { - @Override - public Action getUndoAction() - { - return null; - } - }; - public abstract Action getUndoAction(); +// { +// @Override +// public Action getUndoAction() +// { +// return null; +// } +// } + ; + public Action getUndoAction() { + switch (this) { + case INSERT_GAP: + return DELETE_GAP; + case CUT: + return PASTE; + case DELETE_GAP: + return INSERT_GAP; + case INSERT_NUC: + return null; + case PASTE: + return CUT; + case REPLACE: + return REPLACE; + } + return null; + } }; private List edits = new ArrayList(); diff --git a/src/jalview/datamodel/Alignment.java b/src/jalview/datamodel/Alignment.java index 363ad0d..47e1127 100755 --- a/src/jalview/datamodel/Alignment.java +++ b/src/jalview/datamodel/Alignment.java @@ -22,6 +22,7 @@ package jalview.datamodel; import jalview.analysis.AlignmentUtils; import jalview.io.FastaFile; +import jalview.jsdev.GenericFileAdapter; import jalview.util.Comparison; import jalview.util.MessageManager; @@ -117,16 +118,21 @@ public class Alignment implements AlignmentI /** * Make an alignment from an array of Sequences. * + * * @param sequences */ public Alignment(SequenceI[] seqs) { initAlignment(seqs); } - + /** * Make a new alignment from an array of SeqCigars * + * no references in jalview? + * + * @j2sIgnore + * * @param seqs * SeqCigar[] */ @@ -1713,16 +1719,6 @@ public class Alignment implements AlignmentI } /** - * Returns the alignment in Fasta format. Behaviour of this method is not - * guaranteed between versions. - */ - @Override - public String toString() - { - return new FastaFile().print(getSequencesArray()); - } - - /** * Returns the set of distinct sequence names. No ordering is guaranteed. */ @Override @@ -1735,4 +1731,23 @@ public class Alignment implements AlignmentI } return names; } + + /** + * Returns the alignment in Fasta format. Behaviour of this method is not + * guaranteed between versions. + */ + @Override + public String toString() + { + SequenceI[] seq = this.getSequencesArray(); + /** + * @j2sNative + * + * return "" + JSON.stringify(seq); + */ + { + return ((FastaFile) GenericFileAdapter.getFile("FastaFile")).print(seq); + } + } + } diff --git a/src/jalview/datamodel/AlignmentView.java b/src/jalview/datamodel/AlignmentView.java index 5457fbc..ae8816d 100644 --- a/src/jalview/datamodel/AlignmentView.java +++ b/src/jalview/datamodel/AlignmentView.java @@ -626,7 +626,7 @@ public class AlignmentView } else { - smsa = new SequenceI[1][]; + smsa = new SequenceI[1][]; // BH this is fine; it's just int[n][], float[n][], etc. that are the problem. smsa[0] = new SequenceI[sequences.length]; for (int s = 0; s < sequences.length; s++) { diff --git a/src/jalview/datamodel/CigarBase.java b/src/jalview/datamodel/CigarBase.java index 1506cee..c44cc69 100644 --- a/src/jalview/datamodel/CigarBase.java +++ b/src/jalview/datamodel/CigarBase.java @@ -80,7 +80,7 @@ public abstract class CigarBase public Object[] getSequenceAndDeletions(String reference, char GapChar) { int rlength = 0; - int[][] deletions = new int[length][]; + int[][] deletions = javajs.util.AU.newInt2(length);// BH new int[length][]; int[][] trunc_deletions = null; StringBuffer sq = new StringBuffer(); int cursor = 0, alcursor = 0, start = 0, startpos = 0, end = 0, endpos = 0, delcount = -1; diff --git a/src/jalview/datamodel/Sequence.java b/src/jalview/datamodel/Sequence.java index e1f9d00..1bc559a 100755 --- a/src/jalview/datamodel/Sequence.java +++ b/src/jalview/datamodel/Sequence.java @@ -21,6 +21,8 @@ package jalview.datamodel; import jalview.analysis.AlignSeq; +import jalview.jsdev.api.RegExpInterface; +import jalview.jsdev.api.VarnaRNA; import jalview.schemes.ResidueProperties; import jalview.util.Comparison; import jalview.util.StringUtils; @@ -30,9 +32,9 @@ import java.util.Enumeration; import java.util.List; import java.util.Vector; -import com.stevesoft.pat.Regex; +import jalview.jsdev.RegExp; -import fr.orsay.lri.varna.models.rna.RNA; +//import fr.orsay.lri.varna.models.rna.RNA; /** * @@ -61,7 +63,7 @@ public class Sequence extends ASequence implements SequenceI DBRefEntry[] dbrefs; - RNA rna; + VarnaRNA rna; /** @@ -123,9 +125,9 @@ public class Sequence extends ASequence implements SequenceI checkValidRange(); } - Regex limitrx = new Regex("[/][0-9]{1,}[-][0-9]{1,}$"); + RegExpInterface limitrx = RegExp.newRegex("[/][0-9]{1,}[-][0-9]{1,}$"); - Regex endrx = new Regex("[0-9]{1,}$"); + RegExpInterface endrx = RegExp.newRegex("[0-9]{1,}$"); void parseId() { @@ -1276,12 +1278,12 @@ public class Sequence extends ASequence implements SequenceI index = value; } - public void setRNA(RNA r) + public void setRNA(VarnaRNA r) { rna = r; } - public RNA getRNA() + public VarnaRNA getRNA() { return rna; } @@ -1305,5 +1307,4 @@ public class Sequence extends ASequence implements SequenceI return result; } - } diff --git a/src/jalview/datamodel/SequenceI.java b/src/jalview/datamodel/SequenceI.java index f69c8b6..55215a6 100755 --- a/src/jalview/datamodel/SequenceI.java +++ b/src/jalview/datamodel/SequenceI.java @@ -20,10 +20,12 @@ */ package jalview.datamodel; +import jalview.jsdev.api.VarnaRNA; + import java.util.List; import java.util.Vector; -import fr.orsay.lri.varna.models.rna.RNA; +//import fr.orsay.lri.varna.models.rna.RNA; /** * Methods for manipulating a sequence, its metadata and related annotation in @@ -406,13 +408,13 @@ public interface SequenceI extends ASequenceI * @return The RNA of the sequence in the alignment */ - public RNA getRNA(); + public VarnaRNA getRNA(); /** * @param rna * The RNA. */ - public void setRNA(RNA rna); + public void setRNA(VarnaRNA rna); /** * diff --git a/src/jalview/io/AlignmentProperties.java b/src/jalview/io/AlignmentProperties.java index cb4b7ad..6ba0b7f 100644 --- a/src/jalview/io/AlignmentProperties.java +++ b/src/jalview/io/AlignmentProperties.java @@ -20,8 +20,7 @@ */ package jalview.io; -import java.io.PrintWriter; -import java.io.StringWriter; +import java.io.File; import java.util.Enumeration; import java.util.Hashtable; @@ -50,7 +49,7 @@ public class AlignmentProperties * @param pw * @param html */ - public void writeProperties(PrintWriter pw, boolean html) + public void writeProperties(StringBuffer sb, boolean html) { final String nl = html ? "
" : System.getProperty("line.separator"); float avg = 0; @@ -70,22 +69,22 @@ public class AlignmentProperties } } avg = avg / alignment.getHeight(); - pw.print(nl); - pw.print("Sequences: " + alignment.getHeight()); - pw.print(nl); - pw.print("Minimum Sequence Length: " + min); - pw.print(nl); - pw.print("Maximum Sequence Length: " + max); - pw.print(nl); - pw.print("Average Length: " + (int) avg); + sb.append(nl); + sb.append("Sequences: " + alignment.getHeight()); + sb.append(nl); + sb.append("Minimum Sequence Length: " + min); + sb.append(nl); + sb.append("Maximum Sequence Length: " + max); + sb.append(nl); + sb.append("Average Length: " + (int) avg); if (((Alignment) alignment).alignmentProperties != null) { - pw.print(nl); - pw.print(nl); + sb.append(nl); + sb.append(nl); if (html) { - pw.print(""); + sb.append("
"); } Hashtable props = ((Alignment) alignment).alignmentProperties; Enumeration en = props.keys(); @@ -112,16 +111,16 @@ public class AlignmentProperties } pos = npos + 1; } while (npos != -1); - pw.print(""); + sb.append(""); } else { - pw.print(nl + key + "\t" + vals); + sb.append(nl + key + "\t" + vals); } } if (html) { - pw.print("
" + key + "" + val + "
" + key + "" + val + "
"); + sb.append(""); } } } @@ -138,9 +137,9 @@ public class AlignmentProperties protected StringBuffer formatReport(boolean html) { - StringWriter content = new StringWriter(); - writeProperties(new PrintWriter(content), html); - return content.getBuffer(); + StringBuffer sb = new StringBuffer(); // BH was PrintBuffer + writeProperties(sb, html); + return sb; } /** @@ -152,5 +151,5 @@ public class AlignmentProperties { return formatReport(true); } - + } diff --git a/src/jalview/io/AnnotationFile.java b/src/jalview/io/AnnotationFile.java index 8706ad5..0042141 100755 --- a/src/jalview/io/AnnotationFile.java +++ b/src/jalview/io/AnnotationFile.java @@ -30,6 +30,7 @@ import jalview.datamodel.GraphLine; import jalview.datamodel.HiddenSequences; import jalview.datamodel.SequenceGroup; import jalview.datamodel.SequenceI; +import jalview.jsdev.GenericFileAdapter; import jalview.schemes.ColourSchemeI; import jalview.schemes.ColourSchemeProperty; import jalview.schemes.ResidueProperties; @@ -38,10 +39,8 @@ import jalview.util.Comparison; import jalview.util.Format; import java.io.BufferedReader; -import java.io.FileReader; import java.io.InputStreamReader; import java.io.StringReader; -import java.net.URL; import java.util.ArrayList; import java.util.BitSet; import java.util.Enumeration; @@ -694,12 +693,11 @@ public class AnnotationFile { if (protocol.equals(AppletFormatAdapter.FILE)) { - in = new BufferedReader(new FileReader(file)); + in = GenericFileAdapter.getReader(file, false); } else if (protocol.equals(AppletFormatAdapter.URL)) { - URL url = new URL(file); - in = new BufferedReader(new InputStreamReader(url.openStream())); + in = GenericFileAdapter.getReader(file, true); } else if (protocol.equals(AppletFormatAdapter.PASTE)) { @@ -710,7 +708,7 @@ public class AnnotationFile java.io.InputStream is = getClass().getResourceAsStream("/" + file); if (is != null) { - in = new BufferedReader(new java.io.InputStreamReader(is)); + in = new BufferedReader(new InputStreamReader(is)); } } if (in != null) diff --git a/src/jalview/io/AppletFormatAdapter.java b/src/jalview/io/AppletFormatAdapter.java index e4c4f3d..c908b15 100755 --- a/src/jalview/io/AppletFormatAdapter.java +++ b/src/jalview/io/AppletFormatAdapter.java @@ -32,6 +32,11 @@ import java.io.File; import java.io.InputStream; import java.util.List; +import javajs.J2SIgnoreImport; + +import jalview.jsdev.Constants; +import jalview.jsdev.GenericFileAdapter; + /** * A low level class for alignment and feature IO with alignment formatting * methods used by both applet and application for generating flat alignment @@ -41,6 +46,7 @@ import java.util.List; * @author $author$ * @version $Revision$ */ +@J2SIgnoreImport({java.io.File.class}) public class AppletFormatAdapter { private AlignmentViewPanel viewpanel; @@ -84,7 +90,7 @@ public class AppletFormatAdapter */ public static final String[] READABLE_FORMATS = new String[] { "BLC", "CLUSTAL", "FASTA", "MSF", "PileUp", "PIR", "PFAM", "STH", - "PDB", "JnetFile", "RNAML", PhylipFile.FILE_DESC, JSONFile.FILE_DESC, IdentifyFile.GFF3File, + "PDB", "JnetFile", "RNAML", Constants.Phylip_FILE_DESC, Constants.JSON_FILE_DESC, IdentifyFile.GFF3File, "HTML" }; /** @@ -93,9 +99,9 @@ public class AppletFormatAdapter */ public static final String[] READABLE_EXTENSIONS = new String[] { "fa, fasta, mfa, fastq", "aln", "pfam", "msf", "pir", "blc", "amsa", - "sto,stk", "xml,rnaml", PhylipFile.FILE_EXT, JSONFile.FILE_EXT, + "sto,stk", "xml,rnaml", Constants.Phylip_FILE_EXT, Constants.JSON_FILE_EXT, ".gff2,gff3", - "jar,jvp", HtmlFile.FILE_EXT }; + "jar,jvp", Constants.Html_FILE_EXT }; /** * List of readable formats by application in order corresponding to @@ -103,8 +109,8 @@ public class AppletFormatAdapter */ public static final String[] READABLE_FNAMES = new String[] { "Fasta", "Clustal", "PFAM", "MSF", "PIR", "BLC", "AMSA", "Stockholm", - "RNAML", PhylipFile.FILE_DESC, JSONFile.FILE_DESC, IdentifyFile.GFF3File, "Jalview", - HtmlFile.FILE_DESC }; + "RNAML", Constants.Phylip_FILE_DESC, Constants.JSON_FILE_DESC, IdentifyFile.GFF3File, "Jalview", + Constants.Html_FILE_DESC }; /** * List of valid format strings for use by callers of the formatSequences @@ -112,7 +118,7 @@ public class AppletFormatAdapter */ public static final String[] WRITEABLE_FORMATS = new String[] { "BLC", "CLUSTAL", "FASTA", "MSF", "PileUp", "PIR", "PFAM", "AMSA", - "STH", PhylipFile.FILE_DESC, JSONFile.FILE_DESC }; + "STH", Constants.Phylip_FILE_DESC, Constants.JSON_FILE_DESC }; /** * List of extensions corresponding to file format types in WRITABLE_FNAMES @@ -120,7 +126,7 @@ public class AppletFormatAdapter */ public static final String[] WRITABLE_EXTENSIONS = new String[] { "fa, fasta, mfa, fastq", "aln", "pfam", "msf", "pir", "blc", "amsa", - "sto,stk", PhylipFile.FILE_EXT, JSONFile.FILE_EXT, "jvp" }; + "sto,stk", Constants.Phylip_FILE_EXT, Constants.JSON_FILE_EXT, "jvp" }; /** * List of writable formats by the application. Order must correspond with the @@ -128,7 +134,7 @@ public class AppletFormatAdapter */ public static final String[] WRITABLE_FNAMES = new String[] { "Fasta", "Clustal", "PFAM", "MSF", "PIR", "BLC", "AMSA", "STH", - PhylipFile.FILE_DESC, JSONFile.FILE_DESC, "Jalview" }; + Constants.Phylip_FILE_DESC, Constants.JSON_FILE_DESC, "Jalview" }; public static String INVALID_CHARACTERS = "Contains invalid characters"; @@ -241,35 +247,35 @@ public class AppletFormatAdapter { if (format.equals("FASTA")) { - alignFile = new FastaFile(inFile, type); + alignFile = GenericFileAdapter.getFile("FastaFile", inFile, type); } else if (format.equals("MSF")) { - alignFile = new MSFfile(inFile, type); + alignFile = GenericFileAdapter.getFile("MSFfile", inFile, type); } else if (format.equals("PileUp")) { - alignFile = new PileUpfile(inFile, type); + alignFile = GenericFileAdapter.getFile("PileUpfile", inFile, type); } else if (format.equals("CLUSTAL")) { - alignFile = new ClustalFile(inFile, type); + alignFile = GenericFileAdapter.getFile("ClustalFile", inFile, type); } else if (format.equals("BLC")) { - alignFile = new BLCFile(inFile, type); + alignFile = GenericFileAdapter.getFile("BLCFile", inFile, type); } else if (format.equals("PIR")) { - alignFile = new PIRFile(inFile, type); + alignFile = GenericFileAdapter.getFile("PIRFile", inFile, type); } else if (format.equals("PFAM")) { - alignFile = new PfamFile(inFile, type); + alignFile = GenericFileAdapter.getFile("PfamFile", inFile, type); } else if (format.equals("JnetFile")) { - alignFile = new JPredFile(inFile, type); + alignFile = GenericFileAdapter.getFile("JPredFile", inFile, type); ((JPredFile) alignFile).removeNonSequences(); } else if (format.equals("PDB")) @@ -281,31 +287,31 @@ public class AppletFormatAdapter } else if (format.equals("STH")) { - alignFile = new StockholmFile(inFile, type); + alignFile = GenericFileAdapter.getFile("StockholmFile", inFile, type); } else if (format.equals("SimpleBLAST")) { - alignFile = new SimpleBlastFile(inFile, type); + alignFile = GenericFileAdapter.getFile("SimpleBlastFile", inFile, type); } else if (format.equals(PhylipFile.FILE_DESC)) { - alignFile = new PhylipFile(inFile, type); + alignFile = GenericFileAdapter.getFile("PhylipFile", inFile, type); } - else if (format.equals(JSONFile.FILE_DESC)) + else if (format.equals(Constants.JSON_FILE_DESC)) { - alignFile = new JSONFile(inFile, type); + alignFile = GenericFileAdapter.getFile("JSONFile", inFile, type); } - else if (format.equals(HtmlFile.FILE_DESC)) + else if (format.equals(Constants.Html_FILE_DESC)) { - alignFile = new HtmlFile(inFile, type); + alignFile = GenericFileAdapter.getFile("HtmlFile", inFile, type); } else if (format.equals("RNAML")) { - alignFile = new RnamlFile(inFile, type); + alignFile = GenericFileAdapter.getFile("RnamlFile", inFile, type); } else if (format.equals(IdentifyFile.GFF3File)) { - alignFile = new Gff3File(inFile, type); + alignFile = GenericFileAdapter.getFile("Gff3File", inFile, type); } return buildAlignmentFrom(alignFile); } catch (Exception e) @@ -326,7 +332,7 @@ public class AppletFormatAdapter try { // Possible sequence is just residues with no label - alignFile = new FastaFile(">UNKNOWN\n" + inFile, "Paste"); + alignFile = GenericFileAdapter.getFile("FastaFile", ">UNKNOWN\n" + inFile, "Paste"); return buildAlignmentFrom(alignFile); } catch (Exception ex) @@ -368,35 +374,35 @@ public class AppletFormatAdapter { if (format.equals("FASTA")) { - alignFile = new FastaFile(source); + alignFile = GenericFileAdapter.getFile("FastaFile", source); } else if (format.equals("MSF")) { - alignFile = new MSFfile(source); + alignFile = GenericFileAdapter.getFile("MSFfile", source); } else if (format.equals("PileUp")) { - alignFile = new PileUpfile(source); + alignFile = GenericFileAdapter.getFile("PileUpfile", source); } else if (format.equals("CLUSTAL")) { - alignFile = new ClustalFile(source); + alignFile = GenericFileAdapter.getFile("ClustalFile", source); } else if (format.equals("BLC")) { - alignFile = new BLCFile(source); + alignFile = GenericFileAdapter.getFile("BLCFile", source); } else if (format.equals("PIR")) { - alignFile = new PIRFile(source); + alignFile = GenericFileAdapter.getFile("PIRFile", source); } else if (format.equals("PFAM")) { - alignFile = new PfamFile(source); + alignFile = GenericFileAdapter.getFile("PfamFile", source); } else if (format.equals("JnetFile")) { - alignFile = new JPredFile(source); + alignFile = GenericFileAdapter.getFile("JPredFile", source); ((JPredFile) alignFile).removeNonSequences(); } else if (format.equals("PDB")) @@ -406,31 +412,31 @@ public class AppletFormatAdapter } else if (format.equals("STH")) { - alignFile = new StockholmFile(source); + alignFile = GenericFileAdapter.getFile("StockholmFile", source); } else if (format.equals("RNAML")) { - alignFile = new RnamlFile(source); + alignFile = GenericFileAdapter.getFile("RnamlFile", source); } else if (format.equals("SimpleBLAST")) { - alignFile = new SimpleBlastFile(source); + alignFile = GenericFileAdapter.getFile("SimpleBlastFile", source); } - else if (format.equals(PhylipFile.FILE_DESC)) + else if (format.equals(Constants.Phylip_FILE_DESC)) { - alignFile = new PhylipFile(source); + alignFile = GenericFileAdapter.getFile("PhylipFile", source); } else if (format.equals(IdentifyFile.GFF3File)) { - alignFile = new Gff3File(inFile, type); + alignFile = GenericFileAdapter.getFile("Gff3File", inFile, type); } - else if (format.equals(JSONFile.FILE_DESC)) + else if (format.equals(Constants.JSON_FILE_DESC)) { - alignFile = new JSONFile(source); + alignFile = GenericFileAdapter.getFile("JSONFile", source); } - else if (format.equals(HtmlFile.FILE_DESC)) + else if (format.equals(Constants.Html_FILE_DESC)) { - alignFile = new HtmlFile(source); + alignFile = GenericFileAdapter.getFile("HtmlFile", source); } return buildAlignmentFrom(alignFile); @@ -453,7 +459,7 @@ public class AppletFormatAdapter try { // Possible sequence is just residues with no label - alignFile = new FastaFile(">UNKNOWN\n" + inFile, "Paste"); + alignFile = GenericFileAdapter.getFile("FastaFile", ">UNKNOWN\n" + inFile, "Paste"); return buildAlignmentFrom(alignFile); } catch (Exception ex) @@ -546,51 +552,51 @@ public class AppletFormatAdapter AlignFile afile = null; if (format.equalsIgnoreCase("FASTA")) { - afile = new FastaFile(); + afile = GenericFileAdapter.getFile("FastaFile"); } else if (format.equalsIgnoreCase("MSF")) { - afile = new MSFfile(); + afile = GenericFileAdapter.getFile("MSFfile"); } else if (format.equalsIgnoreCase("PileUp")) { - afile = new PileUpfile(); + afile = GenericFileAdapter.getFile("PileUpfile"); // BH NOTE LOWER CASE "file" } else if (format.equalsIgnoreCase("CLUSTAL")) { - afile = new ClustalFile(); + afile = GenericFileAdapter.getFile("ClustalFile"); } else if (format.equalsIgnoreCase("BLC")) { - afile = new BLCFile(); + afile = GenericFileAdapter.getFile("BLCFile"); } else if (format.equalsIgnoreCase("PIR")) { - afile = new PIRFile(); + afile = GenericFileAdapter.getFile("PIRFile"); } else if (format.equalsIgnoreCase("PFAM")) { - afile = new PfamFile(); + afile = GenericFileAdapter.getFile("PfamFile"); } else if (format.equalsIgnoreCase("STH")) { - afile = new StockholmFile(alignment); + afile = GenericFileAdapter.getFile("StockholmFile", alignment); } else if (format.equalsIgnoreCase("AMSA")) { - afile = new AMSAFile(alignment); + afile = GenericFileAdapter.getFile("AMSAFile", alignment); } - else if (format.equalsIgnoreCase(PhylipFile.FILE_DESC)) + else if (format.equalsIgnoreCase(Constants.Phylip_FILE_DESC)) { - afile = new PhylipFile(); + afile = GenericFileAdapter.getFile("PhylipFile"); } - else if (format.equalsIgnoreCase(JSONFile.FILE_DESC)) + else if (format.equalsIgnoreCase(Constants.JSON_FILE_DESC)) { - afile = new JSONFile(); + afile = GenericFileAdapter.getFile("JSONFile"); } else if (format.equalsIgnoreCase("RNAML")) { - afile = new RnamlFile(); + afile = GenericFileAdapter.getFile("RnamlFile"); } else @@ -644,6 +650,11 @@ public class AppletFormatAdapter return protocol; } + /** + * @j2sIgnore + * + * @param args + */ public static void main(String[] args) { int i = 0; diff --git a/src/jalview/io/FastaFile.java b/src/jalview/io/FastaFile.java index 8dbfbfd..b867ba4 100755 --- a/src/jalview/io/FastaFile.java +++ b/src/jalview/io/FastaFile.java @@ -20,9 +20,13 @@ */ package jalview.io; -import java.io.*; +import jalview.datamodel.Alignment; +import jalview.datamodel.AlignmentAnnotation; +import jalview.datamodel.Annotation; +import jalview.datamodel.Sequence; +import jalview.datamodel.SequenceI; -import jalview.datamodel.*; +import java.io.IOException; /** * DOCUMENT ME! diff --git a/src/jalview/io/FeaturesFile.java b/src/jalview/io/FeaturesFile.java index f965d23..750c984 100755 --- a/src/jalview/io/FeaturesFile.java +++ b/src/jalview/io/FeaturesFile.java @@ -26,6 +26,7 @@ import jalview.datamodel.AlignmentI; import jalview.datamodel.SequenceDummy; import jalview.datamodel.SequenceFeature; import jalview.datamodel.SequenceI; +import jalview.jsdev.GenericFileAdapter; import jalview.schemes.AnnotationColourGradient; import jalview.schemes.GraduatedColor; import jalview.schemes.UserColourScheme; @@ -777,7 +778,7 @@ public class FeaturesFile extends AlignFile } catch (IOException q) { } - FastaFile parser = new FastaFile(this); + AlignFile parser = GenericFileAdapter.getFile("FastaFile"); List includedseqs = parser.getSeqs(); SequenceIdMatcher smatcher = new SequenceIdMatcher(newseqs); // iterate over includedseqs, and replacing matching ones with newseqs diff --git a/src/jalview/io/FileParse.java b/src/jalview/io/FileParse.java index 9228257..153067d 100755 --- a/src/jalview/io/FileParse.java +++ b/src/jalview/io/FileParse.java @@ -38,10 +38,13 @@ import java.net.MalformedURLException; import java.net.URL; import java.util.zip.GZIPInputStream; +import javajs.J2SIgnoreImport; + /** * implements a random access wrapper around a particular datasource, for * passing to identifyFile and AlignFile objects. */ +@J2SIgnoreImport({java.io.File.class, java.io.FileReader.class, java.io.FileInputStream.class }) public class FileParse { /** @@ -149,6 +152,10 @@ public class FileParse * Attempt to open a file as a datasource. Sets error and errormessage if * fileStr was invalid. * + * Not used by applet + * + * @j2sIgnore + * * @param fileStr * @return this.error (true if the source was invalid) */ @@ -191,13 +198,18 @@ public class FileParse } ; } - dataIn = new BufferedReader(new FileReader(fileStr)); dataName = fileStr; } return error; } + /** + * + * @param inputStream + * @return + * @throws Exception + */ private BufferedReader tryAsGzipSource(InputStream inputStream) throws Exception { @@ -279,110 +291,89 @@ public class FileParse * @throws MalformedURLException * @throws IOException */ - public FileParse(String fileStr, String type) - throws MalformedURLException, IOException - { - this.type = type; - error = false; - - if (type.equals(AppletFormatAdapter.FILE)) - { - if (checkFileSource(fileStr)) - { - String suffixLess = extractSuffix(fileStr); - if (suffixLess != null) - { - if (checkFileSource(suffixLess)) - { - throw new IOException(MessageManager.formatMessage("exception.problem_opening_file_also_tried", new String[]{inFile.getName(),suffixLess,errormessage})); - } - } - else - { - throw new IOException(MessageManager.formatMessage("exception.problem_opening_file", new String[]{inFile.getName(),errormessage})); - } - } - } - else if (type.equals(AppletFormatAdapter.URL)) - { - try - { - try - { - checkURLSource(fileStr); - if (suffixSeparator == '#') - { - extractSuffix(fileStr); // URL lref is stored for later reference. - } - } catch (IOException e) - { - String suffixLess = extractSuffix(fileStr); - if (suffixLess == null) - { - throw (e); - } - else - { - try - { - checkURLSource(suffixLess); - } catch (IOException e2) - { - errormessage = "BAD URL WITH OR WITHOUT SUFFIX"; - throw (e); // just pass back original - everything was wrong. - } - } - } - } catch (Exception e) - { - errormessage = "CANNOT ACCESS DATA AT URL '" + fileStr + "' (" - + e.getMessage() + ")"; - error = true; - } - } - else if (type.equals(AppletFormatAdapter.PASTE)) - { - errormessage = "PASTE INACCESSIBLE!"; - dataIn = new BufferedReader(new StringReader(fileStr)); - dataName = "Paste"; - } - else if (type.equals(AppletFormatAdapter.CLASSLOADER)) - { - errormessage = "RESOURCE CANNOT BE LOCATED"; - java.io.InputStream is = getClass() - .getResourceAsStream("/" + fileStr); - if (is == null) - { - String suffixLess = extractSuffix(fileStr); - if (suffixLess != null) - { - is = getClass().getResourceAsStream("/" + suffixLess); - } - } - if (is != null) - { - dataIn = new BufferedReader(new java.io.InputStreamReader(is)); - dataName = fileStr; - } - else - { - error = true; - } - } - else - { - errormessage = "PROBABLE IMPLEMENTATION ERROR : Datasource Type given as '" - + (type != null ? type : "null") + "'"; - error = true; - } - if (dataIn == null || error) - { - // pass up the reason why we have no source to read from - throw new IOException(MessageManager.formatMessage("exception.failed_to_read_data_from_source", new String[]{errormessage})); - } - error = false; - dataIn.mark(READAHEAD_LIMIT); - } + public FileParse(String fileStr, String type) throws MalformedURLException, IOException { + this.type = type; + error = false; + + if (type.equals(AppletFormatAdapter.FILE)) { + /** + * @j2sIgnore + * + */ + { + if (checkFileSource(fileStr)) { + String suffixLess = extractSuffix(fileStr); + if (suffixLess != null) { + if (checkFileSource(suffixLess)) { + throw new IOException(MessageManager.formatMessage( + "exception.problem_opening_file_also_tried", new String[] { + inFile.getName(), suffixLess, errormessage })); + } + } else { + throw new IOException(MessageManager.formatMessage( + "exception.problem_opening_file", + new String[] { inFile.getName(), errormessage })); + } + } + } + } else if (type.equals(AppletFormatAdapter.URL)) { + try { + try { + checkURLSource(fileStr); + if (suffixSeparator == '#') { + extractSuffix(fileStr); // URL lref is stored for later reference. + } + } catch (IOException e) { + String suffixLess = extractSuffix(fileStr); + if (suffixLess == null) { + throw (e); + } else { + try { + checkURLSource(suffixLess); + } catch (IOException e2) { + errormessage = "BAD URL WITH OR WITHOUT SUFFIX"; + throw (e); // just pass back original - everything was wrong. + } + } + } + } catch (Exception e) { + errormessage = "CANNOT ACCESS DATA AT URL '" + fileStr + "' (" + + e.getMessage() + ")"; + error = true; + } + } else if (type.equals(AppletFormatAdapter.PASTE)) { + errormessage = "PASTE INACCESSIBLE!"; + dataIn = new BufferedReader(new StringReader(fileStr)); + dataName = "Paste"; + } else if (type.equals(AppletFormatAdapter.CLASSLOADER)) { + errormessage = "RESOURCE CANNOT BE LOCATED"; + java.io.InputStream is = getClass().getResourceAsStream("/" + fileStr); + if (is == null) { + String suffixLess = extractSuffix(fileStr); + if (suffixLess != null) { + is = getClass().getResourceAsStream("/" + suffixLess); + } + } + if (is != null) { + dataIn = new BufferedReader(new java.io.InputStreamReader(is)); + dataName = fileStr; + } else { + error = true; + } + } else { + errormessage = "PROBABLE IMPLEMENTATION ERROR : Datasource Type given as '" + + (type != null ? type : "null") + "'"; + error = true; + } + if (dataIn == null || error) { + // pass up the reason why we have no source to read from + throw new IOException(MessageManager.formatMessage( + "exception.failed_to_read_data_from_source", + new String[] { errormessage })); + } + error = false; + dataIn.mark(READAHEAD_LIMIT); + } /** * mark the current position in the source as start for the purposes of it diff --git a/src/jalview/io/IdentifyFile.java b/src/jalview/io/IdentifyFile.java index 4c83ac1..14848c7 100755 --- a/src/jalview/io/IdentifyFile.java +++ b/src/jalview/io/IdentifyFile.java @@ -20,6 +20,9 @@ */ package jalview.io; +import jalview.jsdev.Constants; +import jalview.jsdev.GenericFileAdapter; + import java.io.IOException; /** @@ -143,13 +146,13 @@ public class IdentifyFile break; } // if (data.matches("<(\"[^\"]*\"|'[^']*'|[^'\">])*>")) - if (data.matches("<(?i)html(\"[^\"]*\"|'[^']*'|[^'\">])*>")) + if (data.matches("])*>")) // BH was (?i)rnaml, but JavaScript regex does not support (?i); data is already upper case { - reply = HtmlFile.FILE_DESC; + reply = Constants.Html_FILE_DESC; break; } - if (data.matches("<(?i)rnaml (\"[^\"]*\"|'[^']*'|[^'\">])*>")) + if (data.matches("])*>")) // BH was (?i)rnaml, but JavaScript regex does not support (?i); data is already upper case { reply = "RNAML"; break; @@ -157,7 +160,7 @@ public class IdentifyFile if (data.indexOf("{\"") > -1) { - reply = JSONFile.FILE_DESC; + reply = Constants.JSON_FILE_DESC; break; } if ((data.length() < 1) || (data.indexOf("#") == 0)) @@ -287,7 +290,7 @@ public class IdentifyFile } else if (data.matches("\\s*\\d+\\s+\\d+\\s*")) { - reply = PhylipFile.FILE_DESC; + reply = Constants.Phylip_FILE_DESC; break; } @@ -335,6 +338,11 @@ public class IdentifyFile return reply; } + /** + * @j2sIgnore + * + * @param args + */ public static void main(String[] args) { diff --git a/src/jalview/io/JnetAnnotationMaker.java b/src/jalview/io/JnetAnnotationMaker.java index e944720..f5e94f0 100755 --- a/src/jalview/io/JnetAnnotationMaker.java +++ b/src/jalview/io/JnetAnnotationMaker.java @@ -28,10 +28,10 @@ import jalview.util.MessageManager; public class JnetAnnotationMaker { - public static void add_annotation(JPredFile prediction, AlignmentI al, + public static void add_annotation(AlignFile prediction, AlignmentI al, int firstSeq, boolean noMsa) throws Exception { - JnetAnnotationMaker.add_annotation(prediction, al, firstSeq, noMsa, + add_annotation(prediction, al, firstSeq, noMsa, (int[]) null); } @@ -51,7 +51,7 @@ public class JnetAnnotationMaker * mapping from columns in JPredFile prediction to residue number in * al.getSequence(firstSeq) */ - public static void add_annotation(JPredFile prediction, AlignmentI al, + public static void add_annotation(AlignFile prediction, AlignmentI al, int firstSeq, boolean noMsa, int[] delMap) throws Exception { int i = 0; diff --git a/src/jalview/io/ModellerDescription.java b/src/jalview/io/ModellerDescription.java index 9a3453f..49fc1f1 100755 --- a/src/jalview/io/ModellerDescription.java +++ b/src/jalview/io/ModellerDescription.java @@ -23,8 +23,10 @@ package jalview.io; import jalview.datamodel.DBRefEntry; import jalview.datamodel.DBRefSource; import jalview.datamodel.SequenceI; +import jalview.jsdev.RegExp; +import jalview.jsdev.api.RegExpInterface; -import com.stevesoft.pat.Regex; +//import com.stevesoft.pat.Regex; public class ModellerDescription { @@ -99,16 +101,16 @@ public class ModellerDescription private resCode validResidueCode(String field) { Integer val = null; - Regex r = new Regex("\\s*((([-0-9]+).?)|FIRST|LAST|@)"); + RegExpInterface r = RegExp.newRegex("\\s*((([-0-9]+).?)|FIRST|LAST|@)"); if (!r.search(field)) { return null; // invalid } - String value = r.stringMatched(3); + String value = r.stringMatchedI(3); if (value == null) { - value = r.stringMatched(1); + value = r.stringMatchedI(1); } // Cache.log.debug("from '" + field + "' matched '" + value + // "'"); diff --git a/src/jalview/io/NewickFile.java b/src/jalview/io/NewickFile.java index 90f7faf..94f4ea7 100755 --- a/src/jalview/io/NewickFile.java +++ b/src/jalview/io/NewickFile.java @@ -27,6 +27,8 @@ package jalview.io; import jalview.datamodel.SequenceNode; +import jalview.jsdev.RegExp; +import jalview.jsdev.api.RegExpInterface; import jalview.util.MessageManager; import java.io.BufferedReader; @@ -35,7 +37,9 @@ import java.io.FileReader; import java.io.IOException; import java.util.StringTokenizer; -import com.stevesoft.pat.Regex; +import javajs.J2SIgnoreImport; + +//import com.stevesoft.pat.Regex; /** * Parse a new hanpshire style tree Caveats: NHX files are NOT supported and the @@ -74,6 +78,7 @@ import com.stevesoft.pat.Regex; * @author Jim Procter * @version $Revision$ */ +@J2SIgnoreImport({java.io.File.class, java.io.FileReader.class}) public class NewickFile extends FileParse { SequenceNode root; @@ -89,13 +94,13 @@ public class NewickFile extends FileParse boolean printRootInfo = true; - private Regex[] NodeSafeName = new Regex[] - { new Regex().perlCode("m/[\\[,:'()]/"), // test for + private RegExpInterface[] NodeSafeName = new RegExpInterface[] + { RegExp.perlCode("m/[\\[,:'()]/"), // test for // requiring // quotes - new Regex().perlCode("s/'/''/"), // escaping quote + RegExp.perlCode("s/'/''/"), // escaping quote // characters - new Regex().perlCode("s/\\/w/_/") // unqoted whitespace + RegExp.perlCode("s/\\/w/_/") // unqoted whitespace // transformation }; @@ -250,388 +255,317 @@ public class NewickFile extends FileParse return RootHasDistance; } - /** - * parse the filesource as a newick file (new hampshire and/or extended) - * - * @throws IOException - * with a line number and character position for badly formatted NH - * strings - */ - public void parse() throws IOException - { - String nf; - - { // fill nf with complete tree file - - StringBuffer file = new StringBuffer(); - - while ((nf = nextLine()) != null) - { - file.append(nf); - } - - nf = file.toString(); - } - - root = new SequenceNode(); - - SequenceNode realroot = null; - SequenceNode c = root; - - int d = -1; - int cp = 0; - // int flen = nf.length(); - - String Error = null; - String nodename = null; - String commentString2 = null; // comments after simple node props - - float DefDistance = (float) 0.001; // @param Default distance for a node - - // very very small - int DefBootstrap = -1; // @param Default bootstrap for a node - - float distance = DefDistance; - int bootstrap = DefBootstrap; - - boolean ascending = false; // flag indicating that we are leaving the - // current node - - Regex majorsyms = new Regex( - "[(\\['),;]"); - - int nextcp = 0; - int ncp = cp; - boolean parsednodename = false; - while (majorsyms.searchFrom(nf, cp) && (Error == null)) - { - int fcp = majorsyms.matchedFrom(); - char schar; - switch (schar = nf.charAt(fcp)) - { - case '(': - - // ascending should not be set - // New Internal node - if (ascending) - { - Error = ErrorStringrange(Error, "Unexpected '('", 7, fcp, nf); - - continue; - } - - ; - d++; - - if (c.right() == null) - { - c.setRight(new SequenceNode(null, c, null, DefDistance, - DefBootstrap, false)); - c = (SequenceNode) c.right(); - } - else - { - if (c.left() != null) - { - // Dummy node for polytomy - keeps c.left free for new node - SequenceNode tmpn = new SequenceNode(null, c, null, 0, 0, true); - tmpn.SetChildren(c.left(), c.right()); - c.setRight(tmpn); - } - - c.setLeft(new SequenceNode(null, c, null, DefDistance, - DefBootstrap, false)); - c = (SequenceNode) c.left(); - } - - if (realroot == null) - { - realroot = c; - } - - nodename = null; - distance = DefDistance; - bootstrap = DefBootstrap; - cp = fcp + 1; - - break; - - // Deal with quoted fields - case '\'': - - Regex qnodename = new Regex( - "'([^']|'')+'"); - - if (qnodename.searchFrom(nf, fcp)) - { - int nl = qnodename.stringMatched().length(); - nodename = new String(qnodename.stringMatched().substring(1, - nl - 1)); - // unpack any escaped colons - Regex xpandquotes = Regex - .perlCode("s/''/'/"); - String widernodename = xpandquotes.replaceAll(nodename); - nodename = widernodename; - // jump to after end of quoted nodename - nextcp = fcp + nl + 1; - parsednodename = true; - } - else - { - Error = ErrorStringrange(Error, - "Unterminated quotes for nodename", 7, fcp, nf); - } - - break; - - default: - if (schar == ';') - { - if (d != -1) - { - Error = ErrorStringrange(Error, "Wayward semicolon (depth=" + d - + ")", 7, fcp, nf); - } - // cp advanced at the end of default - } - if (schar == '[') - { - // node string contains Comment or structured/extended NH format info - /* - * if ((fcp-cp>1 && nf.substring(cp,fcp).trim().length()>1)) { // will - * process in remains System.err.println("skipped text: - * '"+nf.substring(cp,fcp)+"'"); } - */ - // verify termination. - Regex comment = new Regex("]"); - if (comment.searchFrom(nf, fcp)) - { - // Skip the comment field - nextcp = comment.matchedFrom() + 1; - warningMessage = "Tree file contained comments which may confuse input algorithm."; - break; - - // cp advanced at the end of default to nextcp, ncp is unchanged so - // any node info can be read. - } - else - { - Error = ErrorStringrange(Error, "Unterminated comment", 3, fcp, - nf); - } - - ; - } - // Parse simpler field strings - String fstring = nf.substring(ncp, fcp); - // remove any comments before we parse the node info - // TODO: test newick file with quoted square brackets in node name (is - // this allowed?) - while (fstring.indexOf(']') > -1) - { - int cstart = fstring.indexOf('['); - int cend = fstring.indexOf(']'); - commentString2 = fstring.substring(cstart + 1, cend); - fstring = fstring.substring(0, cstart) - + fstring.substring(cend + 1); - - } - Regex uqnodename = new Regex( - "\\b([^' :;\\](),]+)"); - Regex nbootstrap = new Regex( - "\\s*([0-9+]+)\\s*:"); - Regex ndist = new Regex( - ":([-0-9Ee.+]+)"); - - if (!parsednodename - && uqnodename.search(fstring) - && ((uqnodename.matchedFrom(1) == 0) || (fstring - .charAt(uqnodename.matchedFrom(1) - 1) != ':'))) // JBPNote - // HACK! - { - if (nodename == null) - { - if (ReplaceUnderscores) - { - nodename = uqnodename.stringMatched(1).replace('_', ' '); - } - else - { - nodename = uqnodename.stringMatched(1); - } - } - else - { - Error = ErrorStringrange(Error, - "File has broken algorithm - overwritten nodename", 10, - fcp, nf); - } - } - // get comment bootstraps - - if (nbootstrap.search(fstring)) - { - if (nbootstrap.stringMatched(1).equals( - uqnodename.stringMatched(1))) - { - nodename = null; // no nodename here. - } - if (nodename == null - || nodename.length() == 0 - || nbootstrap.matchedFrom(1) > (uqnodename.matchedFrom(1) + uqnodename - .stringMatched().length())) - { - try - { - bootstrap = (new Integer(nbootstrap.stringMatched(1))) - .intValue(); - HasBootstrap = true; - } catch (Exception e) - { - Error = ErrorStringrange(Error, - "Can't parse bootstrap value", 4, - ncp + nbootstrap.matchedFrom(), nf); - } - } - } - - boolean nodehasdistance = false; - - if (ndist.search(fstring)) - { - try - { - distance = (new Float(ndist.stringMatched(1))).floatValue(); - HasDistances = true; - nodehasdistance = true; - } catch (Exception e) - { - Error = ErrorStringrange(Error, - "Can't parse node distance value", 7, - ncp + ndist.matchedFrom(), nf); - } - } - - if (ascending) - { - // Write node info here - c.setName(nodename); - // Trees without distances still need a render distance - c.dist = (HasDistances) ? distance : DefDistance; - // be consistent for internal bootstrap defaults too - c.setBootstrap((HasBootstrap) ? bootstrap : DefBootstrap); - if (c == realroot) - { - RootHasDistance = nodehasdistance; // JBPNote This is really - // UGLY!!! Ensure root node gets - // its given distance - } - parseNHXNodeProps(c, commentString2); - commentString2 = null; - } - else - { - // Find a place to put the leaf - SequenceNode newnode = new SequenceNode(null, c, nodename, - (HasDistances) ? distance : DefDistance, - (HasBootstrap) ? bootstrap : DefBootstrap, false); - parseNHXNodeProps(c, commentString2); - commentString2 = null; - - if (c.right() == null) - { - c.setRight(newnode); - } - else - { - if (c.left() == null) - { - c.setLeft(newnode); - } - else - { - // Insert a dummy node for polytomy - // dummy nodes have distances - SequenceNode newdummy = new SequenceNode(null, c, null, - (HasDistances ? 0 : DefDistance), 0, true); - newdummy.SetChildren(c.left(), newnode); - c.setLeft(newdummy); - } - } - } - - if (ascending) - { - // move back up the tree from preceding closure - c = c.AscendTree(); - - if ((d > -1) && (c == null)) - { - Error = ErrorStringrange( - Error, - "File broke algorithm: Lost place in tree (is there an extra ')' ?)", - 7, fcp, nf); - } - } - - if (nf.charAt(fcp) == ')') - { - d--; - ascending = true; - } - else - { - if (nf.charAt(fcp) == ',') - { - if (ascending) - { - ascending = false; - } - else - { - // Just advance focus, if we need to - if ((c.left() != null) && (!c.left().isLeaf())) - { - c = (SequenceNode) c.left(); - } - } - } - } - - // Reset new node properties to obvious fakes - nodename = null; - distance = DefDistance; - bootstrap = DefBootstrap; - commentString2 = null; - parsednodename = false; - } - if (nextcp == 0) - { - ncp = cp = fcp + 1; - } - else - { - cp = nextcp; - nextcp = 0; - } - } - - if (Error != null) - { - throw (new IOException(MessageManager.formatMessage("exception.newfile", new String[]{Error.toString()}))); - } - if (root == null) - { - throw (new IOException(MessageManager.formatMessage("exception.newfile", new String[]{MessageManager.getString("label.no_tree_read_in")}))); - } - // THe next line is failing for topali trees - not sure why yet. if - // (root.right()!=null && root.isDummy()) - root = (SequenceNode) root.right().detach(); // remove the imaginary root. - - if (!RootHasDistance) - { - root.dist = (HasDistances) ? 0 : DefDistance; - } - } + /** + * parse the filesource as a newick file (new hampshire and/or extended) + * + * @throws IOException + * with a line number and character position for badly formatted NH + * strings + */ + public void parse() throws IOException { + String nf; + + { // fill nf with complete tree file + + StringBuffer file = new StringBuffer(); + + while ((nf = nextLine()) != null) { + file.append(nf); + } + + nf = file.toString(); + } + + root = new SequenceNode(); + + SequenceNode realroot = null; + SequenceNode c = root; + + int d = -1; + int cp = 0; + // int flen = nf.length(); + + String Error = null; + String nodename = null; + String commentString2 = null; // comments after simple node props + + float DefDistance = (float) 0.001; // @param Default distance for a node - + // very very small + int DefBootstrap = -1; // @param Default bootstrap for a node + + float distance = DefDistance; + int bootstrap = DefBootstrap; + + boolean ascending = false; // flag indicating that we are leaving the + // current node + + RegExpInterface majorsyms = RegExp.newRegex("[(\\['),;]"); + + int nextcp = 0; + int ncp = cp; + boolean parsednodename = false; + while (majorsyms.searchFrom(nf, cp) && (Error == null)) { + int fcp = majorsyms.matchedFrom(); + char schar; + switch (schar = nf.charAt(fcp)) { + case '(': + + // ascending should not be set + // New Internal node + if (ascending) { + Error = ErrorStringrange(Error, "Unexpected '('", 7, fcp, nf); + + continue; + } + + ; + d++; + + if (c.right() == null) { + c.setRight(new SequenceNode(null, c, null, DefDistance, DefBootstrap, + false)); + c = (SequenceNode) c.right(); + } else { + if (c.left() != null) { + // Dummy node for polytomy - keeps c.left free for new node + SequenceNode tmpn = new SequenceNode(null, c, null, 0, 0, true); + tmpn.SetChildren(c.left(), c.right()); + c.setRight(tmpn); + } + + c.setLeft(new SequenceNode(null, c, null, DefDistance, DefBootstrap, + false)); + c = (SequenceNode) c.left(); + } + + if (realroot == null) { + realroot = c; + } + + nodename = null; + distance = DefDistance; + bootstrap = DefBootstrap; + cp = fcp + 1; + + break; + + // Deal with quoted fields + case '\'': + + RegExpInterface qnodename = RegExp.newRegex("'([^']|'')+'"); + + if (qnodename.searchFrom(nf, fcp)) { + int nl = qnodename.stringMatched().length(); + nodename = new String(qnodename.stringMatched().substring(1, nl - 1)); + // unpack any escaped colons + RegExpInterface xpandquotes = RegExp.perlCode("s/''/'/"); + String widernodename = xpandquotes.replaceAll(nodename); + nodename = widernodename; + // jump to after end of quoted nodename + nextcp = fcp + nl + 1; + parsednodename = true; + } else { + Error = ErrorStringrange(Error, "Unterminated quotes for nodename", + 7, fcp, nf); + } + + break; + + default: + if (schar == ';') { + if (d != -1) { + Error = ErrorStringrange(Error, "Wayward semicolon (depth=" + d + + ")", 7, fcp, nf); + } + // cp advanced at the end of default + } + if (schar == '[') { + // node string contains Comment or structured/extended NH format info + /* + * if ((fcp-cp>1 && nf.substring(cp,fcp).trim().length()>1)) { // will + * process in remains System.err.println("skipped text: + * '"+nf.substring(cp,fcp)+"'"); } + */ + // verify termination. + RegExpInterface comment = RegExp.newRegex("]"); + if (comment.searchFrom(nf, fcp)) { + // Skip the comment field + nextcp = comment.matchedFrom() + 1; + warningMessage = "Tree file contained comments which may confuse input algorithm."; + break; + + // cp advanced at the end of default to nextcp, ncp is unchanged so + // any node info can be read. + } else { + Error = ErrorStringrange(Error, "Unterminated comment", 3, fcp, nf); + } + + ; + } + // Parse simpler field strings + String fstring = nf.substring(ncp, fcp); + // remove any comments before we parse the node info + // TODO: test newick file with quoted square brackets in node name (is + // this allowed?) + while (fstring.indexOf(']') > -1) { + int cstart = fstring.indexOf('['); + int cend = fstring.indexOf(']'); + commentString2 = fstring.substring(cstart + 1, cend); + fstring = fstring.substring(0, cstart) + fstring.substring(cend + 1); + + } + RegExpInterface uqnodename = RegExp.newRegex("\\b([^' :;\\](),]+)"); + RegExpInterface nbootstrap = RegExp.newRegex("\\s*([0-9+]+)\\s*:"); + RegExpInterface ndist = RegExp.newRegex(":([-0-9Ee.+]+)"); + + if (!parsednodename + && uqnodename.search(fstring) + && ((uqnodename.matchedFromI(1) == 0) || (fstring.charAt(uqnodename + .matchedFromI(1) - 1) != ':'))) // JBPNote + // HACK! + { + if (nodename == null) { + if (ReplaceUnderscores) { + nodename = uqnodename.stringMatchedI(1).replace('_', ' '); + } else { + nodename = uqnodename.stringMatchedI(1); + } + } else { + Error = ErrorStringrange(Error, + "File has broken algorithm - overwritten nodename", 10, fcp, nf); + } + } + // get comment bootstraps + + if (nbootstrap.search(fstring)) { + if (nbootstrap.stringMatchedI(1).equals(uqnodename.stringMatchedI(1))) { + nodename = null; // no nodename here. + } + if (nodename == null + || nodename.length() == 0 + || nbootstrap.matchedFromI(1) > (uqnodename.matchedFromI(1) + uqnodename + .stringMatched().length())) { + try { + bootstrap = (new Integer(nbootstrap.stringMatchedI(1))) + .intValue(); + HasBootstrap = true; + } catch (Exception e) { + Error = ErrorStringrange(Error, "Can't parse bootstrap value", 4, + ncp + nbootstrap.matchedFrom(), nf); + } + } + } + + boolean nodehasdistance = false; + + if (ndist.search(fstring)) { + try { + distance = (new Float(ndist.stringMatchedI(1))).floatValue(); + HasDistances = true; + nodehasdistance = true; + } catch (Exception e) { + Error = ErrorStringrange(Error, "Can't parse node distance value", + 7, ncp + ndist.matchedFrom(), nf); + } + } + + if (ascending) { + // Write node info here + c.setName(nodename); + // Trees without distances still need a render distance + c.dist = (HasDistances) ? distance : DefDistance; + // be consistent for internal bootstrap defaults too + c.setBootstrap((HasBootstrap) ? bootstrap : DefBootstrap); + if (c == realroot) { + RootHasDistance = nodehasdistance; // JBPNote This is really + // UGLY!!! Ensure root node gets + // its given distance + } + parseNHXNodeProps(c, commentString2); + commentString2 = null; + } else { + // Find a place to put the leaf + SequenceNode newnode = new SequenceNode(null, c, nodename, + (HasDistances) ? distance : DefDistance, + (HasBootstrap) ? bootstrap : DefBootstrap, false); + parseNHXNodeProps(c, commentString2); + commentString2 = null; + + if (c.right() == null) { + c.setRight(newnode); + } else { + if (c.left() == null) { + c.setLeft(newnode); + } else { + // Insert a dummy node for polytomy + // dummy nodes have distances + SequenceNode newdummy = new SequenceNode(null, c, null, + (HasDistances ? 0 : DefDistance), 0, true); + newdummy.SetChildren(c.left(), newnode); + c.setLeft(newdummy); + } + } + } + + if (ascending) { + // move back up the tree from preceding closure + c = c.AscendTree(); + + if ((d > -1) && (c == null)) { + Error = ErrorStringrange( + Error, + "File broke algorithm: Lost place in tree (is there an extra ')' ?)", + 7, fcp, nf); + } + } + + if (nf.charAt(fcp) == ')') { + d--; + ascending = true; + } else { + if (nf.charAt(fcp) == ',') { + if (ascending) { + ascending = false; + } else { + // Just advance focus, if we need to + if ((c.left() != null) && (!c.left().isLeaf())) { + c = (SequenceNode) c.left(); + } + } + } + } + + // Reset new node properties to obvious fakes + nodename = null; + distance = DefDistance; + bootstrap = DefBootstrap; + commentString2 = null; + parsednodename = false; + } + if (nextcp == 0) { + ncp = cp = fcp + 1; + } else { + cp = nextcp; + nextcp = 0; + } + } + + if (Error != null) { + throw (new IOException(MessageManager.formatMessage("exception.newfile", + new String[] { Error.toString() }))); + } + if (root == null) { + throw (new IOException(MessageManager.formatMessage("exception.newfile", + new String[] { MessageManager.getString("label.no_tree_read_in") }))); + } + // THe next line is failing for topali trees - not sure why yet. if + // (root.right()!=null && root.isDummy()) + root = (SequenceNode) root.right().detach(); // remove the imaginary root. + + if (!RootHasDistance) { + root.dist = (HasDistances) ? 0 : DefDistance; + } + } /** * parse NHX codes in comment strings and update NewickFile state flags for @@ -940,6 +874,10 @@ public class NewickFile extends FileParse } // Test + /** + * @J2SIgnore + * @param args + */ public static void main(String[] args) { try @@ -969,7 +907,7 @@ public class NewickFile extends FileParse trf.parse(); System.out.println("Original file :\n"); - Regex nonl = new Regex("\n+", ""); + RegExpInterface nonl = RegExp.newRegex("\n+", ""); System.out.println(nonl.replaceAll(newickfile.toString()) + "\n"); System.out.println("Parsed file.\n"); diff --git a/src/jalview/javascript/JSFunctionExec.java b/src/jalview/javascript/JSFunctionExec.java index cd9ca88..61dccef 100644 --- a/src/jalview/javascript/JSFunctionExec.java +++ b/src/jalview/javascript/JSFunctionExec.java @@ -177,7 +177,7 @@ public class JSFunctionExec implements Runnable ; if (scriptObject != null) { - if (jvlite.debug && dbgMsg != null) + if (JalviewLite.debug && dbgMsg != null) { System.err.println(dbgMsg); } diff --git a/src/jalview/javascript/JsSelectionSender.java b/src/jalview/javascript/JsSelectionSender.java index a028f61..d0bca37 100644 --- a/src/jalview/javascript/JsSelectionSender.java +++ b/src/jalview/javascript/JsSelectionSender.java @@ -28,6 +28,8 @@ import jalview.datamodel.SequenceGroup; import jalview.structure.SelectionListener; import jalview.structure.SelectionSource; +import netscape.javascript.JSException; + public class JsSelectionSender extends JSFunctionExec implements SelectionListener, JsCallBack { diff --git a/src/jalview/jsdev/Constants.java b/src/jalview/jsdev/Constants.java new file mode 100644 index 0000000..2bae93d --- /dev/null +++ b/src/jalview/jsdev/Constants.java @@ -0,0 +1,31 @@ +package jalview.jsdev; + +/** + * note: not all file openers have corresponding String inFile and FileParse source options. Why not? + * + * @author RM + * + */ +abstract public class Constants { + + public final static String TCOFFEE_SCORE = "TCoffeeScore"; + + public static final int Phylip_FILE = 1; + + public static final String Phylip_FILE_EXT = "phy"; + + public static final String Phylip_FILE_DESC = "PHYLIP"; + + public static final int JSON_FILE = 2; + + public static final String JSON_FILE_EXT = "json"; + + public static final String JSON_FILE_DESC = "JSON"; + + public static final int Html_FILE = 3; + + public static final String Html_FILE_EXT = "html"; + + public static final String Html_FILE_DESC = "HTML"; + +} diff --git a/src/jalview/jsdev/GenericFileAdapter.java b/src/jalview/jsdev/GenericFileAdapter.java new file mode 100644 index 0000000..f112ebf --- /dev/null +++ b/src/jalview/jsdev/GenericFileAdapter.java @@ -0,0 +1,130 @@ +package jalview.jsdev; + +import jalview.datamodel.AlignmentI; +import jalview.io.AlignFile; +import jalview.io.FileParse; + +import java.io.BufferedReader; +import java.io.FileReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.net.URL; + +import javajs.J2SIgnoreImport; +/** + * A class to open files via reflection so that their classes are only loaded as necessary + * + * note: not all file openers have corresponding String inFile and FileParse + * source options. Why not? + * + * note: Pileupfile does not have a capital "F"; the method below requires that, + * so if that file name gets changed, so too does the reflection code here. + * + * @author Bob Hanson + * + */ + +@J2SIgnoreImport({java.io.FileReader.class}) +abstract public class GenericFileAdapter extends AlignFile { + + /** + * inFileOrSource class type + * + * @param inFileOrSource + * type will determine constructor -- [], [AlignmentI], + * [inFile,type], or [source] + * @param type + * @param fileName + * @return + */ + public static AlignFile getFile(String fileType, Object... params) { + Class cl = null; + try { + cl = Class.forName("jalview.io." + fileType); + } catch (ClassNotFoundException e) { + System.err.println("did not find file jalview.io." + fileType); + return null; + } + Constructor m; + Throwable ex = null; + try { + switch (params.length) { + case 0: + return (AlignFile) cl.newInstance(); + case 1: + m = (params[0] instanceof FileParse ? cl + .getConstructor(FileParse.class) : cl + .getConstructor(AlignmentI.class)); + break; + case 2: + m = cl.getConstructor(String.class, String.class); + break; + default: + return null; + } + return (AlignFile) m.newInstance(params); + } catch (InstantiationException e) { + ex = e; + } catch (IllegalAccessException e) { + ex = e; + } catch (NoSuchMethodException e) { + ex = e; + } catch (SecurityException e) { + ex = e; + } catch (IllegalArgumentException e) { + ex = e; + } catch (InvocationTargetException e) { + ex = e; + } + if (ex != null) { + System.err.println("Error in GenericFileAdapter: " + ex); + /** + * @j2sNative + * + * alert(ex) + * + */ + { + ex.printStackTrace(); + } + } + return null; + } + + /** + * Determines whether or not we have a JavaScript applet. + * + * @return + */ + public static boolean isJS() { + /** + * @j2sNative + * + * return true; + * + */ + { + return false; + } + } + + /** + * opens a file for line-oriented reading via File() or URL() + * + * @param fileName + * @param forceURL + * @return + * @throws IOException + */ + public static BufferedReader getReader(String fileName, boolean forceURL) throws IOException { + if (!forceURL && !isJS()) + return new BufferedReader(new FileReader(fileName)); + if (fileName.indexOf("//") < 0) + fileName = "file://" + fileName; + return new BufferedReader(new InputStreamReader(new URL(fileName).openStream())); + } + + +} diff --git a/src/jalview/jsdev/JSRegex.java b/src/jalview/jsdev/JSRegex.java new file mode 100644 index 0000000..9437339 --- /dev/null +++ b/src/jalview/jsdev/JSRegex.java @@ -0,0 +1,91 @@ +package jalview.jsdev; + +import jalview.jsdev.api.RegExpInterface; + +/** + * The JavaScript RegEx methods + * + * @author Bob Hanson + * + */ +public class JSRegex implements RegExpInterface { + + @Override + public int charsMatched() { + // TODO Auto-generated method stub + return 0; + } + + @Override + public String left() { + // TODO Auto-generated method stub + return null; + } + + @Override + public int matchedFrom() { + // TODO Auto-generated method stub + return 0; + } + + @Override + public int matchedFromI(int pos) { + // TODO Auto-generated method stub + return 0; + } + + @Override + public int matchedTo() { + // TODO Auto-generated method stub + return 0; + } + + @Override + public int matchedToI(int pos) { + // TODO Auto-generated method stub + return 0; + } + + @Override + public int numSubs() { + // TODO Auto-generated method stub + return 0; + } + + @Override + public String replaceAll(String string) { + // TODO Auto-generated method stub + return null; + } + + @Override + public boolean search(String str) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean searchFrom(String string, int rematchat) { + // TODO Auto-generated method stub + return false; + } + + @Override + public void setIgnoreCase(boolean b) { + // TODO Auto-generated method stub + + } + + @Override + public String stringMatched() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String stringMatchedI(int i) { + // TODO Auto-generated method stub + return null; + } + +} diff --git a/src/jalview/jsdev/JavaScriptRegExp.java b/src/jalview/jsdev/JavaScriptRegExp.java new file mode 100644 index 0000000..fc43637 --- /dev/null +++ b/src/jalview/jsdev/JavaScriptRegExp.java @@ -0,0 +1,17 @@ +package jalview.jsdev; + +/** + * The JavaScript RegEx methods + * + * @author Bob Hanson + * + */ +public interface JavaScriptRegExp { + + String[] exec(String str); + + boolean test(String str); + + String[] match(String str); + +} diff --git a/src/jalview/jsdev/RegExp.java b/src/jalview/jsdev/RegExp.java new file mode 100644 index 0000000..a36ebd8 --- /dev/null +++ b/src/jalview/jsdev/RegExp.java @@ -0,0 +1,26 @@ +package jalview.jsdev; + +import com.stevesoft.pat.Regex; + +import jalview.jsdev.api.RegExpInterface; + +/** + * an intermediary working class allowing options other than com.stevesoft.pat.Regex + * + * @author Bob Hanson + * + */ +public class RegExp { + + RegExpInterface rg; + + public static RegExpInterface newRegex(String... params) { + return new Regex(params.length < 1 ? null : params[0], + params.length < 2 ? "" : params[1]); + } + + public static RegExpInterface perlCode(String s) { + return Regex.perlCode(s); + } + +} diff --git a/src/jalview/jsdev/api/RegExpInterface.java b/src/jalview/jsdev/api/RegExpInterface.java new file mode 100644 index 0000000..44bc865 --- /dev/null +++ b/src/jalview/jsdev/api/RegExpInterface.java @@ -0,0 +1,37 @@ +package jalview.jsdev.api; + +/** + * all methods of com.stevesoft.pat.Regex called within Jalview + * + * @author Bob Hanson + * + */ +public interface RegExpInterface { + + public abstract int charsMatched(); + + public abstract String left(); + + public abstract int matchedFrom(); + + public abstract int matchedFromI(int pos); + + public abstract int matchedTo(); + + public abstract int matchedToI(int pos); + + public abstract int numSubs(); + + public abstract String replaceAll(String string); + + public abstract boolean search(String str); + + public abstract boolean searchFrom(String string, int rematchat); + + public abstract void setIgnoreCase(boolean b); + + public abstract String stringMatched(); + + public abstract String stringMatchedI(int i); + +} \ No newline at end of file diff --git a/src/jalview/jsdev/api/VarnaRNA.java b/src/jalview/jsdev/api/VarnaRNA.java new file mode 100644 index 0000000..a392dc6 --- /dev/null +++ b/src/jalview/jsdev/api/VarnaRNA.java @@ -0,0 +1,5 @@ +package jalview.jsdev.api; + +public interface VarnaRNA { + +} diff --git a/src/jalview/math/Matrix.java b/src/jalview/math/Matrix.java index fb8d295..e4b4fb2 100755 --- a/src/jalview/math/Matrix.java +++ b/src/jalview/math/Matrix.java @@ -781,10 +781,9 @@ public class Matrix } /** - * DOCUMENT ME! + * @j2sIgnore * * @param args - * DOCUMENT ME! */ public static void main(String[] args) throws Exception { diff --git a/src/jalview/math/RotatableMatrix.java b/src/jalview/math/RotatableMatrix.java index 9d92645..44f4374 100755 --- a/src/jalview/math/RotatableMatrix.java +++ b/src/jalview/math/RotatableMatrix.java @@ -253,10 +253,9 @@ public class RotatableMatrix } /** - * DOCUMENT ME! + * @j2sIgnore * * @param args - * DOCUMENT ME! */ public static void main(String[] args) { diff --git a/src/jalview/renderer/AnnotationRenderer.java b/src/jalview/renderer/AnnotationRenderer.java index ca02c29..debbf9a 100644 --- a/src/jalview/renderer/AnnotationRenderer.java +++ b/src/jalview/renderer/AnnotationRenderer.java @@ -27,6 +27,8 @@ import jalview.api.AlignViewportI; import jalview.datamodel.AlignmentAnnotation; import jalview.datamodel.Annotation; import jalview.datamodel.ColumnSelection; +import jalview.jsdev.RegExp; +import jalview.jsdev.api.RegExpInterface; import jalview.schemes.ColourSchemeI; import jalview.schemes.NucleotideColourScheme; import jalview.schemes.ResidueProperties; @@ -46,7 +48,7 @@ import java.awt.image.ImageObserver; import java.util.BitSet; import java.util.Hashtable; -import com.stevesoft.pat.Regex; +//import com.stevesoft.pat.Regex; public class AnnotationRenderer { @@ -80,7 +82,7 @@ public class AnnotationRenderer int sCol = (lastSSX / charWidth) + startRes; int x1 = lastSSX; int x2 = (x * charWidth); - Regex closeparen = new Regex("(\\))"); + RegExpInterface closeparen = RegExp.newRegex("(\\))"); char dc = (column == 0 || row_annotations[column - 1] == null) ? ' ' : row_annotations[column - 1].secondaryStructure; @@ -204,7 +206,7 @@ public class AnnotationRenderer int sCol = (lastSSX / charWidth) + startRes; int x1 = lastSSX; int x2 = (x * charWidth); - Regex closeparen = new Regex("}|]|<|[a-z]"); + RegExpInterface closeparen = RegExp.newRegex("}|]|<|[a-z]"); String dc = (column == 0 || row_annotations[column - 1] == null) ? "" : row_annotations[column - 1].displayCharacter; diff --git a/src/jalview/schemes/AnnotationColourGradient.java b/src/jalview/schemes/AnnotationColourGradient.java index b0822ca..e65d5f5 100755 --- a/src/jalview/schemes/AnnotationColourGradient.java +++ b/src/jalview/schemes/AnnotationColourGradient.java @@ -246,110 +246,82 @@ public class AnnotationColourGradient extends FollowerColourScheme return Color.red; } - /** - * DOCUMENT ME! - * - * @param n - * DOCUMENT ME! - * @param j - * DOCUMENT ME! - * - * @return DOCUMENT ME! - */ - @Override - public Color findColour(char c, int j, SequenceI seq) - { - Color currentColour = Color.white; - AlignmentAnnotation annotation = (seqAssociated && seqannot!=null ? seqannot.get(seq) - : this.annotation); - if (annotation == null) - { - return currentColour; - } - if ((threshold == 0) || aboveThreshold(c, j)) - { - if (annotation.annotations != null - && j < annotation.annotations.length - && annotation.annotations[j] != null - && !Comparison.isGap(c)) - { - Annotation aj = annotation.annotations[j]; - // 'use original colours' => colourScheme != null - // -> look up colour to be used - // predefined colours => preconfigured shading - // -> only use original colours reference if thresholding enabled & - // minmax exists - // annotation.hasIcons => null or black colours replaced with glyph - // colours - // -> reuse original colours if present - // -> if thresholding enabled then return colour on non-whitespace glyph - - if (aboveAnnotationThreshold == NO_THRESHOLD - || (annotationThreshold != null && (aboveAnnotationThreshold == ABOVE_THRESHOLD ? aj.value >= annotationThreshold.value - : aj.value <= annotationThreshold.value))) - { - if (predefinedColours && aj.colour != null - && !aj.colour.equals(Color.black)) - { - currentColour = aj.colour; - } - else if (annotation.hasIcons - && annotation.graph == AlignmentAnnotation.NO_GRAPH) - { - if (aj.secondaryStructure > ' ' && aj.secondaryStructure != '.' - && aj.secondaryStructure != '-') - { - if (colourScheme != null) - { - currentColour = colourScheme.findColour(c, j, seq); - } - else - { - if (annotation.isRNA()) - { - currentColour = ColourSchemeProperty.rnaHelices[(int) aj.value]; - } - else - { - currentColour = annotation.annotations[j].secondaryStructure == 'H' ? AnnotationRenderer.HELIX_COLOUR - : annotation.annotations[j].secondaryStructure == 'E' ? AnnotationRenderer.SHEET_COLOUR - : AnnotationRenderer.STEM_COLOUR; - } - } - } - else - { - // - return Color.white; - } - } - else if (noGradient) - { - if (colourScheme != null) - { - currentColour = colourScheme.findColour(c, j, seq); - } - else - { - if (aj.colour != null) - { - currentColour = aj.colour; - } - } - } - else - { - currentColour = shadeCalculation(annotation, j); - } - } - if (conservationColouring) - { - currentColour = applyConservation(currentColour, j); - } - } - } - return currentColour; - } + /** + * DOCUMENT ME! + * + * @param n + * DOCUMENT ME! + * @param j + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + @Override + public Color findColour(char c, int j, SequenceI seq) { + Color currentColour = Color.white; + AlignmentAnnotation annotation = (seqAssociated && seqannot != null ? seqannot + .get(seq) : this.annotation); + if (annotation == null) { + return currentColour; + } + if ((threshold == 0) || aboveThreshold(c, j)) { + if (annotation.annotations != null && j < annotation.annotations.length + && annotation.annotations[j] != null && !Comparison.isGap(c)) { + Annotation aj = annotation.annotations[j]; + // 'use original colours' => colourScheme != null + // -> look up colour to be used + // predefined colours => preconfigured shading + // -> only use original colours reference if thresholding enabled & + // minmax exists + // annotation.hasIcons => null or black colours replaced with glyph + // colours + // -> reuse original colours if present + // -> if thresholding enabled then return colour on non-whitespace glyph + + if (aboveAnnotationThreshold == NO_THRESHOLD + || (annotationThreshold != null && (aboveAnnotationThreshold == ABOVE_THRESHOLD ? aj.value >= annotationThreshold.value + : aj.value <= annotationThreshold.value))) { + if (predefinedColours && aj.colour != null + && !aj.colour.equals(Color.black)) { + currentColour = aj.colour; + } else if (annotation.hasIcons + && annotation.graph == AlignmentAnnotation.NO_GRAPH) { + if (aj.secondaryStructure > ' ' && aj.secondaryStructure != '.' + && aj.secondaryStructure != '-') { + if (colourScheme != null) { + currentColour = colourScheme.findColour(c, j, seq); + } else { + if (annotation.isRNA()) { + currentColour = ColourSchemeProperty.rnaHelices[(int) aj.value]; + } else { + currentColour = annotation.annotations[j].secondaryStructure == 'H' ? AnnotationRenderer.HELIX_COLOUR + : annotation.annotations[j].secondaryStructure == 'E' ? AnnotationRenderer.SHEET_COLOUR + : AnnotationRenderer.STEM_COLOUR; + } + } + } else { + // + return Color.white; + } + } else if (noGradient) { + if (colourScheme != null) { + currentColour = colourScheme.findColour(c, j, seq); + } else { + if (aj.colour != null) { + currentColour = aj.colour; + } + } + } else { + currentColour = shadeCalculation(annotation, j); + } + } + if (conservationColouring) { + currentColour = applyConservation(currentColour, j); + } + } + } + return currentColour; + } private Color shadeCalculation(AlignmentAnnotation annotation, int j) { diff --git a/src/jalview/schemes/ResidueProperties.java b/src/jalview/schemes/ResidueProperties.java index 662a77e..d5c542c 100755 --- a/src/jalview/schemes/ResidueProperties.java +++ b/src/jalview/schemes/ResidueProperties.java @@ -29,10 +29,15 @@ import java.util.List; import java.util.Map; import java.util.Vector; +import javajs.J2SRequireImport; + import jalview.analysis.scoremodels.FeatureScoreModel; import jalview.analysis.scoremodels.PIDScoreModel; import jalview.api.analysis.ScoreModelI; +// required because of the static defs + +@J2SRequireImport({ScoreMatrix.class, PIDScoreModel.class, FeatureScoreModel.class}) public class ResidueProperties { public static Hashtable scoreMatrices = new Hashtable(); @@ -869,6 +874,8 @@ public class ResidueProperties } // and programmatically add in the ambiguity codes that yield the same amino // acid + + String[] unambcodons = codonHash2.keySet().toArray( new String[codonHash2.size()]); for (String codon : unambcodons) @@ -1739,6 +1746,12 @@ public class ResidueProperties // main method generates perl representation of residue property hash // / cut here + + /** + * @j2sIgnore + * + * @param args + */ public static void main(String[] args) { Hashtable aa = new Hashtable(); diff --git a/src/jalview/schemes/TCoffeeColourScheme.java b/src/jalview/schemes/TCoffeeColourScheme.java index 48c52f1..9e8feea 100644 --- a/src/jalview/schemes/TCoffeeColourScheme.java +++ b/src/jalview/schemes/TCoffeeColourScheme.java @@ -20,20 +20,20 @@ */ package jalview.schemes; -import jalview.analysis.SequenceIdMatcher; import jalview.datamodel.AlignmentAnnotation; import jalview.datamodel.AlignmentI; import jalview.datamodel.AnnotatedCollectionI; import jalview.datamodel.Annotation; import jalview.datamodel.SequenceCollectionI; import jalview.datamodel.SequenceI; -import jalview.io.TCoffeeScoreFile; +import jalview.jsdev.Constants; import java.awt.Color; import java.util.ArrayList; import java.util.IdentityHashMap; import java.util.Map; -import java.util.TreeMap; +//import jalview.io.TCoffeeScoreFile; +//import java.util.TreeMap; /** * Defines the color score for T-Coffee MSA @@ -91,7 +91,7 @@ public class TCoffeeColourScheme extends ResidueColourScheme : alignment.getContext(); int w = 0; for (AlignmentAnnotation al : alcontext - .findAnnotation(TCoffeeScoreFile.TCOFFEE_SCORE)) + .findAnnotation(Constants.TCOFFEE_SCORE)) { if (al.sequenceRef != null && !al.belowAlignment) { diff --git a/src/jalview/structures/models/AAStructureBindingModel.java b/src/jalview/structures/models/AAStructureBindingModel.java index e77a23c..efa951a 100644 --- a/src/jalview/structures/models/AAStructureBindingModel.java +++ b/src/jalview/structures/models/AAStructureBindingModel.java @@ -109,7 +109,7 @@ public abstract class AAStructureBindingModel extends { this.ssm = ssm; this.sequence = sequenceIs; - this.nucleotide = Comparison.isNucleotide(sequenceIs); + this.nucleotide = Comparison.isNucleotide2(sequenceIs); this.chains = chains; this.pdbEntry = pdbentry; this.protocol = protocol; diff --git a/src/jalview/util/AWTConsole.java b/src/jalview/util/AWTConsole.java index 3b95f8a..f664c61 100644 --- a/src/jalview/util/AWTConsole.java +++ b/src/jalview/util/AWTConsole.java @@ -244,6 +244,11 @@ public class AWTConsole extends WindowAdapter implements WindowListener, return input; } + /** + * @j2sIgnore + * + * @param args + */ public static void main(String[] arg) { new AWTConsole(); // create console with not reference diff --git a/src/jalview/util/Comparison.java b/src/jalview/util/Comparison.java index 835a1b4..db120ff 100644 --- a/src/jalview/util/Comparison.java +++ b/src/jalview/util/Comparison.java @@ -311,7 +311,7 @@ public class Comparison * @param seqs * @return */ - public static boolean isNucleotide(SequenceI[][] seqs) + public static boolean isNucleotide2(SequenceI[][] seqs) { if (seqs == null) { diff --git a/src/jalview/util/DBRefUtils.java b/src/jalview/util/DBRefUtils.java index 0349ff2..290db47 100755 --- a/src/jalview/util/DBRefUtils.java +++ b/src/jalview/util/DBRefUtils.java @@ -24,6 +24,8 @@ import jalview.datamodel.DBRefEntry; import jalview.datamodel.DBRefSource; import jalview.datamodel.PDBEntry; import jalview.datamodel.SequenceI; +import jalview.jsdev.RegExp; +import jalview.jsdev.api.RegExpInterface; import java.util.ArrayList; import java.util.HashMap; @@ -31,7 +33,7 @@ import java.util.Hashtable; import java.util.List; import java.util.Map; -import com.stevesoft.pat.Regex; +//import com.stevesoft.pat.Regex; public class DBRefUtils { @@ -430,12 +432,12 @@ public class DBRefUtils * Check for PFAM style stockhom PDB accession id citation e.g. * "1WRI A; 7-80;" */ - Regex r = new Regex( + RegExpInterface r = RegExp.newRegex( "([0-9][0-9A-Za-z]{3})\\s*(.?)\\s*;\\s*([0-9]+)-([0-9]+)"); if (r.search(acn.trim())) { - String pdbid = r.stringMatched(1); - String chaincode = r.stringMatched(2); + String pdbid = r.stringMatchedI(1); + String chaincode = r.stringMatchedI(2); if (chaincode==null) { chaincode = " "; diff --git a/src/jalview/util/GroupUrlLink.java b/src/jalview/util/GroupUrlLink.java index 026e289..d103e67 100644 --- a/src/jalview/util/GroupUrlLink.java +++ b/src/jalview/util/GroupUrlLink.java @@ -22,10 +22,12 @@ package jalview.util; import jalview.datamodel.Sequence; import jalview.datamodel.SequenceI; +import jalview.jsdev.RegExp; +import jalview.jsdev.api.RegExpInterface; import java.util.Hashtable; -import com.stevesoft.pat.Regex; +//import com.stevesoft.pat.Regex; public class GroupUrlLink { @@ -218,7 +220,7 @@ public class GroupUrlLink regexReplace[pass] = link.substring(ptok[pass] + mlength, p); try { - Regex rg = Regex.perlCode("/" + RegExpInterface rg = RegExp.perlCode("/" + regexReplace[pass] + "/"); if (rg == null) { @@ -502,13 +504,13 @@ public class GroupUrlLink // iterate through input, collating segments to be inserted into url StringBuffer matched[] = new StringBuffer[idseq.length]; // and precompile regexes - Regex[] rgxs = new Regex[matched.length]; + RegExpInterface[] rgxs = new RegExpInterface[matched.length]; for (pass = 0; pass < matched.length; pass++) { matched[pass] = new StringBuffer(); if (regexReplace[pass] != null) { - rgxs[pass] = Regex.perlCode("/" + rgxs[pass] = RegExp.perlCode("/" + regexReplace[pass] + "/"); } else @@ -547,7 +549,7 @@ public class GroupUrlLink } if (rgxs[pass] != null) { - Regex rg = rgxs[pass]; + RegExpInterface rg = rgxs[pass]; int rematchat = 0; // concatenate all matches of re in the given string! while (rg.searchFrom(idseq[pass][sq], rematchat)) @@ -595,19 +597,19 @@ public class GroupUrlLink int s = 0; // 1; while (s <= ns) { - if (s + 1 <= ns && rg.matchedTo(s) > -1 - && rg.matchedTo(s + 1) > -1 - && rg.matchedTo(s + 1) < rg.matchedTo(s)) + if (s + 1 <= ns && rg.matchedToI(s) > -1 + && rg.matchedToI(s + 1) > -1 + && rg.matchedToI(s + 1) < rg.matchedToI(s)) { // s is top level submatch. search for submatches enclosed by // this one int r = s + 1; StringBuffer rmtch = new StringBuffer(); - while (r <= ns && rg.matchedTo(r) <= rg.matchedTo(s)) + while (r <= ns && rg.matchedToI(r) <= rg.matchedToI(s)) { - if (rg.matchedFrom(r) > -1) + if (rg.matchedFromI(r) > -1) { - rmtch.append(rg.stringMatched(r)); + rmtch.append(rg.stringMatchedI(r)); } r++; } @@ -619,9 +621,9 @@ public class GroupUrlLink } else { - if (rg.matchedFrom(s) > -1) + if (rg.matchedFromI(s) > -1) { - subs.append(rg.stringMatched(s)); // concatenate + subs.append(rg.stringMatchedI(s)); // concatenate } s++; } @@ -817,6 +819,11 @@ public class GroupUrlLink } } + /** + * @j2sIgnore + * + * @param args + */ public static void main(String argv[]) { // note - JAL-1383 - these services are all dead diff --git a/src/jalview/util/MessageManager.java b/src/jalview/util/MessageManager.java index 4001cb2..5a5c70f 100644 --- a/src/jalview/util/MessageManager.java +++ b/src/jalview/util/MessageManager.java @@ -26,6 +26,8 @@ import java.util.ResourceBundle; import java.util.logging.Level; import java.util.logging.Logger; +import javajs.J2SRequireImport; + /** * * @author David Roldan Martinez @@ -33,6 +35,7 @@ import java.util.logging.Logger; * * */ +@J2SRequireImport ({java.text.MessageFormat.class}) public class MessageManager { @@ -53,7 +56,8 @@ public class MessageManager /* Getting messages for GV */ log.info("Getting messages for lang: " + loc); rb = ResourceBundle.getBundle("lang.Messages", loc); - if (log.isLoggable(Level.FINEST)) + // BH rb == null just throws the exception + if (rb == null || log.isLoggable(Level.FINEST)) { // this might take a while, so we only do it if it will be shown log.finest("Language keys: " + rb.keySet()); @@ -92,12 +96,12 @@ public class MessageManager public static String formatMessage(String key, Object... params) { - return MessageFormat.format(rb.getString(key), params); + return MessageFormat.format(getString(key), params); // BH not rb.getString } public static String formatMessage(String key, String[] params) { - return MessageFormat.format(rb.getString(key), (Object[]) params); + return MessageFormat.format(getString(key), (Object[]) params); // BH not rb.getString } /** diff --git a/src/jalview/util/QuickSort.java b/src/jalview/util/QuickSort.java index b0e75be..2a464c6 100755 --- a/src/jalview/util/QuickSort.java +++ b/src/jalview/util/QuickSort.java @@ -45,7 +45,7 @@ public class QuickSort @Override public int compare(Integer o1, Integer o2) { - return Float.compare(values[o1], values[o2]); + return Float.compare(values[o1.intValue()], values[o2]); } } @@ -87,7 +87,7 @@ public class QuickSort * @param arr * @param s */ - public static void sortFloat(float[] arr, Object[] s) + public static void sortFloatObject(float[] arr, Object[] s) { sortFloat(arr, 0, arr.length - 1, s); } @@ -116,7 +116,7 @@ public class QuickSort stringSort(arr, 0, arr.length - 1, s); } - static void stringSort(String[] arr, int p, int r, Object[] s) + private static void stringSort(String[] arr, int p, int r, Object[] s) { int q; @@ -128,7 +128,7 @@ public class QuickSort } } - static void sortFloat(float[] arr, int p, int r, Object[] s) + private static void sortFloat(float[] arr, int p, int r, Object[] s) { int q; @@ -140,7 +140,17 @@ public class QuickSort } } - static void sortDouble(double[] arr, int p, int r, Object[] s) + /** + * We don't need both of these + * + * @j2sIgnore + * + * @param arr + * @param p + * @param r + * @param s + */ + private static void sortDouble(double[] arr, int p, int r, Object[] s) { int q; @@ -152,7 +162,7 @@ public class QuickSort } } - static void sortInt(int[] arr, int p, int r, Object[] s) + private static void sortInt(int[] arr, int p, int r, Object[] s) { int q; @@ -164,7 +174,7 @@ public class QuickSort } } - static int partitionFloat(float[] arr, int p, int r, Object[] s) + private static int partitionFloat(float[] arr, int p, int r, Object[] s) { float x = arr[p]; int i = p - 1; @@ -199,7 +209,7 @@ public class QuickSort } } - static int partitionFloat(float[] arr, int p, int r, char[] s) + private static int partitionFloatChar(float[] arr, int p, int r, char[] s) { float x = arr[p]; int i = p - 1; @@ -234,7 +244,7 @@ public class QuickSort } } - static int partitionInt(int[] arr, int p, int r, Object[] s) + private static int partitionInt(int[] arr, int p, int r, Object[] s) { int x = arr[p]; int i = p - 1; @@ -269,7 +279,7 @@ public class QuickSort } } - static int partitionDouble(double[] arr, int p, int r, Object[] s) + private static int partitionDouble(double[] arr, int p, int r, Object[] s) { double x = arr[p]; int i = p - 1; @@ -304,7 +314,7 @@ public class QuickSort } } - static int stringPartition(String[] arr, int p, int r, Object[] s) + private static int stringPartition(String[] arr, int p, int r, Object[] s) { String x = arr[p]; int i = p - 1; @@ -346,7 +356,7 @@ public class QuickSort * @param arr * @param s */ - public static void sortFloat(float[] arr, char[] s) + public static void sortFloatChar(float[] arr, char[] s) { /* * Sort all zero values to the front @@ -388,7 +398,7 @@ public class QuickSort float[] nonZeroFloats = Arrays .copyOfRange(f1, nextZeroValue, f1.length); char[] nonZeroChars = Arrays.copyOfRange(s1, nextZeroValue, s1.length); - externalSort(nonZeroFloats, nonZeroChars); + externalSortFloat(nonZeroFloats, nonZeroChars); // sort(nonZeroFloats, 0, nonZeroFloats.length - 1, nonZeroChars); /* @@ -409,7 +419,7 @@ public class QuickSort * @param arr * @param s */ - protected static void externalSort(float[] arr, char[] s) + private static void externalSortFloat(float[] arr, char[] s) { final int length = arr.length; Integer[] indices = makeIndexArray(length); @@ -439,7 +449,7 @@ public class QuickSort * @param length * @return */ - protected static Integer[] makeIndexArray(final int length) + private static Integer[] makeIndexArray(final int length) { Integer[] indices = new Integer[length]; for (int i = 0; i < length; i++) @@ -449,17 +459,17 @@ public class QuickSort return indices; } - static void sortFloat(float[] arr, int p, int r, char[] s) - { - int q; - if (p < r) - { - q = partitionFloat(arr, p, r, s); - sortFloat(arr, p, q, s); - sortFloat(arr, q + 1, r, s); - } - } - +// private static void sortFloat(float[] arr, int p, int r, char[] s) +// { +// int q; +// if (p < r) +// { +// q = partitionFloatChar(arr, p, r, s); +// sortFloat(arr, p, q, s); +// sortFloat(arr, q + 1, r, s); +// } +// } +// /** * Sorts both arrays to give ascending order in the first array, by first * partitioning into zero and non-zero values before sorting the latter. @@ -467,7 +477,7 @@ public class QuickSort * @param arr * @param s */ - public static void sortInt(int[] arr, char[] s) + public static void sortIntChar(int[] arr, char[] s) { /* * Sort all zero values to the front @@ -509,7 +519,7 @@ public class QuickSort int[] nonZeroInts = Arrays .copyOfRange(f1, nextZeroValue, f1.length); char[] nonZeroChars = Arrays.copyOfRange(s1, nextZeroValue, s1.length); - externalSort(nonZeroInts, nonZeroChars); + externalSortInt(nonZeroInts, nonZeroChars); // sort(nonZeroFloats, 0, nonZeroFloats.length - 1, nonZeroChars); /* @@ -529,7 +539,7 @@ public class QuickSort * @param arr * @param s */ - protected static void externalSort(int[] arr, char[] s) + private static void externalSortInt(int[] arr, char[] s) { final int length = arr.length; Integer[] indices = makeIndexArray(length); diff --git a/src/jalview/util/UrlLink.java b/src/jalview/util/UrlLink.java index c0cf821..cf0d466 100644 --- a/src/jalview/util/UrlLink.java +++ b/src/jalview/util/UrlLink.java @@ -20,9 +20,12 @@ */ package jalview.util; +import jalview.jsdev.RegExp; +import jalview.jsdev.api.RegExpInterface; + import java.util.Vector; -import com.stevesoft.pat.Regex; +//import com.stevesoft.pat.Regex; public class UrlLink { @@ -86,7 +89,7 @@ public class UrlLink regexReplace = link.substring(psqid + 14, p); try { - Regex rg = Regex.perlCode("/" + RegExpInterface rg = RegExp.perlCode("/" + regexReplace + "/"); if (rg == null) { @@ -201,7 +204,7 @@ public class UrlLink { if (regexReplace != null) { - Regex rg = Regex.perlCode("/" + regexReplace + "/"); + RegExpInterface rg = RegExp.perlCode("/" + regexReplace + "/"); if (rg.search(idstring)) { int ns = rg.numSubs(); @@ -209,7 +212,7 @@ public class UrlLink { // take whole regex return new String[] - { rg.stringMatched(), + { rg.stringMatchedI(ns), url_prefix + rg.stringMatched() + url_suffix }; } /* * else if (ns==1) { // take only subgroup match return new String[] @@ -221,9 +224,9 @@ public class UrlLink // debug for (int s = 0; s <= rg.numSubs(); s++) { - System.err.println("Sub " + s + " : " + rg.matchedFrom(s) - + " : " + rg.matchedTo(s) + " : '" - + rg.stringMatched(s) + "'"); + System.err.println("Sub " + s + " : " + rg.matchedFromI(s) + + " : " + rg.matchedToI(s) + " : '" + + rg.stringMatchedI(s) + "'"); } // try to collate subgroup matches Vector subs = new Vector(); @@ -232,19 +235,19 @@ public class UrlLink int s = 0; // 1; while (s <= ns) { - if (s + 1 <= ns && rg.matchedTo(s) > -1 - && rg.matchedTo(s + 1) > -1 - && rg.matchedTo(s + 1) < rg.matchedTo(s)) + if (s + 1 <= ns && rg.matchedToI(s) > -1 + && rg.matchedToI(s + 1) > -1 + && rg.matchedToI(s + 1) < rg.matchedToI(s)) { // s is top level submatch. search for submatches enclosed by // this one int r = s + 1; String mtch = ""; - while (r <= ns && rg.matchedTo(r) <= rg.matchedTo(s)) + while (r <= ns && rg.matchedToI(r) <= rg.matchedToI(s)) { - if (rg.matchedFrom(r) > -1) + if (rg.matchedFromI(r) > -1) { - mtch += rg.stringMatched(r); + mtch += rg.stringMatchedI(r); } r++; } @@ -257,10 +260,10 @@ public class UrlLink } else { - if (rg.matchedFrom(s) > -1) + if (rg.matchedFromI(s) > -1) { - subs.addElement(rg.stringMatched(s)); - subs.addElement(url_prefix + rg.stringMatched(s) + subs.addElement(rg.stringMatchedI(s)); + subs.addElement(url_prefix + rg.stringMatchedI(s) + url_suffix); } s++; @@ -327,6 +330,11 @@ public class UrlLink } } + /** + * @j2sIgnore + * + * @param args + */ public static void main(String argv[]) { String[] links = new String[] diff --git a/src/jalview/viewmodel/seqfeatures/FeatureRendererModel.java b/src/jalview/viewmodel/seqfeatures/FeatureRendererModel.java index 63faab9..d3f150b 100644 --- a/src/jalview/viewmodel/seqfeatures/FeatureRendererModel.java +++ b/src/jalview/viewmodel/seqfeatures/FeatureRendererModel.java @@ -5,7 +5,6 @@ import jalview.api.FeaturesDisplayedI; import jalview.datamodel.AlignmentI; import jalview.datamodel.SequenceFeature; import jalview.datamodel.SequenceI; -import jalview.renderer.seqfeatures.FeatureRenderer; import jalview.schemes.GraduatedColor; import jalview.schemes.UserColourScheme; import jalview.util.QuickSort; @@ -72,7 +71,7 @@ public abstract class FeatureRendererModel implements */ public void transferSettings(jalview.api.FeatureRenderer _fr) { - FeatureRenderer fr = (FeatureRenderer) _fr; + FeatureRendererModel fr = (FeatureRendererModel) _fr; FeatureRendererSettings frs = new FeatureRendererSettings(fr); this.renderOrder = frs.renderOrder; this.featureGroups = frs.featureGroups; @@ -508,7 +507,7 @@ public abstract class FeatureRendererModel implements } if (iSize > 1 && sort) { - QuickSort.sortFloat(sortOrder, newf); + QuickSort.sortFloatObject(sortOrder, newf); } sortOrder = null; System.arraycopy(newf, 0, renderOrder, opos, newf.length); diff --git a/src/jalview/workers/ConsensusThread.java b/src/jalview/workers/ConsensusThread.java index f244242..e12c5b8 100644 --- a/src/jalview/workers/ConsensusThread.java +++ b/src/jalview/workers/ConsensusThread.java @@ -44,6 +44,7 @@ public class ConsensusThread extends AlignCalcWorker implements @Override public void run() { + if (calcMan.isPending(this)) { return; diff --git a/src/javajs/J2SIgnoreImport.java b/src/javajs/J2SIgnoreImport.java new file mode 100644 index 0000000..b92c82b --- /dev/null +++ b/src/javajs/J2SIgnoreImport.java @@ -0,0 +1,7 @@ +package javajs; + +public @interface J2SIgnoreImport { + + Class[] value(); + +} diff --git a/src/javajs/J2SRequireImport.java b/src/javajs/J2SRequireImport.java new file mode 100644 index 0000000..646cebd --- /dev/null +++ b/src/javajs/J2SRequireImport.java @@ -0,0 +1,7 @@ +package javajs; + +public @interface J2SRequireImport { + + Class[] value(); + +} diff --git a/src/javajs/api/BytePoster.java b/src/javajs/api/BytePoster.java new file mode 100644 index 0000000..0b0f29a --- /dev/null +++ b/src/javajs/api/BytePoster.java @@ -0,0 +1,7 @@ +package javajs.api; + +public interface BytePoster { + + String postByteArray(String fileName, byte[] bytes); + +} diff --git a/src/javajs/api/EigenInterface.java b/src/javajs/api/EigenInterface.java new file mode 100644 index 0000000..4a1b592 --- /dev/null +++ b/src/javajs/api/EigenInterface.java @@ -0,0 +1,15 @@ +package javajs.api; + +import javajs.util.V3; + +public interface EigenInterface { + + EigenInterface setM(double[][] n); + + double[] getEigenvalues(); + + void fillFloatArrays(V3[] eigenVectors, float[] eigenValues); + + float[][] getEigenvectorsFloatTransposed(); + +} diff --git a/src/javajs/api/EventManager.java b/src/javajs/api/EventManager.java new file mode 100644 index 0000000..a2994be --- /dev/null +++ b/src/javajs/api/EventManager.java @@ -0,0 +1,16 @@ +package javajs.api; + +public interface EventManager { + + boolean keyPressed(int keyCode, int modifiers); + + boolean keyTyped(int keyChar, int modifiers); + + void keyReleased(int keyCode); + + void mouseEnterExit(long time, int x, int y, boolean isExit); + + void mouseAction(int mode, long time, int x, int y, int count, + int buttonMods); + +} diff --git a/src/javajs/api/FontManager.java b/src/javajs/api/FontManager.java new file mode 100644 index 0000000..cc442c4 --- /dev/null +++ b/src/javajs/api/FontManager.java @@ -0,0 +1,23 @@ +package javajs.api; + +import javajs.awt.Font; + +/** + * A generic interface for font queries. + * In JSmol it is handled by org.jmol.api.ApiPlatform + */ + +public interface FontManager { + + int fontStringWidth(Font font, String text); + + int getFontAscent(Object fontMetrics); + + int getFontDescent(Object fontMetrics); + + Object getFontMetrics(Font font, Object graphics); + + Object newFont(String fontFace, boolean isBold, boolean isItalic, float fontSize); + + +} diff --git a/src/javajs/api/GenericBinaryDocument.java b/src/javajs/api/GenericBinaryDocument.java new file mode 100644 index 0000000..3cf4739 --- /dev/null +++ b/src/javajs/api/GenericBinaryDocument.java @@ -0,0 +1,53 @@ +package javajs.api; + +import java.io.BufferedInputStream; +import java.io.DataInputStream; +import java.util.Map; + + +import javajs.util.OC; +import javajs.util.SB; + +public interface GenericBinaryDocument { + + void setStream(GenericZipTools jzt, BufferedInputStream bis, boolean isBigEndian); + + void setStreamData(DataInputStream dataInputStream, boolean isBigEndian); + + long getPosition(); + + SB getAllDataFiles(String binaryFileList, String firstFile); + + void getAllDataMapped(String replace, String string, Map fileData); + + int swapBytesI(int nx); + + short swapBytesS(short s); + + void seek(long i); + + byte readByte() throws Exception; + + int readInt() throws Exception; + + int readIntLE() throws Exception; + + long readLong() throws Exception; + + float readFloat() throws Exception; + + double readDouble() throws Exception; + + short readShort() throws Exception; + + int readUnsignedShort() throws Exception; + + String readString(int i) throws Exception; + + int readByteArray(byte[] b, int off, int len) throws Exception; + + void close(); + + void setOutputChannel(OC out); + +} diff --git a/src/javajs/api/GenericCifDataParser.java b/src/javajs/api/GenericCifDataParser.java new file mode 100644 index 0000000..8dc0091 --- /dev/null +++ b/src/javajs/api/GenericCifDataParser.java @@ -0,0 +1,45 @@ +package javajs.api; + +import java.io.BufferedReader; +import java.util.Map; + + +public interface GenericCifDataParser { + + static final int NONE = -1; + + String fullTrim(String str); + + Map getAllCifData(); + + boolean getData() throws Exception; + + String getField(int i); + + int getFieldCount(); + + String getFileHeader(); + + String getLoopData(int i); + + String getNextDataToken() throws Exception; + + String getNextToken() throws Exception; + + String getTokenPeeked(); + + int parseLoopParameters(String[] fields, int[] fieldOf, int[] propertyOf) throws Exception; + + String peekToken() throws Exception; + + String readLine(); + + GenericCifDataParser set(GenericLineReader reader, BufferedReader br); + + String toUnicode(String data); + + String skipLoop(boolean doReport) throws Exception; + + String fixKey(String key); + +} diff --git a/src/javajs/api/GenericColor.java b/src/javajs/api/GenericColor.java new file mode 100644 index 0000000..57cf169 --- /dev/null +++ b/src/javajs/api/GenericColor.java @@ -0,0 +1,19 @@ +package javajs.api; + +/** + * GenericColor allows both java.awt.Color and javajs.awt.Color to be + * handled by methods that need not distinguish between them. It is used + * in the javajs package for the background color of a javajs.swing.JComponent + * + * @author hansonr + * + */ +public interface GenericColor { + + int getRGB(); + + int getOpacity255(); + + void setOpacity255(int a); + +} diff --git a/src/javajs/api/GenericFileInterface.java b/src/javajs/api/GenericFileInterface.java new file mode 100644 index 0000000..2a32b51 --- /dev/null +++ b/src/javajs/api/GenericFileInterface.java @@ -0,0 +1,15 @@ +package javajs.api; + +public interface GenericFileInterface { + + String getFullPath(); + + String getName(); + + long length(); + + boolean isDirectory(); + + GenericFileInterface getParentAsFile(); + +} diff --git a/src/javajs/api/GenericImageDialog.java b/src/javajs/api/GenericImageDialog.java new file mode 100644 index 0000000..54d8503 --- /dev/null +++ b/src/javajs/api/GenericImageDialog.java @@ -0,0 +1,9 @@ +package javajs.api; + +public interface GenericImageDialog { + + void closeMe(); + + void setImage(Object image); + +} diff --git a/src/javajs/api/GenericImageEncoder.java b/src/javajs/api/GenericImageEncoder.java new file mode 100644 index 0000000..9aa7477 --- /dev/null +++ b/src/javajs/api/GenericImageEncoder.java @@ -0,0 +1,12 @@ +package javajs.api; + +import java.util.Map; + +import javajs.util.OC; + +public interface GenericImageEncoder { + + public boolean createImage(String type, OC out, + Map params) throws Exception; + +} diff --git a/src/javajs/api/GenericLineReader.java b/src/javajs/api/GenericLineReader.java new file mode 100644 index 0000000..f113a8b --- /dev/null +++ b/src/javajs/api/GenericLineReader.java @@ -0,0 +1,5 @@ +package javajs.api; + +public interface GenericLineReader { + public String readNextLine() throws Exception; +} diff --git a/src/javajs/api/GenericMenuInterface.java b/src/javajs/api/GenericMenuInterface.java new file mode 100644 index 0000000..b4017ee --- /dev/null +++ b/src/javajs/api/GenericMenuInterface.java @@ -0,0 +1,18 @@ +package javajs.api; + + +public interface GenericMenuInterface { + + public void jpiDispose(); + public Object jpiGetMenuAsObject(); + public String jpiGetMenuAsString(String string); + public void jpiInitialize(PlatformViewer vwr, String menu); + public void jpiShow(int x, int y); + public void jpiUpdateComputedMenus(); + + public void menuClickCallback(SC source, String actionCommand); + public void menuFocusCallback(String name, String actionCommand, boolean b); + public void menuCheckBoxCallback(SC source); + + +} diff --git a/src/javajs/api/GenericMouseInterface.java b/src/javajs/api/GenericMouseInterface.java new file mode 100644 index 0000000..2b468e4 --- /dev/null +++ b/src/javajs/api/GenericMouseInterface.java @@ -0,0 +1,13 @@ +package javajs.api; + +public interface GenericMouseInterface { + + boolean processEvent(int id, int x, int y, int modifiers, long time); + + void clear(); + + void dispose(); + + void processTwoPointGesture(float[][][] touches); + +} diff --git a/src/javajs/api/GenericPlatform.java b/src/javajs/api/GenericPlatform.java new file mode 100644 index 0000000..9c99e41 --- /dev/null +++ b/src/javajs/api/GenericPlatform.java @@ -0,0 +1,141 @@ +package javajs.api; + + +import java.net.URL; +import java.util.Map; + + +import javajs.awt.Font; +import javajs.util.P3; + +public interface GenericPlatform extends FontManager { + + public final static int CURSOR_DEFAULT = 0; + public final static int CURSOR_CROSSHAIR = 1; + public final static int CURSOR_WAIT = 3; + public final static int CURSOR_ZOOM = 8; + public final static int CURSOR_HAND = 12; + public final static int CURSOR_MOVE = 13; + + void setViewer(PlatformViewer vwr, Object display); + + /////// Display + + boolean isHeadless(); + + void convertPointFromScreen(Object display, P3 ptTemp); + + void getFullScreenDimensions(Object display, int[] widthHeight); + + boolean hasFocus(Object display); + + String prompt(String label, String data, String[] list, boolean asButtons); + + void repaint(Object display); + + void requestFocusInWindow(Object display); + + void setCursor(int i, Object display); + + void setTransparentCursor(Object display); + + //// Mouse + + GenericMouseInterface getMouseManager(double privateKey, Object display); + + ///// core Image handling + + Object allocateRgbImage(int windowWidth, int windowHeight, int[] pBuffer, + int windowSize, boolean backgroundTransparent, boolean isImageWrite); + + void disposeGraphics(Object graphicForText); + + void drawImage(Object g, Object img, int x, int y, int width, int height); + + int[] drawImageToBuffer(Object gObj, Object imageOffscreen, + Object image, int width, int height, int bgcolor); + + void flushImage(Object imagePixelBuffer); + + Object getStaticGraphics(Object image, boolean backgroundTransparent); + + Object getGraphics(Object image); + + int getImageWidth(Object image); + + int getImageHeight(Object image); + + Object newBufferedImage(Object image, int i, int height); + + Object newOffScreenImage(int w, int h); + + @Deprecated + void renderScreenImage(Object g, Object currentSize); + + int[] getTextPixels(String text, Font font3d, Object gObj, + Object image, int mapWidth, int height, + int ascent); + + ///// Image creation for export (optional for any platform) + + /** + * can be ignored (return null) if platform cannot save images + * + * @param ret + * @return null only if this platform cannot save images + */ + Object createImage(Object ret); + + /** + * + * @param image + * @param width + * @param height + * @param pixels + * @param startRow + * @param nRows + * @return pixels + */ + int[] grabPixels(Object image, int width, int height, + int[] pixels, int startRow, int nRows); + + /** + * can be ignored (return false) if platform cannot save images + * + * @param boolIsEcho + * @param image + * @return false only if this platform cannot save images + * @throws InterruptedException + */ + boolean waitForDisplay(Object boolIsEcho, Object image) throws InterruptedException; + + GenericMenuInterface getMenuPopup(String menuStructure, char type); + + Object getJsObjectInfo(Object[] jsObject, String method, Object[] args); + + boolean isSingleThreaded(); + + void notifyEndOfRendering(); + + String getDateFormat(String isoType); + + GenericFileInterface newFile(String name); + + Object getBufferedFileInputStream(String name); + + /** + * + * @param url + * @param outputBytes + * @param post + * @param asString + * @return may be javajs.util.SB or byte[] or java.io.InputStream + */ + Object getURLContents(URL url, byte[] outputBytes, String post, boolean asString); + + String getLocalUrl(String fileName); + + GenericImageDialog getImageDialog(String title, + Map imageMap); + +} diff --git a/src/javajs/api/GenericZipInputStream.java b/src/javajs/api/GenericZipInputStream.java new file mode 100644 index 0000000..e2e8018 --- /dev/null +++ b/src/javajs/api/GenericZipInputStream.java @@ -0,0 +1,13 @@ +package javajs.api; + + +import java.io.InputStream; +import java.util.zip.ZipInputStream; + +public class GenericZipInputStream extends ZipInputStream implements ZInputStream { + + public GenericZipInputStream(InputStream in) { + super(in); + } + +} \ No newline at end of file diff --git a/src/javajs/api/GenericZipTools.java b/src/javajs/api/GenericZipTools.java new file mode 100644 index 0000000..2fcaa10 --- /dev/null +++ b/src/javajs/api/GenericZipTools.java @@ -0,0 +1,45 @@ +package javajs.api; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.InputStream; + +import java.util.Map; + + +public interface GenericZipTools { + + public ZInputStream newZipInputStream(InputStream is); + + public String getZipDirectoryAsStringAndClose(BufferedInputStream t); + + public InputStream newGZIPInputStream(InputStream bis) throws IOException; + + public Object getZipFileDirectory(BufferedInputStream bis, + String[] subFileList, int listPtr, boolean asBufferedInputStream); + + public String[] getZipDirectoryAndClose(BufferedInputStream t, + String manifestID); + + public void getAllZipData(InputStream bis, String[] subFileList, + String replace, String string, + Map fileData); + + public Object getZipFileContentsAsBytes(BufferedInputStream bis, + String[] subFileList, int i); + + public void addZipEntry(Object zos, String fileName) throws IOException; + + public void closeZipEntry(Object zos) throws IOException; + + public Object getZipOutputStream(Object bos); + + public int getCrcValue(byte[] bytes); + + public void readFileAsMap(BufferedInputStream is, Map bdata, String name); + + public String cacheZipContents(BufferedInputStream bis, String shortName, + Map cache, boolean asByteArray); + + BufferedInputStream getUnGzippedInputStream(byte[] bytes); +} diff --git a/src/javajs/api/HTMLElement.java b/src/javajs/api/HTMLElement.java new file mode 100644 index 0000000..ad67114 --- /dev/null +++ b/src/javajs/api/HTMLElement.java @@ -0,0 +1,5 @@ +package javajs.api; + +public interface HTMLElement { + +} diff --git a/src/javajs/api/HTMLWindowEvent.java b/src/javajs/api/HTMLWindowEvent.java new file mode 100644 index 0000000..0321e36 --- /dev/null +++ b/src/javajs/api/HTMLWindowEvent.java @@ -0,0 +1,10 @@ +package javajs.api; + +/** + * The window.Event in HTML5 + * See SwingController. + * + */ +public interface HTMLWindowEvent { + +} diff --git a/src/javajs/api/Interface.java b/src/javajs/api/Interface.java new file mode 100644 index 0000000..a4c9e3f --- /dev/null +++ b/src/javajs/api/Interface.java @@ -0,0 +1,40 @@ +/* $RCSfile$ + * $Author$ + * $Date$ + * $Revision$ + * + * Copyright (C) 2006 The Jmol Development Team + * + * Contact: jmol-developers@lists.sf.net + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +package javajs.api; + +public class Interface { + + public static Object getInterface(String name) { + try { + Class x = Class.forName(name); + return (x == null ? null : x.newInstance()); + } catch (Exception e) { + System.out.println("Interface.java Error creating instance for " + name + ": \n" + e); + return null; + } + } + +} diff --git a/src/javajs/api/JSInterface.java b/src/javajs/api/JSInterface.java new file mode 100644 index 0000000..0f785fa --- /dev/null +++ b/src/javajs/api/JSInterface.java @@ -0,0 +1,30 @@ +package javajs.api; + +/** + * called by JSmol JavaScript methods using + * + * this._applet.xxxx() + * + */ +public interface JSInterface { + + int cacheFileByName(String fileName, boolean isAdd); + void cachePut(String key, Object data); + void destroy(); + String getFullName(); + void openFileAsyncSpecial(String fileName, int flags); + boolean processMouseEvent(int id, int x, int y, int modifiers, long time); + void processTwoPointGesture(float[][][] touches); + void setDisplay(Object canvas); + void setScreenDimension(int width, int height); + boolean setStatusDragDropped(int mode, int x, int y, String fileName); + void startHoverWatcher(boolean enable); + void update(); + + // these are not general methods +//Object getGLmolView(); +//String loadInlineString(String mol, String script, boolean isAppend); +//String openFile(String fileName); + +} + diff --git a/src/javajs/api/JSONEncodable.java b/src/javajs/api/JSONEncodable.java new file mode 100644 index 0000000..b013279 --- /dev/null +++ b/src/javajs/api/JSONEncodable.java @@ -0,0 +1,7 @@ +package javajs.api; + +public interface JSONEncodable { + + String toJSON(); + +} diff --git a/src/javajs/api/JmolObjectInterface.java b/src/javajs/api/JmolObjectInterface.java new file mode 100644 index 0000000..e1872ee --- /dev/null +++ b/src/javajs/api/JmolObjectInterface.java @@ -0,0 +1,12 @@ +package javajs.api; + +/** + * methods in JSmol JavaScript accessed in Jmol + */ +public interface JmolObjectInterface { + + Object _doAjax(Object url, String postOut, Object bytesOrStringOut); + + void _apply(Object func, Object data); + +} diff --git a/src/javajs/api/PlatformViewer.java b/src/javajs/api/PlatformViewer.java new file mode 100644 index 0000000..cd308bf --- /dev/null +++ b/src/javajs/api/PlatformViewer.java @@ -0,0 +1,7 @@ +package javajs.api; + +public interface PlatformViewer { + +// a placeholder for a class that might be used within classes called by Platform.java + +} diff --git a/src/javajs/api/SC.java b/src/javajs/api/SC.java new file mode 100644 index 0000000..1c6da16 --- /dev/null +++ b/src/javajs/api/SC.java @@ -0,0 +1,65 @@ +package javajs.api; + +/** + * SwingComponent interface common to javax.swing and javajs.swing + * + * Can be augmented as needed, provided classes of javajs.swing are also + * updated. (SwingComponents in javajs are subclasses of AbstractButton.) + * + */ + +public interface SC { + + void add(SC item); + + void addActionListener(Object owner); + + void addItemListener(Object owner); + + void addMouseListener(Object owner); + + String getActionCommand(); + + Object getComponent(int i); + + int getComponentCount(); + + Object[] getComponents(); + + String getName(); + + Object getParent(); + + Object getPopupMenu(); + + Object getIcon(); + + String getText(); + + void init(String text, Object icon, String actionCommand, SC popupMenu); + + void insert(SC subMenu, int index); + + boolean isEnabled(); + + boolean isSelected(); + + void remove(int i); + + void removeAll(); + + void setActionCommand(String script); + + void setAutoscrolls(boolean b); + + void setEnabled(boolean enable); + + void setIcon(Object icon); + + void setName(String string); + + void setSelected(boolean state); + + void setText(String entry); + +} diff --git a/src/javajs/api/SwingController.java b/src/javajs/api/SwingController.java new file mode 100644 index 0000000..68aace5 --- /dev/null +++ b/src/javajs/api/SwingController.java @@ -0,0 +1,136 @@ +package javajs.api; + +import javajs.awt.Component; +import javajs.awt.Dimension; + +/** + * SwingController is an interface that javajs.swing classes will need. + * It must be implemented as a JavaScript object PRIOR to + * any calls to create any components. + * + * In JSmol it is Jmol.Swing (see JsmolCore.js) + * + * There should be one and only one SwingController on a page. + * It is called by its class name "SwingController" directly. + * + * @author hansonr + * + */ +public interface SwingController { + + /** + * Fired from clicking an element such as a button or + * check box or table entry, or from entering text in a text box. + * + * SwingController should make the changes in the underlying + * "Java" object directly, then send notification of the event to the manager. + * For instance: + * + * var component = Jmol.Swing.htDialogs[element.id]; + * var info = component.toString(); + * + * if (info.indexOf("JCheck") >= 0) + * component.selected = element.checked; + * var id = $("div.JDialog:has(#" + element.id + ")")[0].id + * var dialog = Jmol.Swing.htDialogs[id]; + * dialog.manager.actionPerformed(component ? component.name : dialog.registryKey + "/" + element.id); + * + * @param element + * @param event + */ + void click(HTMLElement element, HTMLWindowEvent event); + + + /** + * Remove this component's HTML5 equivalent and clear references to it. + * + * @param dialog + */ + void dispose(Component dialog); + + /** + * Return the width and height of the window in d. + * For example: + * + * d.width = $(window).width(); + * d.height = $(window).height(); + * + * @param d + */ + void getScreenDimensions(Dimension d); + + /** + * Set c's id to a unique identifier + * and add it to an associative array that will + * associate that id with c. + * + * @param c + * @param type + */ + void register(Component c, String type); + + /** + * The HTML for this dialog has been generated. + * Now create the HTML on the page for this dialog + * based on dialog.html and wrap it appropriately. + * + * @param dialog + */ + void setDialog(Component dialog); + + /** + * Convey to the HTML object that this check box's selection + * has been changed. + * + * $("#" + chk.id).prop('checked', !!chk.selected); + * + * @param chk + */ + void setSelected(Component chk); + + /** + * Convey to the HTML object that this combo box's selected item + * has been changed. + * + * $("#" + cmb.id).prop('selectedIndex', cmb.selectedIndex); + * + * @param cmb + */ + void setSelectedIndex(Component cmb); + + /** + * Convey to the HTML object that this component's text + * has been changed. + * + * $("#" + btn.id).prop('value', btn.text); + * + * @param text + */ + void setText(String text); + + /** + * Convey to the HTML object that this component's text + * has been changed. + * + * if (c.visible) + * $("#" + c.id).show(); + * else + * $("#" + c.id).hide(); + * + * @param c + */ + void setVisible(Component c); + + /** + * Called by clicking the [x] in the corner of the dialog; + * send a notification back to the manager via processWindowClosing(key) + * + * var id = $("div.JDialog:has(#" + element.id + ")")[0].id + * var dialog = Jmol.Swing.htDialogs[id]; + * dialog.manager.processWindowClosing(dialog.registryKey); + * + * @param element + */ + void windowClosing(HTMLElement element); + +} diff --git a/src/javajs/api/ZInputStream.java b/src/javajs/api/ZInputStream.java new file mode 100644 index 0000000..a3310f6 --- /dev/null +++ b/src/javajs/api/ZInputStream.java @@ -0,0 +1,6 @@ +package javajs.api; + +public interface ZInputStream { + // placeholder for ZipInputStream not requiring direct access to java.util.zip + +} diff --git a/src/javajs/awt/BorderLayout.java b/src/javajs/awt/BorderLayout.java new file mode 100644 index 0000000..0ee97db --- /dev/null +++ b/src/javajs/awt/BorderLayout.java @@ -0,0 +1,12 @@ +package javajs.awt; + + +public class BorderLayout extends LayoutManager { + + public static final String CENTER = "Center"; + public static final String NORTH = "North"; + public static final String SOUTH = "South"; + public static final String EAST = "East"; + public static final String WEST = "West"; + +} diff --git a/src/javajs/awt/Color.java b/src/javajs/awt/Color.java new file mode 100644 index 0000000..82c27f2 --- /dev/null +++ b/src/javajs/awt/Color.java @@ -0,0 +1,53 @@ +package javajs.awt; + +import javajs.api.GenericColor; + +public class Color implements GenericColor { + + public int argb; + + + @Override + public int getRGB() { + return argb & 0x00FFFFFF; + } + + + @Override + public int getOpacity255() { + return ((argb >> 24) & 0xFF); + } + + + @Override + public void setOpacity255(int a) { + argb = argb & 0xFFFFFF | ((a & 0xFF) << 24); + } + + public static GenericColor get1(int rgb) { + Color c = new Color(); + c.argb = rgb | 0xFF000000; + return c; + } + + public static GenericColor get3(int r, int g, int b) { + return new Color().set4(r, g, b, 0xFF); + } + + public static GenericColor get4(int r, int g, int b, int a) { + return new Color().set4(r, g, b, a); + } + + private GenericColor set4(int r, int g, int b, int a) { + argb = ((a << 24) | (r << 16) | (g << 8) | b) & 0xFFFFFFFF; + return this; + } + + @Override + public String toString() { + String s = ("00000000" + Integer.toHexString(argb)); + return "[0x" + s.substring(s.length() - 8, s.length()) + "]"; + } + + +} diff --git a/src/javajs/awt/Component.java b/src/javajs/awt/Component.java new file mode 100644 index 0000000..505d0b3 --- /dev/null +++ b/src/javajs/awt/Component.java @@ -0,0 +1,155 @@ +package javajs.awt; + +import javajs.api.GenericColor; +import javajs.util.CU; + +abstract public class Component { + + protected boolean visible; + protected boolean enabled = true; + protected String text; + protected String name; + protected int width; + protected int height; + protected String id; + + protected Object parent; + + public void setParent(Object p) { + parent = p; + } + + protected Object mouseListener; + + private GenericColor bgcolor; + + protected Component(String type) { + id = newID(type); + if (type == null) + return; + /** + * @j2sNative + * SwingController.register(this, type); + */ + { + } + + } + + public static String newID(String type) { + return type + ("" + Math.random()).substring(3, 10); + } + + abstract public String toHTML(); + + public void setBackground(GenericColor color) { + bgcolor = color; + } + + public void setText(String text) { + this.text = text; + /** + * @j2sNative + * + * SwingController.setText(this); + * + */ + { + } + } + + public void setName(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public Object getParent() { + return parent; + } + + public void setPreferredSize(Dimension dimension) { + this.width = dimension.width; + this.height = dimension.height; + } + + public void addMouseListener(Object listener) { + mouseListener = listener; + } + + public String getText() { + return text; + } + + public boolean isEnabled() { + return enabled; + } + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + /** + * @j2sNative + * + * SwingController.setEnabled(this); + * + */ + {} + } + + public boolean isVisible() { + return visible; + } + + public void setVisible(boolean visible) { + this.visible = visible; + /** + * @j2sNative + * + * SwingController.setVisible(this); + * + */ + {} + } + + public int getHeight() { + return height; + } + + public int getWidth() { + return width; + } + + protected int minWidth = 30; + protected int minHeight = 30; + + public void setMinimumSize(Dimension d) { + minWidth = d.width; + minHeight = d.height; + } + + public int getSubcomponentWidth() { + return width; + } + + public int getSubcomponentHeight() { + return height; + } + + protected int renderWidth; + protected int renderHeight; + + protected String getCSSstyle(int defaultPercentW, int defaultPercentH) { + int width = (renderWidth > 0 ? renderWidth : getSubcomponentWidth()); + int height = (renderHeight > 0 ? renderHeight : getSubcomponentHeight()); + return (width > 0 ? "width:" + width +"px;" : defaultPercentW > 0 ? "width:"+defaultPercentW+"%;" : "") + + (height > 0 ?"height:" + height + "px;" : defaultPercentH > 0 ? "height:"+defaultPercentH+"%;" : "") + + (bgcolor == null ? "" : "background-color:" + CU.toCSSString(bgcolor) + ";"); + } + + public void repaint() { + // for inheritance + } + +} diff --git a/src/javajs/awt/Container.java b/src/javajs/awt/Container.java new file mode 100644 index 0000000..7ef6e90 --- /dev/null +++ b/src/javajs/awt/Container.java @@ -0,0 +1,79 @@ +package javajs.awt; + +import javajs.util.Lst; + +abstract public class Container extends Component { + + protected Lst list; + + private Component[] cList; + + protected Container(String type) { + super(type); + } + + public Component getComponent(int i) { + return list.get(i); + } + + public int getComponentCount() { + return (list == null ? 0 : list.size()); + } + + public Component[] getComponents() { + if (cList == null) { + if (list == null) + return new Component[0]; + cList = (Component[]) list.toArray(); + } + return cList; + } + + public Component add(Component component) { + return addComponent(component); + } + + protected Component addComponent(Component component) { + if (list == null) + list = new Lst(); + list.addLast(component); + cList = null; + component.parent = this; + return component; + } + + protected Component insertComponent(Component component, int index) { + if (list == null) + return addComponent(component); + list.add(index, component); + cList = null; + component.parent = this; + return component; + } + + public void remove(int i) { + Component c = list.remove(i); + c.parent = null; + cList = null; + } + + public void removeAll() { + if (list != null) { + for (int i = list.size(); --i >= 0;) + list.get(i).parent = null; + list.clear(); + } + cList = null; + } + + @Override + public int getSubcomponentWidth() { + return (list != null && list.size() == 1 ? list.get(0).getSubcomponentWidth() : 0); + } + + @Override + public int getSubcomponentHeight() { + return (list != null && list.size() == 1 ? list.get(0).getSubcomponentHeight() : 0); + } + +} diff --git a/src/javajs/awt/Dimension.java b/src/javajs/awt/Dimension.java new file mode 100644 index 0000000..02d9935 --- /dev/null +++ b/src/javajs/awt/Dimension.java @@ -0,0 +1,18 @@ +package javajs.awt; + +public class Dimension { + + public int width; + public int height; + + public Dimension(int w, int h) { + set(w, h); + } + + public Dimension set(int w, int h) { + width = w; + height = h; + return this; + } + +} diff --git a/src/javajs/awt/Font.java b/src/javajs/awt/Font.java new file mode 100644 index 0000000..416089b --- /dev/null +++ b/src/javajs/awt/Font.java @@ -0,0 +1,170 @@ +/* $RCSfile$ + * $Author: hansonr $ + * $Date: 2013-10-30 13:47:37 -0500 (Wed, 30 Oct 2013) $ + * $Revision: 18874 $ + * + * Copyright (C) 2003-2005 Miguel, Jmol Development, www.jmol.org + * + * Contact: jmol-developers@lists.sf.net + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + */ +package javajs.awt; + + +import javajs.api.FontManager; +import javajs.util.AU; + + +/** + *

+ * Provides font support using a byte fid + * (Font ID) as an index into font table. + *

+ *

+ * Supports standard font faces, font styles, and font sizes. + *

+ * + * @author Miguel, miguel@jmol.org + */ +final public class Font { + + public final byte fid; + public final String fontFace; + public final String fontStyle; + public final float fontSizeNominal; + public final int idFontFace; + public final int idFontStyle; + public final float fontSize; + public final Object font; + private final Object fontMetrics; + private FontManager manager; + private int ascent; + private int descent; + private boolean isBold; + private boolean isItalic; + + private Font(FontManager manager, byte fid, int idFontFace, + int idFontStyle, float fontSize, float fontSizeNominal, Object graphics) { + this.manager = manager; + this.fid = fid; + this.fontFace = fontFaces[idFontFace]; + this.fontStyle = fontStyles[idFontStyle]; + this.idFontFace = idFontFace; + this.idFontStyle = idFontStyle; + this.fontSize = fontSize; + this.isBold = (idFontStyle & FONT_STYLE_BOLD) == FONT_STYLE_BOLD; + this.isItalic = (idFontStyle & FONT_STYLE_ITALIC) == FONT_STYLE_ITALIC; + this.fontSizeNominal = fontSizeNominal; + font = manager.newFont(fontFaces[idFontFace], isBold, isItalic, + fontSize); + fontMetrics = manager.getFontMetrics(this, graphics); + descent = manager.getFontDescent(fontMetrics); + ascent = manager.getFontAscent(fontMetrics); + + //System.out.println("font3d constructed for fontsizeNominal=" + fontSizeNominal + " and fontSize=" + fontSize); + } + + //////////////////////////////////////////////////////////////// + + private final static int FONT_ALLOCATION_UNIT = 8; + private static int fontkeyCount = 1; + private static int[] fontkeys = new int[FONT_ALLOCATION_UNIT]; + private static Font[] font3ds = new Font[FONT_ALLOCATION_UNIT]; + + public static Font getFont3D(byte fontID) { + return font3ds[fontID & 0xFF]; + } + + public static synchronized Font createFont3D(int fontface, int fontstyle, + float fontsize, float fontsizeNominal, + FontManager manager, Object graphicsForMetrics) { + //if (graphicsForMetrics == null) + // return null; + if (fontsize > 0xFF) + fontsize = 0xFF; + int fontsizeX16 = ((int) fontsize) << 4; + int fontkey = ((fontface & 3) | ((fontstyle & 3) << 2) | (fontsizeX16 << 4)); + // watch out for race condition here! + for (int i = fontkeyCount; --i > 0;) + if (fontkey == fontkeys[i] + && font3ds[i].fontSizeNominal == fontsizeNominal) + return font3ds[i]; + int fontIndexNext = fontkeyCount++; + if (fontIndexNext == fontkeys.length) + fontkeys = AU.arrayCopyI(fontkeys, fontIndexNext + FONT_ALLOCATION_UNIT); + font3ds = (Font[]) AU.arrayCopyObject(font3ds, fontIndexNext + FONT_ALLOCATION_UNIT); + Font font3d = new Font(manager, (byte) fontIndexNext, fontface, fontstyle, + fontsize, fontsizeNominal, graphicsForMetrics); + // you must set the font3d before setting the fontkey in order + // to prevent a race condition with getFont3D + font3ds[fontIndexNext] = font3d; + fontkeys[fontIndexNext] = fontkey; + return font3d; + } + + public final static int FONT_FACE_SANS = 0; + public final static int FONT_FACE_SERIF = 1; + public final static int FONT_FACE_MONO = 2; + + private final static String[] fontFaces = + {"SansSerif", "Serif", "Monospaced", ""}; + + public final static int FONT_STYLE_PLAIN = 0; + public final static int FONT_STYLE_BOLD = 1; + public final static int FONT_STYLE_ITALIC = 2; + public final static int FONT_STYLE_BOLDITALIC = 3; + + private final static String[] fontStyles = + {"Plain", "Bold", "Italic", "BoldItalic"}; + + public static int getFontFaceID(String fontface) { + return ("Monospaced".equalsIgnoreCase(fontface) ? FONT_FACE_MONO + : "Serif".equalsIgnoreCase(fontface) ? FONT_FACE_SERIF + : FONT_FACE_SANS); + } + + public static int getFontStyleID(String fontstyle) { + for (int i = 4; --i >= 0; ) + if (fontStyles[i].equalsIgnoreCase(fontstyle)) + return i; + return -1; + } + + public int getAscent() { + return ascent; + } + + public int getDescent() { + return descent; + } + + public int getHeight() { + return getAscent() + getDescent(); + } + + public Object getFontMetrics() { + return fontMetrics; + } + + public int stringWidth(String text) { + return manager.fontStringWidth(this, text); + } + + public String getInfo() { + return fontSizeNominal + " " + fontFace + " " + fontStyle; + } +} + diff --git a/src/javajs/awt/LayoutManager.java b/src/javajs/awt/LayoutManager.java new file mode 100644 index 0000000..00e989e --- /dev/null +++ b/src/javajs/awt/LayoutManager.java @@ -0,0 +1,5 @@ +package javajs.awt; + +public class LayoutManager { + +} diff --git a/src/javajs/awt/event/ActionEvent.java b/src/javajs/awt/event/ActionEvent.java new file mode 100644 index 0000000..e24ea13 --- /dev/null +++ b/src/javajs/awt/event/ActionEvent.java @@ -0,0 +1,12 @@ +package javajs.awt.event; + + +public class ActionEvent extends Event { + + private String actionCommand; + + public String getActionCommand() { + return actionCommand; + } + +} diff --git a/src/javajs/awt/event/ActionListener.java b/src/javajs/awt/event/ActionListener.java new file mode 100644 index 0000000..8137e7d --- /dev/null +++ b/src/javajs/awt/event/ActionListener.java @@ -0,0 +1,8 @@ +package javajs.awt.event; + + +public interface ActionListener { + + public abstract void actionPerformed(ActionEvent event); + +} diff --git a/src/javajs/awt/event/Event.java b/src/javajs/awt/event/Event.java new file mode 100644 index 0000000..1a54403 --- /dev/null +++ b/src/javajs/awt/event/Event.java @@ -0,0 +1,59 @@ +package javajs.awt.event; + +public class Event { + + private Object source; + + public Object getSource() { + return source; + } + + public static final int MOUSE_LEFT = 16; + public static final int MOUSE_MIDDLE = 8; //Event.ALT_MASK; + public static final int MOUSE_RIGHT = 4; //Event.META_MASK; + public static final int MOUSE_WHEEL = 32; + + public final static int MAC_COMMAND = MOUSE_LEFT | MOUSE_RIGHT; + public final static int BUTTON_MASK = MOUSE_LEFT | MOUSE_MIDDLE | MOUSE_RIGHT; + + public static final int MOUSE_DOWN = 501; //InputEvent.MOUSE_DOWN; + public static final int MOUSE_UP = 502; //Event.MOUSE_UP; + public static final int MOUSE_MOVE = 503; //Event.MOUSE_MOVE; + public static final int MOUSE_ENTER = 504; //Event.MOUSE_ENTER; + public static final int MOUSE_EXIT = 505; //Event.MOUSE_EXIT; + public static final int MOUSE_DRAG = 506; //Event.MOUSE_DRAG; + + + public static final int SHIFT_MASK = 1;//InputEvent.SHIFT_MASK; + public static final int ALT_MASK = 8;//InputEvent.ALT_MASK; + public static final int CTRL_MASK = 2;//InputEvent.CTRL_MASK; + + public final static int CTRL_ALT = CTRL_MASK | ALT_MASK; + public final static int CTRL_SHIFT = CTRL_MASK | SHIFT_MASK; + + public static final int META_MASK = 4;//InputEvent.META_MASK; + public static final int VK_SHIFT = 16;//KeyEvent.VK_SHIFT; + public static final int VK_ALT = 18;//KeyEvent.VK_ALT; + public static final int VK_CONTROL = 17;//KeyEvent.VK_CONTROL; + public static final int VK_META = 157; // KeyEvent.VK_META; + public static final int VK_LEFT = 37;//KeyEvent.VK_LEFT; + public static final int VK_RIGHT = 39;//KeyEvent.VK_RIGHT; + public static final int VK_PERIOD = 46;//KeyEvent.VK_PERIOD; + public static final int VK_SPACE = 32;//KeyEvent.VK_SPACE; + public static final int VK_DOWN = 40;//KeyEvent.VK_DOWN; + public static final int VK_UP = 38;//KeyEvent.VK_UP; + public static final int VK_ESCAPE = 27;//KeyEvent.VK_ESCAPE; + public static final int VK_DELETE = 127;//KeyEvent.VK_DELETE; + public static final int VK_BACK_SPACE = 8;//KeyEvent.VK_BACK_SPACE; + public static final int VK_PAGE_DOWN = 34;//KeyEvent.VK_PAGE_DOWN; + public static final int VK_PAGE_UP = 33;//KeyEvent.VK_PAGE_UP; + + // for status messages: + public final static int MOVED = 0; + public final static int DRAGGED = 1; + public final static int CLICKED = 2; + public final static int WHEELED = 3; + public final static int PRESSED = 4; + public final static int RELEASED = 5; + +} diff --git a/src/javajs/awt/event/ItemEvent.java b/src/javajs/awt/event/ItemEvent.java new file mode 100644 index 0000000..0592121 --- /dev/null +++ b/src/javajs/awt/event/ItemEvent.java @@ -0,0 +1,6 @@ +package javajs.awt.event; + + +public class ItemEvent extends Event { + +} diff --git a/src/javajs/awt/event/WindowEvent.java b/src/javajs/awt/event/WindowEvent.java new file mode 100644 index 0000000..739526d --- /dev/null +++ b/src/javajs/awt/event/WindowEvent.java @@ -0,0 +1,6 @@ +package javajs.awt.event; + + +public class WindowEvent extends Event { + +} diff --git a/src/javajs/awt/event/WindowListener.java b/src/javajs/awt/event/WindowListener.java new file mode 100644 index 0000000..f60b076 --- /dev/null +++ b/src/javajs/awt/event/WindowListener.java @@ -0,0 +1,9 @@ +package javajs.awt.event; + +import javajs.awt.event.WindowEvent; + +public interface WindowListener { + + public void windowClosing(WindowEvent e); + +} diff --git a/src/javajs/export/PDFCreator.java b/src/javajs/export/PDFCreator.java new file mode 100644 index 0000000..8ffc540 --- /dev/null +++ b/src/javajs/export/PDFCreator.java @@ -0,0 +1,364 @@ +/* $RCSfile$ + * $Author: hansonr $ + * $Date: 2009-06-30 18:58:33 -0500 (Tue, 30 Jun 2009) $ + * $Revision: 11158 $ + * + * Copyright (C) 2002-2005 The Jmol Development Team + * + * Contact: jmol-developers@lists.sf.net + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + */ +package javajs.export; + +import java.io.IOException; +import java.io.OutputStream; +import java.util.Hashtable; +import java.util.Map; +import java.util.Map.Entry; + +import javajs.util.Lst; +import javajs.util.SB; + + + +public class PDFCreator { + + private OutputStream os; + private Lst indirectObjects; + private PDFObject root; + private PDFObject graphics; +// private PDFObject pageResources; +// private PDFObject graphicsResources; + + private int pt; + private int xrefPt; + private int count; + + private int height; + private int width; + + private Mapfonts; + + public PDFCreator() { + // for Class.forName + } + + public void setOutputStream(OutputStream os) { + this.os = os; + } + + public void newDocument(int paperWidth, int paperHeight, boolean isLandscape) { + width = (isLandscape ? paperHeight : paperWidth); + height = (isLandscape ? paperWidth : paperHeight); + System.out.println("Creating PDF with width=" + width + " and height=" + height); + fonts = new Hashtable(); + indirectObjects = new Lst(); + //graphicsResources = newObject(null); + //pageResources = newObject(null); // will set this to compressed stream later + root = newObject("Catalog"); + PDFObject pages = newObject("Pages"); + PDFObject page = newObject("Page"); + PDFObject pageContents = newObject(null); + graphics = newObject("XObject"); + + root.addDef("Pages", pages.getRef()); + pages.addDef("Count", "1"); + pages.addDef("Kids", "[ " + page.getRef() +" ]"); + page.addDef("Parent", pages.getRef()); + page.addDef("MediaBox", "[ 0 0 " + paperWidth + " " + paperHeight + " ]"); + if (isLandscape) + page.addDef("Rotate", "90"); + + pageContents.addDef("Length", "?"); + pageContents.append((isLandscape ? "q 0 1 1 0 0 0 " : "q 1 0 0 -1 0 "+(paperHeight))+" cm /" + graphics.getID() + " Do Q"); + page.addDef("Contents", pageContents.getRef()); + addProcSet(page); + addProcSet(graphics); + // will add fonts as well as they are needed + graphics.addDef("Subtype", "/Form"); + graphics.addDef("FormType", "1"); + graphics.addDef("BBox", "[0 0 " + width + " " + height + "]"); + graphics.addDef("Matrix", "[1 0 0 1 0 0]"); + graphics.addDef("Length", "?"); + page.addResource("XObject", graphics.getID(), graphics.getRef()); + g("q 1 w 1 J 1 j 10 M []0 d q "); // line width 1, line cap circle, line join circle, miter limit 10, solid + clip(0, 0, width, height); + } + + private void addProcSet(PDFObject o) { + o.addResource(null, "ProcSet", "[/PDF /Text /ImageB /ImageC /ImageI]"); + } + + private void clip(int x1, int y1, int x2, int y2) { + moveto(x1, y1); + lineto(x2, y1); + lineto(x2, y2); + lineto(x1, y2); + g("h W n"); + } + + public void moveto(int x, int y) { + g(x + " " + y + " m"); + } + + public void lineto(int x, int y) { + g(x + " " + y + " l"); + } + + private PDFObject newObject(String type) { + PDFObject o = new PDFObject(++count); + if (type != null) + o.addDef("Type", "/" + type); + indirectObjects.addLast(o); + return o; + } + + public void addInfo(Map data) { + Hashtable info = new Hashtable(); + for (Entry e: data.entrySet()) { + String value = "(" + e.getValue().replace(')','_').replace('(','_')+ ")"; + info.put(e.getKey(), value); + } + root.addDef("Info", info); + } + + private PDFObject addFontResource(String fname) { + PDFObject f = newObject("Font"); + fonts.put(fname, f); + f.addDef("BaseFont", fname); + f.addDef("Encoding", "/WinAnsiEncoding"); + f.addDef("Subtype", "/Type1"); + graphics.addResource("Font", f.getID(), f.getRef()); + return f; + } + + private Map images; + + public void addImageResource(Object newImage, int width, int height, int[] buffer, boolean isRGB) { + PDFObject imageObj = newObject("XObject"); + if (images == null) + images = new Hashtable(); + images.put(newImage, imageObj); + imageObj.addDef("Subtype", "/Image"); + imageObj.addDef("Length", "?"); + imageObj.addDef("ColorSpace", isRGB ? "/DeviceRGB" : "/DeviceGray"); + imageObj.addDef("BitsPerComponent", "8"); + imageObj.addDef("Width", "" + width); + imageObj.addDef("Height", "" + height); + graphics.addResource("XObject", imageObj.getID(), imageObj.getRef()); + int n = buffer.length; + byte[] stream = new byte[n * (isRGB ? 3 : 1)]; + if (isRGB) { + for (int i = 0, pt = 0; i < n; i++) { + stream[pt++] = (byte) ((buffer[i] >> 16) & 0xFF); + stream[pt++] = (byte) ((buffer[i] >> 8) & 0xFF); + stream[pt++] = (byte) (buffer[i] & 0xFF); + } + } else { + for (int i = 0; i < n; i++) + stream[i] = (byte) buffer[i]; + } + imageObj.setStream(stream); + graphics.addResource("XObject", imageObj.getID(), imageObj.getRef()); + } + + public void g(String cmd) { + graphics.append(cmd).appendC('\n'); + } + + private void output(String s) throws IOException { + byte[] b = s.getBytes(); + os.write(b, 0, b.length); + pt += b.length; + } + + public void closeDocument() throws IOException { + g("Q Q"); + outputHeader(); + writeObjects(); + writeXRefTable(); + writeTrailer(); + os.flush(); + os.close(); + } + + private void outputHeader() throws IOException { + output("%PDF-1.3\n%"); + byte[] b = new byte[] {-1, -1, -1, -1}; + os.write(b, 0, b.length); + pt += 4; + output("\n"); + } + + private void writeTrailer() throws IOException { + PDFObject trailer = new PDFObject(-2); + output("trailer"); + trailer.addDef("Size", "" + indirectObjects.size()); + trailer.addDef("Root", root.getRef()); + trailer.output(os); + output("startxref\n"); + output("" + xrefPt + "\n"); + output("%%EOF\n"); + } + + /** + * Write Font objects first. + * + * @throws IOException + */ + private void writeObjects() throws IOException { + int nObj = indirectObjects.size(); + for (int i = 0; i < nObj; i++) { + PDFObject o = indirectObjects.get(i); + if (!o.isFont()) + continue; + o.pt = pt; + pt += o.output(os); + } + for (int i = 0; i < nObj; i++) { + PDFObject o = indirectObjects.get(i); + if (o.isFont()) + continue; + o.pt = pt; + pt += o.output(os); + } + } + + private void writeXRefTable() throws IOException { + xrefPt = pt; + int nObj = indirectObjects.size(); + SB sb = new SB(); + // note trailing space, needed because \n is just one character + sb.append("xref\n0 " + (nObj + 1) + + "\n0000000000 65535 f\r\n"); + for (int i = 0; i < nObj; i++) { + PDFObject o = indirectObjects.get(i); + String s = "0000000000" + o.pt; + sb.append(s.substring(s.length() - 10)); + sb.append(" 00000 n\r\n"); + } + output(sb.toString()); + } + + public boolean canDoLineTo() { + return true; + } + + public void fill() { + g("f"); + } + + public void stroke() { + g("S"); + } + + public void doCircle(int x, int y, int r, boolean doFill) { + double d = r*4*(Math.sqrt(2)-1)/3; + double dx = x; + double dy = y; + g((dx + r) + " " + dy + " m"); + g((dx + r) + " " + (dy + d) + " " + (dx + d) + " " + (dy + r) + " " + (dx) + " " + (dy + r) + " " + " c"); + g((dx - d) + " " + (dy + r) + " " + (dx - r) + " " + (dy + d) + " " + (dx - r) + " " + (dy) + " c"); + g((dx - r) + " " + (dy - d) + " " + (dx - d) + " " + (dy - r) + " " + (dx) + " " + (dy - r) + " c"); + g((dx + d) + " " + (dy - r) + " " + (dx + r) + " " + (dy - d) + " " + (dx + r) + " " + (dy) + " c"); + g(doFill ? "f" : "s"); + } + + public void doPolygon(int[] axPoints, int[] ayPoints, int nPoints, boolean doFill) { + moveto(axPoints[0], ayPoints[0]); + for (int i = 1; i < nPoints; i++) + lineto(axPoints[i], ayPoints[i]); + g(doFill ? "f" : "s"); + } + + public void doRect(int x, int y, int width, int height, boolean doFill) { + g(x + " " + y + " " + width + " " + height + " re " + (doFill ? "f" : "s")); + } + + public void drawImage(Object image, int destX0, int destY0, + int destX1, int destY1, int srcX0, int srcY0, int srcX1, int srcY1) { + PDFObject imageObj = images.get(image); + if (imageObj == null) + return; + g("q"); + clip(destX0, destY0, destX1, destY1); + double iw = Double.parseDouble((String) imageObj.getDef("Width")); + double ih = Double.parseDouble((String) imageObj.getDef("Height")); + double dw = (destX1 - destX0 + 1); + double dh = (destY1 - destY0 + 1); + double sw = (srcX1 - srcX0 + 1); + double sh = (srcY1 - srcY0 + 1); + double scaleX = dw / sw; + double scaleY = dh / sh; + double transX = destX0 - srcX0 * scaleX; + double transY = destY0 + (ih - srcY0) * scaleY; + g(scaleX*iw + " 0 0 " + -scaleY*ih + " " + transX + " " + transY + " cm"); + g("/" + imageObj.getID() + " Do"); + g("Q"); + } + + public void drawStringRotated(String s, int x, int y, int angle) { + g("q " + getRotation(angle) + " " + x + " " + y + + " cm BT(" + s + ")Tj ET Q"); + } + + public String getRotation(int angle) { + float cos = 0, sin = 0; + switch (angle) { + case 0: + cos = 1; + break; + case 90: + sin = 1; + break; + case -90: + sin = -1; + break; + case 180: + cos = -1; + break; + default: + float a = (float) (angle / 180.0 * Math.PI); + cos = (float) Math.cos(a); + sin = (float) Math.sin(a); + if (Math.abs(cos) < 0.0001) + cos = 0; + if (Math.abs(sin) < 0.0001) + sin = 0; + } + return cos + " " + sin + " " + sin + " " + -cos; + } + + public void setColor(float[] rgb, boolean isFill) { + g(rgb[0] + " " + rgb[1] + " " + rgb[2] + (isFill ? " rg" : " RG")); + } + + public void setFont(String fname, float size) { + PDFObject f = fonts.get(fname); + if (f == null) + f = addFontResource(fname); + g("/" + f.getID() + " " + size + " Tf"); + } + + public void setLineWidth(float width) { + g(width + " w"); + } + + public void translateScale(float x, float y, float scale) { + g(scale + " 0 0 " + scale + " " + x + " " + y + " cm"); + } + +} diff --git a/src/javajs/export/PDFObject.java b/src/javajs/export/PDFObject.java new file mode 100644 index 0000000..176dc19 --- /dev/null +++ b/src/javajs/export/PDFObject.java @@ -0,0 +1,152 @@ +package javajs.export; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.Hashtable; +import java.util.Map; +import java.util.Map.Entry; +import java.util.zip.Deflater; +import java.util.zip.DeflaterOutputStream; + +import javajs.util.SB; + + +/** + * A rudimentary class for working with PDF document creation. + * Written from scratch based on PDF Reference 13. + * + * @author hansonr Bob Hanson hansonr@stolaf.edu 10/28/2013 + * + */ +class PDFObject extends SB { + private Map dictionary; + private byte[] stream; + private int index; + String type; + int len; + int pt; + + PDFObject(int index) { + this.index = index; + } + + String getRef() { + return index + " 0 R"; + } + + String getID() { + return type.substring(0, 1) + index; + } + + boolean isFont() { + return "Font".equals(type); + } + + void setStream(byte[] stream) { + this.stream = stream; + } + + Object getDef(String key) { + return dictionary.get(key); + } + + void addDef(String key, Object value) { + if (dictionary == null) + dictionary = new Hashtable(); + dictionary.put(key, value); + if (key.equals("Type")) + type = ((String) value).substring(1); + } + + void setAsStream() { + stream = toBytes(0, -1); + setLength(0); + } + + int output(OutputStream os) throws IOException { + if (index > 0) { + String s = index + " 0 obj\n"; + write(os, s.getBytes(), 0); + } + int streamLen = 0; + if (dictionary != null) { + if (dictionary.containsKey("Length")) { + if (stream == null) + setAsStream(); + streamLen = stream.length; + boolean doDeflate = (streamLen > 1000); + if (doDeflate) { + Deflater deflater = new Deflater(9); + ByteArrayOutputStream outBytes = new ByteArrayOutputStream(1024); + DeflaterOutputStream compBytes = new DeflaterOutputStream(outBytes, + deflater); + compBytes.write(stream, 0, streamLen); + compBytes.finish(); + stream = outBytes.toByteArray(); + dictionary.put("Filter", "/FlateDecode"); + streamLen = stream.length; + } + dictionary.put("Length", "" + streamLen); + } + write(os, getDictionaryText(dictionary, "\n").getBytes(), 0); + } + if (length() > 0) + write(os, this.toString().getBytes(), 0); + if (stream != null) { + write(os, "stream\r\n".getBytes(), 0); + write(os, stream, streamLen); + write(os, "\r\nendstream\r\n".getBytes(), 0); + } + if (index > 0) + write(os, "endobj\n".getBytes(), 0); + return len; + } + + private void write(OutputStream os, byte[] bytes, int nBytes) throws IOException { + if (nBytes == 0) + nBytes = bytes.length; + len += nBytes; + os.write(bytes, 0, nBytes); + } + + @SuppressWarnings("unchecked") + private String getDictionaryText(Map d, String nl) { + SB sb = new SB(); + sb.append("<<"); + if (d.containsKey("Type")) + sb.append("/Type").appendO(d.get("Type")); + for (Entry e : d.entrySet()) { + String s = e.getKey(); + if (s.equals("Type") || s.startsWith("!")) + continue; + sb.append("/" + s); + Object o = e.getValue(); + if (o instanceof Map) { + sb.append((getDictionaryText((Map) o, ""))); + continue; + } + s = (String) e.getValue(); + if (!s.startsWith("/")) + sb.append(" "); + sb.appendO(s); + } + return (sb.length() > 3 ? sb.append(">>").append(nl).toString() : ""); + } + + @SuppressWarnings("unchecked") + private Map createSubdict(Map d0, String dict) { + Map d = (Map) d0.get(dict); + if (d == null) + d0.put(dict, d = new Hashtable()); + return d; + } + + void addResource(String type, String key, String value) { + Map r = createSubdict(dictionary, "Resources"); + if (type != null) + r = createSubdict(r, type); + r.put(key, value); + } + +} diff --git a/src/javajs/img/BMPDecoder.java b/src/javajs/img/BMPDecoder.java new file mode 100644 index 0000000..68fb24d --- /dev/null +++ b/src/javajs/img/BMPDecoder.java @@ -0,0 +1,208 @@ +/* $RCSfile$ + * $Author: nicove $ + * $Date: 2007-03-30 12:26:16 -0500 (Fri, 30 Mar 2007) $ + * $Revision: 7275 $ + * + * Copyright (C) 2002-2005 The Jmol Development Team + * + * Contact: jmol-developers@lists.sf.net + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + */ +package javajs.img; + +import java.io.BufferedInputStream; +import java.io.IOException; + +import javajs.util.Rdr; + +/** + * src: http://www.javaworld.com/article/2077542/learn-java/java-tip-43--how-to- + * read-8--and-24-bit-microsoft-windows-bitmaps-in-java-applications.html + * + * see also: http://en.wikipedia.org/wiki/BMP_file_format + * + * Modified by Bob Hanson hansonr@stolaf.edu + * + * @author Bob Hanson (hansonr@stolaf.edu) + * + */ +public class BMPDecoder { + + public BMPDecoder() { + // for reflection + } + + private BufferedInputStream bis; + + /** + * original comment: + * + * loadbitmap() method converted from Windows C code. Reads only uncompressed + * 24- and 8-bit images. Tested with images saved using Microsoft Paint in + * Windows 95. If the image is not a 24- or 8-bit image, the program refuses + * to even try. I guess one could include 4-bit images by masking the byte by + * first 1100 and then 0011. I am not really interested in such images. If a + * compressed image is attempted, the routine will probably fail by generating + * an IOException. Look for variable ncompression to be different from 0 to + * indicate compression is present. + * + * @param bytes + * @return [image byte array, width, height] + */ + public Object[] decodeWindowsBMP(byte[] bytes) { + try { + bis = Rdr.getBIS(bytes); + temp = new byte[4]; + // read BITMAPFILEHEADER + if (readByte() != 'B' || readByte() != 'M') + return null; + readInt(); // file size; ignored + readShort(); // reserved + readShort(); // reserved + readInt(); // ptr to pixel array; ignored + int imageWidth, imageHeight, bitsPerPixel, nColors = 0, imageSize = 0; + // read BITMAP header + int headerSize = readInt(); + switch (headerSize) { + case 12: + // BITMAPCOREHEADER + imageWidth = readShort(); + imageHeight = readShort(); + readShort(); // planes + bitsPerPixel = readShort(); + break; + case 40: + // BITMAPINFOHEADER + imageWidth = readInt(); + imageHeight = readInt(); + readShort(); // planes + bitsPerPixel = readShort(); + int ncompression = readInt(); + if (ncompression != 0) { + System.out.println("BMP Compression is :" + ncompression + + " -- aborting"); + return null; + } + imageSize = readInt(); + readInt(); // hres + readInt(); // vres + nColors = readInt(); + readInt(); // colors used + break; + default: + System.out.println("BMP Header unrecognized, length=" + headerSize + + " -- aborting"); + return null; + } + boolean isYReversed = (imageHeight < 0); + if (isYReversed) + imageHeight = -imageHeight; + int nPixels = imageHeight * imageWidth; + int bytesPerPixel = bitsPerPixel / 8; + nColors = (nColors > 0 ? nColors : 1 << bitsPerPixel); + int npad = (bytesPerPixel == 4 ? 0 + : imageSize == 0 ? 4 - (imageWidth % 4) : (imageSize / imageHeight) + - imageWidth * bytesPerPixel) % 4; + int[] palette; + int[] buf = new int[nPixels]; + int dpt = (isYReversed ? imageWidth : -imageWidth); + int pt0 = (isYReversed ? 0 : nPixels + dpt); + int pt1 = (isYReversed ? nPixels : dpt); + switch (bitsPerPixel) { + case 32: + case 24: + for (int pt = pt0; pt != pt1; pt += dpt, pad(npad)) + for (int i = 0; i < imageWidth; i++) + buf[pt + i] = readColor(bytesPerPixel); + break; + case 8: + palette = new int[nColors]; + for (int i = 0; i < nColors; i++) + palette[i] = readColor(4); + for (int pt = pt0; pt != pt1; pt += dpt, pad(npad)) + for (int i = 0; i < imageWidth; i++) + buf[pt + i] = palette[readByte()]; + break; + case 4: + npad = (4 - (((imageWidth + 1) / 2) % 4)) % 4; + palette = new int[nColors]; + for (int i = 0; i < nColors; i++) + palette[i] = readColor(4); + int b4 = 0; + for (int pt = pt0; pt != pt1; pt += dpt, pad(npad)) + for (int i = 0, shift = 4; i < imageWidth; i++, shift = 4 - shift) + buf[pt + i] = palette[((shift == 4 ? (b4 = readByte()) : b4) >> shift) & 0xF]; + break; + case 1: + int color1 = readColor(3); + int color2 = readColor(3); + npad = (4 - (((imageWidth + 7) / 8) % 4)) % 4; + int b = 0; + for (int pt = pt0; pt != pt1; pt += dpt, pad(npad)) + for (int i = 0, bpt = -1; i < imageWidth; i++, bpt--) { + if (bpt < 0) { + b = readByte(); + bpt = 7; + } + buf[pt + i] = ((b & (1 << bpt)) == 0 ? color1 : color2); + } + break; + case 64: + case 2: + default: + System.out + .println("Not a 32-, 24-, 8-, 4-, or 1-bit Windows Bitmap, aborting..."); + return null; + } + return new Object[] { buf, Integer.valueOf(imageWidth), + Integer.valueOf(imageHeight) }; + } catch (Exception e) { + System.out.println("Caught exception in loadbitmap!"); + } + return null; + } + + private boolean pad(int npad) throws IOException { + for (int i = 0; i < npad; i++) + readByte(); + return true; + } + + private byte[] temp; + + private int readColor(int n) throws IOException { + bis.read(temp, 0, n); + return 0xff << 24 | ((temp[2] & 0xff) << 16) + | ((temp[1] & 0xff) << 8) | temp[0] & 0xff; + } + + private int readInt() throws IOException { + bis.read(temp, 0, 4); + return ((temp[3] & 0xff) << 24) | ((temp[2] & 0xff) << 16) + | ((temp[1] & 0xff) << 8) | temp[0] & 0xff; + } + + private int readShort() throws IOException { + bis.read(temp, 0, 2); + return ((temp[1] & 0xff) << 8) | temp[0] & 0xff; + } + + private int readByte() throws IOException { + bis.read(temp, 0, 1); + return temp[0] & 0xff; + } + +} diff --git a/src/javajs/img/CRCEncoder.java b/src/javajs/img/CRCEncoder.java new file mode 100644 index 0000000..77ed11e --- /dev/null +++ b/src/javajs/img/CRCEncoder.java @@ -0,0 +1,110 @@ +package javajs.img; + +import java.util.zip.CRC32; + + +import javajs.util.AU; + +abstract class CRCEncoder extends ImageEncoder { + + protected int startPos, bytePos; + + private CRC32 crc; + protected byte[] pngBytes; + protected int dataLen; + private byte[] int2 = new byte[2]; + private byte[] int4 = new byte[4]; + + CRCEncoder() { + pngBytes = new byte[250]; + crc = new CRC32(); + } + + protected void setData(byte[] b, int pt) { + pngBytes = b; + dataLen = b.length; + startPos = bytePos = pt; + } + + protected byte[] getBytes() { + return (dataLen == pngBytes.length ? pngBytes : AU.arrayCopyByte( + pngBytes, dataLen)); + } + + protected void writeCRC() { + crc.reset(); + crc.update(pngBytes, startPos, bytePos - startPos); + writeInt4((int) crc.getValue()); + } + + /** + * Write a two-byte integer into the pngBytes array at a given position. + * + * @param n The integer to be written into pngBytes. + */ + protected void writeInt2(int n) { + int2[0] = (byte) ((n >> 8) & 0xff); + int2[1] = (byte) (n & 0xff); + writeBytes(int2); + } + + /** + * Write a four-byte integer into the pngBytes array at a given position. + * + * @param n The integer to be written into pngBytes. + */ + protected void writeInt4(int n) { + getInt4(n, int4); + writeBytes(int4); + } + + protected static void getInt4(int n, byte[] int4) { + int4[0] = (byte) ((n >> 24) & 0xff); + int4[1] = (byte) ((n >> 16) & 0xff); + int4[2] = (byte) ((n >> 8) & 0xff); + int4[3] = (byte) (n & 0xff); + } + + /** + * Write a single byte into the pngBytes array at a given position. + * + * @param b The byte to be written into pngBytes. + */ + protected void writeByte(int b) { + byte[] temp = { + (byte) b + }; + writeBytes(temp); + } + + /** + * Write a string into the pngBytes array at a given position. + * This uses the getBytes method, so the encoding used will + * be its default. + * + * @param s The string to be written into pngBytes. + * @see java.lang.String#getBytes() + */ + protected void writeString(String s) { + writeBytes(s.getBytes()); + } + + /** + * Write an array of bytes into the pngBytes array. + * Both dataLen and bytePos are updated. If we don't have + * enough room, this is certainly in image data writing, + * so we add just enough for CRC END CRC + * + * @param data + * The data to be written into pngBytes. + */ + protected void writeBytes(byte[] data) { + int newPos = bytePos + data.length; + dataLen = Math.max(dataLen, newPos); + if (newPos > pngBytes.length) + pngBytes = AU.arrayCopyByte(pngBytes, newPos + 16); + System.arraycopy(data, 0, pngBytes, bytePos, data.length); + bytePos = newPos; + } + +} diff --git a/src/javajs/img/GifEncoder.java b/src/javajs/img/GifEncoder.java new file mode 100644 index 0000000..89c9579 --- /dev/null +++ b/src/javajs/img/GifEncoder.java @@ -0,0 +1,1132 @@ +/* $RCSfile$ + * $Author: hansonr $ + * $Date: 2007-06-02 12:14:13 -0500 (Sat, 02 Jun 2007) $ + * $Revision: 7831 $ + * + * Copyright (C) 2000-2005 The Jmol Development Team + * + * Contact: jmol-developers@lists.sf.net + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +// Final encoding code from http://acme.com/resources/classes/Acme/JPM/Encoders/GifEncoder.java +// +// GifEncoder - write out an image as a GIF +// +// +// Transparency handling and variable bit size courtesy of Jack Palevich. +// +// Copyright (C)1996,1998 by Jef Poskanzer . All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +// SUCH DAMAGE. +// +// Visit the ACME Labs Java page for up-to-date versions of this and other +// fine Java utilities: http://www.acme.com/java/ +// +/// Write out an image as a GIF. +//

+// Fetch the software.
+// Fetch the entire Acme package. +//

+// @see ToGif + +package javajs.img; + +import javajs.util.CU; +import javajs.util.Lst; +import javajs.util.M3; +import javajs.util.P3; + +import java.util.Hashtable; +import java.util.Map; +import java.io.IOException; + +/** + * + * GifEncoder extensively adapted for Jmol by Bob Hanson + * + * Color quantization roughly follows the GIMP method + * "dither Floyd-Steinberg (normal)" but with some twists. (For example, we + * exclude the background color.) + * + * Note that although GIMP code annotation refers to "median-cut", it is really + * using MEAN-cut. That is what I use here as well. + * + * -- commented code allows visualization of the color space using Jmol. Very + * enlightening! + * + * -- much simplified interface with ImageEncoder + * + * -- uses simple Hashtable with Integer() to catalog colors + * + * -- allows progressive production of animated GIF via Jmol CAPTURE command + * + * -- uses general purpose javajs.util.OutputChannel for byte-handling options + * such as posting to a server, writing to disk, and retrieving bytes. + * + * -- allows JavaScript port + * + * -- Bob Hanson, first try: 24 Sep 2013; final coding: 9 Nov 2014 + * + * + * @author Bob Hanson hansonr@stolaf.edu + */ + +public class GifEncoder extends ImageEncoder { + + private Map params; + private P3[] palette; + private int backgroundColor; + + private boolean interlaced; + private boolean addHeader = true; + private boolean addImage = true; + private boolean addTrailer = true; + private boolean isTransparent; + private boolean floydSteinberg = true; + private boolean capturing; + private boolean looping; + + private int delayTime100ths = -1; + private int bitsPerPixel = 1; + + private int byteCount; + + /** + * we allow for animated GIF by being able to re-enter the code with different + * parameters held in params + * + * + */ + @Override + protected void setParams(Map params) { + this.params = params; + Integer ic = (Integer) params.get("transparentColor"); + if (ic == null) { + ic = (Integer) params.get("backgroundColor"); + if (ic != null) + backgroundColor = ic.intValue(); + } else { + backgroundColor = ic.intValue(); + isTransparent = true; + } + + interlaced = (Boolean.TRUE == params.get("interlaced")); + if (params.containsKey("captureRootExt") // file0000.gif + || !params.containsKey("captureMode")) // animated gif + return; + interlaced = false; + capturing = true; + try { + byteCount = ((Integer) params.get("captureByteCount")).intValue(); + } catch (Exception e) { + // ignore + } + switch ("maec" + .indexOf(((String) params.get("captureMode")).substring(0, 1))) { + case 0: //"movie" + params.put("captureMode", "add"); + addImage = false; + addTrailer = false; + break; + case 1: // add + addHeader = false; + addTrailer = false; + int fps = Math.abs(((Integer) params.get("captureFps")).intValue()); + delayTime100ths = (fps == 0 ? 0 : 100 / fps); + looping = (Boolean.FALSE != params.get("captureLooping")); + break; + case 2: // end + addHeader = false; + addImage = false; + break; + case 3: // cancel + addHeader = false; + addImage = false; + out.cancel(); + break; + } + } + + @Override + protected void generate() throws IOException { + if (addHeader) + writeHeader(); + addHeader = false; // only one header + if (addImage) { + createPalette(); + writeGraphicControlExtension(); + if (delayTime100ths >= 0 && looping) + writeNetscapeLoopExtension(); + writeImage(); + } + } + + @Override + protected void close() { + if (addTrailer) { + writeTrailer(); + } else { + doClose = false; + } + if (capturing) + params.put("captureByteCount", Integer.valueOf(byteCount)); + } + + ////////////// 256-color quantization ////////////// + + /** + * a color point in normalized L*a*b space with a flag indicating whether it + * is the background color + */ + private class ColorItem extends P3 { + protected boolean isBackground; + + ColorItem(int rgb, boolean isBackground) { + this.isBackground = isBackground; + setT(toLABnorm(rgb)); + } + } + + /** + * A list of normalized L*a*b points with an index and a center and volume + * + */ + private class ColorCell extends Lst { + + protected int index; + protected P3 center; + + private float volume; + + ColorCell(int index) { + this.index = index; + } + + /** + * @param doVisualize + * debugging only + * @return volume in normalized L*a*b space + */ + public float getVolume(boolean doVisualize) { + if (volume != 0) + return volume; + if (size() < 2) + return -1; + //if (true) + //return lst.size(); + //float d; + float maxx = -Integer.MAX_VALUE; + float minx = Integer.MAX_VALUE; + float maxy = -Integer.MAX_VALUE; + float miny = Integer.MAX_VALUE; + float maxz = -Integer.MAX_VALUE; + float minz = Integer.MAX_VALUE; + int n = size(); + for (int i = n; --i >= 0;) { + P3 xyz = get(i); + if (xyz.x < minx) + minx = xyz.x; + if (xyz.y < miny) + miny = xyz.y; + if (xyz.z < minz) + minz = xyz.z; + if (xyz.x > maxx) + maxx = xyz.x; + if (xyz.y > maxy) + maxy = xyz.y; + if (xyz.z > maxz) + maxz = xyz.z; + } + float dx = (maxx - minx); + float dy = (maxy - miny); + float dz = (maxz - minz); + // Jmol visualization only + // if (doVisualize) { + // P3 ptRGB = toRGB(center); + // drawPt(index, -size(), ptRGB); + // //for (int i = n; --i >= 0;) + // //drawPt(index, i, toRGB(get(i))); + // P3 pt0 = toRGB(P3.new3(Math.max(minx, 0), Math.max(miny, 0), + // Math.max(minz, 0))); + // P3 pt1 = toRGB(P3.new3(Math.min(maxx, 100), Math.min(maxy, 100), + // Math.min(maxz, 100))); + // rgbToXyz(pt0, pt0); + // xyzToLab(pt0, pt0); + // rgbToXyz(pt1, pt1); + // xyzToLab(pt1, pt1); + // System.out.println("boundbox corners " + pt0 + " " + pt1); + // System.out.println("draw d" + index + " boundbox color " + ptRGB + // + " mesh nofill"); + // } + return volume = dx * dx + dy * dy + dz * dz; + } + + // // Jmol visualization only + // private void drawPt(int index, int i, P3 rgb) { + // boolean isMain = (i < 0); + // P3 lab = rgbToXyz(rgb, null); + // xyzToLab(lab, lab); + // System.out.println("draw d" + index + (isMain ? "_" : "_" + i) + " width " + // + (isMain ? 1.0 : 0.2) + " " + lab + // + " color " + rgb + (isMain ? " '" + -i + "'" : "")); + // } + + /** + * Set the average normalized L*a*b value for this cell and return its RGB point + * + * @return RGB point + * + */ + protected P3 setColor() { + int count = size(); + center = new P3(); + for (int i = count; --i >= 0;) + center.add(get(i)); + center.scale(1f / count); + // Jmol visualization only + //volume = 0; + //getVolume(true); + return toRGB(center); + } + + /** + * use median_cut algorithm to split the cell, creating a doubly linked + * list. + * + * Paul Heckbert, MIT thesis COLOR IMAGE QUANTIZATION FOR FRAME BUFFER + * DISPLAY https://www.cs.cmu.edu/~ph/ciq_thesis + * + * except, as in GIMP, we use center (not median) here. + * + * @param cells + * @return true if split + */ + protected boolean splitCell(Lst cells) { + int n = size(); + if (n < 2) + return false; + int newIndex = cells.size(); + ColorCell newCell = new ColorCell(newIndex); + cells.addLast(newCell); + float[][] ranges = new float[3][3]; + for (int ic = 0; ic < 3; ic++) { + float low = Float.MAX_VALUE; + float high = -Float.MAX_VALUE; + for (int i = n; --i >= 0;) { + P3 lab = get(i); + float v = (ic == 0 ? lab.x : ic == 1 ? lab.y : lab.z); + if (low > v) + low = v; + if (high < v) + high = v; + } + ranges[0][ic] = low; + ranges[1][ic] = high; + ranges[2][ic] = high - low; + } + float[] r = ranges[2]; + int mode = (r[0] >= r[1] ? (r[0] >= r[2] ? 0 : 2) : r[1] >= r[2] ? 1 : 2); + float val = ranges[0][mode] + ranges[2][mode] / 2; + volume = 0; // recalculate volume if needed + switch (mode) { + case 0: + for (int i = n; --i >= 0;) + if (get(i).x >= val) + newCell.addLast(remove(i)); + break; + case 1: + for (int i = n; --i >= 0;) + if (get(i).y >= val) + newCell.addLast(remove(i)); + break; + case 2: + for (int i = size(); --i >= 0;) + if (get(i).z >= val) + newCell.addLast(remove(i)); + break; + } + return true; + } + } + + /** + * Quantize all colors and create the final palette; + * replace pixels[] with an array of color indices. + * + */ + private void createPalette() { + + // catalog all pixel colors + + Lst tempColors = new Lst(); + Map ciHash = new Hashtable(); + for (int i = 0, n = pixels.length; i < n; i++) { + int rgb = pixels[i]; + Integer key = Integer.valueOf(rgb); + ColorItem item = ciHash.get(key); + if (item == null) { + item = new ColorItem(rgb, rgb == backgroundColor); + ciHash.put(key, item); + tempColors.addLast(item); + } + } + int nColors = tempColors.size(); + System.out.println("GIF total image colors: " + nColors); + ciHash = null; + + // create a set of <= 256 color cells + + Lst cells = quantizeColors(tempColors); + nColors = cells.size(); + System.out.println("GIF final color count: " + nColors); + + // generate the palette and map each cell's rgb color to itself + + Map colorMap = new Hashtable(); + bitsPerPixel = (nColors <= 2 ? 1 : nColors <= 4 ? 2 : nColors <= 16 ? 4 : 8); + palette = new P3[1 << bitsPerPixel]; + for (int i = 0; i < nColors; i++) { + ColorCell c = cells.get(i); + colorMap.put( + Integer.valueOf(CU.colorPtToFFRGB(palette[i] = c.setColor())), c); + } + + // index all pixels to a pallete color + + pixels = indexPixels(cells, colorMap); + } + + /** + * Quantize colors by generating a set of cells in normalized L*a*b space + * containing all colors. Start with just two cells -- fixed background color + * and all others. Keep splitting cells while there are fewer than 256 and + * some with multiple colors in them. + * + * It is possible that we will end up with fewer than 256 colors. + * + * @param tempColors + * @return final list of colors + */ + private Lst quantizeColors(Lst tempColors) { + int n = tempColors.size(); + Lst cells = new Lst(); + ColorCell cc = new ColorCell(0); + cc.addLast(new ColorItem(backgroundColor, true)); + cells.addLast(cc); + cc = new ColorCell(1); + if (n > 256) + cells.addLast(cc); + for (int i = 0; i < n; i++) { + ColorItem c = tempColors.get(i); + if (c.isBackground) + continue; + cc.addLast(c); + if (n <= 256) { + cells.addLast(cc); + cc = new ColorCell(cells.size()); + } + } + tempColors.clear(); + if (n > 256) + while ((n = cells.size()) < 256) { + float maxVol = 0; + ColorCell maxCell = null; + for (int i = n; --i >= 1;) { + ColorCell c = cells.get(i); + float v = c.getVolume(false); + if (v > maxVol) { + maxVol = v; + maxCell = c; + } + } + if (maxCell == null || !maxCell.splitCell(cells)) + break; + } + return cells; + } + + /** + * + * Assign all colors to their closest approximation and return an array of + * color indexes. + * + * Uses Floyd-Steinberg dithering, finding the closest known color and then + * spreading out the error over four leading pixels. Limits error to +/- 75 + * percent in normalized L*a*b space. + * + * @param cells + * quantized color cells + * @param colorMap + * map of quantized rgb to its cell + * @return array of color indexes, one for each pixel + * + */ + private int[] indexPixels(Lst cells, + Map colorMap) { + // We need a strip only width+2 wide to process all the errors. + // Errors are added to the next pixel and the next row's pixels + // only through p + width + 1: + // p +1 + // +w-1 +w +w+1 + // so including p as well, we need a total of width + 2 errors. + // + // as p moves through the pixels, we just use mod to cycle through + // this strip. + // + int w2 = width + 2; + P3[] errors = new P3[w2]; + // We should replace, not overwrite, pixels + // as this may be the raw canvas.buf32. + int[] newPixels = new int[pixels.length]; + P3 err = new P3(); + P3 lab; + int rgb; + Map nearestCell = new Hashtable(); + for (int i = 0, p = 0; i < height; ++i) { + boolean notLastRow = (i != height - 1); + for (int j = 0; j < width; ++j, p++) { + if (pixels[p] == backgroundColor) { + // leave as 0 + continue; + } + P3 pe = errors[p % w2]; + if (pe == null || pe.x == Float.MAX_VALUE) { + lab = null; + rgb = pixels[p]; + } else { + lab = toLABnorm(pixels[p]); + err = pe; + // important not to round the clamp here -- full floating precision + err.x = clamp(err.x, -75, 75); + err.y = clamp(err.y, -75, 75); + err.z = clamp(err.z, -75, 75); + lab.add(err); + rgb = CU.colorPtToFFRGB(toRGB(lab)); + } + Integer key = Integer.valueOf(rgb); + ColorCell cell = colorMap.get(key); + if (cell == null) { + // critical to generate normalized L*a*b from RGB here for nearestCell mapping. + // otherwise future RGB keys may match the wrong cell + lab = toLABnorm(rgb); + cell = nearestCell.get(key); + if (cell == null) { + // find nearest cell + float maxerr = Float.MAX_VALUE; + // skip 0 0 0 + for (int ib = cells.size(); --ib >= 1;) { + ColorCell c = cells.get(ib); + err.sub2(lab, c.center); + float d = err.lengthSquared(); + if (d < maxerr) { + maxerr = d; + cell = c; + } + } + nearestCell.put(key, cell); + } + if (floydSteinberg) { + // dither + err.sub2(lab, cell.center); + boolean notLastCol = (j < width - 1); + if (notLastCol) + addError(err, 7, errors, p + 1, w2); + if (notLastRow) { + if (j > 0) + addError(err, 3, errors, p + width - 1, w2); + addError(err, 5, errors, p + width, w2); + if (notLastCol) + addError(err, 1, errors, p + width + 1, w2); + } + } + err.x = Float.MAX_VALUE; // used; flag for resetting to 0 + } + newPixels[p] = cell.index; + } + } + return newPixels; + } + + private void addError(P3 err, int f, P3[] errors, int p, int w2) { + // GIMP will allow changing the background color. + if (pixels[p] == backgroundColor) + return; + p %= w2; + P3 errp = errors[p]; + if (errp == null) + errp = errors[p] = new P3(); + else if (errp.x == Float.MAX_VALUE) // reuse + errp.set(0, 0, 0); + errp.scaleAdd2(f / 16f, err, errp); + } + + ///////////////////////// CIE L*a*b / XYZ / sRGB conversion methods ///////// + + // these could be static, but that just makes for more JavaScript code + + protected P3 toLABnorm(int rgb) { + P3 lab = CU.colorPtFromInt(rgb, null); + rgbToXyz(lab, lab); + xyzToLab(lab, lab); + // normalize to 0-100 + lab.y = (lab.y + 86.185f) / (98.254f + 86.185f) * 100f; + lab.z = (lab.z + 107.863f) / (94.482f + 107.863f) * 100f; + return lab; + } + + protected P3 toRGB(P3 lab) { + P3 xyz = P3.newP(lab); + // normalized to 0-100 + xyz.y = xyz.y / 100f * (98.254f + 86.185f) - 86.185f; + xyz.z = xyz.z / 100f * (94.482f + 107.863f) - 107.863f; + labToXyz(xyz, xyz); + return xyzToRgb(xyz, xyz); + } + + private static M3 xyz2rgb; + private static M3 rgb2xyz; + + static { + rgb2xyz = M3.newA9(new float[] { 0.4124f, 0.3576f, 0.1805f, 0.2126f, + 0.7152f, 0.0722f, 0.0193f, 0.1192f, 0.9505f }); + + xyz2rgb = M3.newA9(new float[] { 3.2406f, -1.5372f, -0.4986f, -0.9689f, + 1.8758f, 0.0415f, 0.0557f, -0.2040f, 1.0570f }); + } + + public P3 rgbToXyz(P3 rgb, P3 xyz) { + // http://en.wikipedia.org/wiki/CIE_1931_color_space + // http://rsb.info.nih.gov/ij/plugins/download/Color_Space_Converter.java + if (xyz == null) + xyz = new P3(); + xyz.x = sxyz(rgb.x); + xyz.y = sxyz(rgb.y); + xyz.z = sxyz(rgb.z); + rgb2xyz.rotate(xyz); + return xyz; + } + + private float sxyz(float x) { + x /= 255; + return (float) (x <= 0.04045 ? x / 12.92 : Math.pow(((x + 0.055) / 1.055), + 2.4)) * 100; + } + + public P3 xyzToRgb(P3 xyz, P3 rgb) { + // http://en.wikipedia.org/wiki/CIE_1931_color_space + // http://rsb.info.nih.gov/ij/plugins/download/Color_Space_Converter.java + if (rgb == null) + rgb = new P3(); + rgb.setT(xyz); + rgb.scale(0.01f); + xyz2rgb.rotate(rgb); + rgb.x = clamp(srgb(rgb.x), 0, 255); + rgb.y = clamp(srgb(rgb.y), 0, 255); + rgb.z = clamp(srgb(rgb.z), 0, 255); + return rgb; + } + + private float srgb(float x) { + return (float) (x > 0.0031308f ? (1.055 * Math.pow(x, 1.0 / 2.4)) - 0.055 + : x * 12.92) * 255; + } + + public P3 xyzToLab(P3 xyz, P3 lab) { + // http://en.wikipedia.org/wiki/Lab_color_space + // http://rsb.info.nih.gov/ij/plugins/download/Color_Space_Converter.java + // Lab([0..100], [-86.185..98.254], [-107.863..94.482]) + // XYZn = D65 = {95.0429, 100.0, 108.8900}; + if (lab == null) + lab = new P3(); + float x = flab(xyz.x / 95.0429f); + float y = flab(xyz.y / 100); + float z = flab(xyz.z / 108.89f); + lab.x = (116 * y) - 16; + lab.y = 500 * (x - y); + lab.z = 200 * (y - z); + return lab; + } + + private float flab(float t) { + return (float) (t > 8.85645168E-3 /* (24/116)^3 */? Math.pow(t, + 0.333333333) : 7.78703704 /* 1/3*116/24*116/24 */* t + 0.137931034 /* 16/116 */ + ); + } + + public P3 labToXyz(P3 lab, P3 xyz) { + // http://en.wikipedia.org/wiki/Lab_color_space + // http://rsb.info.nih.gov/ij/plugins/download/Color_Space_Converter.java + // XYZn = D65 = {95.0429, 100.0, 108.8900}; + if (xyz == null) + xyz = new P3(); + + xyz.setT(lab); + float y = (xyz.x + 16) / 116; + float x = xyz.y / 500 + y; + float z = y - xyz.z / 200; + xyz.x = fxyz(x) * 95.0429f; + xyz.y = fxyz(y) * 100; + xyz.z = fxyz(z) * 108.89f; + + return xyz; + } + + private float fxyz(float t) { + return (float) (t > 0.206896552 /* (24/116) */? t * t * t + : 0.128418549 /* 3*24/116*24/116 */* (t - 0.137931034 /* 16/116 */)); + } + + private float clamp(float c, float min, float max) { + c = (c < min ? min : c > max ? max : c); + return (min == 0 ? Math.round(c) : c); + } + + ///////////////////////// GifEncoder writing methods //////////////////////// + + /** + * includes logical screen descriptor + * + * @throws IOException + */ + private void writeHeader() throws IOException { + putString("GIF89a"); + putWord(width); + putWord(height); + putByte(0); // no global color table -- using local instead + putByte(0); // no background + putByte(0); // no pixel aspect ratio given + } + + private void writeGraphicControlExtension() { + if (isTransparent || delayTime100ths >= 0) { + putByte(0x21); // graphic control extension + putByte(0xf9); // graphic control label + putByte(4); // block size + putByte((isTransparent ? 9 : 0) | (delayTime100ths > 0 ? 2 : 0)); // packed bytes + putWord(delayTime100ths > 0 ? delayTime100ths : 0); + putByte(0); // transparent index + putByte(0); // end-of-block + } + } + + // see http://www.vurdalakov.net/misc/gif/netscape-looping-application-extension + // +---------------+ + // 0 | 0x21 | Extension Label + // +---------------+ + // 1 | 0xFF | Application Extension Label + // +---------------+ + // 2 | 0x0B | Block Size + // +---------------+ + // 3 | | + // +- -+ + // 4 | | + // +- -+ + // 5 | | + // +- -+ + // 6 | | + // +- NETSCAPE -+ Application Identifier (8 bytes) + // 7 | | + // +- -+ + // 8 | | + // +- -+ + // 9 | | + // +- -+ + // 10 | | + // +---------------+ + // 11 | | + // +- -+ + // 12 | 2.0 | Application Authentication Code (3 bytes) + // +- -+ + // 13 | | + // +===============+ --+ + // 14 | 0x03 | Sub-block Data Size | + // +---------------+ | + // 15 | 0x01 | Sub-block ID | + // +---------------+ | Application Data Sub-block + // 16 | | | + // +- -+ Loop Count (2 bytes) | + // 17 | | | + // +===============+ --+ + // 18 | 0x00 | Block Terminator + // +---------------+ + + private void writeNetscapeLoopExtension() { + putByte(0x21); // graphic control extension + putByte(0xff); // netscape loop extension + putByte(0x0B); // block size + putString("NETSCAPE2.0"); + putByte(3); + putByte(1); + putWord(0); // loop indefinitely + putByte(0); // end-of-block + + } + + private int initCodeSize; + private int curpt; + + private void writeImage() { + putByte(0x2C); + putWord(0); //left + putWord(0); //top + putWord(width); + putWord(height); + + // = LISx xZZZ + + // L Local Color Table Flag + // I Interlace Flag + // S Sort Flag + // x Reserved + // ZZZ Size of Local Color Table + + int packedFields = 0x80 | (interlaced ? 0x40 : 0) | (bitsPerPixel - 1); + putByte(packedFields); + int colorMapSize = 1 << bitsPerPixel; + P3 p = new P3(); + for (int i = 0; i < colorMapSize; i++) { + if (palette[i] != null) + p = palette[i]; + putByte((int) p.x); + putByte((int) p.y); + putByte((int) p.z); + } + putByte(initCodeSize = (bitsPerPixel <= 1 ? 2 : bitsPerPixel)); + compress(); + putByte(0); + } + + private void writeTrailer() { + // Write the GIF file terminator + putByte(0x3B); + } + + ///// compression routines ///// + + private static final int EOF = -1; + + // Return the next pixel from the image + private int nextPixel() { + if (countDown-- == 0) + return EOF; + int colorIndex = pixels[curpt]; + // Bump the current X position + ++curx; + if (curx == width) { + // If we are at the end of a scan line, set curx back to the beginning + // If we are interlaced, bump the cury to the appropriate spot, + // otherwise, just increment it. + curx = 0; + if (interlaced) + updateY(INTERLACE_PARAMS[pass], INTERLACE_PARAMS[pass + 4]); + else + ++cury; + } + curpt = cury * width + curx; + return colorIndex & 0xff; + } + + private static final int[] INTERLACE_PARAMS = { 8, 8, 4, 2, 4, 2, 1, 0 }; + + /** + * + * Group 1 : Every 8th. row, starting with row 0. (Pass 1) + * + * Group 2 : Every 8th. row, starting with row 4. (Pass 2) + * + * Group 3 : Every 4th. row, starting with row 2. (Pass 3) + * + * Group 4 : Every 2nd. row, starting with row 1. (Pass 4) + * + * @param yNext + * @param yNew + */ + private void updateY(int yNext, int yNew) { + cury += yNext; + if (yNew >= 0 && cury >= height) { + cury = yNew; + ++pass; + } + } + + // Write out a word to the GIF file + private void putWord(int w) { + putByte(w); + putByte(w >> 8); + } + + // GIFCOMPR.C - GIF Image compression routines + // + // Lempel-Ziv compression based on 'compress'. GIF modifications by + // David Rowley (mgardi@watdcsu.waterloo.edu) + + // General DEFINEs + + private static final int BITS = 12; + + private static final int HSIZE = 5003; // 80% occupancy + + // GIF Image compression - modified 'compress' + // + // Based on: compress.c - File compression ala IEEE Computer, June 1984. + // + // By Authors: Spencer W. Thomas (decvax!harpo!utah-cs!utah-gr!thomas) + // Jim McKie (decvax!mcvax!jim) + // Steve Davies (decvax!vax135!petsd!peora!srd) + // Ken Turkowski (decvax!decwrl!turtlevax!ken) + // James A. Woods (decvax!ihnp4!ames!jaw) + // Joe Orost (decvax!vax135!petsd!joe) + + private int nBits; // number of bits/code + private int maxbits = BITS; // user settable max # bits/code + private int maxcode; // maximum code, given n_bits + private int maxmaxcode = 1 << BITS; // should NEVER generate this code + + private final static int MAXCODE(int nBits) { + return (1 << nBits) - 1; + } + + private int[] htab = new int[HSIZE]; + private int[] codetab = new int[HSIZE]; + + private int hsize = HSIZE; // for dynamic table sizing + + private int freeEnt = 0; // first unused entry + + // block compression parameters -- after all codes are used up, + // and compression rate changes, start over. + private boolean clearFlag = false; + + // Algorithm: use open addressing double hashing (no chaining) on the + // prefix code / next character combination. We do a variant of Knuth's + // algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime + // secondary probe. Here, the modular division first probe is gives way + // to a faster exclusive-or manipulation. Also do block compression with + // an adaptive reset, whereby the code table is cleared when the compression + // ratio decreases, but after the table fills. The variable-length output + // codes are re-sized at this point, and a special CLEAR code is generated + // for the decompressor. Late addition: construct the table according to + // file size for noticeable speed improvement on small files. Please direct + // questions about this implementation to ames!jaw. + + private int clearCode; + private int EOFCode; + + private int countDown; + private int pass = 0; + private int curx, cury; + + private void compress() { + + // Calculate number of bits we are expecting + countDown = width * height; + + // Indicate which pass we are on (if interlace) + pass = 0; + // Set up the current x and y position + curx = 0; + cury = 0; + + // Set up the necessary values + clearFlag = false; + nBits = initCodeSize + 1; + maxcode = MAXCODE(nBits); + + clearCode = 1 << initCodeSize; + EOFCode = clearCode + 1; + freeEnt = clearCode + 2; + + // Set up the 'byte output' routine + bufPt = 0; + + int ent = nextPixel(); + + int hshift = 0; + int fcode; + for (fcode = hsize; fcode < 65536; fcode *= 2) + ++hshift; + hshift = 8 - hshift; // set hash code range bound + + int hsizeReg = hsize; + clearHash(hsizeReg); // clear hash table + + output(clearCode); + + int c; + outer_loop: while ((c = nextPixel()) != EOF) { + fcode = (c << maxbits) + ent; + int i = (c << hshift) ^ ent; // xor hashing + + if (htab[i] == fcode) { + ent = codetab[i]; + continue; + } else if (htab[i] >= 0) // non-empty slot + { + int disp = hsizeReg - i; // secondary hash (after G. Knott) + if (i == 0) + disp = 1; + do { + if ((i -= disp) < 0) + i += hsizeReg; + + if (htab[i] == fcode) { + ent = codetab[i]; + continue outer_loop; + } + } while (htab[i] >= 0); + } + output(ent); + ent = c; + if (freeEnt < maxmaxcode) { + codetab[i] = freeEnt++; // code -> hashtable + htab[i] = fcode; + } else { + clearBlock(); + } + } + // Put out the final code. + output(ent); + output(EOFCode); + } + + // output + // + // Output the given code. + // Inputs: + // code: A n_bits-bit integer. If == -1, then EOF. This assumes + // that n_bits =< wordsize - 1. + // Outputs: + // Outputs code to the file. + // Assumptions: + // Chars are 8 bits long. + // Algorithm: + // Maintain a BITS character long buffer (so that 8 codes will + // fit in it exactly). Use the VAX insv instruction to insert each + // code in turn. When the buffer fills up empty it and start over. + + private int curAccum = 0; + private int curBits = 0; + + private int masks[] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, + 0x003F, 0x007F, 0x00FF, 0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF, + 0x7FFF, 0xFFFF }; + + private void output(int code) { + curAccum &= masks[curBits]; + + if (curBits > 0) + curAccum |= (code << curBits); + else + curAccum = code; + + curBits += nBits; + + while (curBits >= 8) { + byteOut((byte) (curAccum & 0xff)); + curAccum >>= 8; + curBits -= 8; + } + + // If the next entry is going to be too big for the code size, + // then increase it, if possible. + if (freeEnt > maxcode || clearFlag) { + if (clearFlag) { + maxcode = MAXCODE(nBits = initCodeSize + 1); + clearFlag = false; + } else { + ++nBits; + if (nBits == maxbits) + maxcode = maxmaxcode; + else + maxcode = MAXCODE(nBits); + } + } + + if (code == EOFCode) { + // At EOF, write the rest of the buffer. + while (curBits > 0) { + byteOut((byte) (curAccum & 0xff)); + curAccum >>= 8; + curBits -= 8; + } + flushBytes(); + } + } + + // Clear out the hash table + + // table clear for block compress + private void clearBlock() { + clearHash(hsize); + freeEnt = clearCode + 2; + clearFlag = true; + + output(clearCode); + } + + // reset code table + private void clearHash(int hsize) { + for (int i = 0; i < hsize; ++i) + htab[i] = -1; + } + + // GIF-specific routines (byte array buffer) + + // Number of bytes so far in this 'packet' + private int bufPt; + + // Define the storage for the packet accumulator + final private byte[] buf = new byte[256]; + + // Add a byte to the end of the current packet, and if it is 254 + // byte, flush the packet to disk. + private void byteOut(byte c) { + buf[bufPt++] = c; + if (bufPt >= 254) + flushBytes(); + } + + // Flush the packet to disk, and reset the accumulator + protected void flushBytes() { + if (bufPt > 0) { + putByte(bufPt); + out.write(buf, 0, bufPt); + byteCount += bufPt; + bufPt = 0; + } + } + +} diff --git a/src/javajs/img/ImageEncoder.java b/src/javajs/img/ImageEncoder.java new file mode 100644 index 0000000..91a91fc --- /dev/null +++ b/src/javajs/img/ImageEncoder.java @@ -0,0 +1,124 @@ +/* $RCSfile$ + * $Author: hansonr $ + * $Date: 2007-06-02 12:14:13 -0500 (Sat, 02 Jun 2007) $ + * $Revision: 7831 $ + * + * Copyright (C) 2000-2005 The Jmol Development Team + * + * Contact: jmol-developers@lists.sf.net + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +// ImageEncoder - abstract class for writing out an image +// +// Copyright (C) 1996 by Jef Poskanzer . All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +// SUCH DAMAGE. +// +// Visit the ACME Labs Java page for up-to-date versions of this and other +// fine Java utilities: http://www.acme.com/java/ + +package javajs.img; + +import java.util.Map; + +import javajs.api.GenericImageEncoder; +import javajs.util.OC; + + + +/** + * Generic abstract image creator: + * + * (1) set parameters + * + * (2) encode the image bytes, if necessary + * + * (3) generate the image + * @author Bob Hanson hansonr@stolaf.edu + */ + +public abstract class ImageEncoder implements GenericImageEncoder { + + protected OC out; + + protected int width = -1; + protected int height = -1; + protected int quality = -1; + protected String date; + protected boolean logging; + protected boolean doClose = true; + + /** + * @param type + * @param out + * @param params + */ + @Override + public boolean createImage(String type, OC out, Map params) + throws Exception { + this.out = out; + logging = (Boolean.TRUE == params.get("logging")); + width = ((Integer) params.get("imageWidth")).intValue(); + height = ((Integer) params.get("imageHeight")).intValue(); + pixels = (int[]) params.get("imagePixels"); + date = (String) params.get("date"); + Integer q = (Integer) params.get("quality"); + quality = (q == null ? -1 : q.intValue()); + setParams(params); + generate(); + close(); // GIF will override this and not close + return doClose; + } + + abstract protected void setParams(Map params); + abstract protected void generate() throws Exception; + + protected int[] pixels; + + protected void putString(String s) { + byte[] b = s.getBytes(); + out.write(b, 0, b.length); + } + + protected void putByte(int b) { + out.writeByteAsInt(b); + } + + protected void close() { + // your responsibility to close the output channel + } + +} diff --git a/src/javajs/img/Jpg64Encoder.java b/src/javajs/img/Jpg64Encoder.java new file mode 100644 index 0000000..796972f --- /dev/null +++ b/src/javajs/img/Jpg64Encoder.java @@ -0,0 +1,64 @@ +// Version 1.0a +// Copyright (C) 1998, James R. Weeks and BioElectroMech. +// Visit BioElectroMech at www.obrador.com. Email James@obrador.com. + +// See license.txt for details about the allowed used of this software. +// This software is based in part on the work of the Independent JPEG Group. +// See IJGreadme.txt for details about the Independent JPEG Group's license. + +// This encoder is inspired by the Java Jpeg encoder by Florian Raemy, +// studwww.eurecom.fr/~raemy. +// It borrows a great deal of code and structure from the Independent +// Jpeg Group's Jpeg 6a library, Copyright Thomas G. Lane. +// See license.txt for details + +/* + * JpegEncoder and its associated classes are Copyright (c) 1998, James R. Weeks and BioElectroMech + * see(Jmol/src/com/obrador/license.txt) + * + * javajs.img.JpegEncoder.java was adapted by Bob Hanson + * for Jmol in the following ways: + * + * 1) minor coding efficiencies were made in some for() loops. + * 2) methods not used by Jmol were commented out + * 3) method and variable signatures were modified to provide + * more appropriate method privacy. + * 4) additions for Java2Script compatibility + * + * Original files are maintained in the Jmol.src.com.obrador package, but + * these original files are not distributed with Jmol. + * +*/ + +package javajs.img; + +import java.io.IOException; +import java.util.Map; + +import javajs.util.Base64; +import javajs.util.OC; + + +public class Jpg64Encoder extends JpgEncoder { + + private OC outTemp; + + @Override + protected void setParams(Map params) { + defaultQuality = 75; + outTemp = (OC) params.remove("outputChannelTemp"); + super.setParams(params); + } + + @Override + protected void generate() throws IOException { + OC out0 = out; + out = outTemp; + super.generate(); + byte[] bytes = Base64.getBytes64(out.toByteArray()); + outTemp = null; + out = out0; + out.write(bytes, 0, bytes.length); + } + +} diff --git a/src/javajs/img/JpgEncoder.java b/src/javajs/img/JpgEncoder.java new file mode 100644 index 0000000..5c128d6 --- /dev/null +++ b/src/javajs/img/JpgEncoder.java @@ -0,0 +1,1208 @@ +// Version 1.0a +// Copyright (C) 1998, James R. Weeks and BioElectroMech. +// Visit BioElectroMech at www.obrador.com. Email James@obrador.com. + +// See license.txt for details about the allowed used of this software. +// This software is based in part on the work of the Independent JPEG Group. +// See IJGreadme.txt for details about the Independent JPEG Group's license. + +// This encoder is inspired by the Java Jpeg encoder by Florian Raemy, +// studwww.eurecom.fr/~raemy. +// It borrows a great deal of code and structure from the Independent +// Jpeg Group's Jpeg 6a library, Copyright Thomas G. Lane. +// See license.txt for details + +/* + * JpegEncoder and its associated classes are Copyright (c) 1998, James R. Weeks and BioElectroMech + * see(Jmol/src/com/obrador/license.txt) + * + * javjs.img.JpegEncoder.java was adapted by Bob Hanson + * + * for Jmol in the following ways: + * + * 1) minor coding efficiencies were made in some for() loops. + * 2) methods not used by Jmol were commented out + * 3) method and variable signatures were modified to provide + * more appropriate method privacy. + * 4) additions for Java2Script compatibility + * + * Original files are maintained in the Jmol.src.com.obrador package, but + * these original files are not distributed with Jmol. + * +*/ + +package javajs.img; + +import java.io.IOException; +import java.util.Map; + +import javajs.img.ImageEncoder; +import javajs.util.AU; +import javajs.util.OC; + +/** + * JpegEncoder - The JPEG main program which performs a jpeg compression of an + * image. + * + * A system to allow the full Jmol state -- regardless of length -- + * to be encoded in a set of APP1 (FFE1) tags. + * But we have to be careful about line ends for backward compatibility. + * This solution is not 100% effective, because some data lines may in principle be + * Very large and may not contain new lines for more than 65500 characters, + * But that would be very unusual. Perhaps a huge data set loaded from a + * string. Introduced in Jmol 12.1.36. Bob Hanson + * + * See org.com.obrador.license.txt + * + */ + +public class JpgEncoder extends ImageEncoder { + + // this string will GENERALLY appear at the end of lines and be escaped + private static final int CONTINUE_MAX = 65500; // some room to spare here. + private static final int CONTINUE_MAX_BUFFER = CONTINUE_MAX + 10; // never break up last 10 bytes + + private JpegObj jpegObj; + private Huffman huf; + private DCT dct; + protected int defaultQuality = 100; + private String applicationTag; + + public JpgEncoder() { + + } + + @Override + protected void setParams(Map params) { + if (quality <= 0) + quality = (params.containsKey("qualityJPG") ? ((Integer) params.get("qualityJPG")).intValue() : defaultQuality); + jpegObj = new JpegObj(); + jpegObj.comment = (String) params.get("comment"); + applicationTag = (String) params.get("jpgAppTag"); + } + + @Override + protected void generate() throws IOException { + jpegObj.imageWidth = width; + jpegObj.imageHeight = height; + dct = new DCT(quality); + huf = new Huffman(width, height); + if (jpegObj == null) + return; + jpegObj.getYCCArray(pixels); + String longState = writeHeaders(jpegObj, dct); + writeCompressedData(jpegObj, dct, huf); + writeMarker(eoi); + if (longState != null) { + byte[] b = longState.getBytes(); + out.write(b, 0, b.length); + } + } + + private void writeCompressedData(JpegObj jpegObj, DCT dct, Huffman huf) { + int i, j, r, c, a, b; + int comp, xpos, ypos, xblockoffset, yblockoffset; + float inputArray[][]; + float dctArray1[][] = new float[8][8]; + double dctArray2[][] = new double[8][8]; + int dctArray3[] = new int[8 * 8]; + + /* + * This method controls the compression of the image. + * Starting at the upper left of the image, it compresses 8x8 blocks + * of data until the entire image has been compressed. + */ + + int lastDCvalue[] = new int[jpegObj.numberOfComponents]; + //int zeroArray[] = new int[64]; // initialized to hold all zeros + //int Width = 0, Height = 0; + //int nothing = 0, not; + int minBlockWidth, minBlockHeight; + // This initial setting of MinBlockWidth and MinBlockHeight is done to + // ensure they start with values larger than will actually be the case. + minBlockWidth = ((huf.imageWidth % 8 != 0) ? (int) (Math + .floor(huf.imageWidth / 8.0) + 1) * 8 : huf.imageWidth); + minBlockHeight = ((huf.imageHeight % 8 != 0) ? (int) (Math + .floor(huf.imageHeight / 8.0) + 1) * 8 : huf.imageHeight); + for (comp = 0; comp < jpegObj.numberOfComponents; comp++) { + minBlockWidth = Math.min(minBlockWidth, jpegObj.blockWidth[comp]); + minBlockHeight = Math.min(minBlockHeight, jpegObj.blockHeight[comp]); + } + xpos = 0; + for (r = 0; r < minBlockHeight; r++) { + for (c = 0; c < minBlockWidth; c++) { + xpos = c * 8; + ypos = r * 8; + for (comp = 0; comp < jpegObj.numberOfComponents; comp++) { + //Width = JpegObj.BlockWidth[comp]; + //Height = JpegObj.BlockHeight[comp]; + inputArray = jpegObj.components[comp]; + int vsampF = jpegObj.vsampFactor[comp]; + int hsampF = jpegObj.hsampFactor[comp]; + int qNumber = jpegObj.qtableNumber[comp]; + int dcNumber = jpegObj.dctableNumber[comp]; + int acNumber = jpegObj.actableNumber[comp]; + + for (i = 0; i < vsampF; i++) { + for (j = 0; j < hsampF; j++) { + xblockoffset = j * 8; + yblockoffset = i * 8; + for (a = 0; a < 8; a++) { + for (b = 0; b < 8; b++) { + + // I believe this is where the dirty line at the bottom of + // the image is coming from. + // I need to do a check here to make sure I'm not reading past + // image data. + // This seems to not be a big issue right now. (04/04/98) + + dctArray1[a][b] = inputArray[ypos + yblockoffset + a][xpos + + xblockoffset + b]; + } + } + // The following code commented out because on some images this technique + // results in poor right and bottom borders. + // if ((!JpegObj.lastColumnIsDummy[comp] || c < Width - 1) && + // (!JpegObj.lastRowIsDummy[comp] || r < Height - 1)) { + dctArray2 = DCT.forwardDCT(dctArray1); + dctArray3 = DCT.quantizeBlock(dctArray2, dct.divisors[qNumber]); + // } + // else { + // zeroArray[0] = dctArray3[0]; + // zeroArray[0] = lastDCvalue[comp]; + // dctArray3 = zeroArray; + // } + huf.HuffmanBlockEncoder(out, dctArray3, lastDCvalue[comp], + dcNumber, acNumber); + lastDCvalue[comp] = dctArray3[0]; + } + } + } + } + } + huf.flushBuffer(out); + } + + private static byte[] eoi = { (byte) 0xFF, (byte) 0xD9 }; + + private static byte[] jfif = new byte[] { + /* JFIF[0] =*/(byte) 0xff, + /* JFIF[1] =*/(byte) 0xe0, + /* JFIF[2] =*/0, + /* JFIF[3] =*/16, + /* JFIF[4] =*/(byte) 0x4a, //'J' + /* JFIF[5] =*/(byte) 0x46, //'F' + /* JFIF[6] =*/(byte) 0x49, //'I' + /* JFIF[7] =*/(byte) 0x46, //'F' + /* JFIF[8] =*/0, + /* JFIF[9] =*/1, + /* JFIF[10] =*/0, + /* JFIF[11] =*/0, + /* JFIF[12] =*/0, + /* JFIF[13] =*/1, + /* JFIF[14] =*/0, + /* JFIF[15] =*/1, + /* JFIF[16] =*/0, + /* JFIF[17] =*/0 }; + + private static byte[] soi = { (byte) 0xFF, (byte) 0xD8 }; + + private String writeHeaders(JpegObj jpegObj, DCT dct) { + int i, j, index, offset; + int tempArray[]; + + // the SOI marker + writeMarker(soi); + + // The order of the following headers is quite inconsequential. + // the JFIF header + writeArray(jfif); + + // Comment Header + String comment = null; + if (jpegObj.comment.length() > 0) + writeString(jpegObj.comment, (byte) 0xE1); // App data 1 + writeString( + "JPEG Encoder Copyright 1998, James R. Weeks and BioElectroMech.\n\n", + (byte) 0xFE); + + // The DQT header + // 0 is the luminance index and 1 is the chrominance index + byte dqt[] = new byte[134]; + dqt[0] = (byte) 0xFF; + dqt[1] = (byte) 0xDB; + dqt[2] = 0; + dqt[3] = (byte) 132; + offset = 4; + for (i = 0; i < 2; i++) { + dqt[offset++] = (byte) ((0 << 4) + i); + tempArray = dct.quantum[i]; + for (j = 0; j < 64; j++) { + dqt[offset++] = (byte) tempArray[Huffman.jpegNaturalOrder[j]]; + } + } + writeArray(dqt); + + // Start of Frame Header + byte sof[] = new byte[19]; + sof[0] = (byte) 0xFF; + sof[1] = (byte) 0xC0; + sof[2] = 0; + sof[3] = 17; + sof[4] = (byte) jpegObj.precision; + sof[5] = (byte) ((jpegObj.imageHeight >> 8) & 0xFF); + sof[6] = (byte) ((jpegObj.imageHeight) & 0xFF); + sof[7] = (byte) ((jpegObj.imageWidth >> 8) & 0xFF); + sof[8] = (byte) ((jpegObj.imageWidth) & 0xFF); + sof[9] = (byte) jpegObj.numberOfComponents; + index = 10; + for (i = 0; i < sof[9]; i++) { + sof[index++] = (byte) jpegObj.compID[i]; + sof[index++] = (byte) ((jpegObj.hsampFactor[i] << 4) + jpegObj.vsampFactor[i]); + sof[index++] = (byte) jpegObj.qtableNumber[i]; + } + writeArray(sof); + + WriteDHTHeader(Huffman.bitsDCluminance, Huffman.valDCluminance); + WriteDHTHeader(Huffman.bitsACluminance, Huffman.valACluminance); + WriteDHTHeader(Huffman.bitsDCchrominance, Huffman.valDCchrominance); + WriteDHTHeader(Huffman.bitsACchrominance, Huffman.valACchrominance); + + // Start of Scan Header + byte sos[] = new byte[14]; + sos[0] = (byte) 0xFF; + sos[1] = (byte) 0xDA; + sos[2] = 0; + sos[3] = 12; + sos[4] = (byte) jpegObj.numberOfComponents; + index = 5; + for (i = 0; i < sos[4]; i++) { + sos[index++] = (byte) jpegObj.compID[i]; + sos[index++] = (byte) ((jpegObj.dctableNumber[i] << 4) + jpegObj.actableNumber[i]); + } + sos[index++] = (byte) jpegObj.ss; + sos[index++] = (byte) jpegObj.se; + sos[index++] = (byte) ((jpegObj.ah << 4) + jpegObj.al); + writeArray(sos); + return comment; + } + + private void writeString(String s, byte id) { + int len = s.length(); + int i0 = 0; + String suffix = applicationTag; + while (i0 < len) { + int nBytes = len - i0; + if (nBytes > CONTINUE_MAX_BUFFER) { + nBytes = CONTINUE_MAX; + // but break only at line breaks + int pt = s.lastIndexOf('\n', i0 + nBytes); + if (pt > i0 + 1) + nBytes = pt - i0; + } + if (i0 + nBytes == len) + suffix = ""; + writeTag(nBytes + suffix.length(), id); + writeArray(s.substring(i0, i0 + nBytes).getBytes()); + if (suffix.length() > 0) + writeArray(suffix.getBytes()); + i0 += nBytes; + } + } + + private void writeTag(int length, byte id) { + length += 2; + byte com[] = new byte[4]; + com[0] = (byte) 0xFF; + com[1] = id; + com[2] = (byte) ((length >> 8) & 0xFF); + com[3] = (byte) (length & 0xFF); + writeArray(com); + } + + void WriteDHTHeader(int[] bits, int[] val) { + // hansonr@stolaf.edu: simplified code. + byte[] dht; + int bytes = 0; + for (int j = 1; j < 17; j++) + bytes += bits[j]; + dht = new byte[21 + bytes]; + dht[0] = (byte) 0xFF; + dht[1] = (byte) 0xC4; + int index = 4; + for (int j = 0; j < 17; j++) + dht[index++] = (byte) bits[j]; + for (int j = 0; j < bytes; j++) + dht[index++] = (byte) val[j]; + dht[2] = (byte) (((index - 2) >> 8) & 0xFF); + dht[3] = (byte) ((index - 2) & 0xFF); + writeArray(dht); + } + + void writeMarker(byte[] data) { + out.write(data, 0, 2); + } + + void writeArray(byte[] data) { + out.write(data, 0, data.length); + } + +} + +// This class incorporates quality scaling as implemented in the JPEG-6a +// library. + +/* + * DCT - A Java implementation of the Discreet Cosine Transform + */ + +class DCT { + + /** + * DCT Block Size - default 8 + */ + private final static int N = 8; + private final static int NN = N * N; + + /** + * Image Quality (0-100) - default 80 (good image / good compression) + */ + //public int QUALITY = 80; + + int[][] quantum = AU.newInt2(2); + double[][] divisors = AU.newDouble2(2); + + /** + * Quantitization Matrix for luminace. + */ + private int quantum_luminance[] = new int[NN]; + private double DivisorsLuminance[] = new double[NN]; + + /** + * Quantitization Matrix for chrominance. + */ + private int quantum_chrominance[] = new int[NN]; + private double DivisorsChrominance[] = new double[NN]; + + /** + * Constructs a new DCT object. Initializes the cosine transform matrix these + * are used when computing the DCT and it's inverse. This also initializes the + * run length counters and the ZigZag sequence. Note that the image quality + * can be worse than 25 however the image will be extemely pixelated, usually + * to a block size of N. + * + * @param quality + * The quality of the image (0 worst - 100 best) + * + */ + DCT(int quality) { + initMatrix(quality); + } + + /* + * This method sets up the quantization matrix for luminance and + * chrominance using the Quality parameter. + */ + private void initMatrix(int quality) { + // converting quality setting to that specified in the jpeg_quality_scaling + // method in the IJG Jpeg-6a C libraries + + quality = (quality < 1 ? 1 : quality > 100 ? 100 : quality); + quality = (quality < 50 ? 5000 / quality : 200 - quality * 2); + + // Creating the luminance matrix + + quantum_luminance[0] = 16; + quantum_luminance[1] = 11; + quantum_luminance[2] = 10; + quantum_luminance[3] = 16; + quantum_luminance[4] = 24; + quantum_luminance[5] = 40; + quantum_luminance[6] = 51; + quantum_luminance[7] = 61; + quantum_luminance[8] = 12; + quantum_luminance[9] = 12; + quantum_luminance[10] = 14; + quantum_luminance[11] = 19; + quantum_luminance[12] = 26; + quantum_luminance[13] = 58; + quantum_luminance[14] = 60; + quantum_luminance[15] = 55; + quantum_luminance[16] = 14; + quantum_luminance[17] = 13; + quantum_luminance[18] = 16; + quantum_luminance[19] = 24; + quantum_luminance[20] = 40; + quantum_luminance[21] = 57; + quantum_luminance[22] = 69; + quantum_luminance[23] = 56; + quantum_luminance[24] = 14; + quantum_luminance[25] = 17; + quantum_luminance[26] = 22; + quantum_luminance[27] = 29; + quantum_luminance[28] = 51; + quantum_luminance[29] = 87; + quantum_luminance[30] = 80; + quantum_luminance[31] = 62; + quantum_luminance[32] = 18; + quantum_luminance[33] = 22; + quantum_luminance[34] = 37; + quantum_luminance[35] = 56; + quantum_luminance[36] = 68; + quantum_luminance[37] = 109; + quantum_luminance[38] = 103; + quantum_luminance[39] = 77; + quantum_luminance[40] = 24; + quantum_luminance[41] = 35; + quantum_luminance[42] = 55; + quantum_luminance[43] = 64; + quantum_luminance[44] = 81; + quantum_luminance[45] = 104; + quantum_luminance[46] = 113; + quantum_luminance[47] = 92; + quantum_luminance[48] = 49; + quantum_luminance[49] = 64; + quantum_luminance[50] = 78; + quantum_luminance[51] = 87; + quantum_luminance[52] = 103; + quantum_luminance[53] = 121; + quantum_luminance[54] = 120; + quantum_luminance[55] = 101; + quantum_luminance[56] = 72; + quantum_luminance[57] = 92; + quantum_luminance[58] = 95; + quantum_luminance[59] = 98; + quantum_luminance[60] = 112; + quantum_luminance[61] = 100; + quantum_luminance[62] = 103; + quantum_luminance[63] = 99; + + AANscale(DivisorsLuminance, quantum_luminance, quality); + + // Creating the chrominance matrix + + for (int i = 4; i < 64; i++) + quantum_chrominance[i] = 99; + + quantum_chrominance[0] = 17; + quantum_chrominance[1] = 18; + quantum_chrominance[2] = 24; + quantum_chrominance[3] = 47; + + quantum_chrominance[8] = 18; + quantum_chrominance[9] = 21; + quantum_chrominance[10] = 26; + quantum_chrominance[11] = 66; + + quantum_chrominance[16] = 24; + quantum_chrominance[17] = 26; + quantum_chrominance[18] = 56; + + quantum_chrominance[24] = 47; + quantum_chrominance[25] = 66; + + AANscale(DivisorsChrominance, quantum_chrominance, quality); + + // quantum and Divisors are objects used to hold the appropriate matices + + quantum[0] = quantum_luminance; + quantum[1] = quantum_chrominance; + + divisors[0] = DivisorsLuminance; + divisors[1] = DivisorsChrominance; + + } + + private final static double[] AANscaleFactor = { 1.0, 1.387039845, + 1.306562965, 1.175875602, 1.0, 0.785694958, 0.541196100, 0.275899379 }; + + static private void AANscale(double[] divisors, int[] values, int quality) { + + for (int j = 0; j < 64; j++) { + int temp = (values[j] * quality + 50) / 100; + values[j] = (temp < 1 ? 1 : temp > 255 ? 255 : temp); + } + + for (int i = 0, index = 0; i < 8; i++) + for (int j = 0; j < 8; j++, index++) + // The divisors for the LL&M method (the slow integer method used in + // jpeg 6a library). This method is currently (04/04/98) incompletely + // implemented. + // DivisorsLuminance[index] = ((double) quantum_luminance[index]) << 3; + // The divisors for the AAN method (the float method used in jpeg 6a library. + divisors[index] = (0.125 / (values[index] * AANscaleFactor[i] * AANscaleFactor[j])); + } + + /* + * This method preforms forward DCT on a block of image data using + * the literal method specified for a 2-D Discrete Cosine Transform. + * It is included as a curiosity and can give you an idea of the + * difference in the compression result (the resulting image quality) + * by comparing its output to the output of the AAN method below. + * It is ridiculously inefficient. + */ + + // For now the final output is unusable. The associated quantization step + // needs some tweaking. If you get this part working, please let me know. + /* + public double[][] forwardDCTExtreme(float input[][]) + { + double output[][] = new double[N][N]; + int v, u, x, y; + for (v = 0; v < 8; v++) { + for (u = 0; u < 8; u++) { + for (x = 0; x < 8; x++) { + for (y = 0; y < 8; y++) { + output[v][u] += input[x][y] * + Math.cos(((double)(2*x + 1)*(double)u*Math.PI)/16)* + Math.cos(((double)(2*y + 1)*(double)v*Math.PI)/16); + } + } + output[v][u] *= (0.25)*((u == 0) ? (1.0/Math.sqrt(2)) : (double) 1.0)*((v == 0) ? (1.0/Math.sqrt(2)) : (double) 1.0); + } + } + return output; + } + + */ + /* + * This method preforms a DCT on a block of image data using the AAN + * method as implemented in the IJG Jpeg-6a library. + */ + static double[][] forwardDCT(float input[][]) { + double output[][] = new double[N][N]; + double tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + double tmp10, tmp11, tmp12, tmp13; + double z1, z2, z3, z4, z5, z11, z13; + // Subtracts 128 from the input values + for (int i = 0; i < 8; i++) + for (int j = 0; j < 8; j++) + output[i][j] = (input[i][j] - 128.0); + // input[i][j] -= 128; + + for (int i = 0; i < 8; i++) { + tmp0 = output[i][0] + output[i][7]; + tmp7 = output[i][0] - output[i][7]; + tmp1 = output[i][1] + output[i][6]; + tmp6 = output[i][1] - output[i][6]; + tmp2 = output[i][2] + output[i][5]; + tmp5 = output[i][2] - output[i][5]; + tmp3 = output[i][3] + output[i][4]; + tmp4 = output[i][3] - output[i][4]; + + tmp10 = tmp0 + tmp3; + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + + output[i][0] = tmp10 + tmp11; + output[i][4] = tmp10 - tmp11; + + z1 = (tmp12 + tmp13) * 0.707106781; + output[i][2] = tmp13 + z1; + output[i][6] = tmp13 - z1; + + tmp10 = tmp4 + tmp5; + tmp11 = tmp5 + tmp6; + tmp12 = tmp6 + tmp7; + + z5 = (tmp10 - tmp12) * 0.382683433; + z2 = 0.541196100 * tmp10 + z5; + z4 = 1.306562965 * tmp12 + z5; + z3 = tmp11 * 0.707106781; + + z11 = tmp7 + z3; + z13 = tmp7 - z3; + + output[i][5] = z13 + z2; + output[i][3] = z13 - z2; + output[i][1] = z11 + z4; + output[i][7] = z11 - z4; + } + + for (int i = 0; i < 8; i++) { + tmp0 = output[0][i] + output[7][i]; + tmp7 = output[0][i] - output[7][i]; + tmp1 = output[1][i] + output[6][i]; + tmp6 = output[1][i] - output[6][i]; + tmp2 = output[2][i] + output[5][i]; + tmp5 = output[2][i] - output[5][i]; + tmp3 = output[3][i] + output[4][i]; + tmp4 = output[3][i] - output[4][i]; + + tmp10 = tmp0 + tmp3; + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + + output[0][i] = tmp10 + tmp11; + output[4][i] = tmp10 - tmp11; + + z1 = (tmp12 + tmp13) * 0.707106781; + output[2][i] = tmp13 + z1; + output[6][i] = tmp13 - z1; + + tmp10 = tmp4 + tmp5; + tmp11 = tmp5 + tmp6; + tmp12 = tmp6 + tmp7; + + z5 = (tmp10 - tmp12) * 0.382683433; + z2 = 0.541196100 * tmp10 + z5; + z4 = 1.306562965 * tmp12 + z5; + z3 = tmp11 * 0.707106781; + + z11 = tmp7 + z3; + z13 = tmp7 - z3; + + output[5][i] = z13 + z2; + output[3][i] = z13 - z2; + output[1][i] = z11 + z4; + output[7][i] = z11 - z4; + } + + return output; + } + + /* + * This method quantitizes data and rounds it to the nearest integer. + */ + static int[] quantizeBlock(double inputData[][], double[] divisorsCode) { + int outputData[] = new int[NN]; + for (int i = 0, index = 0; i < 8; i++) + for (int j = 0; j < 8; j++, index++) + // The second line results in significantly better compression. + outputData[index] = (int) (Math.round(inputData[i][j] + * divisorsCode[index])); + // outputData[index] = (int)(((inputData[i][j] * (((double[]) (Divisors[code]))[index])) + 16384.5) -16384); + return outputData; + } + + /* + * This is the method for quantizing a block DCT'ed with forwardDCTExtreme + * This method quantitizes data and rounds it to the nearest integer. + */ + + /* + + public double[][] forwardDCTExtreme(float input[][]) + { + double output[][] = new double[N][N]; + int v, u, x, y; + for (v = 0; v < 8; v++) { + for (u = 0; u < 8; u++) { + for (x = 0; x < 8; x++) { + for (y = 0; y < 8; y++) { + output[v][u] += input[x][y] * + Math.cos(((double)(2*x + 1)*(double)u*Math.PI)/16)* + Math.cos(((double)(2*y + 1)*(double)v*Math.PI)/16); + } + } + output[v][u] *= (0.25)*((u == 0) ? (1.0/Math.sqrt(2)) : (double) 1.0)*((v == 0) ? (1.0/Math.sqrt(2)) : (double) 1.0); + } + } + return output; + } + + */ + /* + public int[] quantizeBlockExtreme(double inputData[][], int code) + { + int outputData[] = new int[NN]; + int i, j; + int index; + index = 0; + for (i = 0; i < 8; i++) { + for (j = 0; j < 8; j++) { + outputData[index] = (int)(Math.round(inputData[i][j] / (((int[]) (quantum[code]))[index]))); + index++; + } + } + + return outputData; + } + */ +} + +// This class was modified by James R. Weeks on 3/27/98. +// It now incorporates Huffman table derivation as in the C jpeg library +// from the IJG, Jpeg-6a. + +class Huffman { + private int bufferPutBits, bufferPutBuffer; + int imageHeight; + int imageWidth; + private int dc_matrix0[][]; + private int ac_matrix0[][]; + private int dc_matrix1[][]; + private int ac_matrix1[][]; + private int[][][] dc_matrix; + private int[][][] ac_matrix; + //private int code; + int numOfDCTables; + int numOfACTables; + final static int[] bitsDCluminance = { 0x00, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0 }; + final static int[] valDCluminance = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; + final static int[] bitsDCchrominance = { 0x01, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 0, 0, 0, 0, 0 }; + final static int[] valDCchrominance = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; + final static int[] bitsACluminance = { 0x10, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, + 4, 0, 0, 1, 0x7d }; + final static int[] valACluminance = { 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, + 0x05, 0x12, 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, 0x22, 0x71, + 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, + 0xd1, 0xf0, 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16, 0x17, 0x18, + 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x53, + 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x83, + 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, + 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, + 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, + 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, + 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, + 0xe9, 0xea, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa }; + final static int[] bitsACchrominance = { 0x11, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, + 4, 4, 0, 1, 2, 0x77 }; + final static int[] valACchrominance = { 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, + 0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, 0x13, 0x22, + 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, + 0x52, 0xf0, 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, 0xe1, 0x25, + 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, + 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, + 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, + 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, + 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, + 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, + 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, + 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, + 0xe8, 0xe9, 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa }; + + /* + * jpegNaturalOrder[i] is the natural-order position of the i'th element + * of zigzag order. + */ + final static int[] jpegNaturalOrder = { 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, + 25, 18, 11, 4, 5, 12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, + 21, 28, 35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51, + 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63, }; + + Huffman(int width, int height) { + initHuf(); + imageWidth = width; + imageHeight = height; + + } + + /** + * HuffmanBlockEncoder run length encodes and Huffman encodes the quantized + * data. + * + * @param out + * @param zigzag + * @param prec + * @param dcCode + * @param acCode + **/ + + void HuffmanBlockEncoder(OC out, int zigzag[], int prec, + int dcCode, int acCode) { + int temp, temp2, nbits, k, r, i; + + numOfDCTables = 2; + numOfACTables = 2; + + int[][] matrixDC = dc_matrix[dcCode]; + int[][] matrixAC = ac_matrix[acCode]; + + // The DC portion + + temp = temp2 = zigzag[0] - prec; + if (temp < 0) { + temp = -temp; + temp2--; + } + nbits = 0; + while (temp != 0) { + nbits++; + temp >>= 1; + } + // if (nbits > 11) nbits = 11; + bufferIt(out, matrixDC[nbits][0], matrixDC[nbits][1]); + // The arguments in bufferIt are code and size. + if (nbits != 0) { + bufferIt(out, temp2, nbits); + } + + // The AC portion + + r = 0; + + for (k = 1; k < 64; k++) { + if ((temp = zigzag[jpegNaturalOrder[k]]) == 0) { + r++; + } else { + while (r > 15) { + bufferIt(out, matrixAC[0xF0][0], matrixAC[0xF0][1]); + r -= 16; + } + temp2 = temp; + if (temp < 0) { + temp = -temp; + temp2--; + } + nbits = 1; + while ((temp >>= 1) != 0) { + nbits++; + } + i = (r << 4) + nbits; + bufferIt(out, matrixAC[i][0], matrixAC[i][1]); + bufferIt(out, temp2, nbits); + + r = 0; + } + } + + if (r > 0) { + bufferIt(out, matrixAC[0][0], matrixAC[0][1]); + } + + } + + // Uses an integer long (32 bits) buffer to store the Huffman encoded bits + // and sends them to out by the byte. + + void bufferIt(OC out, int code, int size) { + int putBuffer = code; + int putBits = bufferPutBits; + + putBuffer &= (1 << size) - 1; + putBits += size; + putBuffer <<= 24 - putBits; + putBuffer |= bufferPutBuffer; + + while (putBits >= 8) { + int c = ((putBuffer >> 16) & 0xFF); + out.writeByteAsInt(c); + if (c == 0xFF) { + out.writeByteAsInt(0); + } + putBuffer <<= 8; + putBits -= 8; + } + bufferPutBuffer = putBuffer; + bufferPutBits = putBits; + + } + + void flushBuffer(OC out) { + int putBuffer = bufferPutBuffer; + int putBits = bufferPutBits; + while (putBits >= 8) { + int c = ((putBuffer >> 16) & 0xFF); + out.writeByteAsInt(c); + if (c == 0xFF) { + out.writeByteAsInt(0); + } + putBuffer <<= 8; + putBits -= 8; + } + if (putBits > 0) { + int c = ((putBuffer >> 16) & 0xFF); + out.writeByteAsInt(c); + } + } + + /* + * Initialisation of the Huffman codes for Luminance and Chrominance. + * This code results in the same tables created in the IJG Jpeg-6a + * library. + */ + + private void initHuf() { + dc_matrix0 = new int[12][2]; + dc_matrix1 = new int[12][2]; + ac_matrix0 = new int[255][2]; + ac_matrix1 = new int[255][2]; + dc_matrix = AU.newInt3(2, -1); + ac_matrix = AU.newInt3(2, -1); + int p, l, i, lastp, si, code; + int[] huffsize = new int[257]; + int[] huffcode = new int[257]; + + /* + * init of the DC values for the chrominance + * [][0] is the code [][1] is the number of bit + */ + + p = 0; + for (l = 1; l <= 16; l++) { + // for (i = 1; i <= bitsDCchrominance[l]; i++) + for (i = bitsDCchrominance[l]; --i >= 0;) { + huffsize[p++] = l; //that's an "el", not a "one" + } + } + huffsize[p] = 0; + lastp = p; + + code = 0; + si = huffsize[0]; + p = 0; + while (huffsize[p] != 0) { + while (huffsize[p] == si) { + huffcode[p++] = code; + code++; + } + code <<= 1; + si++; + } + + for (p = 0; p < lastp; p++) { + dc_matrix1[valDCchrominance[p]][0] = huffcode[p]; + dc_matrix1[valDCchrominance[p]][1] = huffsize[p]; + } + + /* + * Init of the AC huffman code for the chrominance + * matrix [][][0] is the code & matrix[][][1] is the number of bit needed + */ + + p = 0; + for (l = 1; l <= 16; l++) { + for (i = bitsACchrominance[l]; --i >= 0;) + // for (i = 1; i <= bitsACchrominance[l]; i++) + { + huffsize[p++] = l; + } + } + huffsize[p] = 0; + lastp = p; + + code = 0; + si = huffsize[0]; + p = 0; + while (huffsize[p] != 0) { + while (huffsize[p] == si) { + huffcode[p++] = code; + code++; + } + code <<= 1; + si++; + } + + for (p = 0; p < lastp; p++) { + ac_matrix1[valACchrominance[p]][0] = huffcode[p]; + ac_matrix1[valACchrominance[p]][1] = huffsize[p]; + } + + /* + * init of the DC values for the luminance + * [][0] is the code [][1] is the number of bit + */ + p = 0; + for (l = 1; l <= 16; l++) { + // for (i = 1; i <= bitsDCluminance[l]; i++) + for (i = bitsDCluminance[l]; --i >= 0;) { + huffsize[p++] = l; + } + } + huffsize[p] = 0; + lastp = p; + + code = 0; + si = huffsize[0]; + p = 0; + while (huffsize[p] != 0) { + while (huffsize[p] == si) { + huffcode[p++] = code; + code++; + } + code <<= 1; + si++; + } + + for (p = 0; p < lastp; p++) { + dc_matrix0[valDCluminance[p]][0] = huffcode[p]; + dc_matrix0[valDCluminance[p]][1] = huffsize[p]; + } + + /* + * Init of the AC huffman code for luminance + * matrix [][][0] is the code & matrix[][][1] is the number of bit + */ + + p = 0; + for (l = 1; l <= 16; l++) { + // for (i = 1; i <= bitsACluminance[l]; i++) + for (i = bitsACluminance[l]; --i >= 0;) { + huffsize[p++] = l; + } + } + huffsize[p] = 0; + lastp = p; + + code = 0; + si = huffsize[0]; + p = 0; + while (huffsize[p] != 0) { + while (huffsize[p] == si) { + huffcode[p++] = code; + code++; + } + code <<= 1; + si++; + } + for (int q = 0; q < lastp; q++) { + ac_matrix0[valACluminance[q]][0] = huffcode[q]; + ac_matrix0[valACluminance[q]][1] = huffsize[q]; + } + + dc_matrix[0] = dc_matrix0; + dc_matrix[1] = dc_matrix1; + ac_matrix[0] = ac_matrix0; + ac_matrix[1] = ac_matrix1; + } + +} + +/* + * JpegInfo - Given an image, sets default information about it and divides + * it into its constituant components, downsizing those that need to be. + */ + +class JpegObj { + String comment; + int imageHeight; + int imageWidth; + int blockWidth[]; + int blockHeight[]; + + int precision = 8; + int numberOfComponents = 3; + float[][][] components; + int[] compID = { 1, 2, 3 }; + int[] hsampFactor = { 1, 1, 1 }; + int[] vsampFactor = { 1, 1, 1 }; + int[] qtableNumber = { 0, 1, 1 }; + int[] dctableNumber = { 0, 1, 1 }; + int[] actableNumber = { 0, 1, 1 }; + private boolean[] lastColumnIsDummy = { false, false, false }; + private boolean[] lastRowIsDummy = { false, false, false }; + int ss = 0; + int se = 63; + int ah = 0; + int al = 0; + private int compWidth[]; + private int compHeight[]; + private int maxHsampFactor; + private int maxVsampFactor; + + public JpegObj() { + components = AU.newFloat3(numberOfComponents, -1); + compWidth = new int[numberOfComponents]; + compHeight = new int[numberOfComponents]; + blockWidth = new int[numberOfComponents]; + blockHeight = new int[numberOfComponents]; + } + + /* + * This method creates and fills three arrays, Y, Cb, and Cr using the + * input image. + */ + + void getYCCArray(int[] pixels) { + // In order to minimize the chance that grabPixels will throw an exception + // it may be necessary to grab some pixels every few scanlines and process + // those before going for more. The time expense may be prohibitive. + // However, for a situation where memory overhead is a concern, this may be + // the only choice. + maxHsampFactor = 1; + maxVsampFactor = 1; + for (int y = 0; y < numberOfComponents; y++) { + maxHsampFactor = Math.max(maxHsampFactor, hsampFactor[y]); + maxVsampFactor = Math.max(maxVsampFactor, vsampFactor[y]); + } + for (int y = 0; y < numberOfComponents; y++) { + compWidth[y] = (((imageWidth % 8 != 0) ? ((int) Math + .ceil(imageWidth / 8.0)) * 8 : imageWidth) / maxHsampFactor) + * hsampFactor[y]; + if (compWidth[y] != ((imageWidth / maxHsampFactor) * hsampFactor[y])) { + lastColumnIsDummy[y] = true; + } + // results in a multiple of 8 for compWidth + // this will make the rest of the program fail for the unlikely + // event that someone tries to compress an 16 x 16 pixel image + // which would of course be worse than pointless + blockWidth[y] = (int) Math.ceil(compWidth[y] / 8.0); + compHeight[y] = (((imageHeight % 8 != 0) ? ((int) Math + .ceil(imageHeight / 8.0)) * 8 : imageHeight) / maxVsampFactor) + * vsampFactor[y]; + if (compHeight[y] != ((imageHeight / maxVsampFactor) * vsampFactor[y])) { + lastRowIsDummy[y] = true; + } + blockHeight[y] = (int) Math.ceil(compHeight[y] / 8.0); + } + float Y[][] = new float[compHeight[0]][compWidth[0]]; + float Cr1[][] = new float[compHeight[0]][compWidth[0]]; + float Cb1[][] = new float[compHeight[0]][compWidth[0]]; + //float Cb2[][] = new float[compHeight[1]][compWidth[1]]; + //float Cr2[][] = new float[compHeight[2]][compWidth[2]]; + for (int pt = 0, y = 0; y < imageHeight; ++y) { + for (int x = 0; x < imageWidth; ++x, pt++) { + int p = pixels[pt]; + int r = ((p >> 16) & 0xff); + int g = ((p >> 8) & 0xff); + int b = (p & 0xff); + // The following three lines are a more correct color conversion but + // the current conversion technique is sufficient and results in a higher + // compression rate. + // Y[y][x] = 16 + (float)(0.8588*(0.299 * (float)r + 0.587 * (float)g + 0.114 * (float)b )); + // Cb1[y][x] = 128 + (float)(0.8784*(-0.16874 * (float)r - 0.33126 * (float)g + 0.5 * (float)b)); + // Cr1[y][x] = 128 + (float)(0.8784*(0.5 * (float)r - 0.41869 * (float)g - 0.08131 * (float)b)); + Y[y][x] = (float) ((0.299 * r + 0.587 * g + 0.114 * b)); + Cb1[y][x] = 128 + (float) ((-0.16874 * r - 0.33126 * g + 0.5 * b)); + Cr1[y][x] = 128 + (float) ((0.5 * r - 0.41869 * g - 0.08131 * b)); + } + } + + // Need a way to set the H and V sample factors before allowing downsampling. + // For now (04/04/98) downsampling must be hard coded. + // Until a better downsampler is implemented, this will not be done. + // Downsampling is currently supported. The downsampling method here + // is a simple box filter. + + components[0] = Y; + // Cb2 = DownSample(Cb1, 1); + components[1] = Cb1; + // Cr2 = DownSample(Cr1, 2); + components[2] = Cr1; + } + /* + float[][] DownSample(float[][] C, int comp) + { + int inrow, incol; + int outrow, outcol; + float output[][]; + int bias; + inrow = 0; + incol = 0; + int cHeight = compHeight[comp]; + int cWidth = compWidth[comp]; + output = new float[cHeight][cWidth]; + + for (outrow = 0; outrow < cHeight; outrow++) { + bias = 1; + for (outcol = 0; outcol < cWidth; outcol++) { + output[outrow][outcol] = (C[inrow][incol++] + C[inrow++][incol--] + + C[inrow][incol++] + C[inrow--][incol++] + bias)/(float)4.0; + bias ^= 3; + } + inrow += 2; + incol = 0; + } + return output; + } + */ + +} diff --git a/src/javajs/img/PdfEncoder.java b/src/javajs/img/PdfEncoder.java new file mode 100644 index 0000000..c75b032 --- /dev/null +++ b/src/javajs/img/PdfEncoder.java @@ -0,0 +1,105 @@ +/* $RCSfile$ + * $Author: hansonr $ + * $Date: 2009-06-30 18:58:33 -0500 (Tue, 30 Jun 2009) $ + * $Revision: 11158 $ + * + * Copyright (C) 2002-2005 The Jmol Development Team + * + * Contact: jmol-developers@lists.sf.net + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + */ +package javajs.img; + +import java.util.Hashtable; +import java.util.Map; + +import javajs.export.PDFCreator; + +/** + * A relatively primitive PDF generator that just makes a document with an image + * in it. + * + */ +public class PdfEncoder extends ImageEncoder { + + private boolean isLandscape; + private PDFCreator pdf; + private String comment; + + public PdfEncoder() { + // for Class.forName + } + + @Override + protected void setParams(Map params) { + isLandscape = (quality > 1); + comment = "Jmol " + (String) params.get("comment"); + } + + @Override + protected void generate() throws Exception { + pdf = new PDFCreator(); + int pageWidth = 8 * 72; + int pageHeight = 11 * 72; + pdf.setOutputStream(out); + pdf.newDocument(pageWidth, pageHeight, isLandscape); // A4 or Letter + addMyImage(pageWidth, pageHeight); + Map ht = new Hashtable(); + if (comment != null) + ht.put("Producer", comment); + ht.put("Author", "JMol"); + ht.put("CreationDate", date); + pdf.addInfo(ht); + pdf.closeDocument(); + } + + + /** + * centered on the page + * + * @param pageWidth + * @param pageHeight + */ + private void addMyImage(int pageWidth, int pageHeight) { + pdf.addImageResource("img1", width, height, pixels, true); + int w = (isLandscape ? pageHeight : pageWidth); + int h = (isLandscape ? pageWidth : pageHeight); + int iw = width; + int ih = height; + if (iw > 0.9 * w) { + ih = (int) (ih * 0.9 * w / iw); + iw = (int) (w * 0.9); + } + if (ih > 0.9 * h) { + iw = (int) (iw * 0.9 * h / ih); + ih = (int) (h * 0.9); + } + int x = 0; + int y = 0; + int x1 = iw; + int y1 = ih; + if (w > iw) { + x = (w - iw) / 2; + x1 = iw + x; + } + if (h > ih) { + y = (h - ih) / 2; + y1 = ih + y; + } + pdf.drawImage("img1", x, y, x1, y1, 0, 0, width, height); + } + +} diff --git a/src/javajs/img/PngEncoder.java b/src/javajs/img/PngEncoder.java new file mode 100644 index 0000000..7c583a1 --- /dev/null +++ b/src/javajs/img/PngEncoder.java @@ -0,0 +1,453 @@ +/* $RCSfile$ + * $Author: nicove $ + * $Date: 2007-03-30 12:26:16 -0500 (Fri, 30 Mar 2007) $ + * $Revision: 7275 $ + * + * Copyright (C) 2002-2005 The Jmol Development Team + * + * Contact: jmol-developers@lists.sf.net + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + */ +package javajs.img; + +import java.util.Map; +import java.util.zip.Deflater; +import java.util.zip.DeflaterOutputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; + + + +/** + * + * Modified by Bob Hanson hansonr@stolaf.edu to be a subclass of ImageEncoder + * and to use javajs.util.OutputChannel instead of just returning bytes. Also includes: + * + * -- JavaScript-compatible image processing + * + * -- transparent background option + * + * -- more efficient calculation of needs for pngBytes + * + * -- option to use pre-created PNGJ image data (3/19/14; Jmol 14.1.12) + * + * -- PNGJ format: + * + * // IHDR chunk + * + * // tEXt chunk "Jmol type - <0000000pt>+<000000len>" + * + * // tEXt chunk "Software - Jmol " + * + * // tEXt chunk "Creation Time - " + * + * // tRNS chunk transparent color, if desired + * + * // IDAT chunk (image data) + * + * // IEND chunk + * + * // [JMOL ZIP FILE APPENDIX] + * + * Original Comment: + * + * PngEncoder takes a Java Image object and creates a byte string which can be + * saved as a PNG file. The Image is presumed to use the DirectColorModel. + * + * Thanks to Jay Denny at KeyPoint Software http://www.keypoint.com/ who let me + * develop this code on company time. + * + * You may contact me with (probably very-much-needed) improvements, comments, + * and bug fixes at: + * + * david@catcode.com + * + * @author J. David Eisenberg + * @author http://catcode.com/pngencoder/ + * @author Christian Ribeaud (christian.ribeaud@genedata.com) + * @author Bob Hanson (hansonr@stolaf.edu) + * + * @version 1.4, 31 March 2000 + */ +public class PngEncoder extends CRCEncoder { + + /** Constants for filters */ + public static final int FILTER_NONE = 0; + public static final int FILTER_SUB = 1; + public static final int FILTER_UP = 2; + public static final int FILTER_LAST = 2; + + private static final int PT_FIRST_TAG = 37; + + private boolean encodeAlpha; + private int filter = FILTER_NONE; + private int bytesPerPixel; + private int compressionLevel; + private String type; + private Integer transparentColor; + + private byte[] appData; + private String appPrefix; + private String comment; + private byte[] bytes; + + + public PngEncoder() { + super(); + } + + @Override + protected void setParams(Map params) { + if (quality < 0) + quality = (params.containsKey("qualityPNG") ? ((Integer) params + .get("qualityPNG")).intValue() : 2); + if (quality > 9) + quality = 9; + encodeAlpha = false; + filter = FILTER_NONE; + compressionLevel = quality; + transparentColor = (Integer) params.get("transparentColor"); + comment = (String) params.get("comment"); + type = (params.get("type") + "0000").substring(0, 4); + bytes = (byte[]) params.get("pngImgData"); + appData = (byte[]) params.get("pngAppData"); + appPrefix = (String) params.get("pngAppPrefix"); + } + + + + @Override + protected void generate() throws IOException { + if (bytes == null) { + if (!pngEncode()) { + out.cancel(); + return; + } + bytes = getBytes(); + } else { + dataLen = bytes.length; + } + int len = dataLen; + if (appData != null) { + setJmolTypeText(appPrefix, bytes, len, appData.length, + type); + out.write(bytes, 0, len); + len = (bytes = appData).length; + } + out.write(bytes, 0, len); + } + + + /** + * Creates an array of bytes that is the PNG equivalent of the current image, + * specifying whether to encode alpha or not. + * + * @return true if successful + * + */ + private boolean pngEncode() { + + byte[] pngIdBytes = { -119, 80, 78, 71, 13, 10, 26, 10 }; + + writeBytes(pngIdBytes); + //hdrPos = bytePos; + writeHeader(); + writeText(getApplicationText(appPrefix, type, 0, 0)); + + writeText("Software\0Jmol " + comment); + writeText("Creation Time\0" + date); + + if (!encodeAlpha && transparentColor != null) + writeTransparentColor(transparentColor.intValue()); + //dataPos = bytePos; + return writeImageData(); + } + + /** + * Fill in the Jmol type text area with number of bytes of PNG data and number + * of bytes of Jmol state data and fix checksum. + * + * If we do not do this, then the checksum will be wrong, and Jmol and some + * other programs may not be able to read the PNG image. + * + * This was corrected for Jmol 12.3.30. Between 12.3.7 and 12.3.29, PNG files + * created by Jmol have incorrect checksums. + * + * @param prefix + * + * @param b + * @param nPNG + * @param nState + * @param type + */ + private static void setJmolTypeText(String prefix, byte[] b, int nPNG, int nState, String type) { + String s = "tEXt" + getApplicationText(prefix, type, nPNG, nState); + CRCEncoder encoder = new PngEncoder(); + byte[] test = s.substring(0, 4 + prefix.length()).getBytes(); + for (int i = test.length; -- i >= 0;) + if (b[i + PT_FIRST_TAG] != test[i]) { + System.out.println("image is not of the right form; appending data, but not adding tEXt tag."); + return; + } + encoder.setData(b, PT_FIRST_TAG); + encoder.writeString(s); + encoder.writeCRC(); + } + + private static String getApplicationText(String prefix, String type, int nPNG, int nState) { + String sPNG = "000000000" + nPNG; + sPNG = sPNG.substring(sPNG.length() - 9); + String sState = "000000000" + nState; + sState = sState.substring(sState.length() - 9); + return prefix + "\0" + type + (type.equals("PNG") ? "0" : "") + sPNG + "+" + + sState; + } + + // /** + // * Set the filter to use + // * + // * @param whichFilter from constant list + // */ + // public void setFilter(int whichFilter) { + // this.filter = (whichFilter <= FILTER_LAST ? whichFilter : FILTER_NONE); + // } + + // /** + // * Retrieve filtering scheme + // * + // * @return int (see constant list) + // */ + // public int getFilter() { + // return filter; + // } + + // /** + // * Set the compression level to use + // * + // * @param level 0 through 9 + // */ + // public void setCompressionLevel(int level) { + // if ((level >= 0) && (level <= 9)) { + // this.compressionLevel = level; + // } + // } + + // /** + // * Retrieve compression level + // * + // * @return int in range 0-9 + // */ + // public int getCompressionLevel() { + // return compressionLevel; + // } + + /** + * Write a PNG "IHDR" chunk into the pngBytes array. + */ + private void writeHeader() { + + writeInt4(13); + startPos = bytePos; + writeString("IHDR"); + writeInt4(width); + writeInt4(height); + writeByte(8); // bit depth + writeByte(encodeAlpha ? 6 : 2); // color type or direct model + writeByte(0); // compression method + writeByte(0); // filter method + writeByte(0); // no interlace + writeCRC(); + } + + private void writeText(String msg) { + writeInt4(msg.length()); + startPos = bytePos; + writeString("tEXt" + msg); + writeCRC(); + } + + /** + * Write a PNG "tRNS" chunk into the pngBytes array. + * + * @param icolor + */ + private void writeTransparentColor(int icolor) { + + writeInt4(6); + startPos = bytePos; + writeString("tRNS"); + writeInt2((icolor >> 16) & 0xFF); + writeInt2((icolor >> 8) & 0xFF); + writeInt2(icolor & 0xFF); + writeCRC(); + } + + private byte[] scanLines; // the scan lines to be compressed + private int byteWidth; // width * bytesPerPixel + + //private int hdrPos, dataPos, endPos; + //private byte[] priorRow; + //private byte[] leftBytes; + + + /** + * Write the image data into the pngBytes array. This will write one or more + * PNG "IDAT" chunks. In order to conserve memory, this method grabs as many + * rows as will fit into 32K bytes, or the whole image; whichever is less. + * + * + * @return true if no errors; false if error grabbing pixels + */ + private boolean writeImageData() { + + bytesPerPixel = (encodeAlpha ? 4 : 3); + byteWidth = width * bytesPerPixel; + + int scanWidth = byteWidth + 1; // the added 1 is for the filter byte + + //boolean doFilter = (filter != FILTER_NONE); + + int rowsLeft = height; // number of rows remaining to write + //int startRow = 0; // starting row to process this time through + int nRows; // how many rows to grab at a time + + int scanPos; // where we are in the scan lines + + Deflater deflater = new Deflater(compressionLevel); + ByteArrayOutputStream outBytes = new ByteArrayOutputStream(1024); + + DeflaterOutputStream compBytes = new DeflaterOutputStream(outBytes, + deflater); + + int pt = 0; // overall image byte pointer + + // Jmol note: The entire image has been stored in pixels[] already + + try { + while (rowsLeft > 0) { + nRows = Math.max(1, Math.min(32767 / scanWidth, rowsLeft)); + scanLines = new byte[scanWidth * nRows]; + // if (doFilter) + // switch (filter) { + // case FILTER_SUB: + // leftBytes = new byte[16]; + // break; + // case FILTER_UP: + // priorRow = new byte[scanWidth - 1]; + // break; + // } + int nPixels = width * nRows; + scanPos = 0; + //startPos = 1; + for (int i = 0; i < nPixels; i++, pt++) { + if (i % width == 0) { + scanLines[scanPos++] = (byte) filter; + //startPos = scanPos; + } + scanLines[scanPos++] = (byte) ((pixels[pt] >> 16) & 0xff); + scanLines[scanPos++] = (byte) ((pixels[pt] >> 8) & 0xff); + scanLines[scanPos++] = (byte) ((pixels[pt]) & 0xff); + if (encodeAlpha) { + scanLines[scanPos++] = (byte) ((pixels[pt] >> 24) & 0xff); + } + // if (doFilter && i % width == width - 1) { + // switch (filter) { + // case FILTER_SUB: + // filterSub(); + // break; + // case FILTER_UP: + // filterUp(); + // break; + // } + // } + } + + /* + * Write these lines to the output area + */ + compBytes.write(scanLines, 0, scanPos); + + //startRow += nRows; + rowsLeft -= nRows; + } + compBytes.close(); + + /* + * Write the compressed bytes + */ + byte[] compressedLines = outBytes.toByteArray(); + writeInt4(compressedLines.length); + startPos = bytePos; + writeString("IDAT"); + writeBytes(compressedLines); + writeCRC(); + writeEnd(); + deflater.finish(); + return true; + } catch (IOException e) { + System.err.println(e.toString()); + return false; + } + } + + /** + * Write a PNG "IEND" chunk into the pngBytes array. + */ + private void writeEnd() { + writeInt4(0); + startPos = bytePos; + writeString("IEND"); + writeCRC(); + } + + ///** + //* Perform "sub" filtering on the given row. + //* Uses temporary array leftBytes to store the original values + //* of the previous pixels. The array is 16 bytes long, which + //* will easily hold two-byte samples plus two-byte alpha. + //* + //*/ + //private void filterSub() { + // int offset = bytesPerPixel; + // int actualStart = startPos + offset; + // int leftInsert = offset; + // int leftExtract = 0; + // //byte current_byte; + // + // for (int i = actualStart; i < startPos + byteWidth; i++) { + // leftBytes[leftInsert] = scanLines[i]; + // scanLines[i] = (byte) ((scanLines[i] - leftBytes[leftExtract]) % 256); + // leftInsert = (leftInsert + 1) % 0x0f; + // leftExtract = (leftExtract + 1) % 0x0f; + // } + //} + // + ///** + //* Perform "up" filtering on the given row. Side effect: refills the prior row + //* with current row + //* + //*/ + //private void filterUp() { + // int nBytes = width * bytesPerPixel; + // for (int i = 0; i < nBytes; i++) { + // int pt = startPos + i; + // byte b = scanLines[pt]; + // scanLines[pt] = (byte) ((scanLines[pt] - priorRow[i]) % 256); + // priorRow[i] = b; + // } + //} + +} diff --git a/src/javajs/img/PpmEncoder.java b/src/javajs/img/PpmEncoder.java new file mode 100644 index 0000000..4bdc980 --- /dev/null +++ b/src/javajs/img/PpmEncoder.java @@ -0,0 +1,60 @@ +// PpmEncoder - write out an image as a PPM +// +// Copyright (C)1996,1998 by Jef Poskanzer . All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +// SUCH DAMAGE. +// +// Visit the ACME Labs Java page for up-to-date versions of this and other +// fine Java utilities: http://www.acme.com/java/ + +package javajs.img; + +import java.util.Map; + + +/** + * see http://netpbm.sourceforge.net/doc/ppm.html + */ +public class PpmEncoder extends ImageEncoder { + + @Override + protected void setParams(Map params) { + // no params + } + + @Override + protected void generate() { + putString("P6\n"); + putString(width + " " + height + "\n"); + putString("255\n"); + byte[] ppmPixels = new byte[width * 3]; + for (int pt = 0, row = 0; row < height; ++row) { + for (int col = 0, j = 0; col < width; ++col, pt++) { + int p = pixels[pt]; + ppmPixels[j++] = (byte) ((p >> 16) & 0xff); + ppmPixels[j++] = (byte) ((p >> 8) & 0xff); + ppmPixels[j++] = (byte) (p & 0xff); + } + out.write(ppmPixels, 0, ppmPixels.length); + } + } +} diff --git a/src/javajs/swing/AbstractButton.java b/src/javajs/swing/AbstractButton.java new file mode 100644 index 0000000..3ea6ab9 --- /dev/null +++ b/src/javajs/swing/AbstractButton.java @@ -0,0 +1,118 @@ +package javajs.swing; + +import javajs.awt.Component; + +import javajs.api.SC; + +public abstract class AbstractButton extends JComponent implements SC { + + Object itemListener; + Object applet; + String htmlName; + boolean selected; + + private SC popupMenu; + + private String icon; + + protected AbstractButton(String type) { + super(type); + enabled = true; + } + + @Override + public void setSelected(boolean selected) { + this.selected = selected; + /** + * @j2sNative + * + * SwingController.setSelected(this); + * + */ + { + } + } + + @Override + public boolean isSelected() { + return selected; + } + + @Override + public void addItemListener(Object listener) { + itemListener = listener; + } + + @Override + public Object getIcon() { + return icon; + } + + @Override + public void setIcon(Object icon) { + this.icon = (String) icon; + } + + @Override + public void init(String text, Object icon, String actionCommand, SC popupMenu) { + this.text = text; + this.icon = (String) icon; + this.actionCommand = actionCommand; + this.popupMenu = popupMenu; + /** + * @j2sNative + * + * SwingController.initMenuItem(this); + * + */ + { + } + } + + public SC getTopPopupMenu() { + // note that JMenu.getPopupMenu refers to ITSELF, not the main one) + return popupMenu; + } + + @Override + public void add(SC item) { + addComponent((Component) item); + } + + @Override + public void insert(SC subMenu, int index) { + // JMenu, JPopupMenu only, but implemented here as well + // for simplicity + insertComponent((Component) subMenu, index); + } + + @Override + public Object getPopupMenu() { + // JMenu only + return null; + } + + protected String getMenuHTML() { + String label = (this.icon != null ? this.icon + : this.text != null ? this.text + : null); + String s = (label == null ? "" : "

  • " + label + "" + + htmlMenuOpener("ul")); + int n = getComponentCount(); + if (n > 0) + for(int i = 0; i < n; i++) + s += getComponent(i).toHTML(); + if (label != null) + s += "
  • "; + return s; + } + + protected String htmlMenuOpener(String type) { + return "<" + type + " id=\"" + this.id + "\"" + (this.enabled ? "" : getHtmlDisabled()) + ">"; + } + + protected String getHtmlDisabled() { + return " disabled=\"disabled\""; + } + +} diff --git a/src/javajs/swing/AbstractTableModel.java b/src/javajs/swing/AbstractTableModel.java new file mode 100644 index 0000000..a7c3540 --- /dev/null +++ b/src/javajs/swing/AbstractTableModel.java @@ -0,0 +1,13 @@ +package javajs.swing; + +import javajs.util.BS; +import javajs.util.SB; + + +abstract public interface AbstractTableModel extends TableColumn { + + TableColumn getColumn(int i); + + void toHTML(SB sb, String id, BS bsSelectedRows); + +} diff --git a/src/javajs/swing/ButtonGroup.java b/src/javajs/swing/ButtonGroup.java new file mode 100644 index 0000000..e457616 --- /dev/null +++ b/src/javajs/swing/ButtonGroup.java @@ -0,0 +1,18 @@ +package javajs.swing; + +import javajs.api.SC; +import javajs.awt.Component; + +public class ButtonGroup { + + private String id; + + public ButtonGroup() { + id = Component.newID("bg"); + } + + public void add(SC item) { + ((AbstractButton) item).htmlName = this.id; + } + +} diff --git a/src/javajs/swing/Cell.java b/src/javajs/swing/Cell.java new file mode 100644 index 0000000..dd53025 --- /dev/null +++ b/src/javajs/swing/Cell.java @@ -0,0 +1,25 @@ +package javajs.swing; + +public class Cell { + + private JComponent component; + private int colspan; + private int rowspan; + int textAlign; + private GridBagConstraints c; + + public Cell(JComponent btn, GridBagConstraints c) { + this.component = btn; + colspan = c.gridwidth; + rowspan = c.gridheight; // ignoring for now + this.c = c; + } + + public String toHTML(String id) { + String style = c.getStyle(false); + return "" + component.toHTML() + ""; + } + + +} diff --git a/src/javajs/swing/ColumnSelectionModel.java b/src/javajs/swing/ColumnSelectionModel.java new file mode 100644 index 0000000..ee3738c --- /dev/null +++ b/src/javajs/swing/ColumnSelectionModel.java @@ -0,0 +1,9 @@ +package javajs.swing; + +public interface ColumnSelectionModel { + + ListSelectionModel getSelectionModel(); + + TableColumn getColumn(int i); + +} diff --git a/src/javajs/swing/Document.java b/src/javajs/swing/Document.java new file mode 100644 index 0000000..5abfa9b --- /dev/null +++ b/src/javajs/swing/Document.java @@ -0,0 +1,7 @@ +package javajs.swing; + +public interface Document { + + void insertString(int i, String text, Object object); + +} diff --git a/src/javajs/swing/FlowLayout.java b/src/javajs/swing/FlowLayout.java new file mode 100644 index 0000000..301d9a8 --- /dev/null +++ b/src/javajs/swing/FlowLayout.java @@ -0,0 +1,7 @@ +package javajs.swing; + +import javajs.awt.LayoutManager; + +public class FlowLayout extends LayoutManager { + +} diff --git a/src/javajs/swing/Grid.java b/src/javajs/swing/Grid.java new file mode 100644 index 0000000..516110f --- /dev/null +++ b/src/javajs/swing/Grid.java @@ -0,0 +1,54 @@ +package javajs.swing; + +import javajs.util.AU; +import javajs.util.SB; + + +public class Grid { + + private int nrows; + private int ncols; + + private Cell[][] grid; + private String renderer; + + + Grid(int rows, int cols) { + grid = new Cell[0][0]; + } + + public void add(JComponent btn, GridBagConstraints c) { + if (c.gridx >= ncols) { + ncols = c.gridx + 1; + for (int i = 0; i < nrows; i++) { + grid[i] = (Cell[]) AU.ensureLength(grid[i], ncols * 2); + } + } + if (c.gridy >= nrows) { + Cell[][] g = new Cell[c.gridy * 2 + 1][]; + for (int i = 0; i < nrows; i++) + g[i] = grid[i]; + for (int i = g.length; --i >= nrows;) + g[i] = new Cell[ncols * 2 + 1]; + grid = g; + nrows = c.gridy + 1; + } + grid[c.gridy][c.gridx] = new Cell(btn, c); + } + + public String toHTML(String id) { + SB sb = new SB(); + id += "_grid"; + sb.append("\n"); + for (int i = 0; i < nrows; i++) { + String rowid = id + "_" + i; + sb.append("\n"); + for (int j = 0; j < ncols; j++) + if (grid[i][j] != null) + sb.append(grid[i][j].toHTML(rowid + "_" + j)); + sb.append(""); + } + sb.append("\n
    \n"); + return sb.toString(); + } +} diff --git a/src/javajs/swing/GridBagConstraints.java b/src/javajs/swing/GridBagConstraints.java new file mode 100644 index 0000000..578edc3 --- /dev/null +++ b/src/javajs/swing/GridBagConstraints.java @@ -0,0 +1,47 @@ +package javajs.swing; + +public class GridBagConstraints { + + public static final int NONE = 0; + public static final int CENTER = 10; + public static final int WEST = 17; + public static final int EAST = 13; + + public int gridx; + public int gridy; + public int gridwidth; + public int gridheight; + double weightx; + double weighty; + public int anchor; + public int fill; + Insets insets; + public int ipadx; + public int ipady; + + public GridBagConstraints(int gridx, int gridy, int gridwidth, + int gridheight, double weightx, double weighty, int anchor, int fill, + Insets insets, int ipadx, int ipady) { + this.gridx = gridx; + this.gridy = gridy; + this.gridwidth = gridwidth; + this.gridheight = gridheight; + this.weightx = weightx; + this.weighty = weighty; + this.anchor = anchor; + this.fill = fill; + if (insets == null) + insets = new Insets(0, 0, 0, 0); + this.insets = insets; + this.ipadx = ipadx; + this.ipady = ipady; + } + + String getStyle(boolean margins) { + return "style='" + (margins ? + "margin:" + insets.top + "px " + (ipady + insets.right) + "px " + + insets.bottom + "px " + (ipadx + insets.left) + "px;" + : "text-align:" + (anchor == EAST ? "right" : anchor == WEST? "left" : "center")) + "'"; + } + +} diff --git a/src/javajs/swing/GridBagLayout.java b/src/javajs/swing/GridBagLayout.java new file mode 100644 index 0000000..35b459a --- /dev/null +++ b/src/javajs/swing/GridBagLayout.java @@ -0,0 +1,7 @@ +package javajs.swing; + +import javajs.awt.LayoutManager; + +public class GridBagLayout extends LayoutManager { + +} diff --git a/src/javajs/swing/Insets.java b/src/javajs/swing/Insets.java new file mode 100644 index 0000000..1ebed19 --- /dev/null +++ b/src/javajs/swing/Insets.java @@ -0,0 +1,14 @@ +package javajs.swing; + +public class Insets { + + int top, left, bottom, right; + + public Insets(int top, int left, int bottom, int right) { + this.top = top; + this.left = left; + this.bottom = bottom; + this.right = right; + } + +} diff --git a/src/javajs/swing/JButton.java b/src/javajs/swing/JButton.java new file mode 100644 index 0000000..77118b7 --- /dev/null +++ b/src/javajs/swing/JButton.java @@ -0,0 +1,16 @@ +package javajs.swing; + +import javajs.util.SB; + +public class JButton extends AbstractButton { + + public JButton() { + super("btnJB"); + } + @Override + public String toHTML() { + SB sb = new SB(); + sb.append(""); + return sb.toString(); + } +} diff --git a/src/javajs/swing/JCheckBox.java b/src/javajs/swing/JCheckBox.java new file mode 100644 index 0000000..4cd97e7 --- /dev/null +++ b/src/javajs/swing/JCheckBox.java @@ -0,0 +1,19 @@ +package javajs.swing; + +public class JCheckBox extends AbstractButton { + + public JCheckBox() { + super("chkJCB"); + } + + @Override + public String toHTML() { + String s = ""; + return s; + } + + +} diff --git a/src/javajs/swing/JCheckBoxMenuItem.java b/src/javajs/swing/JCheckBoxMenuItem.java new file mode 100644 index 0000000..4f0fecb --- /dev/null +++ b/src/javajs/swing/JCheckBoxMenuItem.java @@ -0,0 +1,10 @@ +package javajs.swing; + +public class JCheckBoxMenuItem extends JMenuItem { + + + public JCheckBoxMenuItem() { + super("chk", TYPE_CHECKBOX); + } + +} diff --git a/src/javajs/swing/JComboBox.java b/src/javajs/swing/JComboBox.java new file mode 100644 index 0000000..73c6db5 --- /dev/null +++ b/src/javajs/swing/JComboBox.java @@ -0,0 +1,47 @@ +package javajs.swing; + +import javajs.util.SB; + +public class JComboBox extends AbstractButton { + + private String[] info; + private int selectedIndex; + + public JComboBox(String[] info){ + super("cmbJCB"); + this.info = info; + } + + public void setSelectedIndex(int i) { + selectedIndex = i; + /** + * @j2sNative + * + * SwingController.setSelectedIndex(this); + * + */ + { + } + } + + public int getSelectedIndex() { + return selectedIndex; + } + + public Object getSelectedItem() { + return (selectedIndex < 0 ? null : info[selectedIndex]); + } + + @Override + public String toHTML() { + SB sb = new SB(); + sb.append("\n\n"); + return sb.toString(); + } + + + +} diff --git a/src/javajs/swing/JComponent.java b/src/javajs/swing/JComponent.java new file mode 100644 index 0000000..2f17ba0 --- /dev/null +++ b/src/javajs/swing/JComponent.java @@ -0,0 +1,45 @@ +package javajs.swing; + +import javajs.awt.Container; + +public abstract class JComponent extends Container { + + protected boolean autoScrolls; + protected String actionCommand; + protected Object actionListener; + + protected JComponent(String type) { + super(type); + } + + public void setAutoscrolls(boolean b) { + autoScrolls = b; + } + + /** + * Note that it will be the job of the JavaScript on the + * page to do with actionListener what is desired. + * + * In javax.swing, these methods are in AbstractButton, but + * this is better for javajs.swing, reducing the duplication + * of JTextField's actionListener business. + * + * @param listener + * + */ + public void addActionListener(Object listener) { + actionListener = listener; + } + + public String getActionCommand() { + return actionCommand; + } + + public void setActionCommand(String actionCommand) { + this.actionCommand = actionCommand; + } + + + + +} diff --git a/src/javajs/swing/JComponentImp.java b/src/javajs/swing/JComponentImp.java new file mode 100644 index 0000000..7693fc4 --- /dev/null +++ b/src/javajs/swing/JComponentImp.java @@ -0,0 +1,18 @@ +package javajs.swing; + +/** + * implementation of a JComponent + * + */ +class JComponentImp extends JComponent { + + protected JComponentImp(String type) { + super(type); + } + + @Override + public String toHTML() { + return null; + } + +} diff --git a/src/javajs/swing/JContentPane.java b/src/javajs/swing/JContentPane.java new file mode 100644 index 0000000..b118fb1 --- /dev/null +++ b/src/javajs/swing/JContentPane.java @@ -0,0 +1,23 @@ +package javajs.swing; + +import javajs.util.SB; + +public class JContentPane extends JComponent { + + public JContentPane() { + super("JCP"); + } + + @Override + public String toHTML() { + SB sb = new SB(); + sb.append("\n
    \n"); + if (list != null) + for (int i = 0; i < list.size(); i++) + sb.append(list.get(i).toHTML()); + sb.append("\n
    \n"); + return sb.toString(); + } + +} diff --git a/src/javajs/swing/JDialog.java b/src/javajs/swing/JDialog.java new file mode 100644 index 0000000..1720214 --- /dev/null +++ b/src/javajs/swing/JDialog.java @@ -0,0 +1,126 @@ +package javajs.swing; + +import javajs.awt.Color; +import javajs.awt.Container; +import javajs.util.SB; + + +/** + * There is really no need here for awt.Dialog. + * We would not use FileDialog in an HTML5 context anyway. + * + */ +public class JDialog extends Container { + + private static final int headerHeight = 25; + private int defaultWidth = 600; + private int defaultHeight = 300; + + private JContentPane contentPane; + private String title; + private String html; + private int zIndex = 9000; + + public void setZIndex(int zIndex) { + this.zIndex = zIndex; + } + + int[] loc; + + public JDialog() { + super("JD"); + add(contentPane = new JContentPane()); + setBackground(Color.get3(210, 210, 240)); + contentPane.setBackground(Color.get3(230, 230, 230)); + } + + public void setLocation(int[] loc) { + this.loc = loc; + } + + public JContentPane getContentPane() { + return contentPane; + } + + public void setTitle(String title) { + this.title = title; + } + + public void pack() { + html = null; + } + + public void validate() { + html = null; + } + + @Override + public void setVisible(boolean tf) { + if (tf && html == null) + setDialog(); + super.setVisible(tf); + } + + public void dispose() { + { + + /** + * @j2sNative + * + * SwingController.dispose(this); + * + */ + { + } + + } + } + + @Override + public void repaint() { + setDialog(); + } + + /** + * Set it into DOM, but don't show it yet. + * this.loc, this.manager, this.id, etc. + * + */ + private void setDialog() { + html = toHTML(); + /** + * @j2sNative + * + * SwingController.setDialog(this); + * + * + */ + { + System.out.println(html); + } + } + + @Override + public String toHTML() { + renderWidth = getSubcomponentWidth(); + if (renderWidth == 0) + renderWidth = defaultWidth; + renderHeight = contentPane.getSubcomponentHeight(); + if (renderHeight == 0) + renderHeight = defaultHeight; + int h = renderHeight - headerHeight; + SB sb = new SB(); + sb.append("\n
    \n"); + sb.append("\n
    " + +"" + title + "" + + "
    \n"); + sb.append("\n
    \n"); + sb.append(contentPane.toHTML()); + sb.append("\n
    \n"); + return sb.toString(); + } + + + +} diff --git a/src/javajs/swing/JEditorPane.java b/src/javajs/swing/JEditorPane.java new file mode 100644 index 0000000..c0e365b --- /dev/null +++ b/src/javajs/swing/JEditorPane.java @@ -0,0 +1,26 @@ +package javajs.swing; + +import javajs.util.SB; + +/** + * A simple implementation of a Swing JTextPane. + * Operates as its own Document; no attributes + * + * @author hansonr + * + */ +public class JEditorPane extends JComponent { + + public JEditorPane() { + super("txtJEP"); + text = ""; + } + + @Override + public String toHTML() { + SB sb = new SB(); + sb.append(""); + return sb.toString(); + } + +} diff --git a/src/javajs/swing/JLabel.java b/src/javajs/swing/JLabel.java new file mode 100644 index 0000000..70080f5 --- /dev/null +++ b/src/javajs/swing/JLabel.java @@ -0,0 +1,22 @@ +package javajs.swing; + +import javajs.util.SB; + +public class JLabel extends JComponent { + + public JLabel(String text) { + super("lblJL"); + this.text = text; + } + + @Override + public String toHTML() { + SB sb = new SB(); + sb.append(""); + sb.append(text); + sb.append(""); + return sb.toString(); + } + + +} diff --git a/src/javajs/swing/JMenu.java b/src/javajs/swing/JMenu.java new file mode 100644 index 0000000..57bfade --- /dev/null +++ b/src/javajs/swing/JMenu.java @@ -0,0 +1,28 @@ +package javajs.swing; + +import javajs.awt.Component; + +public class JMenu extends JMenuItem { + + public JMenu() { + super("mnu",TYPE_MENU); + } + + public int getItemCount() { + return getComponentCount(); + } + + public Component getItem(int i) { + return getComponent(i); + } + + @Override + public Object getPopupMenu() { + return this; + } + + @Override + public String toHTML() { + return getMenuHTML(); + } +} diff --git a/src/javajs/swing/JMenuItem.java b/src/javajs/swing/JMenuItem.java new file mode 100644 index 0000000..643da95 --- /dev/null +++ b/src/javajs/swing/JMenuItem.java @@ -0,0 +1,46 @@ +package javajs.swing; + +public class JMenuItem extends AbstractButton { + + public final int btnType; + + public static final int TYPE_SEPARATOR = 0; + public static final int TYPE_BUTTON = 1; + public static final int TYPE_CHECKBOX = 2; + public static final int TYPE_RADIO = 3; + public static final int TYPE_MENU = 4; + + + public JMenuItem(String text) { + super("btn"); + setText(text); + btnType = (text == null ? 0 : 1); + } + + public JMenuItem(String type, int i) { + super(type); + btnType = i; + } + + @Override + public String toHTML() { + return htmlMenuOpener("li") + + (text == null ? "" : "" + htmlLabel() + "") + ""; + } + + @Override + protected String getHtmlDisabled() { + return " class=\"ui-state-disabled\""; + } + + private String htmlLabel() { + return (btnType == TYPE_BUTTON ? text + : ""); + } + + +} diff --git a/src/javajs/swing/JPanel.java b/src/javajs/swing/JPanel.java new file mode 100644 index 0000000..64f08a2 --- /dev/null +++ b/src/javajs/swing/JPanel.java @@ -0,0 +1,67 @@ +package javajs.swing; + +import javajs.awt.BorderLayout; +import javajs.awt.LayoutManager; +import javajs.util.SB; + +public class JPanel extends JComponent { + + //private LayoutManager layoutManager; + + private Grid grid; + + private int nElements; + private JComponent last; + + + /** + * @param manager ignored. we just use the layout designations with a grid + */ + public JPanel(LayoutManager manager) { + super("JP"); + //this.layoutManager = manager; + grid = new Grid(10,10); + } + + public void add(JComponent btn, Object c) { + last = (++nElements == 1 ? btn : null); + if (c instanceof String) { + if (c.equals(BorderLayout.NORTH)) + c = new GridBagConstraints(0, 0, 3, 1, 0, 0, GridBagConstraints.CENTER, + 0, null, 0, 0); + else if (c.equals(BorderLayout.SOUTH)) + c = new GridBagConstraints(0, 2, 3, 1, 0, 0, GridBagConstraints.CENTER, + 0, null, 0, 0); + else if (c.equals(BorderLayout.EAST)) + c = new GridBagConstraints(2, 1, 1, 1, 0, 0, GridBagConstraints.EAST, + 0, null, 0, 0); + else if (c.equals(BorderLayout.WEST)) + c = new GridBagConstraints(0, 1, 1, 1, 0, 0, GridBagConstraints.WEST, + 0, null, 0, 0); + else + c = new GridBagConstraints(1, 1, 1, 1, 0, 0, GridBagConstraints.CENTER, + 0, null, 0, 0); + } + grid.add(btn, (GridBagConstraints) c); + } + + @Override + public String toHTML() { + if (last != null) { + // only one element + grid = new Grid(1, 1); + grid.add(last, new GridBagConstraints(0, 0, 1, 1, 0, 0, + GridBagConstraints.CENTER, 0, null, 0, 0)); + last = null; + } + SB sb = new SB(); + sb.append("\n
    \n"); + sb.append("\n"); + sb.append(grid.toHTML(id)); + sb.append(""); + sb.append("\n
    \n"); + return sb.toString(); + } +} diff --git a/src/javajs/swing/JPopupMenu.java b/src/javajs/swing/JPopupMenu.java new file mode 100644 index 0000000..47983c7 --- /dev/null +++ b/src/javajs/swing/JPopupMenu.java @@ -0,0 +1,70 @@ +package javajs.swing; + +import javajs.awt.Component; + +public class JPopupMenu extends AbstractButton { + + // note that in Java Swing JPopupMenu extends + // JComponent, but here we extend AbstractButton + // so that it shares the SwingComponent interface + + boolean tainted = true; + + static { + /** + * @j2sNative + * + * SwingController.setDraggable(javajs.swing.JPopupMenu); + */ + { + } + } + + public JPopupMenu(String name) { + super("mnu"); + this.name = name; + } + + public void setInvoker(Object applet) { + this.applet = applet; + /** + * @j2sNative + * + * SwingController.setMenu(this); + * + */ + {} + } + + /** + * @param applet + * @param x + * @param y + */ + public void show(Component applet, int x, int y) { + /** + * @j2sNative + * + * if (applet != null) + * this.tainted = true; + * SwingController.showMenu(this, x, y); + * + */ + {} + } + + public void disposeMenu() { + /** + * @j2sNative + * + * SwingController.disposeMenu(this); + */ + {} + } + + @Override + public String toHTML() { + return getMenuHTML(); + } + +} diff --git a/src/javajs/swing/JRadioButtonMenuItem.java b/src/javajs/swing/JRadioButtonMenuItem.java new file mode 100644 index 0000000..7187725 --- /dev/null +++ b/src/javajs/swing/JRadioButtonMenuItem.java @@ -0,0 +1,11 @@ +package javajs.swing; + +public class JRadioButtonMenuItem extends JMenuItem { + + protected boolean isRadio = true; + + public JRadioButtonMenuItem() { + super("rad",TYPE_RADIO); + } + +} diff --git a/src/javajs/swing/JScrollPane.java b/src/javajs/swing/JScrollPane.java new file mode 100644 index 0000000..a7c1e27 --- /dev/null +++ b/src/javajs/swing/JScrollPane.java @@ -0,0 +1,32 @@ +package javajs.swing; + +import javajs.awt.Component; +import javajs.awt.Dimension; +import javajs.util.SB; + +public class JScrollPane extends JComponent { + + public JScrollPane(JComponent component) { + super("JScP"); + add(component); + } + + @Override + public String toHTML() { + SB sb = new SB(); + sb.append("\n
    \n"); + if (list != null) { + Component c = list.get(0); + sb.append(c.toHTML()); + } + sb.append("\n
    \n"); + return sb.toString(); + } + + @Override + public void setMinimumSize(Dimension dimension) { + // TODO Auto-generated method stub + + } + +} diff --git a/src/javajs/swing/JSplitPane.java b/src/javajs/swing/JSplitPane.java new file mode 100644 index 0000000..3662cf9 --- /dev/null +++ b/src/javajs/swing/JSplitPane.java @@ -0,0 +1,88 @@ +package javajs.swing; + +import javajs.awt.Container; +import javajs.util.SB; + +public class JSplitPane extends JComponent { + + public static final int HORIZONTAL_SPLIT = 1; + boolean isH = true; + private int split = 1; + private Container right; + private Container left; + + public JSplitPane(int split) { + super("JSpP"); + this.split = split; + isH = (split == HORIZONTAL_SPLIT); + } + + public void setRightComponent(JComponent r) { + right = new JComponentImp(null); + right.add(r); + } + + public void setLeftComponent(JComponent l) { + left = new JComponentImp(null); + left.add(l); + } + + @Override + public int getSubcomponentWidth() { + int w = this.width; + if (w == 0) { + int wleft = left.getSubcomponentWidth(); + int wright = right.getSubcomponentWidth(); + if (wleft > 0 && wright > 0) { + if (isH) + w = wleft + wright; + else + w = Math.max(wleft, wright); + } + } + return w; + } + + @Override + public int getSubcomponentHeight() { + int h = this.height; + if (h == 0) { + int hleft = left.getSubcomponentHeight(); + int hright = right.getSubcomponentHeight(); + if (hleft > 0 && hright > 0) { + if (isH) + h = Math.max(hleft, hright); + else + h = hleft + hright; + } + } + return h; + } + + @Override + public String toHTML() { + if (left == null || right == null) + return ""; + boolean isH = (split == HORIZONTAL_SPLIT); + if (width == 0) + width = getSubcomponentWidth(); + if (height == 0) + height = getSubcomponentHeight(); + SB sb = new SB(); + sb.append("
    "); + if (isH) + sb.append("
    "); + else + sb.append("
    "); + sb.append(left.getComponents()[0].toHTML()); + if (isH) + sb.append("
    "); + else + sb.append("
    "); + sb.append(right.getComponents()[0].toHTML()); + sb.append("
    \n"); + return sb.toString(); + } + + +} diff --git a/src/javajs/swing/JTable.java b/src/javajs/swing/JTable.java new file mode 100644 index 0000000..afa6c03 --- /dev/null +++ b/src/javajs/swing/JTable.java @@ -0,0 +1,83 @@ +package javajs.swing; + +import javajs.awt.Dimension; +import javajs.util.BS; +import javajs.util.SB; + + +public class JTable extends JComponent implements ListSelectionModel, ColumnSelectionModel { + + private AbstractTableModel tableModel; + private BS bsSelectedCells; + private BS bsSelectedRows; + + boolean rowSelectionAllowed; + boolean cellSelectionEnabled; + Object selectionListener; + + public JTable(AbstractTableModel tableModel) { + super("JT"); + this.tableModel = tableModel; + this.bsSelectedCells = new BS(); + this.bsSelectedRows = new BS(); + } + + @Override + public ListSelectionModel getSelectionModel() { + return this; + } + + public ColumnSelectionModel getColumnModel() { + return this; + } + + public void setPreferredScrollableViewportSize(Dimension dimension) { + this.width = dimension.width; + this.height = dimension.height; + } + + public void clearSelection() { + bsSelectedCells.clearAll(); + bsSelectedRows.clearAll(); + } + + public void setRowSelectionAllowed(boolean b) { + rowSelectionAllowed = b; + } + + public void setRowSelectionInterval(int i, int j) { + bsSelectedRows.clearAll(); + bsSelectedRows.setBits(i, j); + bsSelectedCells.clearAll(); + } + + public void setCellSelectionEnabled(boolean enabled) { + cellSelectionEnabled = enabled; + } + + /** + * It will be the function of the JavaScript on the + * page to do with selectionListener what is desired. + * + * @param listener + * + */ + @Override + public void addListSelectionListener(Object listener) { + selectionListener = listener; + } + + @Override + public TableColumn getColumn(int i) { + return tableModel.getColumn(i); + } + + @Override + public String toHTML() { + SB sb = new SB(); + sb.append("\n"); + tableModel.toHTML(sb, id, bsSelectedRows); + sb.append("\n
    \n"); + return sb.toString(); + } +} diff --git a/src/javajs/swing/JTextField.java b/src/javajs/swing/JTextField.java new file mode 100644 index 0000000..069f646 --- /dev/null +++ b/src/javajs/swing/JTextField.java @@ -0,0 +1,21 @@ + +package javajs.swing; + +import javajs.util.SB; + +public class JTextField extends JComponent { + + public JTextField(String value) { + super("txtJT"); + text = value; + } + + @Override + public String toHTML() { + SB sb = new SB(); + sb.append(""); + return sb.toString(); + } + + +} diff --git a/src/javajs/swing/JTextPane.java b/src/javajs/swing/JTextPane.java new file mode 100644 index 0000000..fd3eeb8 --- /dev/null +++ b/src/javajs/swing/JTextPane.java @@ -0,0 +1,36 @@ +package javajs.swing; + +import javajs.util.SB; + +/** + * A simple implementation of a Swing JTextPane. + * Operates as its own Document; no attributes + * + * @author hansonr + * + */ +public class JTextPane extends JComponent implements Document { + + public JTextPane() { + super("txtJTP"); + text = ""; + } + + public Document getDocument() { + return this; + } + + @Override + public void insertString(int i, String s, Object object) { + i = Math.min(i, text.length()); + text = text.substring(0, i) + s + text.substring(i); + } + + @Override + public String toHTML() { + SB sb = new SB(); + sb.append(""); + return sb.toString(); + } + +} diff --git a/src/javajs/swing/ListSelectionModel.java b/src/javajs/swing/ListSelectionModel.java new file mode 100644 index 0000000..f1afd74 --- /dev/null +++ b/src/javajs/swing/ListSelectionModel.java @@ -0,0 +1,7 @@ +package javajs.swing; + +public interface ListSelectionModel { + + void addListSelectionListener(Object listener); + +} diff --git a/src/javajs/swing/SwingConstants.java b/src/javajs/swing/SwingConstants.java new file mode 100644 index 0000000..7211cac --- /dev/null +++ b/src/javajs/swing/SwingConstants.java @@ -0,0 +1,9 @@ +package javajs.swing; + +public class SwingConstants { + + public static final int LEFT = 2; + public static final int CENTER = 0; + public static final int RIGHT = 4; + +} diff --git a/src/javajs/swing/TableCellRenderer.java b/src/javajs/swing/TableCellRenderer.java new file mode 100644 index 0000000..f8679f0 --- /dev/null +++ b/src/javajs/swing/TableCellRenderer.java @@ -0,0 +1,7 @@ +package javajs.swing; + +public interface TableCellRenderer { + + String getCellStyle(int iRow, int iCol, GridBagConstraints c); + +} diff --git a/src/javajs/swing/TableColumn.java b/src/javajs/swing/TableColumn.java new file mode 100644 index 0000000..bd4e3a0 --- /dev/null +++ b/src/javajs/swing/TableColumn.java @@ -0,0 +1,7 @@ +package javajs.swing; + +public interface TableColumn { + + void setPreferredWidth(int n); + +} diff --git a/src/javajs/util/A4.java b/src/javajs/util/A4.java new file mode 100644 index 0000000..f27c02e --- /dev/null +++ b/src/javajs/util/A4.java @@ -0,0 +1,252 @@ +/* + Copyright (C) 1997,1998,1999 + Kenji Hiranabe, Eiwa System Management, Inc. + + This program is free software. + Implemented by Kenji Hiranabe(hiranabe@esm.co.jp), + conforming to the Java(TM) 3D API specification by Sun Microsystems. + + Permission to use, copy, modify, distribute and sell this software + and its documentation for any purpose is hereby granted without fee, + provided that the above copyright notice appear in all copies and + that both that copyright notice and this permission notice appear + in supporting documentation. Kenji Hiranabe and Eiwa System Management,Inc. + makes no representations about the suitability of this software for any + purpose. It is provided "AS IS" with NO WARRANTY. +*/ +package javajs.util; + +import java.io.Serializable; + +import javajs.api.JSONEncodable; +import javajs.util.T3; + + + +/** + * A 4 element axis angle represented by single precision floating point + * x,y,z,angle components. An axis angle is a rotation of angle (radians) about + * the vector (x,y,z). + * + * @version specification 1.1, implementation $Revision: 1.9 $, $Date: + * 2006/07/28 17:01:32 $ + * @author Kenji hiranabe + * + * additions by Bob Hanson hansonr@stolaf.edu 9/30/2012 + * for unique constructor and method names + * for the optimization of compiled JavaScript using Java2Script + */ +public class A4 implements JSONEncodable, Serializable { + + /* + * I assumed that the length of the axis vector is not significant. + */ + + /** + * The x coordinate. + */ + public float x; + + /** + * The y coordinate. + */ + public float y; + + /** + * The z coordinate. + */ + public float z; + + /** + * The angle. + */ + public float angle; + + /** + * Constructs and initializes a AxisAngle4f to (0,0,1,0). + */ + public A4() { + z = 1.0f; + } + + /** + * Constructs and initializes an AxisAngle4f from the specified x, y, z, and + * angle. + * + * @param x + * the x coordinate + * @param y + * the y coordinate + * @param z + * the z coordinate + * @param angle + * the angle. + * @return a + */ + public static A4 new4(float x, float y, float z, float angle) { + A4 a = new A4(); + a.set4(x, y, z, angle); + return a; + } + + /** + * Constructs and initializes a AxisAngle4f from the specified AxisAngle4f. + * + * @param a1 + * the AxisAngle4f containing the initialization x y z angle data + * @return a + */ + public static A4 newAA(A4 a1) { + A4 a = new A4(); + a.set4(a1.x, a1.y, a1.z, a1.angle); + return a; + } + + /** + * Constructs and initializes an AxisAngle4f from the specified axis and + * angle. + * + * @param axis + * the axis + * @param angle + * the angle + * @return a + */ + public static A4 newVA(V3 axis, float angle) { + A4 a = new A4(); + a.setVA(axis, angle); + return a; + } + + /** + * Sets the value of this AxisAngle4f to the specified axis and angle. + * + * @param axis + * the axis + * @param angle + * the angle + * @since Java 3D 1.2 + */ + public final void setVA(V3 axis, float angle) { + x = axis.x; + y = axis.y; + z = axis.z; + this.angle = angle; + } + + /** + * Sets the value of this axis angle to the specified x,y,z,angle. + * + * @param x + * the x coordinate + * @param y + * the y coordinate + * @param z + * the z coordinate + * @param angle + * the angle + */ + public final void set4(float x, float y, float z, float angle) { + this.x = x; + this.y = y; + this.z = z; + this.angle = angle; + } + + /** + * Sets the value of this axis angle to the value of axis angle t1. + * + * @param a + * the axis angle to be copied + */ + public final void setAA(A4 a) { + x = a.x; + y = a.y; + z = a.z; + angle = a.angle; + } + + + /** + * Sets the value of this axis-angle to the rotational component of the passed + * matrix. + * + * @param m1 + * the matrix3f + */ + public final void setM(M3 m1) { + setFromMat(m1.m00, m1.m01, m1.m02, m1.m10, m1.m11, m1.m12, m1.m20, m1.m21, + m1.m22); + } + + // helper method + private void setFromMat(double m00, double m01, double m02, double m10, + double m11, double m12, double m20, double m21, + double m22) { + // assuming M is normalized. + + double cos = (m00 + m11 + m22 - 1.0) * 0.5; + x = (float) (m21 - m12); + y = (float) (m02 - m20); + z = (float) (m10 - m01); + double sin = 0.5 * Math.sqrt(x * x + y * y + z * z); + if (sin == 0 && cos == 1) { + x = y = 0; + z = 1; + angle = 0; + } else { + angle = (float) Math.atan2(sin, cos); + } + + // no need to normalize + // x /= n; + // y /= n; + // z /= n; + } + + /** + * Returns a hash number based on the data values in this object. Two + * different AxisAngle4f objects with identical data values (ie, returns true + * for equals(AxisAngle4f) ) will return the same hash number. Two vectors + * with different data members may return the same hash value, although this + * is not likely. + */ + @Override + public int hashCode() { + return T3.floatToIntBits0(x) ^ T3.floatToIntBits0(y) + ^ T3.floatToIntBits0(z) ^ T3.floatToIntBits0(angle); + } + + /** + * Returns true if the Object o is of type AxisAngle4f and all of the data + * members of o1 are equal to the corresponding data members in this + * AxisAngle4f. + * + * @param o + * the object with which the comparison is made. + * @return T/F + */ + @Override + public boolean equals(Object o) { + if (!(o instanceof A4)) + return false; + A4 a1 = (A4) o; + return x == a1.x && y == a1.y && z == a1.z && angle == a1.angle; + } + + /** + * Returns a string that contains the values of this AxisAngle4f. The form is + * (x,y,z,angle). + * + * @return the String representation + */ + @Override + public String toString() { + return "(" + x + ", " + y + ", " + z + ", " + angle + ")"; + } + + @Override + public String toJSON() { + return "[" + x + "," + y + "," + z + "," + (float) (angle * 180.0 / Math.PI) + "]"; + } +} diff --git a/src/javajs/util/AU.java b/src/javajs/util/AU.java new file mode 100644 index 0000000..50c5912 --- /dev/null +++ b/src/javajs/util/AU.java @@ -0,0 +1,655 @@ +/* $RCSfile$ + * $Author: egonw $ + * $Date: 2005-11-10 09:52:44 -0600 (Thu, 10 Nov 2005) $ + * $Revision: 4255 $ + * + * Copyright (C) 2003-2005 The Jmol Development Team + * + * Contact: jmol-developers@lists.sf.net + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + */ +package javajs.util; + +// 4/23/15 BH getComponentType fix + +import java.lang.reflect.Array; + +import java.util.Arrays; +import java.util.Hashtable; +import java.util.Map; + + +final public class AU { + + /** + * Very important that this not be used with Int32Array or Float32Array, + * because it is not initialized to all zeros in MSIE 9. + * + * @param array + * @param minimumLength + * @return array + */ + public static Object ensureLength(Object array, int minimumLength) { + if (array != null && getLength(array) >= minimumLength) + return array; + return arrayCopyObject(array, minimumLength); + } + + public static String[] ensureLengthS(String[] array, int minimumLength) { + if (array != null && array.length >= minimumLength) + return array; + return arrayCopyS(array, minimumLength); + } + + public static float[] ensureLengthA(float[] array, int minimumLength) { + if (array != null && array.length >= minimumLength) + return array; + return arrayCopyF(array, minimumLength); + } + + public static int[] ensureLengthI(int[] array, int minimumLength) { + if (array != null && array.length >= minimumLength) + return array; + return arrayCopyI(array, minimumLength); + } + + public static short[] ensureLengthShort(short[] array, int minimumLength) { + if (array != null && array.length >= minimumLength) + return array; + return arrayCopyShort(array, minimumLength); + } + + public static byte[] ensureLengthByte(byte[] array, int minimumLength) { + if (array != null && array.length >= minimumLength) + return array; + return arrayCopyByte(array, minimumLength); + } + + /** + * Very important that this not be used with Int32Array or Float32Array, + * because it is not initialized to all zeros in MSIE 9. + * + * @param array + * @return array + */ + public static Object doubleLength(Object array) { + return arrayCopyObject(array, (array == null ? 16 : 2 * getLength(array))); + } + + public static String[] doubleLengthS(String[] array) { + return arrayCopyS(array, (array == null ? 16 : 2 * array.length)); + } + + public static float[] doubleLengthF(float[] array) { + return arrayCopyF(array, (array == null ? 16 : 2 * array.length)); + } + + public static int[] doubleLengthI(int[] array) { + return arrayCopyI(array, (array == null ? 16 : 2 * array.length)); + } + + public static short[] doubleLengthShort(short[] array) { + return arrayCopyShort(array, (array == null ? 16 : 2 * array.length)); + } + + public static byte[] doubleLengthByte(byte[] array) { + return arrayCopyByte(array, (array == null ? 16 : 2 * array.length)); + } + + public static boolean[] doubleLengthBool(boolean[] array) { + return arrayCopyBool(array, (array == null ? 16 : 2 * array.length)); + } + + public static Object deleteElements(Object array, int firstElement, + int nElements) { + if (nElements == 0 || array == null) + return array; + int oldLength = getLength(array); + if (firstElement >= oldLength) + return array; + int n = oldLength - (firstElement + nElements); + if (n < 0) + n = 0; + Object t = newInstanceO(array, firstElement + n); + if (firstElement > 0) + System.arraycopy(array, 0, t, 0, firstElement); + if (n > 0) + System.arraycopy(array, firstElement + nElements, t, firstElement, n); + return t; + } + + /** + * note -- cannot copy if array is null! + * + * @param array + * @param newLength + * @return array + */ + public static Object arrayCopyObject(Object array, int newLength) { + //System.out.println("ArrayUtil.copy " + newLength + " " + array + " "); + if (array == null) { + return null; // We can't allocate since we don't know the type of array + } + int oldLength = getLength(array); + if (newLength == oldLength) + return array; + Object t = newInstanceO(array, newLength); + System.arraycopy(array, 0, t, 0, oldLength < newLength ? oldLength + : newLength); + return t; + + } + + /** + * Very important that this not be used with Int32Array or Float32Array, + * because those need to be initialized to all zeros in MSIE 9, and + * MSIE 9 cannot distinguish Int32Array or Float32Array from Array. + * + * @param array + * @param n + * @return array + */ + private static Object newInstanceO(Object array, int n) { + /** + * @j2sNative + * + * if (!array.getClass().getComponentType) + * return new Array(n); + * + */ + { + return Array.newInstance(array.getClass().getComponentType(), n); + } + } + + public static int getLength(Object array) { + /** + * @j2sNative + * + * return array.length + * + */ + { + return Array.getLength(array); + } + } + + public static String[] arrayCopyS(String[] array, int newLength) { + if (newLength < 0) + newLength = array.length; + String[] t = new String[newLength]; + if (array != null) { + int oldLength = array.length; + System.arraycopy(array, 0, t, 0, oldLength < newLength ? oldLength + : newLength); + } + return t; + } + + public static int[][] arrayCopyII(int[][] array, int newLength) { + int[][] t = newInt2(newLength); + if (array != null) { + int oldLength = array.length; + System.arraycopy(array, 0, t, 0, oldLength < newLength ? oldLength + : newLength); + } + return t; + } + + public static T3[] arrayCopyPt(T3[] array, int newLength) { + if (newLength < 0) + newLength = array.length; + T3[] t = new T3[newLength]; + if (array != null) { + int oldLength = array.length; + System.arraycopy(array, 0, t, 0, oldLength < newLength ? oldLength + : newLength); + } + return t; + } + + public static float[] arrayCopyF(float[] array, int newLength) { + if (newLength < 0) + newLength = array.length; + float[] t = new float[newLength]; + if (array != null) { + int oldLength = array.length; + System.arraycopy(array, 0, t, 0, oldLength < newLength ? oldLength + : newLength); + } + return t; + } + + public static int[] arrayCopyI(int[] array, int newLength) { + if (newLength < 0) + newLength = array.length; + int[] t = new int[newLength]; + if (array != null) { + int oldLength = array.length; + System.arraycopy(array, 0, t, 0, oldLength < newLength ? oldLength + : newLength); + } + return t; + } + + /** + * a specialized method that allows copying from a starting point either + * to the end or to the middle (color schemes, especially) + * @param array + * @param i0 + * @param n + * @return array or null + */ + public static int[] arrayCopyRangeI(int[] array, int i0, int n) { + if (array == null) + return null; + int oldLength = array.length; + if (n == -1) n = oldLength; + if (n == -2) n = oldLength / 2; + n = n - i0; + int[] t = new int[n]; + System.arraycopy(array, i0, t, 0, n); + return t; + } + + public static int[] arrayCopyRangeRevI(int[] array, int i0, int n) { + if (array == null) + return null; + int[] t = arrayCopyRangeI(array, i0, n); + if (n < 0) + n = array.length; + for (int i = n / 2; --i >= 0;) + swapInt(t, i, n - 1 - i); + return t; + } + + public static short[] arrayCopyShort(short[] array, int newLength) { + if (newLength < 0) + newLength = array.length; + short[] t = new short[newLength]; + if (array != null) { + int oldLength = array.length; + System.arraycopy(array, 0, t, 0, oldLength < newLength ? oldLength + : newLength); + } + return t; + } + + public static byte[] arrayCopyByte(byte[] array, int newLength) { + if (newLength < 0) + newLength = array.length; + byte[] t = new byte[newLength]; + if (array != null) { + int oldLength = array.length; + System.arraycopy(array, 0, t, 0, oldLength < newLength ? oldLength + : newLength); + } + return t; + } + + public static boolean[] arrayCopyBool(boolean[] array, int newLength) { + if (newLength < 0) + newLength = array.length; + boolean[] t = new boolean[newLength]; + if (array != null) { + int oldLength = array.length; + System.arraycopy(array, 0, t, 0, oldLength < newLength ? oldLength + : newLength); + } + return t; + } + + public static void swapInt(int[] array, int indexA, int indexB) { + int t = array[indexA]; + array[indexA] = array[indexB]; + array[indexB] = t; + } + + /* + public static void swap(short[] array, int indexA, int indexB) { + short t = array[indexA]; + array[indexA] = array[indexB]; + array[indexB] = t; + } + + public static void swap(float[] array, int indexA, int indexB) { + float t = array[indexA]; + array[indexA] = array[indexB]; + array[indexB] = t; + } + */ + + public static String dumpArray(String msg, float[][] A, int x1, int x2, int y1, int y2) { + String s = "dumpArray: " + msg + "\n"; + for (int x = x1; x <= x2; x++) + s += "\t*" + x + "*"; + for (int y = y2; y >= y1; y--) { + s += "\n*" + y + "*"; + for (int x = x1; x <= x2; x++) + s += "\t" + (x < A.length && y < A[x].length ? A[x][y] : Float.NaN); + } + return s; + } + + public static String dumpIntArray(int[] A, int n) { + String str = ""; + for (int i = 0; i < n; i++) + str += " " + A[i]; + return str; + } + + public static String sortedItem(Lst v, int n) { + if (v.size() == 0) + return null; + if (v.size() == 1) + return v.get(0); + String[] keys = v.toArray(new String[v.size()]); + Arrays.sort(keys); + return keys[n % keys.length]; + } + + /** + * Helper method for creating a List[] without warnings. + * + * @param Type of objects in the list. + * @param size Array size. + * @return Array of List + */ + @SuppressWarnings("unchecked") + public static Lst[] createArrayOfArrayList(int size) { + return new Lst[size]; + } + + /** + * Helper method for creating a Map[] without warnings. + * + * @param Type of object for the keys in the map. + * @param Type of object for the values in the map. + * @param size Array size. + * @return Array of Map + */ + @SuppressWarnings("unchecked") + public static Map[] createArrayOfHashtable(int size) { + return new Hashtable[size]; + } + + public static void swap(Object[] o, int i, int j) { + Object oi = o[i]; + o[i] = o[j]; + o[j] = oi; + } + + public static float[][] newFloat2(int n) { + /** + * @j2sNative + * + * return Clazz.newArray(n, null); + * + */ + { + return new float[n][]; + } + } + + public static int[][] newInt2(int n) { + /** + * @j2sNative + * + * return Clazz.newArray(n, null); + * + */ + { + return new int[n][]; + } + } + + public static int[][][] newInt3(int nx, int ny) { + /** + * @j2sNative + * + * return Clazz.newArray(nx, null); + * + */ + { + return (ny < 0 ? new int[nx][][] : new int[nx][ny][]); + } + } + + public static float[][][] newFloat3(int nx, int ny) { + /** + * @j2sNative + * + * return Clazz.newArray(nx, null); + * + */ + { + return (ny < 0 ? new float[nx][][] : new float[nx][ny][]); + } + } + + public static int[][][][] newInt4(int n) { + /** + * @j2sNative + * + * return Clazz.newArray(n, null); + * + */ + { + return new int[n][][][]; + } + } + + public static short[][] newShort2(int n) { + /** + * @j2sNative + * + * return Clazz.newArray(n, null); + * + */ + { + return new short[n][]; + } + } + + public static byte[][] newByte2(int n) { + /** + * @j2sNative + * + * return Clazz.newArray(n, null); + * + */ + { + return new byte[n][]; + } + } + + public static double[][] newDouble2(int n) { + /** + * @j2sNative + * + * return Clazz.newArray(n, null); + * + */ + { + return new double[n][]; + } + } + + /** + * remove all keys from a map that start with given root + * @param map + * @param root + * @return number removed + */ + public static int removeMapKeys(Map map, String root) { + Lst list = new Lst(); + for (String key: map.keySet()) + if (key.startsWith(root)) + list.addLast(key); + for (int i = list.size(); --i >= 0;) + map.remove(list.get(i)); + return list.size(); + } + + public static boolean isAS(Object x) { + /** + * + * look also for array with first null element + * so untypable -- just call it a String[] + * (group3Lists, created in ModelLoader) + * + * @j2sNative + * return Clazz.isAS(x); + */ + { + return x instanceof String[]; + } + } + + public static boolean isASS(Object x) { + /** + * @j2sNative + * return Clazz.isASS(x); + */ + { + return x instanceof String[][]; + } + } + + public static boolean isAP(Object x) { + /** + * @j2sNative + * return Clazz.isAP(x); + */ + { + return x instanceof T3[]; + } + } + + public static boolean isAF(Object x) { + /** + * @j2sNative + * return Clazz.isAF(x); + */ + { + return x instanceof float[]; + } + } + + public static boolean isAFloat(Object x) { + /** + * @j2sNative + * return Clazz.isAFloat(x); + */ + { + return x instanceof Float[]; + } + } + + public static boolean isAD(Object x) { + /** + * @j2sNative + * return Clazz.isAF(x); + */ + { + return x instanceof double[]; + } + } + + public static boolean isADD(Object x) { + /** + * @j2sNative + * return Clazz.isAFF(x); + */ + { + return x instanceof double[][]; + } + } + + public static boolean isAB(Object x) { + /** + * @j2sNative + * return Clazz.isAI(x); + */ + { + return x instanceof byte[]; + } + } + + public static boolean isAI(Object x) { + /** + * @j2sNative + * return Clazz.isAI(x); + */ + { + return x instanceof int[]; + } + } + + public static boolean isAII(Object x) { + /** + * @j2sNative + * return Clazz.isAII(x); + */ + { + return (x instanceof int[][]); + } + } + + public static boolean isAFF(Object x) { + /** + * @j2sNative + * return Clazz.isAFF(x); + */ + { + return x instanceof float[][]; + } + } + + public static boolean isAFFF(Object x) { + /** + * @j2sNative + * return Clazz.isAFFF(x); + */ + { + return x instanceof float[][][]; + } + } + + /** + * Ensure that we have signed and not unsigned bytes + * coming out of any process, but particularly out of + * file reading. + * + * @param b + */ + public static void ensureSignedBytes(byte[] b) { + /** + * @j2sNative + * + * for (var i = b.length; --i >= 0;) { + * var j = b[i] & 0xFF; + * if (j >= 0x80) j -= 0x100; + * b[i] = j; + * } + * + */ + { + } + } + + +} diff --git a/src/javajs/util/AjaxURLConnection.java b/src/javajs/util/AjaxURLConnection.java new file mode 100644 index 0000000..1122bc9 --- /dev/null +++ b/src/javajs/util/AjaxURLConnection.java @@ -0,0 +1,89 @@ +package javajs.util; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.net.URLConnection; + +import javajs.api.JmolObjectInterface; + +/** + * + * A method to allow a JavaScript Ajax + * + */ +public class AjaxURLConnection extends URLConnection { + + protected AjaxURLConnection(URL url) { + super(url); + } + + byte[] bytesOut; + String postOut = ""; + + /** + * + * doAjax() is where the synchronous call to AJAX is to happen. or at least + * where we wait for the asynchronous call to return. This method should fill + * the dataIn field with either a string or byte array, or null if you want to + * throw an error. + * + * url, bytesOut, and postOut are all available for use + * + * the method is "private", but in JavaScript that can still be overloaded. + * Just set something to org.jmol.awtjs.JmolURLConnection.prototype.doAjax + * + * @return file data as a javajs.util.SB or byte[] depending upon the file + * type. + * + * + */ + @SuppressWarnings("null") + private Object doAjax() { + JmolObjectInterface jmol = null; + /** + * @j2sNative + * + * jmol = Jmol; + * + */ + { + } + return jmol._doAjax(url, postOut, bytesOut); + } + + @Override + public void connect() throws IOException { + // not expected to be used. + } + + public void outputBytes(byte[] bytes) { + // type = "application/octet-stream;"; + bytesOut = bytes; + } + + public void outputString(String post) { + postOut = post; + // type = "application/x-www-form-urlencoded"; + } + + @Override + public InputStream getInputStream() { + InputStream is = null; + Object o = doAjax(); + if (AU.isAB(o)) + is = Rdr.getBIS((byte[]) o); + else if (o instanceof SB) + is = Rdr.getBIS(Rdr.getBytesFromSB((SB)o)); + else if (o instanceof String) + is = Rdr.getBIS(((String) o).getBytes()); + return is; + } + /** + * @return javajs.util.SB or byte[], depending upon the file type + */ + public Object getContents() { + return doAjax(); + } + +} diff --git a/src/javajs/util/AjaxURLStreamHandler.java b/src/javajs/util/AjaxURLStreamHandler.java new file mode 100644 index 0000000..3d6d4d7 --- /dev/null +++ b/src/javajs/util/AjaxURLStreamHandler.java @@ -0,0 +1,53 @@ +package javajs.util; + +import java.io.IOException; +import java.net.URL; +import java.net.URLConnection; +import java.net.URLStreamHandler; + + + +/** + * + * A method to allow a JavaScript AJAX adapter to + * deliver web content to JSmol. This handler is just a formality. + * + */ +public class AjaxURLStreamHandler extends URLStreamHandler { + + String protocol; + + public AjaxURLStreamHandler(String protocol) { + this.protocol = protocol; + } + + @Override + protected URLConnection openConnection(URL url) throws IOException { + return new AjaxURLConnection(url); + } + + + @Override + protected String toExternalForm(URL u) { + SB result = new SB(); + result.append(u.getProtocol()); + result.append(":"); + if (u.getAuthority() != null && u.getAuthority().length() > 0) { + result.append("//"); + result.append(u.getAuthority()); + } + if (u.getPath() != null) { + result.append(u.getPath()); + } + if (u.getQuery() != null) { + result.append("?"); + result.append(u.getQuery()); + } + if (u.getRef() != null) { + result.append("#"); + result.append(u.getRef()); + } + return result.toString(); + } + +} diff --git a/src/javajs/util/AjaxURLStreamHandlerFactory.java b/src/javajs/util/AjaxURLStreamHandlerFactory.java new file mode 100644 index 0000000..a050653 --- /dev/null +++ b/src/javajs/util/AjaxURLStreamHandlerFactory.java @@ -0,0 +1,27 @@ +package javajs.util; + +import java.net.URLStreamHandler; +import java.net.URLStreamHandlerFactory; +import java.util.Hashtable; +import java.util.Map; + + +/** + * + * For handling URL file IO via AJAX in JavaScript version + * + */ + +public class AjaxURLStreamHandlerFactory implements URLStreamHandlerFactory { + + Map htFactories = new Hashtable(); + + @Override + public URLStreamHandler createURLStreamHandler(String protocol) { + AjaxURLStreamHandler fac = htFactories.get(protocol); + if (fac == null) + htFactories.put(protocol, fac = new AjaxURLStreamHandler(protocol)); + return (fac.protocol == null ? null : fac); + } + +} diff --git a/src/javajs/util/ArrayDataReader.java b/src/javajs/util/ArrayDataReader.java new file mode 100644 index 0000000..737a6ab --- /dev/null +++ b/src/javajs/util/ArrayDataReader.java @@ -0,0 +1,57 @@ +package javajs.util; + +import java.io.IOException; + + + + + + +/** + * + * ArrayDataReader subclasses BufferedReader and overrides its + * read, readLine, mark, and reset methods so that JmolAdapter + * works with String[] arrays without any further adaptation. + * + */ + +public class ArrayDataReader extends DataReader { + private String[] data; + private int pt; + private int len; + + public ArrayDataReader() { + super(); + } + + @Override + public DataReader setData(Object data) { + this.data = (String[]) data; + len = this.data.length; + return this; + } + + @Override + public int read(char[] buf, int off, int len) throws IOException { + return readBuf(buf, off, len); + } + + @Override + public String readLine() { + return (pt < len ? data[pt++] : null); + } + + /** + * + * @param ptr + */ + public void mark(long ptr) { + //ignore ptr. + ptMark = pt; + } + + @Override + public void reset() { + pt = ptMark; + } +} \ No newline at end of file diff --git a/src/javajs/util/BArray.java b/src/javajs/util/BArray.java new file mode 100644 index 0000000..f09d272 --- /dev/null +++ b/src/javajs/util/BArray.java @@ -0,0 +1,33 @@ +package javajs.util; + +public class BArray { + public byte[] data; + + public BArray(byte[] data) { + this.data = data; + } + + @Override + public boolean equals(Object o) { + if (o instanceof BArray) { + byte[] d = ((BArray) o).data; + if (d.length == data.length){ + for (int i = 0; i < d.length; i++) + if (d[i] != data[i]) + return false; + return true; + } + } + return false; + } + + @Override + public int hashCode() { + return data.hashCode(); + } + + @Override + public String toString() { + return new String(data); + } +} diff --git a/src/javajs/util/BC.java b/src/javajs/util/BC.java new file mode 100644 index 0000000..1648f9e --- /dev/null +++ b/src/javajs/util/BC.java @@ -0,0 +1,163 @@ +package javajs.util; + +public class BC { + + public BC() { + // unnecessary to instantialize unless subclassed + } + + public static float bytesToFloat(byte[] bytes, int j, boolean isBigEndian) throws Exception { + return intToFloat(bytesToInt(bytes, j, isBigEndian)); + } + + public static int bytesToInt(byte[] bytes, int j, boolean isBigEndian) { + int n = (isBigEndian ? (bytes[j + 3] & 0xff) | (bytes[j + 2] & 0xff) << 8 + | (bytes[j + 1] & 0xff) << 16 | (bytes[j] & 0xff) << 24 + : (bytes[j++] & 0xff) | (bytes[j++] & 0xff) << 8 + | (bytes[j++] & 0xff) << 16 | (bytes[j++] & 0xff) << 24); + /** + * @j2sNative + * + * return (n > 0x7FFFFFFF ? n - 0x100000000 : n); + * + */ + { + return n; + } + } + + public static float intToFloat(int x) throws Exception { + /** + * see http://en.wikipedia.org/wiki/Binary32 + * + * [sign] [8 bits power] [23 bits fraction] + * 0x80000000 0x7F800000 0x7FFFFF + * + * (untested) + * + * @j2sNative + * + * if (x == 0) return 0; + * var o = javajs.util.BC; + * if (o.fracIEEE == null) + * o.setFracIEEE(); + * var m = ((x & 0x7F800000) >> 23); + * return ((x & 0x80000000) == 0 ? 1 : -1) * o.shiftIEEE((x & 0x7FFFFF) | 0x800000, m - 149); + * + */ + { + return Float.intBitsToFloat(x); + } + } + + /** + * see http://en.wikipedia.org/wiki/Binary64 + * + * not concerning ourselves with very small or very large numbers and getting + * this exactly right. Just need a float here. + * + * @param bytes + * @param j + * @param isBigEndian + * @return float + */ + public static float bytesToDoubleToFloat(byte[] bytes, int j, boolean isBigEndian) { + { + // IEEE754: sign (1 bit), exponent (11 bits), fraction (52 bits). + // seeeeeee eeeeffff ffffffff ffffffff ffffffff xxxxxxxx xxxxxxxx xxxxxxxx + // b1 b2 b3 b4 b5 ---------float ignores---- + + if (fracIEEE == null) + setFracIEEE(); + + /** + * @j2sNative + * var o = javajs.util.BC; + * var b1, b2, b3, b4, b5; + * + * if (isBigEndian) { + * b1 = bytes[j] & 0xFF; + * b2 = bytes[j + 1] & 0xFF; + * b3 = bytes[j + 2] & 0xFF; + * b4 = bytes[j + 3] & 0xFF; + * b5 = bytes[j + 4] & 0xFF; + * } else { + * b1 = bytes[j + 7] & 0xFF; + * b2 = bytes[j + 6] & 0xFF; + * b3 = bytes[j + 5] & 0xFF; + * b4 = bytes[j + 4] & 0xFF; + * b5 = bytes[j + 3] & 0xFF; + * } + * var s = ((b1 & 0x80) == 0 ? 1 : -1); + * var e = (((b1 & 0x7F) << 4) | (b2 >> 4)) - 1026; + * b2 = (b2 & 0xF) | 0x10; + * return s * (o.shiftIEEE(b2, e) + o.shiftIEEE(b3, e - 8) + o.shiftIEEE(b4, e - 16) + * + o.shiftIEEE(b5, e - 24)); + */ + { + double d; + + if (isBigEndian) + d = Double.longBitsToDouble((((long) bytes[j]) & 0xff) << 56 + | (((long) bytes[j + 1]) & 0xff) << 48 + | (((long) bytes[j + 2]) & 0xff) << 40 + | (((long) bytes[j + 3]) & 0xff) << 32 + | (((long) bytes[j + 4]) & 0xff) << 24 + | (((long) bytes[j + 5]) & 0xff) << 16 + | (((long) bytes[j + 6]) & 0xff) << 8 + | (((long) bytes[7]) & 0xff)); + else + d = Double.longBitsToDouble((((long) bytes[j + 7]) & 0xff) << 56 + | (((long) bytes[j + 6]) & 0xff) << 48 + | (((long) bytes[j + 5]) & 0xff) << 40 + | (((long) bytes[j + 4]) & 0xff) << 32 + | (((long) bytes[j + 3]) & 0xff) << 24 + | (((long) bytes[j + 2]) & 0xff) << 16 + | (((long) bytes[j + 1]) & 0xff) << 8 + | (((long) bytes[j]) & 0xff)); + return (float) d; + } + + } + } + + private static float[] fracIEEE; + + private static void setFracIEEE() { + fracIEEE = new float[270]; + for (int i = 0; i < 270; i++) + fracIEEE[i] = (float) Math.pow(2, i - 141); + // System.out.println(fracIEEE[0] + " " + Parser.FLOAT_MIN_SAFE); + // System.out.println(fracIEEE[269] + " " + Float.MAX_VALUE); + } + + /** + * only concerned about reasonable float values here -- private but not designated; called by JavaScript + * + * @param f + * @param i + * @return f * 2^i + */ + static double shiftIEEE(double f, int i) { + if (f == 0 || i < -140) + return 0; + if (i > 128) + return Float.MAX_VALUE; + return f * fracIEEE[i + 140]; + } + +// static { +// setFracIEEE(); +// for (int i = -50; i < 50; i++) { +// float f = i * (float) (Math.random() * Math.pow(2, Math.random() * 100 - 50)); +// int x = Float.floatToIntBits(f); +// int m = ((x & 0x7F800000) >> 23); +// float f1 = (float) (f == 0 ? 0 : ((x & 0x80000000) == 0 ? 1 : -1) * shiftIEEE((x & 0x7FFFFF) | 0x800000, m - 149)); +// System.out.println(f + " " + f1); +// } +// System.out.println("binarydo"); +// } + + + +} diff --git a/src/javajs/util/BS.java b/src/javajs/util/BS.java new file mode 100644 index 0000000..89c9a2b --- /dev/null +++ b/src/javajs/util/BS.java @@ -0,0 +1,934 @@ +/* + * Copyright 1995-2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package javajs.util; + +import javajs.api.JSONEncodable; + + + +/** + * + * a fast 32-bit BitSet optimized for Java2Script -- about 25 times faster than + * java.util.BitSet + * + * @author Bob Hanson hansonr@stolaf.edu + * + * Additions by Bob Hanson to allow for JavaScript mix of int/long Note + * that Firefox (Sept 2012) does not really treat "Int32Array" as such, + * because any element can be pushed into being a 64-bit number, which + * really isn't because the last 8 bits are not usable. + * + * This class implements a vector of bits that grows as needed. Each + * component of the bit set has a {@code boolean} value. The bits of a + * {@code BitSet} are indexed by nonnegative integers. Individual + * indexed bits can be examined, set, or cleared. One {@code BitSet} may + * be used to modify the contents of another {@code BitSet} through + * logical AND, logical inclusive OR, and logical exclusive OR + * operations. + * + *

    + * By default, all bits in the set initially have the value {@code + * false}. + * + *

    + * Every bit set has a current size, which is the number of bits of + * space currently in use by the bit set. Note that the size is related + * to the implementation of a bit set, so it may change with + * implementation. The length of a bit set relates to logical length of + * a bit set and is defined independently of implementation. + * + *

    + * Unless otherwise noted, passing a null parameter to any of the + * methods in a {@code BitSet} will result in a {@code + * NullPointerException}. + * + *

    + * A {@code BitSet} is not safe for multithreaded use without external + * synchronization. + * + * @author Arthur van Hoff + * @author Michael McCloskey + * @author Martin Buchholz + * @since JDK1.0 + */ +public class BS implements Cloneable, JSONEncodable { + /* + * BitSets are packed into arrays of "words." + * + * An int, which consists of 32 bits, requiring 5 address bits, is used for + * the JavaScript port. + */ + private final static int ADDRESS_BITS_PER_WORD = 5; + private final static int BITS_PER_WORD = 1 << ADDRESS_BITS_PER_WORD; + + /* Used to shift left or right for a partial word mask */ + private static final int WORD_MASK = 0xffffffff; + + + /** + * The internal field corresponding to the serialField "bits". + */ + private int[] words; + + /** + * The number of words in the logical size of this BitSet. + */ + private transient int wordsInUse = 0; + + /** + * Whether the size of "words" is user-specified. If so, we assume the user + * knows what he's doing and try harder to preserve it. + */ + private transient boolean sizeIsSticky = false; + + /* use serialVersionUID from JDK 1.0.2 for interoperability */ + //private static final long serialVersionUID = 7997698588986878753L; + + /** + * Given a bit index, return word index containing it. + * @param bitIndex + * @return b + */ + private static int wordIndex(int bitIndex) { + return bitIndex >> ADDRESS_BITS_PER_WORD; + } + + /** + * Sets the field wordsInUse to the logical size in words of the bit set. + * WARNING:This method assumes that the number of words actually in use is + * less than or equal to the current value of wordsInUse! + */ + private void recalculateWordsInUse() { + // Traverse the bitset until a used word is found + int i; + for (i = wordsInUse - 1; i >= 0; i--) + if (words[i] != 0) + break; + + wordsInUse = i + 1; // The new logical size + } + + /** + * Creates a new bit set. All bits are initially {@code false}. + */ + public BS() { + initWords(BITS_PER_WORD); + sizeIsSticky = false; + } + + /** + * Creates a bit set whose initial size is large enough to explicitly + * represent bits with indices in the range {@code 0} through {@code nbits-1}. + * All bits are initially {@code false}. + * + * @param nbits + * the initial size of the bit set + * @return bs + * @throws NegativeArraySizeException + * if the specified initial size is negative + */ + public static BS newN(int nbits) { + BS bs = new BS(); + bs.init(nbits); + return bs; + } + + private void init(int nbits) { + // nbits can't be negative; size 0 is OK + if (nbits < 0) + throw new NegativeArraySizeException("nbits < 0: " + nbits); + initWords(nbits); + sizeIsSticky = true; + } + + private void initWords(int nbits) { + words = new int[wordIndex(nbits - 1) + 1]; + } + + /** + * Ensures that the BitSet can hold enough words. + * + * @param wordsRequired + * the minimum acceptable number of words. + */ + private void ensureCapacity(int wordsRequired) { + if (words.length < wordsRequired) { + // Allocate larger of doubled size or required size + int request = Math.max(2 * words.length, wordsRequired); + setLength(request); + sizeIsSticky = false; + } + } + + /** + * Ensures that the BitSet can accommodate a given wordIndex, temporarily + * violating the invariants. The caller must restore the invariants before + * returning to the user, possibly using recalculateWordsInUse(). + * + * @param wordIndex + * the index to be accommodated. + */ + private void expandTo(int wordIndex) { + int wordsRequired = wordIndex + 1; + if (wordsInUse < wordsRequired) { + ensureCapacity(wordsRequired); + wordsInUse = wordsRequired; + } + } + + + /** + * Sets the bit at the specified index to {@code true}. + * + * @param bitIndex + * a bit index + * @throws IndexOutOfBoundsException + * if the specified index is negative + * @since JDK1.0 + */ + public void set(int bitIndex) { + if (bitIndex < 0) + throw new IndexOutOfBoundsException("bitIndex < 0: " + bitIndex); + + int wordIndex = wordIndex(bitIndex); + expandTo(wordIndex); + + words[wordIndex] |= (1 << bitIndex); // Restores invariants + + } + + /** + * Sets the bit at the specified index to the specified value. + * + * @param bitIndex + * a bit index + * @param value + * a boolean value to set + * @throws IndexOutOfBoundsException + * if the specified index is negative + * @since 1.4 + */ + public void setBitTo(int bitIndex, boolean value) { + if (value) + set(bitIndex); + else + clear(bitIndex); + } + + /** + * Sets the bits from the specified {@code fromIndex} (inclusive) to the + * specified {@code toIndex} (exclusive) to {@code true}. + * + * @param fromIndex + * index of the first bit to be set + * @param toIndex + * index after the last bit to be set + * @throws IndexOutOfBoundsException + * if {@code fromIndex} is negative, or {@code toIndex} is negative, + * or {@code fromIndex} is larger than {@code toIndex} + * @since 1.4 + */ + public void setBits(int fromIndex, int toIndex) { + + if (fromIndex == toIndex) + return; + + // Increase capacity if necessary + int startWordIndex = wordIndex(fromIndex); + int endWordIndex = wordIndex(toIndex - 1); + expandTo(endWordIndex); + + int firstWordMask = WORD_MASK << fromIndex; + int lastWordMask = WORD_MASK >>> -toIndex; + if (startWordIndex == endWordIndex) { + // Case 1: One word + words[startWordIndex] |= (firstWordMask & lastWordMask); + } else { + // Case 2: Multiple words + // Handle first word + words[startWordIndex] |= firstWordMask; + + // Handle intermediate words, if any + for (int i = startWordIndex + 1; i < endWordIndex; i++) + words[i] = WORD_MASK; + + // Handle last word (restores invariants) + words[endWordIndex] |= lastWordMask; + } + } + + /** + * Sets the bit specified by the index to {@code false}. + * + * @param bitIndex + * the index of the bit to be cleared + * @throws IndexOutOfBoundsException + * if the specified index is negative + * @since JDK1.0 + */ + public void clear(int bitIndex) { + if (bitIndex < 0) + throw new IndexOutOfBoundsException("bitIndex < 0: " + bitIndex); + + int wordIndex = wordIndex(bitIndex); + if (wordIndex >= wordsInUse) + return; + + words[wordIndex] &= ~(1 << bitIndex); + + recalculateWordsInUse(); + } + + /** + * Sets the bits from the specified {@code fromIndex} (inclusive) to the + * specified {@code toIndex} (exclusive) to {@code false}. + * + * @param fromIndex + * index of the first bit to be cleared + * @param toIndex + * index after the last bit to be cleared + * @throws IndexOutOfBoundsException + * if {@code fromIndex} is negative, or {@code toIndex} is negative, + * or {@code fromIndex} is larger than {@code toIndex} + * @since 1.4 + */ + public void clearBits(int fromIndex, int toIndex) { + if (fromIndex == toIndex) + return; + + int startWordIndex = wordIndex(fromIndex); + if (startWordIndex >= wordsInUse) + return; + + int endWordIndex = wordIndex(toIndex - 1); + if (endWordIndex >= wordsInUse) { + toIndex = length(); + endWordIndex = wordsInUse - 1; + } + + int firstWordMask = WORD_MASK << fromIndex; + int lastWordMask = WORD_MASK >>> -toIndex; + if (startWordIndex == endWordIndex) { + // Case 1: One word + words[startWordIndex] &= ~(firstWordMask & lastWordMask); + } else { + // Case 2: Multiple words + // Handle first word + words[startWordIndex] &= ~firstWordMask; + + // Handle intermediate words, if any + for (int i = startWordIndex + 1; i < endWordIndex; i++) + words[i] = 0; + + // Handle last word + words[endWordIndex] &= ~lastWordMask; + } + + recalculateWordsInUse(); + } + + /** + * Sets all of the bits in this BitSet to {@code false}. + * + * @since 1.4 + */ + public void clearAll() { + while (wordsInUse > 0) + words[--wordsInUse] = 0; + } + + /** + * Returns the value of the bit with the specified index. The value is {@code + * true} if the bit with the index {@code bitIndex} is currently set in this + * {@code BitSet}; otherwise, the result is {@code false}. + * + * @param bitIndex + * the bit index + * @return the value of the bit with the specified index + * @throws IndexOutOfBoundsException + * if the specified index is negative + */ + public boolean get(int bitIndex) { + if (bitIndex < 0) + throw new IndexOutOfBoundsException("bitIndex < 0: " + bitIndex); + + int wordIndex = wordIndex(bitIndex); + return (wordIndex < wordsInUse) + && ((words[wordIndex] & (1 << bitIndex)) != 0); + } + + /** + * Returns the index of the first bit that is set to {@code true} that occurs + * on or after the specified starting index. If no such bit exists then + * {@code -1} is returned. + * + *

    + * To iterate over the {@code true} bits in a {@code BitSet}, use the + * following loop: + * + *

    +   * @code
    +   * for (int i = bs.nextSetBit(0); i >= 0; i = bs.nextSetBit(i+1)) {
    +   *     // operate on index i here
    +   * }}
    +   * 
    + * + * @param fromIndex + * the index to start checking from (inclusive) + * @return the index of the next set bit, or {@code -1} if there is no such + * bit + * @throws IndexOutOfBoundsException + * if the specified index is negative + * @since 1.4 + */ + public int nextSetBit(int fromIndex) { + if (fromIndex < 0) + throw new IndexOutOfBoundsException("fromIndex < 0: " + fromIndex); + + int u = wordIndex(fromIndex); + if (u >= wordsInUse) + return -1; + + int word = words[u] & (WORD_MASK << fromIndex); + + while (true) { + if (word != 0) + return (u * BITS_PER_WORD) + Integer.numberOfTrailingZeros(word); + if (++u == wordsInUse) + return -1; + word = words[u]; + } + } + + /** + * Returns the index of the first bit that is set to {@code false} that occurs + * on or after the specified starting index. + * + * @param fromIndex + * the index to start checking from (inclusive) + * @return the index of the next clear bit + * @throws IndexOutOfBoundsException + * if the specified index is negative + * @since 1.4 + */ + public int nextClearBit(int fromIndex) { + // Neither spec nor implementation handle bitsets of maximal length. + // See 4816253. + if (fromIndex < 0) + throw new IndexOutOfBoundsException("fromIndex < 0: " + fromIndex); + + int u = wordIndex(fromIndex); + if (u >= wordsInUse) + return fromIndex; + + int word = ~words[u] & (WORD_MASK << fromIndex); + + while (true) { + if (word != 0) + return (u * BITS_PER_WORD) + Integer.numberOfTrailingZeros(word); + if (++u == wordsInUse) + return wordsInUse * BITS_PER_WORD; + word = ~words[u]; + } + } + + /** + * Returns the "logical size" of this {@code BitSet}: the index of the highest + * set bit in the {@code BitSet} plus one. Returns zero if the {@code BitSet} + * contains no set bits. + * + * @return the logical size of this {@code BitSet} + * @since 1.2 + */ + public int length() { + if (wordsInUse == 0) + return 0; + + return BITS_PER_WORD * (wordsInUse - 1) + + (BITS_PER_WORD - Integer.numberOfLeadingZeros(words[wordsInUse - 1])); + } + + /** + * Returns true if this {@code BitSet} contains no bits that are set to + * {@code true}. + * + * @return boolean indicating whether this {@code BitSet} is empty + * @since 1.4 + */ + public boolean isEmpty() { + return wordsInUse == 0; + } + + /** + * Returns true if the specified {@code BitSet} has any bits set to {@code + * true} that are also set to {@code true} in this {@code BitSet}. + * + * @param set + * {@code BitSet} to intersect with + * @return boolean indicating whether this {@code BitSet} intersects the + * specified {@code BitSet} + * @since 1.4 + */ + public boolean intersects(BS set) { + for (int i = Math.min(wordsInUse, set.wordsInUse) - 1; i >= 0; i--) + if ((words[i] & set.words[i]) != 0) + return true; + return false; + } + + /** + * Returns the number of bits set to {@code true} in this {@code BitSet}. + * + * @return the number of bits set to {@code true} in this {@code BitSet} + * @since 1.4 + */ + public int cardinality() { + int sum = 0; + for (int i = 0; i < wordsInUse; i++) + sum += Integer.bitCount(words[i]); + return sum; + } + + /** + * Performs a logical AND of this target bit set with the argument bit + * set. This bit set is modified so that each bit in it has the value {@code + * true} if and only if it both initially had the value {@code true} and the + * corresponding bit in the bit set argument also had the value {@code true}. + * + * @param set + * a bit set + */ + public void and(BS set) { + if (this == set) + return; + + while (wordsInUse > set.wordsInUse) + words[--wordsInUse] = 0; + + // Perform logical AND on words in common + for (int i = 0; i < wordsInUse; i++) + words[i] &= set.words[i]; + + recalculateWordsInUse(); + } + + /** + * Performs a logical OR of this bit set with the bit set argument. + * This bit set is modified so that a bit in it has the value {@code true} if + * and only if it either already had the value {@code true} or the + * corresponding bit in the bit set argument has the value {@code true}. + * + * @param set + * a bit set + */ + public void or(BS set) { + if (this == set) + return; + + int wordsInCommon = Math.min(wordsInUse, set.wordsInUse); + + if (wordsInUse < set.wordsInUse) { + ensureCapacity(set.wordsInUse); + wordsInUse = set.wordsInUse; + } + + // Perform logical OR on words in common + for (int i = 0; i < wordsInCommon; i++) + words[i] |= set.words[i]; + + // Copy any remaining words + if (wordsInCommon < set.wordsInUse) + System.arraycopy(set.words, wordsInCommon, words, wordsInCommon, + wordsInUse - wordsInCommon); + + } + + /** + * Performs a logical XOR of this bit set with the bit set argument. + * This bit set is modified so that a bit in it has the value {@code true} if + * and only if one of the following statements holds: + *
      + *
    • The bit initially has the value {@code true}, and the corresponding bit + * in the argument has the value {@code false}. + *
    • The bit initially has the value {@code false}, and the corresponding + * bit in the argument has the value {@code true}. + *
    + * + * @param set + * a bit set + */ + public void xor(BS set) { + int wordsInCommon = Math.min(wordsInUse, set.wordsInUse); + + if (wordsInUse < set.wordsInUse) { + ensureCapacity(set.wordsInUse); + wordsInUse = set.wordsInUse; + } + + // Perform logical XOR on words in common + for (int i = 0; i < wordsInCommon; i++) + words[i] ^= set.words[i]; + + // Copy any remaining words + if (wordsInCommon < set.wordsInUse) + System.arraycopy(set.words, wordsInCommon, words, wordsInCommon, + set.wordsInUse - wordsInCommon); + + recalculateWordsInUse(); + } + + /** + * Clears all of the bits in this {@code BitSet} whose corresponding bit is + * set in the specified {@code BitSet}. + * + * @param set + * the {@code BitSet} with which to mask this {@code BitSet} + * @since 1.2 + */ + public void andNot(BS set) { + // Perform logical (a & !b) on words in common + for (int i = Math.min(wordsInUse, set.wordsInUse) - 1; i >= 0; i--) + words[i] &= ~set.words[i]; + + recalculateWordsInUse(); + } + + /** + * Returns a hash code value for this bit set. The hash code depends only on + * which bits have been set within this BitSet. The algorithm + * used to compute it may be described as follows. + *

    + * Suppose the bits in the BitSet were to be stored in an array + * of long integers called, say, words, in such a + * manner that bit k is set in the BitSet (for + * nonnegative values of k) if and only if the expression + * + *

    +   * ((k >> 6) < words.length) && ((words[k >> 6] & (1 << (bit & 0x3F))) != 0)
    +   * 
    + * + * is true. Then the following definition of the hashCode method + * would be a correct implementation of the actual algorithm: + * + *
    +   * public int hashCode() {
    +   *  long h = 1234;
    +   *  for (int i = words.length; --i >= 0;) {
    +   *    h ˆ= words[i] * (i + 1);
    +   *  }
    +   *  return (int) ((h >> 32) ˆ h);
    +   * }
    +   * 
    + * + * Note that the hash code values change if the set of bits is altered. + *

    + * Overrides the hashCode method of Object. + * + * @return a hash code value for this bit set. + */ + @Override + public int hashCode() { + long h = 1234; + for (int i = wordsInUse; --i >= 0;) + h ^= words[i] * (i + 1); + + return (int) ((h >> 32) ^ h); + } + + /** + * Returns the number of bits of space actually in use by this {@code BitSet} + * to represent bit values. The maximum element in the set is the size - 1st + * element. + * + * @return the number of bits currently in this bit set + */ + public int size() { + return words.length * BITS_PER_WORD; + } + + /** + * Compares this object against the specified object. The result is {@code + * true} if and only if the argument is not {@code null} and is a {@code + * Bitset} object that has exactly the same set of bits set to {@code true} as + * this bit set. That is, for every nonnegative {@code int} index {@code k}, + * + *

    +   * ((BitSet) obj).get(k) == this.get(k)
    +   * 
    + * + * must be true. The current sizes of the two bit sets are not compared. + * + * @param obj + * the object to compare with + * @return {@code true} if the objects are the same; {@code false} otherwise + * @see #size() + */ + @Override + public boolean equals(Object obj) { + if (!(obj instanceof BS)) + return false; + if (this == obj) + return true; + + BS set = (BS) obj; + + if (wordsInUse != set.wordsInUse) + return false; + + // Check words in use by both BitSets + for (int i = 0; i < wordsInUse; i++) + if (words[i] != set.words[i]) + return false; + + return true; + } + + /** + * Cloning this {@code BitSet} produces a new {@code BitSet} that is equal to + * it. The clone of the bit set is another bit set that has exactly the same + * bits set to {@code true} as this bit set. + * + * @return a clone of this bit set + * @see #size() + */ + @Override + public Object clone() { + if (!sizeIsSticky && wordsInUse != words.length) + setLength(wordsInUse); + return copy(this); + } + + /** + * Attempts to reduce internal storage used for the bits in this bit set. + * Calling this method may, but is not required to, affect the value returned + * by a subsequent call to the {@link #size()} method. + * @param n + */ + private void setLength(int n) { + int[] a = new int[n]; + System.arraycopy(words, 0, a, 0, Math.min(wordsInUse, n)); + words = a; + } + + /** + * Returns a string representation of this bit set. For every index for which + * this {@code BitSet} contains a bit in the set state, the decimal + * representation of that index is included in the result. Such indices are + * listed in order from lowest to highest, separated by ", " (a comma and + * a space) and surrounded by braces, resulting in the usual mathematical + * notation for a set of integers. + * + *

    + * Example: + * + *

    +   * BitSet drPepper = new BitSet();
    +   * 
    + * + * Now {@code drPepper.toString()} returns "{}". + *

    + * + *

    +   * drPepper.set(2);
    +   * 
    + * + * Now {@code drPepper.toString()} returns "{2}". + *

    + * + *

    +   * drPepper.set(4);
    +   * drPepper.set(10);
    +   * 
    + * + * Now {@code drPepper.toString()} returns "{2, 4, 10}". + * + * @return a string representation of this bit set + */ + @Override + public String toString() { + return escape(this, '{', '}'); + } + + private final static int[] emptyBitmap = new int[0]; + + /** + * fast copy + * + * @param bitsetToCopy + * @return bs + */ + public static BS copy(BS bitsetToCopy) { + BS bs; + /** + * Clazz.clone will copy wordsInUse and sizeIsSticky, + * but just a pointer to the words array. + * + * @j2sNative + * + * bs = Clazz.clone(bitsetToCopy); + * + */ + { + bs = new BS(); + } + int wordCount = bitsetToCopy.wordsInUse; + if (wordCount == 0) { + bs.words = emptyBitmap; + } else { + bs.words = new int[bs.wordsInUse = wordCount]; + System.arraycopy(bitsetToCopy.words, 0, bs.words, 0, wordCount); + } + return bs; + } + + /** + * + * @param max + * @return n bits below max + */ + public int cardinalityN(int max) { + int n = cardinality(); + for (int i = length(); --i >= max;) + if (get(i)) + n--; + return n; + } + + @Override + public String toJSON() { + + int numBits = (wordsInUse > 128) ? cardinality() : wordsInUse + * BITS_PER_WORD; + SB b = SB.newN(6 * numBits + 2); + b.appendC('['); + + int i = nextSetBit(0); + if (i != -1) { + b.appendI(i); + for (i = nextSetBit(i + 1); i >= 0; i = nextSetBit(i + 1)) { + int endOfRun = nextClearBit(i); + do { + b.append(", ").appendI(i); + } while (++i < endOfRun); + } + } + + b.appendC(']'); + return b.toString(); + } + + public static String escape(BS bs, char chOpen, char chClose) { + if (bs == null) + return chOpen + "{}" + chClose; + SB s = new SB(); + s.append(chOpen + "{"); + int imax = bs.length(); + int iLast = -1; + int iFirst = -2; + int i = -1; + while (++i <= imax) { + boolean isSet = bs.get(i); + if (i == imax || iLast >= 0 && !isSet) { + if (iLast >= 0 && iFirst != iLast) + s.append((iFirst == iLast - 1 ? " " : ":") + iLast); + if (i == imax) + break; + iLast = -1; + } + if (bs.get(i)) { + if (iLast < 0) { + s.append((iFirst == -2 ? "" : " ") + i); + iFirst = i; + } + iLast = i; + } + } + s.append("}").appendC(chClose); + return s.toString(); + } + + public static BS unescape(String str) { + char ch; + int len; + if (str == null || (len = (str = str.trim()).length()) < 4 + || str.equalsIgnoreCase("({null})") + || (ch = str.charAt(0)) != '(' && ch != '[' + || str.charAt(len - 1) != (ch == '(' ? ')' : ']') + || str.charAt(1) != '{' || str.indexOf('}') != len - 2) + return null; + len -= 2; + for (int i = len; --i >= 2;) + if (!PT.isDigit(ch = str.charAt(i)) && ch != ' ' && ch != '\t' + && ch != ':') + return null; + int lastN = len; + while (PT.isDigit(str.charAt(--lastN))) { + // loop + } + if (++lastN == len) + lastN = 0; + else + try { + lastN = Integer.parseInt(str.substring(lastN, len)); + } catch (NumberFormatException e) { + return null; + } + BS bs = BS.newN(lastN); + lastN = -1; + int iPrev = -1; + int iThis = -2; + for (int i = 2; i <= len; i++) { + switch (ch = str.charAt(i)) { + case '\t': + case ' ': + case '}': + if (iThis < 0) + break; + if (iThis < lastN) + return null; + lastN = iThis; + if (iPrev < 0) + iPrev = iThis; + bs.setBits(iPrev, iThis + 1); + iPrev = -1; + iThis = -2; + break; + case ':': + iPrev = lastN = iThis; + iThis = -2; + break; + default: + if (PT.isDigit(ch)) { + if (iThis < 0) + iThis = 0; + iThis = (iThis * 10) + (ch - 48); + } + } + } + return (iPrev >= 0 ? null : bs); + } + +} diff --git a/src/javajs/util/Base64.java b/src/javajs/util/Base64.java new file mode 100644 index 0000000..a7ac3a9 --- /dev/null +++ b/src/javajs/util/Base64.java @@ -0,0 +1,120 @@ +// Version 1.0a +// Copyright (C) 1998, James R. Weeks and BioElectroMech. +// Visit BioElectroMech at www.obrador.com. Email James@obrador.com. + +// See license.txt for details about the allowed used of this software. +// This software is based in part on the work of the Independent JPEG Group. +// See IJGreadme.txt for details about the Independent JPEG Group's license. + +// This encoder is inspired by the Java Jpeg encoder by Florian Raemy, +// studwww.eurecom.fr/~raemy. +// It borrows a great deal of code and structure from the Independent +// Jpeg Group's Jpeg 6a library, Copyright Thomas G. Lane. +// See license.txt for details. + +package javajs.util; + + +public class Base64 { + + // 0 1 2 3 4 5 6 + // 0123456789012345678901234567890123456789012345678901234567890123 + private static String base64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + // 41----------------------5A + // 61----------------------7A + // 30------39 + // 2B + // 2F + // alternative "URL-SAFE" 2D and 5F -_ + + private static int[] decode64 = new int[] { + 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, //0x00-0x0F + 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, //0x10-0x1F + 0,0,0,0, 0,0,0,0, 0,0,0,62, 0,62,0,63, //0x20-0x2F + 52,53,54,55, 56,57,58,59, 60,61,0,0, 0,0,0,0, //0x30-0x3F + 0,0,1,2, 3,4,5,6, 7,8,9,10, 11,12,13,14, //0x40-0x4F + 15,16,17,18, 19,20,21,22, 23,24,25,0, 0,0,0,63, //0x50-0x5F + 0,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40, //0x60-0x6F + 41,42,43,44, 45,46,47,48, 49,50,51,0, 0,0,0,0, //0x70-0x7F + }; + +// public static void write(byte[] bytes, OutputChannel out) { +// SB sb = getBase64(bytes); +// int len = sb.length(); +// byte[] b = new byte[1]; +// for (int i = 0; i < len; i++) { +// b[0] = (byte) sb.charAt(i); +// out.write(b, 0, 1); +// } +// } + + public static byte[] getBytes64(byte[] bytes) { + return getBase64(bytes).toBytes(0, -1); + } + + /** + * + * @param bytes + * @return BASE64-encoded string, without ";base64," + */ + public static SB getBase64(byte[] bytes) { + long nBytes = bytes.length; + SB sout = new SB(); + if (nBytes == 0) + return sout; + for (int i = 0, nPad = 0; i < nBytes && nPad == 0;) { + if (i % 75 == 0 && i != 0) + sout.append("\r\n"); + nPad = (i + 2 == nBytes ? 1 : i + 1 == nBytes ? 2 : 0); + int outbytes = ((bytes[i++] << 16) & 0xFF0000) + | ((nPad == 2 ? 0 : bytes[i++] << 8) & 0x00FF00) + | ((nPad >= 1 ? 0 : (int) bytes[i++]) & 0x0000FF); + //System.out.println(Integer.toHexString(outbytes)); + sout.appendC(base64.charAt((outbytes >> 18) & 0x3F)); + sout.appendC(base64.charAt((outbytes >> 12) & 0x3F)); + sout.appendC(nPad == 2 ? '=' : base64.charAt((outbytes >> 6) & 0x3F)); + sout.appendC(nPad >= 1 ? '=' : base64.charAt(outbytes & 0x3F)); + } + return sout; + } + + //Note: Just a simple decoder here. Nothing fancy at all + // Because of the 0s in decode64, this is not a VERIFIER + // Rather, it may decode even bad Base64-encoded data + // + // Bob Hanson 4/2007 + + public static byte[] decodeBase64(String strBase64) { + int nBytes = 0; + int ch; + int pt0 = strBase64.indexOf(";base64,") + 1; + if (pt0 > 0) + pt0 += 7; + char[] chars64 = strBase64.toCharArray(); + int len64 = chars64.length; + if (len64 == 0) + return new byte[0]; + for (int i = len64; --i >= pt0;) + nBytes += ((ch = chars64[i] & 0x7F) == 'A' || decode64[ch] > 0 ? 3 : 0); + nBytes = nBytes >> 2; + byte[] bytes = new byte[nBytes]; + int offset = 18; + for (int i = pt0, pt = 0, b = 0; i < len64; i++) { + if (decode64[ch = chars64[i] & 0x7F] > 0 || ch == 'A' || ch == '=') { + b |= decode64[ch] << offset; + //System.out.println(chars64[i] + " " + decode64[ch] + " " + offset + " " + Integer.toHexString(b)); + offset -= 6; + if (offset < 0) { + bytes[pt++] = (byte) ((b & 0xFF0000) >> 16); + if (pt < nBytes) + bytes[pt++] = (byte) ((b & 0xFF00) >> 8); + if (pt < nBytes) + bytes[pt++] = (byte) (b & 0xFF); + offset = 18; + b = 0; + } + } + } + return bytes; + } +} \ No newline at end of file diff --git a/src/javajs/util/BinaryDocument.java b/src/javajs/util/BinaryDocument.java new file mode 100644 index 0000000..172ed7c --- /dev/null +++ b/src/javajs/util/BinaryDocument.java @@ -0,0 +1,360 @@ +/* $RCSfile$ + * $Author: egonw $ + * $Date: 2006-03-18 15:59:33 -0600 (Sat, 18 Mar 2006) $ + * $Revision: 4652 $ + * + * Copyright (C) 2003-2005 Miguel, Jmol Development, www.jmol.org + * + * Contact: hansonr@stolaf.edu + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + */ +package javajs.util; + + +import java.io.BufferedInputStream; +import java.io.DataInputStream; +import java.util.Map; + + +import javajs.api.GenericBinaryDocument; +import javajs.api.GenericZipTools; + + +//import java.io.RandomAccessFile; + +/* a basic binary file reader (extended by CompoundDocument). + * + * random access file info: + * http://java.sun.com/docs/books/tutorial/essential/io/rafs.html + * + * SHOOT! random access is only for applications, not applets! + * + * Note that YOU are responsible for determining whether a file + * is bigEndian or littleEndian; the default is bigEndian. + * + * JavaScript note: readShort() malfunctioned because (short) (xx << 8) + * isn't the same as (int) (xx << 8); same problem in java.io.DataStream + * + * + */ + +public class BinaryDocument extends BC implements GenericBinaryDocument { + + /** + * @j2sIgnore + */ + public BinaryDocument() { + } + + + // called by reflection + + protected DataInputStream stream; + protected boolean isRandom = false; + public boolean isBigEndian = true; + protected GenericZipTools jzt; + + @Override + public void close() { + if (stream != null) + try { + stream.close(); + } catch (Exception e) { + // ignore + } + if (out != null) + out.closeChannel(); + } + + @Override + public void setStream(GenericZipTools jzt, BufferedInputStream bis, boolean isBigEndian) { + if (jzt != null) + this.jzt = jzt; + if (bis != null) + stream = new DataInputStream(bis); + this.isBigEndian = isBigEndian; + } + + @Override + public void setStreamData(DataInputStream stream, boolean isBigEndian) { + if (stream != null) + this.stream = stream; + this.isBigEndian = isBigEndian; + } + + public void setRandom(boolean TF) { + isRandom = TF; + //CANNOT be random for web + } + + @Override + public byte readByte() throws Exception { + nBytes++; + return ioReadByte(); + } + + private byte ioReadByte() throws Exception { + byte b = stream.readByte(); + if (out != null) + out.writeByteAsInt(b); + return b; + } + + @Override + public int readByteArray(byte[] b, int off, int len) throws Exception { + int n = ioRead(b, off, len); + nBytes += n; + return n; + } + + private int ioRead(byte[] b, int off, int len) throws Exception { + int m = 0; + while (len > 0) { + int n = stream.read(b, off, len); + m += n; + if (n > 0 && out != null) + writeBytes(b, off, n); + if (n >= len) + break; + off += n; + len -= n; + } + return m; + } + + public void writeBytes(byte[] b, int off, int n) throws Exception { + out.write(b, off, n); + } + + @Override + public String readString(int nChar) throws Exception { + byte[] temp = new byte[nChar]; + int n = readByteArray(temp, 0, nChar); + return new String(temp, 0, n, "UTF-8"); + } + + @Override + public short readShort() throws Exception { + nBytes += 2; + short n = (isBigEndian ? ioReadShort() + : (short) ((ioReadByte() & 0xff) + | (ioReadByte() & 0xff) << 8)); + /** + * @j2sNative + * + * return (n > 0x7FFF ? n - 0x10000 : n); + */ + { + return n; + } + } + + private short ioReadShort() throws Exception { + short b = stream.readShort(); + if (out != null) + writeShort(b); + return b; + } + + + public void writeShort(short i) throws Exception { + out.writeByteAsInt(i >> 8); + out.writeByteAsInt(i); + } + + @Override + public int readIntLE() throws Exception { + nBytes += 4; + return readLEInt(); + } + + @Override + public int readInt() throws Exception { + nBytes += 4; + return (isBigEndian ? ioReadInt() : readLEInt()); + } + + private int ioReadInt() throws Exception { + int i = stream.readInt(); + if (out != null) + writeInt(i); + return i; + } + + public void writeInt(int i) throws Exception { + out.writeByteAsInt(i >> 24); + out.writeByteAsInt(i >> 16); + out.writeByteAsInt(i >> 8); + out.writeByteAsInt(i); + } + + @Override + public int swapBytesI(int n) { + return (((n >> 24) & 0xff) + | ((n >> 16) & 0xff) << 8 + | ((n >> 8) & 0xff) << 16 + | (n & 0xff) << 24); + } + + @Override + public short swapBytesS(short n) { + return (short) ((((n >> 8) & 0xff) + | (n & 0xff) << 8)); + } + + + @Override + public int readUnsignedShort() throws Exception { + nBytes += 2; + int a = (ioReadByte() & 0xff); + int b = (ioReadByte() & 0xff); + return (isBigEndian ? (a << 8) + b : (b << 8) + a); + } + + @Override + public long readLong() throws Exception { + nBytes += 8; + return (isBigEndian ? ioReadLong() + : ((((long) ioReadByte()) & 0xff) + | (((long) ioReadByte()) & 0xff) << 8 + | (((long) ioReadByte()) & 0xff) << 16 + | (((long) ioReadByte()) & 0xff) << 24 + | (((long) ioReadByte()) & 0xff) << 32 + | (((long) ioReadByte()) & 0xff) << 40 + | (((long) ioReadByte()) & 0xff) << 48 + | (((long) ioReadByte()) & 0xff) << 54)); + } + + private long ioReadLong() throws Exception { + long b = stream.readLong(); + if (out != null) + writeLong(b); + return b; + } + + public void writeLong(long b) throws Exception { + writeInt((int)((b >> 32) & 0xFFFFFFFFl)); + writeInt((int)(b & 0xFFFFFFFFl)); + } + + private int readLEInt() throws Exception { + ioRead(t8, 0, 4); + return bytesToInt(t8, 0, false); + } + + byte[] t8 = new byte[8]; + + @Override + public float readFloat() throws Exception { + return intToFloat(readInt()); + } + + @Override + public double readDouble() throws Exception { + /** + * + * reading the float equivalent here in JavaScript + * + * @j2sNative + * + * this.readByteArray(this.t8, 0, 8); + * return this.bytesToDoubleToFloat(this.t8, 0, this.isBigEndian); + * + */ + { + nBytes += 8; + return (isBigEndian ? ioReadDouble() : Double.longBitsToDouble(readLELong())); + } + } + + private double ioReadDouble() throws Exception { + double d = stream.readDouble(); + if (out != null) + writeLong(Double.doubleToRawLongBits(d)); + return d; + } + + private long readLELong() throws Exception { + return ((((long) ioReadByte()) & 0xff) + | (((long) ioReadByte()) & 0xff) << 8 + | (((long) ioReadByte()) & 0xff) << 16 + | (((long) ioReadByte()) & 0xff) << 24 + | (((long) ioReadByte()) & 0xff) << 32 + | (((long) ioReadByte()) & 0xff) << 40 + | (((long) ioReadByte()) & 0xff) << 48 + | (((long) ioReadByte()) & 0xff) << 56); + } + + @Override + public void seek(long offset) { + // slower, but all that is available using the applet + try { + if (offset == nBytes) + return; + if (offset < nBytes) { + stream.reset(); + if (out != null && nBytes != 0) + out.reset(); + nBytes = 0; + } else { + offset -= nBytes; + } + if (out == null) { + stream.skipBytes((int)offset); + } else { + readByteArray(new byte[(int)offset], 0, (int) offset); + } + nBytes += offset; + } catch (Exception e) { + System.out.println(e.toString()); + } + } + + long nBytes; + + @Override + public long getPosition() { + return nBytes; + } + + OC out; + @Override + public void setOutputChannel(OC out) { + this.out = out; + } + + @Override + public SB getAllDataFiles(String binaryFileList, String firstFile) { + return null; + } + + @Override + public void getAllDataMapped(String replace, String string, + Map fileData) { + } + + +/* random access -- application only: + * + void seekFile(long offset) { + try { + file.seek(offset); + } catch (Exception e) { + System.out.println(e.getMessage()); + } + } +*/ +} diff --git a/src/javajs/util/CU.java b/src/javajs/util/CU.java new file mode 100644 index 0000000..f28657a --- /dev/null +++ b/src/javajs/util/CU.java @@ -0,0 +1,550 @@ +package javajs.util; + +import java.util.Hashtable; +import java.util.Map; + +import javajs.api.GenericColor; + +/** + * ColorUtility + * + */ + +public class CU { + + public static String toRGBHexString(GenericColor c) { + int rgb = c.getRGB(); + if (rgb == 0) + return "000000"; + String r = "00" + Integer.toHexString((rgb >> 16) & 0xFF); + r = r.substring(r.length() - 2); + String g = "00" + Integer.toHexString((rgb >> 8) & 0xFF); + g = g.substring(g.length() - 2); + String b = "00" + Integer.toHexString(rgb & 0xFF); + b = b.substring(b.length() - 2); + return r + g + b; + } + + public static String toCSSString(GenericColor c) { + int opacity = c.getOpacity255(); + if (opacity == 255) + return "#" + toRGBHexString(c); + int rgb = c.getRGB(); + return "rgba(" + ((rgb>>16)&0xFF) + "," + ((rgb>>8)&0xff) + "," + (rgb&0xff) + "," + opacity/255f + ")"; + } + + private final static String[] colorNames = { + "black", // 000000 + "pewhite", // ffffff + "pecyan", // 00ffff + "pepurple", // d020ff + "pegreen", // 00ff00 + "peblue", // 6060ff + "peviolet", // ff80c0 + "pebrown", // a42028 + "pepink", // ffd8d8 + "peyellow", // ffff00 + "pedarkgreen", // 00c000 + "peorange", // ffb000 + "pelightblue", // b0b0ff + "pedarkcyan", // 00a0a0 + "pedarkgray", // 606060 + + "aliceblue", // F0F8FF + "antiquewhite", // FAEBD7 + "aqua", // 00FFFF + "aquamarine", // 7FFFD4 + "azure", // F0FFFF + "beige", // F5F5DC + "bisque", // FFE4C4 + "blanchedalmond", // FFEBCD + "blue", // 0000FF + "blueviolet", // 8A2BE2 + "brown", // A52A2A + "burlywood", // DEB887 + "cadetblue", // 5F9EA0 + "chartreuse", // 7FFF00 + "chocolate", // D2691E + "coral", // FF7F50 + "cornflowerblue", // 6495ED + "cornsilk", // FFF8DC + "crimson", // DC143C + "cyan", // 00FFFF + "darkblue", // 00008B + "darkcyan", // 008B8B + "darkgoldenrod", // B8860B + "darkgray", // A9A9A9 + "darkgreen", // 006400 + "darkkhaki", // BDB76B + "darkmagenta", // 8B008B + "darkolivegreen", // 556B2F + "darkorange", // FF8C00 + "darkorchid", // 9932CC + "darkred", // 8B0000 + "darksalmon", // E9967A + "darkseagreen", // 8FBC8F + "darkslateblue", // 483D8B + "darkslategray", // 2F4F4F + "darkturquoise", // 00CED1 + "darkviolet", // 9400D3 + "deeppink", // FF1493 + "deepskyblue", // 00BFFF + "dimgray", // 696969 + "dodgerblue", // 1E90FF + "firebrick", // B22222 + "floralwhite", // FFFAF0 16775920 + "forestgreen", // 228B22 + "fuchsia", // FF00FF + "gainsboro", // DCDCDC + "ghostwhite", // F8F8FF + "gold", // FFD700 + "goldenrod", // DAA520 + "gray", // 808080 + "green", // 008000 + "greenyellow", // ADFF2F + "honeydew", // F0FFF0 + "hotpink", // FF69B4 + "indianred", // CD5C5C + "indigo", // 4B0082 + "ivory", // FFFFF0 + "khaki", // F0E68C + "lavender", // E6E6FA + "lavenderblush", // FFF0F5 + "lawngreen", // 7CFC00 + "lemonchiffon", // FFFACD + "lightblue", // ADD8E6 + "lightcoral", // F08080 + "lightcyan", // E0FFFF + "lightgoldenrodyellow", // FAFAD2 + "lightgreen", // 90EE90 + "lightgrey", // D3D3D3 + "lightpink", // FFB6C1 + "lightsalmon", // FFA07A + "lightseagreen", // 20B2AA + "lightskyblue", // 87CEFA + "lightslategray", // 778899 + "lightsteelblue", // B0C4DE + "lightyellow", // FFFFE0 + "lime", // 00FF00 + "limegreen", // 32CD32 + "linen", // FAF0E6 + "magenta", // FF00FF + "maroon", // 800000 + "mediumaquamarine", // 66CDAA + "mediumblue", // 0000CD + "mediumorchid", // BA55D3 + "mediumpurple", // 9370DB + "mediumseagreen", // 3CB371 + "mediumslateblue", // 7B68EE + "mediumspringgreen", // 00FA9A + "mediumturquoise", // 48D1CC + "mediumvioletred", // C71585 + "midnightblue", // 191970 + "mintcream", // F5FFFA + "mistyrose", // FFE4E1 + "moccasin", // FFE4B5 + "navajowhite", // FFDEAD + "navy", // 000080 + "oldlace", // FDF5E6 + "olive", // 808000 + "olivedrab", // 6B8E23 + "orange", // FFA500 + "orangered", // FF4500 + "orchid", // DA70D6 + "palegoldenrod", // EEE8AA + "palegreen", // 98FB98 + "paleturquoise", // AFEEEE + "palevioletred", // DB7093 + "papayawhip", // FFEFD5 + "peachpuff", // FFDAB9 + "peru", // CD853F + "pink", // FFC0CB + "plum", // DDA0DD + "powderblue", // B0E0E6 + "purple", // 800080 + "red", // FF0000 + "rosybrown", // BC8F8F + "royalblue", // 4169E1 + "saddlebrown", // 8B4513 + "salmon", // FA8072 + "sandybrown", // F4A460 + "seagreen", // 2E8B57 + "seashell", // FFF5EE + "sienna", // A0522D + "silver", // C0C0C0 + "skyblue", // 87CEEB + "slateblue", // 6A5ACD + "slategray", // 708090 + "snow", // FFFAFA 16775930 + "springgreen", // 00FF7F + "steelblue", // 4682B4 + "tan", // D2B48C + "teal", // 008080 + "thistle", // D8BFD8 + "tomato", // FF6347 + "turquoise", // 40E0D0 + "violet", // EE82EE + "wheat", // F5DEB3 + "white", // FFFFFF 16777215 + "whitesmoke", // F5F5F5 + "yellow", // FFFF00 + "yellowgreen", // 9ACD32 + // plus a few rasmol names/values + "bluetint", // AFD7FF + "greenblue", // 2E8B57 + "greentint", // 98FFB3 + "grey", // 808080 + "pinktint", // FFABBB + "redorange", // FF4500 + "yellowtint", // F6F675 + }; + + private final static int[] colorArgbs = { + //#FFFFC3 hover + 0xFF000000, // black + // plus the PE chain colors + 0xFFffffff, // pewhite + 0xFF00ffff, // pecyan + 0xFFd020ff, // pepurple + 0xFF00ff00, // pegreen + 0xFF6060ff, // peblue + 0xFFff80c0, // peviolet + 0xFFa42028, // pebrown + 0xFFffd8d8, // pepink + 0xFFffff00, // peyellow + 0xFF00c000, // pedarkgreen + 0xFFffb000, // peorange + 0xFFb0b0ff, // pelightblue + 0xFF00a0a0, // pedarkcyan + 0xFF606060, // pedarkgray + // standard JavaScript + 0xFFF0F8FF, // aliceblue + 0xFFFAEBD7, // antiquewhite + 0xFF00FFFF, // aqua + 0xFF7FFFD4, // aquamarine + 0xFFF0FFFF, // azure + 0xFFF5F5DC, // beige + 0xFFFFE4C4, // bisque + 0xFFFFEBCD, // blanchedalmond + 0xFF0000FF, // blue + 0xFF8A2BE2, // blueviolet + 0xFFA52A2A, // brown + 0xFFDEB887, // burlywood + 0xFF5F9EA0, // cadetblue + 0xFF7FFF00, // chartreuse + 0xFFD2691E, // chocolate + 0xFFFF7F50, // coral + 0xFF6495ED, // cornflowerblue + 0xFFFFF8DC, // cornsilk + 0xFFDC143C, // crimson + 0xFF00FFFF, // cyan + 0xFF00008B, // darkblue + 0xFF008B8B, // darkcyan + 0xFFB8860B, // darkgoldenrod + 0xFFA9A9A9, // darkgray + 0xFF006400, // darkgreen + + 0xFFBDB76B, // darkkhaki + 0xFF8B008B, // darkmagenta + 0xFF556B2F, // darkolivegreen + 0xFFFF8C00, // darkorange + 0xFF9932CC, // darkorchid + 0xFF8B0000, // darkred + 0xFFE9967A, // darksalmon + 0xFF8FBC8F, // darkseagreen + 0xFF483D8B, // darkslateblue + 0xFF2F4F4F, // darkslategray + 0xFF00CED1, // darkturquoise + 0xFF9400D3, // darkviolet + 0xFFFF1493, // deeppink + 0xFF00BFFF, // deepskyblue + 0xFF696969, // dimgray + 0xFF1E90FF, // dodgerblue + 0xFFB22222, // firebrick + 0xFFFFFAF0, // floralwhite + 0xFF228B22, // forestgreen + 0xFFFF00FF, // fuchsia + 0xFFDCDCDC, // gainsboro + 0xFFF8F8FF, // ghostwhite + 0xFFFFD700, // gold + 0xFFDAA520, // goldenrod + 0xFF808080, // gray + 0xFF008000, // green + 0xFFADFF2F, // greenyellow + 0xFFF0FFF0, // honeydew + 0xFFFF69B4, // hotpink + 0xFFCD5C5C, // indianred + 0xFF4B0082, // indigo + 0xFFFFFFF0, // ivory + 0xFFF0E68C, // khaki + 0xFFE6E6FA, // lavender + 0xFFFFF0F5, // lavenderblush + 0xFF7CFC00, // lawngreen + 0xFFFFFACD, // lemonchiffon + 0xFFADD8E6, // lightblue + 0xFFF08080, // lightcoral + 0xFFE0FFFF, // lightcyan + 0xFFFAFAD2, // lightgoldenrodyellow + 0xFF90EE90, // lightgreen + 0xFFD3D3D3, // lightgrey + 0xFFFFB6C1, // lightpink + 0xFFFFA07A, // lightsalmon + 0xFF20B2AA, // lightseagreen + 0xFF87CEFA, // lightskyblue + 0xFF778899, // lightslategray + 0xFFB0C4DE, // lightsteelblue + 0xFFFFFFE0, // lightyellow + 0xFF00FF00, // lime + 0xFF32CD32, // limegreen + 0xFFFAF0E6, // linen + 0xFFFF00FF, // magenta + 0xFF800000, // maroon + 0xFF66CDAA, // mediumaquamarine + 0xFF0000CD, // mediumblue + 0xFFBA55D3, // mediumorchid + 0xFF9370DB, // mediumpurple + 0xFF3CB371, // mediumseagreen + 0xFF7B68EE, // mediumslateblue + 0xFF00FA9A, // mediumspringgreen + 0xFF48D1CC, // mediumturquoise + 0xFFC71585, // mediumvioletred + 0xFF191970, // midnightblue + 0xFFF5FFFA, // mintcream + 0xFFFFE4E1, // mistyrose + 0xFFFFE4B5, // moccasin + 0xFFFFDEAD, // navajowhite + 0xFF000080, // navy + 0xFFFDF5E6, // oldlace + 0xFF808000, // olive + 0xFF6B8E23, // olivedrab + 0xFFFFA500, // orange + 0xFFFF4500, // orangered + 0xFFDA70D6, // orchid + 0xFFEEE8AA, // palegoldenrod + 0xFF98FB98, // palegreen + 0xFFAFEEEE, // paleturquoise + 0xFFDB7093, // palevioletred + 0xFFFFEFD5, // papayawhip + 0xFFFFDAB9, // peachpuff + 0xFFCD853F, // peru + 0xFFFFC0CB, // pink + 0xFFDDA0DD, // plum + 0xFFB0E0E6, // powderblue + 0xFF800080, // purple + 0xFFFF0000, // red + 0xFFBC8F8F, // rosybrown + 0xFF4169E1, // royalblue + 0xFF8B4513, // saddlebrown + 0xFFFA8072, // salmon + 0xFFF4A460, // sandybrown + 0xFF2E8B57, // seagreen + 0xFFFFF5EE, // seashell + 0xFFA0522D, // sienna + 0xFFC0C0C0, // silver + 0xFF87CEEB, // skyblue + 0xFF6A5ACD, // slateblue + 0xFF708090, // slategray + 0xFFFFFAFA, // snow + 0xFF00FF7F, // springgreen + 0xFF4682B4, // steelblue + 0xFFD2B48C, // tan + 0xFF008080, // teal + 0xFFD8BFD8, // thistle + 0xFFFF6347, // tomato + 0xFF40E0D0, // turquoise + 0xFFEE82EE, // violet + 0xFFF5DEB3, // wheat + 0xFFFFFFFF, // white + 0xFFF5F5F5, // whitesmoke + 0xFFFFFF00, // yellow + 0xFF9ACD32, // yellowgreen + // plus a few rasmol names/values + 0xFFAFD7FF, // bluetint + 0xFF2E8B57, // greenblue + 0xFF98FFB3, // greentint + 0xFF808080, // grey + 0xFFFFABBB, // pinktint + 0xFFFF4500, // redorange + 0xFFF6F675, // yellowtint + }; + + private static final Map mapJavaScriptColors = new Hashtable(); + + static { + for (int i = colorNames.length; --i >= 0; ) + mapJavaScriptColors.put(colorNames[i], Integer.valueOf(colorArgbs[i])); + } + + /** + * accepts [xRRGGBB] or [0xRRGGBB] or [0xFFRRGGBB] or #RRGGBB or + * [red,green,blue] or a valid JavaScript color + * + * @param strColor + * @return 0 if invalid or integer color + */ + public static int getArgbFromString(String strColor) { + int len = 0; + if (strColor == null || (len = strColor.length()) == 0) + return 0; + if (strColor.charAt(0) == '[' && strColor.charAt(len - 1) == ']') { + String check; + if (strColor.indexOf(",") >= 0) { + String[] tokens = PT.split(strColor.substring(1, strColor + .length() - 1), ","); + if (tokens.length != 3) + return 0; + float red = PT.parseFloat(tokens[0]); + float grn = PT.parseFloat(tokens[1]); + float blu = PT.parseFloat(tokens[2]); + return colorTriadToFFRGB(red, grn, blu); + } + switch (len) { + case 9: + check = "x"; + break; + case 10: + check = "0x"; + break; + default: + return 0; + } + if (strColor.indexOf(check) != 1) + return 0; + strColor = "#" + strColor.substring(len - 7, len - 1); + len = 7; + } + if (len == 7 && strColor.charAt(0) == '#') { + try { + return PT.parseIntRadix(strColor.substring(1, 7), 16) | 0xFF000000; + } catch (Exception e) { + return 0; + } + } + Integer boxedArgb = mapJavaScriptColors.get(strColor.toLowerCase()); + return (boxedArgb == null ? 0 : boxedArgb.intValue()); + } + + public static int colorTriadToFFRGB(float x, float y, float z) { + if (x <= 1 && y <= 1 && z <= 1) { + if (x > 0) + x = x * 256 - 1; + if (y > 0) + y = y * 256 - 1; + if (z > 0) + z = z * 256 - 1; + } + return rgb((int) x, (int) y, (int) z); + } + + public static int rgb(int red, int grn, int blu) { + return 0xFF000000 | (red << 16) | (grn << 8) | blu; + } + + public final static P3 colorPtFromString(String colorName) { + return colorPtFromInt(getArgbFromString(colorName), null); + } + + public final static P3 colorPtFromInt(int color, P3 pt) { + if (pt == null) + pt = new P3(); + pt.set((color >> 16) & 0xFF, (color >> 8) & 0xFF, color & 0xFF); + return pt; + } + + public static int colorPtToFFRGB(T3 pt) { + return colorTriadToFFRGB(pt.x, pt.y, pt.z); + } + + public static void toRGB3f(int c, float[] f) { + f[0] = ((c >> 16) & 0xFF) / 255f; // red + f[1] = ((c >> 8) & 0xFF) / 255f; + f[2] = (c & 0xFF) / 255f; + } + + /** + * Return a greyscale rgb value 0-FF using NTSC color lightness algorithm + *

    + * the alpha component is set to 0xFF. If you want a value in the + * range 0-255 then & the result with 0xFF; + * + * @param rgb the rgb value + * @return a grayscale value in the range 0 - 255 decimal + */ + public static int toFFGGGfromRGB(int rgb) { + int grey = (((2989 * ((rgb >> 16) & 0xFF)) + + (5870 * ((rgb >> 8) & 0xFF)) + + (1140 * (rgb & 0xFF)) + 5000) / 10000) & 0xFFFFFF; + return rgb(grey, grey, grey); + } + + + /** + * Convert RGB values to HSL (hue/saturation/lightness) + * + * @param rgb + * range 255 255 255 + * @param doRound + * set to false when just using this for + * for RGB -- HSL -- HSL' -- RGB' conversion + * + * @return the HSL as P3 range 360 100 100 + * @author hansonr + */ + + public static P3 rgbToHSL(P3 rgb, boolean doRound) { + // adapted from http://tips4java.wordpress.com/2009/07/05/hsl-color/ + // see http://en.wikipedia.org/wiki/HSL_color_space + float r = rgb.x / 255; + float g = rgb.y / 255; + float b = rgb.z / 255; + float min = Math.min(r, Math.min(g, b)); + float max = Math.max(r, Math.max(g, b)); + + // lightness is just p * 50 + + float p = (max + min); + float q = (max - min); + + float h = (60 * ((q == 0 ? 0 : max == r ? ((g - b) / q + 6) + : max == g ? (b - r) / q + 2 : (r - g) / q + 4))) % 360; + + float s = q / (q == 0 ? 1 : p <= 1 ? p : 2 - p); + + // we round to tenths for HSL so that we can return enough + // precision to get back 1-255 in RGB + return (doRound ? P3.new3(Math.round(h*10)/10f, Math.round(s * 1000)/10f, + Math.round(p * 500)/10f) : P3.new3(h, s * 100, p * 50)); + } + + /** + * Convert HSL (hue/saturation/luninance) values to RGB + * + * @param hsl in the range 360, 100, 100 + * @return the RGB as P3 range 0 to 255 + * @author hansonr + */ + public static P3 hslToRGB(P3 hsl) { + // adapted from http://tips4java.wordpress.com/2009/07/05/hsl-color/ + // see http://en.wikipedia.org/wiki/HSL_color_space + + // highly condensed + + float h = Math.max(0, Math.min(360, hsl.x)) / 60; + float s = Math.max(0, Math.min(100, hsl.y)) / 100; + float l = Math.max(0, Math.min(100, hsl.z)) / 100; + + float p = l - (l < 0.5 ? l : 1 - l) * s; + float q = 2 * (l - p); + + float r = toRGB(p, q, h + 2); + float g = toRGB(p, q, h); + float b = toRGB(p, q, h - 2); + return P3.new3(Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)); + } + + private static float toRGB(float p, float q, float h) { + return ((h = (h + (h < 0 ? 6 : h > 6 ? -6 : 0))) < 1 ? p + q * h + : h < 3 ? p + q : h < 4 ? p + q * (4 - h) : p); + } + +} diff --git a/src/javajs/util/CifDataParser.java b/src/javajs/util/CifDataParser.java new file mode 100644 index 0000000..d0cb3fd --- /dev/null +++ b/src/javajs/util/CifDataParser.java @@ -0,0 +1,633 @@ +package javajs.util; + +import java.io.BufferedReader; + +import java.util.Hashtable; + +import java.util.Map; + +import javajs.api.GenericCifDataParser; +import javajs.api.GenericLineReader; + + + +public class CifDataParser implements GenericCifDataParser { + /** + * + * A special tokenizer class for dealing with quoted strings in CIF files. + * + * Greek letters implemented in Jmol 13.3.9 and only for + * titles and space groups. All other mark ups ignored. + * + *

    + * regarding the treatment of single quotes vs. primes in + * cif file, PMR wrote: + *

    + *

    + * * There is a formal grammar for CIF + * (see http://www.iucr.org/iucr-top/cif/index.html) + * which confirms this. The textual explanation is + *

    + *

    + * 14. Matching single or double quote characters (' or ") may + * be used to bound a string representing a non-simple data value + * provided the string does not extend over more than one line. + *

    + *

    + * 15. Because data values are invariably separated from other + * tokens in the file by white space, such a quote-delimited + * character string may contain instances of the character used + * to delimit the string provided they are not followed by white + * space. For example, the data item + * + * _example 'a dog's life' + * + * is legal; the data value is a dog's life. + *

    + *

    + * [PMR - the terminating character(s) are quote+whitespace. + * That would mean that: + * + * _example 'Jones' life' + * + * would be an error + *

    + *

    + * The CIF format was developed in that late 1980's under the aegis of the + * International Union of Crystallography (I am a consultant to the COMCIFs + * committee). It was ratified by the Union and there have been several + * workshops. mmCIF is an extension of CIF which includes a relational + * structure. The formal publications are: + *

    + *

    + * Hall, S. R. (1991). "The STAR File: A New Format for Electronic Data + * Transfer and Archiving", J. Chem. Inform. Comp. Sci., 31, 326-333. + * Hall, S. R., Allen, F. H. and Brown, I. D. (1991). "The Crystallographic + * Information File (CIF): A New Standard Archive File for Crystallography", + * Acta Cryst., A47, 655-685. + * Hall, S.R. & Spadaccini, N. (1994). "The STAR File: Detailed + * Specifications," J. Chem. Info. Comp. Sci., 34, 505-508. + *

    + */ + private GenericLineReader reader; + private BufferedReader br; + + private String line; + private String str; + private int ich; + private int cch; + private boolean wasUnQuoted; + private String strPeeked; + private int ichPeeked; + private int fieldCount; + private String[] loopData; + private SB fileHeader = new SB(); + private boolean isHeader = true; + private String nullString = "\0"; + + /** + * Set the string value of what is returned for "." and "?" + * + * @param nullString null here returns "." and "?"; default is "\0" + * + */ + public void setNullValue(String nullString) { + this.nullString = nullString; + } + + /** + * A global, static map that contains field information. The assumption is that + * if we read a set of fields for, say, atom_site, once in a lifetime, then + * that should be good forever. Those are static lists. Or should be.... + */ + private static Map htFields = new Hashtable(); + + //////////////////////////////////////////////////////////////// + // special tokenizer class + //////////////////////////////////////////////////////////////// + + public CifDataParser() { + // for reflection + } + + private String[] fields; + + @Override + public String getLoopData(int i) { + return loopData[i]; + } + + @Override + public int getFieldCount() { + return fieldCount; + } + + @Override + public String getField(int i) { + return fields[i]; + } + + /** + * A Chemical Information File data parser. + * + * Should be called immediately upon construction. + * + * Two options; one of reader or br should be null, or reader will be + * ignored. Just simpler this way... + * + * @param reader Anything that can deliver a line of text or null + * @param br A standard BufferedReader. + * + */ + @Override + public CifDataParser set(GenericLineReader reader, BufferedReader br) { + this.reader = reader; + this.br = br; + return this; + } + + /** + * + * @return commented-out section at the start of a CIF file. + * + */ + @Override + public String getFileHeader() { + return fileHeader.toString(); + } + + + /** + * Parses all CIF data for a reader defined in the constructor + * into a standard Map structure and close the BufferedReader if + * it exists. + * + * @return Hashtable of models Vector of Hashtable data + */ + @Override + public Map getAllCifData() { + line = ""; + String key; + Map data = null; + Map allData = new Hashtable(); + Lst> models = new Lst>(); + allData.put("models", models); + try { + while ((key = getNextToken()) != null) { + if (key.startsWith("global_") || key.startsWith("data_")) { + models.addLast(data = new Hashtable()); + data.put("name", key); + continue; + } + if (key.startsWith("loop_")) { + getAllCifLoopData(data); + continue; + } + if (key.charAt(0) != '_') { + System.out.println("CIF ERROR ? should be an underscore: " + key); + } else { + String value = getNextToken(); + if (value == null) { + System.out.println("CIF ERROR ? end of file; data missing: " + key); + } else { + data.put(fixKey(key), value); + } + } + } + } catch (Exception e) { + // ? + } + try { + if (br != null) + br.close(); + } catch (Exception e) { + // ? + } + return allData; + } + + /** + * create our own list of keywords and for each one create a list + * of data associated with that keyword. For example, a list of all + * x coordinates, then a list of all y coordinates, etc. + * + * @param data + * @throws Exception + */ + @SuppressWarnings("unchecked") + private void getAllCifLoopData(Map data) throws Exception { + String key; + Lst keyWords = new Lst(); + while ((key = peekToken()) != null && key.charAt(0) == '_') { + key = fixKey(getTokenPeeked()); + keyWords.addLast(key); + data.put(key, new Lst()); + } + fieldCount = keyWords.size(); + if (fieldCount == 0) + return; + loopData = new String[fieldCount]; + while (getData()) + for (int i = 0; i < fieldCount; i++) + ((Lst)data.get(keyWords.get(i))).addLast(loopData[i]); + } + + @Override + public String readLine() { + try { + line = (reader == null ? br.readLine() : reader.readNextLine()); + if (line == null) + return null; + if (isHeader) { + if (line.startsWith("#")) + fileHeader.append(line).appendC('\n'); + else + isHeader = false; + } + return line; + } catch (Exception e) { + return null; + } + } + + /** + * The work horse; a general reader for loop data. + * Fills loopData with fieldCount fields. + * + * @return false if EOF + * @throws Exception + */ + @Override + public boolean getData() throws Exception { + // line is already present, and we leave with the next line to parse + for (int i = 0; i < fieldCount; ++i) + if ((loopData[i] = getNextDataToken()) == null) + return false; + return (fieldCount > 0); + } + + /** + * + * Skips all associated loop data. (Skips to next control word.) + * + * @throws Exception + */ + @Override + public String skipLoop(boolean doReport) throws Exception { + String str; + SB ret = (doReport ? new SB() : null); + int n = 0; + while ((str = peekToken()) != null && str.charAt(0) == '_') { + if (ret != null) + ret.append(str).append("\n"); + getTokenPeeked(); + n++; + } + int m = 0; + while ((str = getNextDataToken()) != null) { + if (ret == null) + continue; + ret.append(str).append(" "); + if ((++m % n) == 0) + ret.append("\n"); + } + return (ret == null ? null : ret.toString()); + } + + /** + * + * @return the next token of any kind, or null + * @throws Exception + */ + @Override + public String getNextToken() throws Exception { + while (!strHasMoreTokens()) + if (setStringNextLine() == null) + return null; + return nextStrToken(); + } + + /** + * + * first checks to see if the next token is an unquoted + * control code, and if so, returns null + * + * @return next data token or null + * @throws Exception + */ + @Override + public String getNextDataToken() throws Exception { + String str = peekToken(); + if (str == null) + return null; + if (wasUnQuoted) + if (str.charAt(0) == '_' || str.startsWith("loop_") + || str.startsWith("data_") + || str.startsWith("stop_") + || str.startsWith("global_")) + return null; + return getTokenPeeked(); + } + + /** + * Just look at the next token. Saves it for retrieval + * using getTokenPeeked() + * + * @return next token or null if EOF + * @throws Exception + */ + @Override + public String peekToken() throws Exception { + while (!strHasMoreTokens()) + if (setStringNextLine() == null) + return null; + int ich = this.ich; + strPeeked = nextStrToken(); + ichPeeked= this.ich; + this.ich = ich; + return strPeeked; + } + + /** + * + * @return the token last acquired; may be null + */ + @Override + public String getTokenPeeked() { + ich = ichPeeked; + return strPeeked; + } + + /** + * Used especially for data that might be multi-line data that + * might have unwanted white space at start or end. + * + * @param str + * @return str without any leading/trailing white space, and no '\n' + */ + @Override + public String fullTrim(String str) { + int pt0 = -1; + int pt1 = str.length(); + while (++pt0 < pt1 && PT.isWhitespace(str.charAt(pt0))) { + } + while (--pt1 > pt0 && PT.isWhitespace(str.charAt(pt1))) { + } + return str.substring(pt0, pt1 + 1); + } + + private final static String grABC = + "ABX\u0394E\u03A6\u0393H" // ABCDEFGH + + "I_K\u039BMNO\u03A0" // I_KLMNOP + + "\u0398P\u03A3TY_\u03A9\u039E\u03A5Z"; // QRSTU_WXYZ + private final static String grabc = + "\u03B1\u03B2\u03C7\u03A4\u03A5\u03C6\u03B3\u03B7" // abcdefgh + + "\u03B9_\u03BA\u03BB\u03BC\u03BD\u03BF\u03C0" // i_klmnop + + "\u03B8\u03C1\u03C3\u03C4\u03C5_\u03C9\u03BE\u03C5\u03B6"; // qrstu_wxyz + + /** + * Only translating the basic Greek set here, not all the other stuff. See + * http://www.iucr.org/resources/cif/spec/version1.1/semantics#markup + * + * @param data + * @return cleaned string + */ + @Override + public String toUnicode(String data) { + int pt; + try { + while ((pt = data.indexOf('\\')) >= 0) { + int c = data.charAt(pt + 1); + String ch = (c >= 65 && c <= 90 ? grABC.substring(c - 65, c - 64) + : c >= 97 && c <= 122 ? grabc.substring(c - 97, c - 96) : "_"); + data = data.substring(0, pt) + ch + data.substring(pt + 2); + } + } catch (Exception e) { + // ignore + } + + return data; + } + + /** + * Passing an array of field names, this method fills two arrays. + * The first, fieldOf, identifies + * It does this by first creating a map of names to their indices in fields[]. + * + * Alternatively, if fields is null, then a private array is filled, in order, + * with key data. This is used in cases such as matrices for which there are simply + * too many possibilities to list, and the key name itself contains the x-y + * information that we need. + * + */ + @Override + public int parseLoopParameters(String[] fields, int[] fieldOf, int[] propertyOf) throws Exception { + int propertyCount = 0; + if (fields == null) { + // for reading full list of keys, as for matrices + this.fields = new String[100]; + } else { + if (!htFields.containsKey(fields[0])) + for (int i = fields.length; --i >= 0;) + htFields.put(fields[i], Integer.valueOf(i)); + for (int i = fields.length; --i >= 0;) + fieldOf[i] = NONE; + propertyCount = fields.length; + } + fieldCount = 0; + while (true) { + String str = peekToken(); + if (str == null) { + // we are PREMATURELY done; reset + fieldCount = 0; + break; + } + // end of the loop is a new token starting with underscore + if (str.charAt(0) != '_') + break; + + int pt = fieldCount++; + str = fixKey(getTokenPeeked()); + if (fields == null) { + // just make a linear model, saving the list + this.fields[propertyOf[pt] = fieldOf[pt] = pt] = str; + continue; + } + Integer iField = htFields.get(str); + int i = (iField == null ? NONE : iField.intValue()); + if ((propertyOf[pt] = i) != NONE) + fieldOf[i] = pt; + } + if (fieldCount > 0) + loopData = new String[fieldCount]; + return propertyCount; + } + + @Override + public String fixKey(String key) { + // PRELIMINARY -- BilBao _magnetic + // PRELIMINARY -- Jana2006 + return (PT.rep( + key.startsWith("_magnetic") ? key.substring(9) + : key.startsWith("_jana") ? key.substring(5) + : key, ".", "_").toLowerCase()); + } + + //////////////////// private methods //////////////////// + + + /** + * sets a string to be parsed from the beginning + * + * @param str + */ + private void setString(String str) { + this.str = line = str; + cch = (str == null ? 0 : str.length()); + ich = 0; + } + + /* + * http://www.iucr.org/resources/cif/spec/version1.1/cifsyntax + * + * 17. The special sequence of end-of-line followed + * immediately by a semicolon in column one (denoted ";") + * may also be used as a delimiter at the beginning and end + * of a character string comprising a data value. The complete + * bounded string is called a text field, and may be used to + * convey multi-line values. The end-of-line associated with + * the closing semicolon does not form part of the data value. + * Within a multi-line text field, leading white space within + * text lines must be retained as part of the data value; trailing + * white space on a line may however be elided. + * + * 18. A text field delimited by the ; digraph may not + * include a semicolon at the start of a line of text as + * part of its value. + * + * 20. For example, the data value foo may be expressed + * equivalently as an unquoted string foo, as a quoted + * string 'foo' or as a text field + * + *;foo + *; + * + * By contrast the value of the text field + * + *; foo + * bar + *; + * + * is foo bar (where represents an end-of-line); + * the embedded space characters are significant. + * + * + * I (BH) note, however, that we sometimes have: + * + * _some_name + * ; + * the name here + * ; + * + * so this should actually be + * + * ;the name here + * ; + * + * for this, we use fullTrim(); + * + */ + + /** + * + * sets the string for parsing to be from the next line + * when the token buffer is empty, and if ';' is at the + * beginning of that line, extends the string to include + * that full multiline string. Uses \1 to indicate that + * this is a special quotation. + * + * @return the next line or null if EOF + * @throws Exception + */ + private String setStringNextLine() throws Exception { + setString(readLine()); + if (line == null || line.length() == 0) + return line; + if (line.charAt(0) != ';') { + if (str.startsWith("###non-st#")) + ich = 10; + return line; + } + ich = 1; + String str = '\1' + line.substring(1) + '\n'; + while (readLine() != null) { + if (line.startsWith(";")) { + // remove trailing only, and attach rest of next line + str = str.substring(0, str.length() - 1) + + '\1' + line.substring(1); + break; + } + str += line + '\n'; + } + setString(str); + return str; + } + + /** + * @return TRUE if there are more tokens in the line buffer + * + */ + private boolean strHasMoreTokens() { + if (str == null) + return false; + char ch = '#'; + while (ich < cch && ((ch = str.charAt(ich)) == ' ' || ch == '\t')) + ++ich; + return (ich < cch && ch != '#'); + } + + /** + * assume that hasMoreTokens() has been called and that + * ich is pointing at a non-white character. Also sets + * boolean wasUnQuoted, because we need to know if we should + * be checking for a control keyword. 'loop_' is different from just + * loop_ without the quotes. + * + * @return null if no more tokens, "\0" if '.' or '?', or next token + */ + private String nextStrToken() { + if (ich == cch) + return null; + int ichStart = ich; + char ch = str.charAt(ichStart); + if (ch != '\'' && ch != '"' && ch != '\1') { + wasUnQuoted = true; + while (ich < cch && (ch = str.charAt(ich)) != ' ' && ch != '\t') + ++ich; + if (ich == ichStart + 1) + if (nullString != null && (str.charAt(ichStart) == '.' || str.charAt(ichStart) == '?')) + return nullString; + String s = str.substring(ichStart, ich); + return s; + } + wasUnQuoted = false; + char chOpeningQuote = ch; + boolean previousCharacterWasQuote = false; + while (++ich < cch) { + ch = str.charAt(ich); + if (previousCharacterWasQuote && (ch == ' ' || ch == '\t')) + break; + previousCharacterWasQuote = (ch == chOpeningQuote); + } + if (ich == cch) { + if (previousCharacterWasQuote) // close quote was last char of string + return str.substring(ichStart + 1, ich - 1); + // reached the end of the string without finding closing ' + return str.substring(ichStart, ich); + } + ++ich; // throw away the last white character + return str.substring(ichStart + 1, ich - 2); + } + + +} \ No newline at end of file diff --git a/src/javajs/util/CompoundDocDirEntry.java b/src/javajs/util/CompoundDocDirEntry.java new file mode 100644 index 0000000..3eaab5e --- /dev/null +++ b/src/javajs/util/CompoundDocDirEntry.java @@ -0,0 +1,93 @@ +/* $RCSfile$ + * $Author$ + * $Date$ + * $Revision$ + * + * Copyright (C) 2011 The Jmol Development Team + * + * Contact: jmol-developers@lists.sf.net + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +package javajs.util; + + +class CompoundDocDirEntry { + + private final CompoundDocument cd; + + /** + * @param compoundDocument + */ + CompoundDocDirEntry(CompoundDocument compoundDocument) { + cd = compoundDocument; + } + + // 128 bytes + //offset 0: + byte[] unicodeName64 = new byte[64]; + short nBytesUnicodeName; // twice the ascii length, including terminating 0 + byte entryType; // 0 empty; 1 storage; 2 stream; 5 root storage + //byte entryColor; // 0 red or 1 black + //int DIDchildLeft; + //int DIDchildRight; + //int DIDstorageRoot; + byte[] uniqueID16 = new byte[16]; + byte[] userflags4 = new byte[4]; + //long timeStamp1; + //long timeStamp2; + //offset 116: + int SIDfirstSector; // either SAT or SSAT + int lenStream; + byte[] unused = new byte[8]; + + // derived: + + String entryName; + boolean isStandard; + boolean isEmpty; + + final boolean readData() { + try { + cd.readByteArray(unicodeName64, 0, 64); + nBytesUnicodeName = cd.readShort(); + entryType = cd.readByte(); + /*entryColor = */cd.readByte(); + /*DIDchildLeft = */cd.readInt(); + /*DIDchildRight = */cd.readInt(); + /*DIDstorageRoot = */cd.readInt(); + cd.readByteArray(uniqueID16, 0, 16); + cd.readByteArray(userflags4, 0, 4); + /*timeStamp1 = */ cd.readByteArray(unused, 0, 8);//cd.readLong(); + /*timeStamp2 = */ cd.readByteArray(unused, 0, 8);//cd.readLong(); + //offset 116: + SIDfirstSector = cd.readInt(); + lenStream = cd.readInt(); + cd.readByteArray(unused, 0, 4); + } catch (Exception e) { + System.out.println(e.toString()); + return false; + } + entryName = ""; + for (int i = 0; i < nBytesUnicodeName - 2; i += 2) + entryName += (char) unicodeName64[i]; + isStandard = (entryType == 5 || lenStream >= cd.header.minBytesStandardStream); + isEmpty = (entryType == 0 || lenStream <= 0); + //System.out.println(entryName + " type " + entryType); + return true; + } +} \ No newline at end of file diff --git a/src/javajs/util/CompoundDocHeader.java b/src/javajs/util/CompoundDocHeader.java new file mode 100644 index 0000000..e81c79e --- /dev/null +++ b/src/javajs/util/CompoundDocHeader.java @@ -0,0 +1,112 @@ +/* $RCSfile$ + * $Author$ + * $Date$ + * $Revision$ + * + * Copyright (C) 2011 The Jmol Development Team + * + * Contact: jmol-developers@lists.sf.net + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +package javajs.util; + + +class CompoundDocHeader { + + /** + * + */ + private final CompoundDocument cd; + + /** + * @param compoundDocument + */ + CompoundDocHeader(CompoundDocument compoundDocument) { + cd = compoundDocument; + } + + //512 bytes + //offset 0: + byte[] magicNumbers = new byte[8]; // D0CF11E0A1B11AE1 + byte[] uniqueID16 = new byte[16]; + byte revNumber; // 3E = 62 + //byte unusedb1; + byte verNumber; // 3 + //byte unusedb2; + //short byteOrder; // -2 littleEndian + short sectorPower; // 2^sectorPower = sector size; 512 = 2^9 + short shortSectorPower; // 2^shortSectorPower = short sector size; 64 = 2^6 + byte[] unused = new byte[10]; + int nSATsectors; // number of sectors for sector allocation table + int SID_DIR_start; // sector identifier of start of directory sector + //offset 56: + int minBytesStandardStream; // less than this (and not DIR) will be "short" + int SID_SSAT_start; // start of short sector allocation table (SSAT) + int nSSATsectors; // number of sectors allocated to SSAT + int SID_MSAT_next; // pointer to next master sector allocation table sector + int nAdditionalMATsectors; // number of sectors allocated to more MSAT sectors + //offset 76; 436 bytes: + int[] MSAT0 = new int[109]; // beginning of master allocation table + + /* + * Sector 0 is first sector AFTER this header + * + * If sectorPower = 9, then this allows for 109 PAGES + * of sector allocation tables, with 127 pointers per + * page (plus 1 pointer to the next SAT page), each + * pointing to a sector of 512 bytes. Thus, with no additional + * MSAT pages, the header allows for 109*128*512 = 7.1 Mb file + * + */ + + final boolean readData() { + try { + cd.readByteArray(magicNumbers, 0, 8); + if (magicNumbers[0] != (byte) 0xD0 || magicNumbers[1] != (byte) 0xCF + || magicNumbers[2] != (byte) 0x11 || magicNumbers[3] != (byte) 0xE0 + || magicNumbers[4] != (byte) 0xA1 || magicNumbers[5] != (byte) 0xB1 + || magicNumbers[6] != (byte) 0x1A || magicNumbers[7] != (byte) 0xE1) + return false; + cd.readByteArray(uniqueID16, 0, 16); + revNumber = cd.readByte(); + cd.readByte(); + verNumber = cd.readByte(); + cd.readByte(); + byte b1 = cd.readByte(); + byte b2 = cd.readByte(); + cd.isBigEndian = (b1 == -1 && b2 == -2); + sectorPower = cd.readShort(); + shortSectorPower = cd.readShort(); + cd.readByteArray(unused, 0, 10); + nSATsectors = cd.readInt(); + SID_DIR_start = cd.readInt(); + cd.readByteArray(unused, 0, 4); + minBytesStandardStream = cd.readInt(); + SID_SSAT_start = cd.readInt(); + nSSATsectors = cd.readInt(); + SID_MSAT_next = cd.readInt(); + nAdditionalMATsectors = cd.readInt(); + for (int i = 0; i < 109; i++) + MSAT0[i] = cd.readInt(); + } catch (Exception e) { + System.out.println(e.toString()); + return false; + } + return true; + } +} \ No newline at end of file diff --git a/src/javajs/util/CompoundDocument.java b/src/javajs/util/CompoundDocument.java new file mode 100644 index 0000000..15168a5 --- /dev/null +++ b/src/javajs/util/CompoundDocument.java @@ -0,0 +1,395 @@ +/* $RCSfile$ + * $Author: egonw $ + * $Date: 2006-03-18 15:59:33 -0600 (Sat, 18 Mar 2006) $ + * $Revision: 4652 $ + * + * Copyright (C) 2003-2005 Miguel, Jmol Development, www.jmol.org + * + * Contact: hansonr@stolaf.edu + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + */ +package javajs.util; + + +import java.io.DataInputStream; +import java.io.BufferedInputStream; + + +import java.util.Map; + +import javajs.api.GenericZipTools; + + + +/* a simple compound document reader. + * See http://sc.openoffice.org/compdocfileformat.pdf + * + * random access file info: + * http://java.sun.com/docs/books/tutorial/essential/io/rafs.html + * + * SHOOT! random access is only for applications, not applets! + * + * With a bit more work, this could be set up to deliver binary files, but + * right now I've only implemented it for string-based data. All Jmol is using + * is getAllData(). + * + */ + +public class CompoundDocument extends BinaryDocument{ + +// RandomAccessFile file; + CompoundDocHeader header = new CompoundDocHeader(this); + Lst directory = new Lst(); + CompoundDocDirEntry rootEntry; + + int[] SAT; + int[] SSAT; + int sectorSize; + int shortSectorSize; + int nShortSectorsPerStandardSector; + int nIntPerSector; + int nDirEntriesperSector; + + // called by reflection + + public CompoundDocument(){ + super(); + this.isBigEndian = true; + } + + @Override + public void setStream(GenericZipTools jzt, BufferedInputStream bis, boolean isBigEndian) { + // isBigEndian is ignored here; it must be true + /* try { + file = new RandomAccessFile(fileName, "r"); + isRandom = true; + } catch (Exception e) { + // probably an applet + } + */ + this.jzt = jzt; + if (!isRandom) { + stream = new DataInputStream(bis); + } + stream.mark(Integer.MAX_VALUE); + if (!readHeader()) + return; + getSectorAllocationTable(); + getShortSectorAllocationTable(); + getDirectoryTable(); + } + + public Lst getDirectory() { + return directory; + } + + public String getDirectoryListing(String separator) { + String str = ""; + for (int i = 0; i < directory.size(); i++) { + CompoundDocDirEntry thisEntry = directory.get(i); + if (!thisEntry.isEmpty) + str += separator + + thisEntry.entryName + + "\tlen=" + + thisEntry.lenStream + + "\tSID=" + + thisEntry.SIDfirstSector + + (thisEntry.isStandard ? "\tfileOffset=" + + getOffset(thisEntry.SIDfirstSector) : ""); + } + return str; + } + + SB data; + + public SB getAllData() { + return getAllDataFiles(null, null); + } + + /** + * reads a compound document directory and saves all data in a Hashtable + * so that the files may be organized later in a different order. Also adds + * a #Directory_Listing entry. + * + * Files are bracketed by BEGIN Directory Entry and END Directory Entry lines, + * similar to ZipUtil.getAllData. + * + * @param prefix + * @param binaryFileList |-separated list of files that should be saved + * as xx xx xx hex byte strings. The directory listing + * is appended with ":asBinaryString" + * @param fileData + */ + @Override + public void getAllDataMapped(String prefix, + String binaryFileList, Map fileData) { + fileData.put("#Directory_Listing", getDirectoryListing("|")); + binaryFileList = "|" + binaryFileList + "|"; + for (int i = 0; i < directory.size(); i++) { + CompoundDocDirEntry thisEntry = directory.get(i); + if (!thisEntry.isEmpty && thisEntry.entryType != 5) { + String name = thisEntry.entryName; + System.out.println("CompoundDocument file " + name); + boolean isBinary = (binaryFileList.indexOf("|" + name + "|") >= 0); + if (isBinary) + name += ":asBinaryString"; + SB data = new SB(); + data.append("BEGIN Directory Entry ").append(name).append("\n"); + data.appendSB(getEntryAsString(thisEntry, isBinary)); + data.append("\nEND Directory Entry ").append(name).append("\n"); + fileData.put(prefix + "/" + name, data.toString()); + } + } + close(); + } + + @Override + public SB getAllDataFiles(String binaryFileList, String firstFile) { + if (firstFile != null) { + for (int i = 0; i < directory.size(); i++) { + CompoundDocDirEntry thisEntry = directory.get(i); + if (thisEntry.entryName.equals(firstFile)) { + directory.remove(i); + directory.add(1, thisEntry); // after ROOT_ENTRY + break; + } + } + } + data = new SB(); + data.append("Compound Document File Directory: "); + data.append(getDirectoryListing("|")); + data.append("\n"); + binaryFileList = "|" + binaryFileList + "|"; + for (int i = 0; i < directory.size(); i++) { + CompoundDocDirEntry thisEntry = directory.get(i); + //System.out.println("CompoundDocument reading " + thisEntry.entryName); + if (!thisEntry.isEmpty && thisEntry.entryType != 5) { + String name = thisEntry.entryName; + if (name.endsWith(".gz")) + name = name.substring(0, name.length() - 3); + data.append("BEGIN Directory Entry ").append(name).append("\n"); + data.appendSB(getEntryAsString(thisEntry, binaryFileList.indexOf("|" + thisEntry.entryName + "|") >= 0)); + data.append("\n"); + data.append("END Directory Entry ").append(thisEntry.entryName).append("\n"); + } + } + close(); + return data; + } + + public SB getFileAsString(String entryName) { + for (int i = 0; i < directory.size(); i++) { + CompoundDocDirEntry thisEntry = directory.get(i); + if (thisEntry.entryName.equals(entryName)) + return getEntryAsString(thisEntry, false); + } + return new SB(); + } + + private long getOffset(int SID) { + return (SID + 1) * sectorSize; + } + + private void gotoSector(int SID) { + seek(getOffset(SID)); + } + + private boolean readHeader() { + if (!header.readData()) + return false; + sectorSize = 1 << header.sectorPower; + shortSectorSize = 1 << header.shortSectorPower; + nShortSectorsPerStandardSector = sectorSize / shortSectorSize; // e.g. 512 / 64 = 8 + nIntPerSector = sectorSize / 4; // e.g. 512 / 4 = 128 + nDirEntriesperSector = sectorSize / 128; // e.g. 512 / 128 = 4 +// System.out.println( +// "compound document: revNum=" + header.revNumber + +// " verNum=" + header.verNumber + " isBigEndian=" + isBigEndian + +// " bytes per standard/short sector=" + sectorSize + "/" + shortSectorSize); + return true; + } + + private void getSectorAllocationTable() { + int nSID = 0; + int thisSID; + SAT = new int[header.nSATsectors * nIntPerSector + 109]; + + try { + for (int i = 0; i < 109; i++) { + thisSID = header.MSAT0[i]; + if (thisSID < 0) + break; + gotoSector(thisSID); + for (int j = 0; j < nIntPerSector; j++) { + SAT[nSID++] = readInt(); + //Logger.debug(thisSID+"."+j + "/" + (nSID - 1) + " : " + SAT[nSID - 1]); + } + } + int nMaster = header.nAdditionalMATsectors; + thisSID = header.SID_MSAT_next; + int[] MSAT = new int[nIntPerSector]; + out: while (nMaster-- > 0 && thisSID >= 0) { + // read a page of sector identifiers pointing to SAT sectors + gotoSector(thisSID); + for (int i = 0; i < nIntPerSector; i++) + MSAT[i] = readInt(); + // read each page of SAT sector identifiers + // last entry is pointer to next master sector allocation table page + for (int i = 0; i < nIntPerSector - 1; i++) { + thisSID = MSAT[i]; + if (thisSID < 0) + break out; + gotoSector(thisSID); + for (int j = nIntPerSector; --j >= 0;) + SAT[nSID++] = readInt(); + } + thisSID = MSAT[nIntPerSector - 1]; + } + } catch (Exception e) { + System.out.println(e.toString()); + } + } + + private void getShortSectorAllocationTable() { + int nSSID = 0; + int thisSID = header.SID_SSAT_start; + int nMax = header.nSSATsectors * nIntPerSector; + SSAT = new int[nMax]; + try { + while (thisSID > 0 && nSSID < nMax) { + gotoSector(thisSID); + for (int j = 0; j < nIntPerSector; j++) { + SSAT[nSSID++] = readInt(); + //System.out.println("short: " + thisSID+"."+j+" SSID=" +(nSSID-1)+" "+SSAT[nSSID-1]); + } + thisSID = SAT[thisSID]; + } + } catch (Exception e) { + System.out.println(e.toString()); + } + } + + private void getDirectoryTable() { + int thisSID = header.SID_DIR_start; + CompoundDocDirEntry thisEntry; + rootEntry = null; + try { + while (thisSID > 0) { + gotoSector(thisSID); + for (int j = nDirEntriesperSector; --j >= 0;) { + thisEntry = new CompoundDocDirEntry(this); + thisEntry.readData(); + if (thisEntry.lenStream > 0) { + directory.addLast(thisEntry); + //System.out.println(thisEntry.entryName); + } + if (thisEntry.entryType == 5) + rootEntry = thisEntry; + } + thisSID = SAT[thisSID]; + } + } catch (Exception e) { + System.out.println(e.toString()); + } +// System.out.println("CompoundDocument directory entry: \n" +// + getDirectoryListing("\n")); + } + + private SB getEntryAsString(CompoundDocDirEntry thisEntry, boolean asBinaryString) { + if(thisEntry.isEmpty) + return new SB(); + //System.out.println(thisEntry.entryName + " " + thisEntry.entryType + " " + thisEntry.lenStream + " " + thisEntry.isStandard + " " + thisEntry.SIDfirstSector); + return (thisEntry.isStandard ? getStandardStringData( + thisEntry.SIDfirstSector, thisEntry.lenStream, asBinaryString) + : getShortStringData(thisEntry.SIDfirstSector, thisEntry.lenStream, asBinaryString)); + } + private SB getStandardStringData(int thisSID, int nBytes, + boolean asBinaryString) { + SB data = new SB(); + byte[] byteBuf = new byte[sectorSize]; + ZipData gzipData = new ZipData(nBytes); + try { + while (thisSID > 0 && nBytes > 0) { + gotoSector(thisSID); + nBytes = getSectorData(data, byteBuf, sectorSize, nBytes, asBinaryString, gzipData); + thisSID = SAT[thisSID]; + } + if (nBytes == -9999) + return new SB(); + } catch (Exception e) { + System.out.println(e.toString()); + } + if (gzipData.isEnabled) + gzipData.addTo(jzt, data); + return data; + } + + private int getSectorData(SB data, byte[] byteBuf, + int nSectorBytes, int nBytes, + boolean asBinaryString, ZipData gzipData) + throws Exception { + readByteArray(byteBuf, 0, byteBuf.length); + int n = gzipData.addBytes(byteBuf, nSectorBytes, nBytes); + if (n >= 0) + return n; + if (asBinaryString) { + for (int i = 0; i < nSectorBytes; i++) { + data.append(Integer.toHexString(byteBuf[i] & 0xFF)).appendC(' '); + if (--nBytes < 1) + break; + } + } else { + for (int i = 0; i < nSectorBytes; i++) { + if (byteBuf[i] == 0) + return -9999; // don't allow binary data + data.appendC((char) byteBuf[i]); + if (--nBytes < 1) + break; + } + } + return nBytes; + } + + private SB getShortStringData(int shortSID, int nBytes, boolean asBinaryString) { + SB data = new SB(); + if (rootEntry == null) + return data; + int thisSID = rootEntry.SIDfirstSector; + int ptShort = 0; + byte[] byteBuf = new byte[shortSectorSize]; + ZipData gzipData = new ZipData(nBytes); + try { + //System.out.println("CD shortSID=" + shortSID); + // point to correct short data sector, 512/64 = 4 per page + while (thisSID >= 0 && shortSID >= 0 && nBytes > 0) { + while (shortSID - ptShort >= nShortSectorsPerStandardSector) { + ptShort += nShortSectorsPerStandardSector; + thisSID = SAT[thisSID]; + } + seek(getOffset(thisSID) + (shortSID - ptShort) * shortSectorSize); + nBytes = getSectorData(data, byteBuf, shortSectorSize, nBytes, asBinaryString, gzipData); + shortSID = SSAT[shortSID]; + //System.out.println("CD shortSID=" + shortSID); + } + } catch (Exception e) { + System.out.println(data.toString()); + System.out.println("reader error in CompoundDocument " + e.toString()); + } + if (gzipData.isEnabled) + gzipData.addTo(jzt, data); + return data; + } +} diff --git a/src/javajs/util/DF.java b/src/javajs/util/DF.java new file mode 100644 index 0000000..ccff3e2 --- /dev/null +++ b/src/javajs/util/DF.java @@ -0,0 +1,161 @@ +/* $RCSfile$ + * $Author: hansonr $ + * $Date: 2007-04-26 16:57:51 -0500 (Thu, 26 Apr 2007) $ + * $Revision: 7502 $ + * + * Copyright (C) 2005 The Jmol Development Team + * + * Contact: jmol-developers@lists.sf.net + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +package javajs.util; + +/** + * created to remove ambiguities and make a simpler DecimalFormat + */ +public class DF { + + private final static String[] formattingStrings = { "0", "0.0", "0.00", + "0.000", "0.0000", "0.00000", "0.000000", "0.0000000", "0.00000000", + "0.000000000" }; + private final static String zeros = "0000000000000000000000000000000000000000"; + + private final static float[] formatAdds = { 0.5f, 0.05f, 0.005f, 0.0005f, + 0.00005f, 0.000005f, 0.0000005f, 0.00000005f, 0.000000005f, 0.0000000005f }; + + private final static Boolean[] useNumberLocalization = new Boolean[] { Boolean.TRUE }; + + public static void setUseNumberLocalization(boolean TF) { + useNumberLocalization[0] = (TF ? Boolean.TRUE : Boolean.FALSE); + } + + public static String formatDecimalDbl(double value, int decimalDigits) { + if (decimalDigits == Integer.MAX_VALUE + || value == Double.NEGATIVE_INFINITY + || value == Double.POSITIVE_INFINITY + || Double.isNaN(value)) + return "" + value; + return DF.formatDecimal((float) value, decimalDigits); + } + + /** + * a simple alternative to DecimalFormat (which Java2Script does not have + * and which is quite too complex for our use here.) + * + * @param value + * @param decimalDigits + * @return formatted decimal + */ + public static String formatDecimal(float value, int decimalDigits) { + if (decimalDigits == Integer.MAX_VALUE + || value == Float.NEGATIVE_INFINITY || value == Float.POSITIVE_INFINITY || Float.isNaN(value)) + return "" + value; + int n; + if (decimalDigits < 0) { + decimalDigits = -decimalDigits; + if (decimalDigits > formattingStrings.length) + decimalDigits = formattingStrings.length; + if (value == 0) + return formattingStrings[decimalDigits] + "E+0"; + //scientific notation + n = 0; + double d; + if (Math.abs(value) < 1) { + n = 10; + d = value * 1e-10; + } else { + n = -10; + d = value * 1e10; + } + String s = ("" + d).toUpperCase(); + int i = s.indexOf("E"); + n = PT.parseInt(s.substring(i + 1)) + n; + return (i < 0 ? "" + value : formatDecimal(PT.parseFloat(s.substring( + 0, i)), decimalDigits - 1) + + "E" + (n >= 0 ? "+" : "") + n); + } + + if (decimalDigits >= formattingStrings.length) + decimalDigits = formattingStrings.length - 1; + String s1 = ("" + value).toUpperCase(); + int pt = s1.indexOf("."); + if (pt < 0) // specifically JavaScript "-2" not "-2.0" + return s1 + formattingStrings[decimalDigits].substring(1); + boolean isNeg = s1.startsWith("-"); + if (isNeg) { + s1 = s1.substring(1); + pt--; + } + int pt1 = s1.indexOf("E-"); + if (pt1 > 0) { + n = PT.parseInt(s1.substring(pt1 + 1)); + // 3.567E-2 + // 0.03567 + s1 = "0." + zeros.substring(0, -n - 1) + s1.substring(0, 1) + s1.substring(2, pt1); + pt = 1; + } + + pt1 = s1.indexOf("E"); + // 3.5678E+3 + // 3567.800000000 + // 1.234E10 %3.8f -> 12340000000.00000000 + if (pt1 > 0) { + n = PT.parseInt(s1.substring(pt1 + 1)); + s1 = s1.substring(0, 1) + s1.substring(2, pt1) + zeros; + s1 = s1.substring(0, n + 1) + "." + s1.substring(n + 1); + pt = s1.indexOf("."); + } + // "234.345667 len == 10; pt = 3 + // " 0.0 " decimalDigits = 1 + + int len = s1.length(); + int pt2 = decimalDigits + pt + 1; + if (pt2 < len && s1.charAt(pt2) >= '5') { + return formatDecimal( + value + (isNeg ? -1 : 1) * formatAdds[decimalDigits], decimalDigits); + } + + SB sb = SB.newS(s1.substring(0, (decimalDigits == 0 ? pt + : ++pt))); + for (int i = 0; i < decimalDigits; i++, pt++) { + if (pt < len) + sb.appendC(s1.charAt(pt)); + else + sb.appendC('0'); + } + s1 = (isNeg ? "-" : "") + sb; + return (Boolean.TRUE.equals(useNumberLocalization[0]) ? s1 : s1.replace(',', + '.')); + } + + /** + * an alternative to DecimalFormat "0.#" + * + * @param x + * @param precision + * @return formatted number + */ + public static String formatDecimalTrimmed(double x, int precision) { + String str = formatDecimalDbl(x, precision); + int m = str.length() - 1; + char zero = '0'; + while (m >= 0 && str.charAt(m) == zero) + m--; + return str.substring(0, m + 1); // 0.##... + } + +} diff --git a/src/javajs/util/DataReader.java b/src/javajs/util/DataReader.java new file mode 100644 index 0000000..1eb8ade --- /dev/null +++ b/src/javajs/util/DataReader.java @@ -0,0 +1,56 @@ +package javajs.util; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.Reader; +import java.io.StringReader; + +/** + * Just a simple abstract class to join a String reader and a String[] + * reader under the same BufferedReader umbrella. + * + * Subclassed as StringDataReader, ArrayDataReader, and ListDataReader + * + */ + +public abstract class DataReader extends BufferedReader { + + public abstract DataReader setData(Object data); + + protected int ptMark; + + public DataReader() { + super(new StringReader("")); + } + + protected DataReader(Reader in) { + super(in); + } + + public BufferedReader getBufferedReader() { + return this; + } + + protected int readBuf(char[] buf, int off, int len) throws IOException { + // not used by StringDataReader + int nRead = 0; + String line = readLine(); + if (line == null) + return 0; + int linept = 0; + int linelen = line.length(); + for (int i = off; i < len && linelen >= 0; i++) { + if (linept >= linelen) { + linept = 0; + buf[i] = '\n'; + line = readLine(); + linelen = (line == null ? -1 : line.length()); + } else { + buf[i] = line.charAt(linept++); + } + nRead++; + } + return nRead; + } + +} \ No newline at end of file diff --git a/src/javajs/util/Eigen.java b/src/javajs/util/Eigen.java new file mode 100644 index 0000000..f7b5adf --- /dev/null +++ b/src/javajs/util/Eigen.java @@ -0,0 +1,1060 @@ +/* $RCSfile$ + * $Author: egonw $ + * $Date: 2005-11-10 09:52:44f -0600 (Thu, 10 Nov 2005) $ + * $Revision: 4255 $ + * + * Copyright (C) 2003-2005 Miguel, Jmol Development, www.jmol.org + * + * Contact: jmol-developers@lists.sf.net + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +package javajs.util; + +import javajs.api.EigenInterface; + + +/** + * Eigenvalues and eigenvectors of a real matrix. + * See javajs.api.EigenInterface() as well. + * + * adapted by Bob Hanson from http://math.nist.gov/javanumerics/jama/ (public + * domain); adding quaternion superimposition capability; removing + * nonsymmetric reduction to Hessenberg form, which we do not need in Jmol. + * + * Output is as a set of double[n] columns, but for the EigenInterface + * we return them as V3[3] and float[3] (or double[3]) values. + * + * Eigenvalues and eigenvectors are sorted from smallest to largest eigenvalue. + * + *

    + * 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. + *

    + * 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 Eigen implements EigenInterface { + + /* ------------------------ + Public Methods + * ------------------------ */ + + public Eigen() {} + + public Eigen set(int n) { + this.n = n; + V = new double[n][n]; + d = new double[n]; + e = new double[n]; + return this; + } + + @Override + public Eigen setM(double[][] m) { + set(m.length); + calc(m); + return this; + } + + /** + * return values sorted from smallest to largest value. + */ + @Override + public double[] getEigenvalues() { + return d; + } + + /** + * Specifically for 3x3 systems, returns eigenVectors as V3[3] + * and values as float[3]; sorted from smallest to largest value. + * + * @param eigenVectors returned vectors + * @param eigenValues returned values + * + */ + @Override + public void fillFloatArrays(V3[] eigenVectors, float[] eigenValues) { + for (int i = 0; i < 3; i++) { + if (eigenVectors != null) { + if (eigenVectors[i] == null) + eigenVectors[i] = new V3(); + eigenVectors[i].set((float) V[0][i], (float) V[1][i], (float) V[2][i]); + } + if (eigenValues != null) + eigenValues[i] = (float) d[i]; + } + } + + /** + * Transpose V and turn into floats; sorted from smallest to largest value. + * + * @return ROWS of eigenvectors f[0], f[1], f[2], etc. + */ + @Override + public float[][] getEigenvectorsFloatTransposed() { + float[][] f = new float[n][n]; + for (int i = n; --i >= 0;) + for (int j = n; --j >= 0;) + f[j][i] = (float) V[i][j]; + return f; + } + + + /** + * Check for symmetry, then construct the eigenvalue decomposition + * + * @param A + * Square matrix + */ + + public void calc(double[][] A) { + + /* Jmol only has need of symmetric solutions + * + 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(); + } + */ + + } + + /** + * 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; + } + + /* ------------------------ + Class variables + * ------------------------ */ + + /** + * Row and column dimension (square matrix). + * + * @serial matrix dimension. + */ + private int n = 3; + + /** + * Symmetry flag. + * + * @serial internal symmetry flag. + */ + //private boolean issymmetric = true; + + /** + * 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 = 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 = 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; + } + } + } + } + + private static double hypot(double a, double b) { + + // sqrt(a^2 + b^2) without under/overflow. + + 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; + } + + // 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; + } + } + } + */ + + +} diff --git a/src/javajs/util/Encoding.java b/src/javajs/util/Encoding.java new file mode 100644 index 0000000..11e0180 --- /dev/null +++ b/src/javajs/util/Encoding.java @@ -0,0 +1,30 @@ +/* $RCSfile$ + * $Author$ + * $Date$ + * $Revision$ + * + * Copyright (C) 2011 The Jmol Development Team + * + * Contact: jmol-developers@lists.sf.net + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +package javajs.util; + +public enum Encoding { + NONE, UTF8, UTF_16BE, UTF_16LE, UTF_32BE, UTF_32LE +} \ No newline at end of file diff --git a/src/javajs/util/LimitedLineReader.java b/src/javajs/util/LimitedLineReader.java new file mode 100644 index 0000000..e1d973f --- /dev/null +++ b/src/javajs/util/LimitedLineReader.java @@ -0,0 +1,48 @@ +package javajs.util; + +import java.io.BufferedReader; + +/** + * A simple class to read a designated number of bytes from a + * file and then return them line by line, skipping lines that + * start with #, and including the \n or \r characters at line ends. + * + * Generally useful for determining what sort of data a file contains. + * + */ +public class LimitedLineReader { + private char[] buf; + private int cchBuf; + private int ichCurrent; + + public LimitedLineReader(BufferedReader bufferedReader, int readLimit) + throws Exception { + bufferedReader.mark(readLimit + 1); + buf = new char[readLimit]; + cchBuf = Math.max(bufferedReader.read(buf, 0, readLimit), 0); + ichCurrent = 0; + bufferedReader.reset(); + } + + public String getHeader(int n) { + return (n == 0 ? new String(buf) : new String(buf, 0, Math.min(cchBuf, n))); + } + + public String readLineWithNewline() { + while (ichCurrent < cchBuf) { + int ichBeginningOfLine = ichCurrent; + char ch = 0; + while (ichCurrent < cchBuf && + (ch = buf[ichCurrent++]) != '\r' && ch != '\n') { + } + if (ch == '\r' && ichCurrent < cchBuf && buf[ichCurrent] == '\n') + ++ichCurrent; + int cchLine = ichCurrent - ichBeginningOfLine; + if (buf[ichBeginningOfLine] == '#') + continue; // flush comment lines; + return new String(buf, ichBeginningOfLine, cchLine); + } + return ""; + } +} + diff --git a/src/javajs/util/ListDataReader.java b/src/javajs/util/ListDataReader.java new file mode 100644 index 0000000..7814977 --- /dev/null +++ b/src/javajs/util/ListDataReader.java @@ -0,0 +1,57 @@ +package javajs.util; + +import java.io.IOException; + + + + + +/** + * + * VectorDataReader subclasses BufferedReader and overrides its + * read, readLine, mark, and reset methods so that JmolAdapter + * works with Vector arrays without any further adaptation. + * + */ + +public class ListDataReader extends DataReader { + private Lst data; + private int pt; + private int len; + + public ListDataReader() { + super(); + } + + @SuppressWarnings("unchecked") + @Override + public DataReader setData(Object data) { + this.data = (Lst) data; + len = this.data.size(); + return this; + } + + @Override + public int read(char[] buf, int off, int len) throws IOException { + return readBuf(buf, off, len); + } + + @Override + public String readLine() { + return (pt < len ? data.get(pt++) : null); + } + + /** + * + * @param ptr + */ + public void mark(long ptr) { + //ignore ptr. + ptMark = pt; + } + + @Override + public void reset() { + pt = ptMark; + } +} \ No newline at end of file diff --git a/src/javajs/util/Lst.java b/src/javajs/util/Lst.java new file mode 100644 index 0000000..8d5d62c --- /dev/null +++ b/src/javajs/util/Lst.java @@ -0,0 +1,88 @@ +/* $RCSfile$ + * $Author: hansonr $ + * $Date: 2007-04-26 16:57:51 -0500 (Thu, 26 Apr 2007) $ + * $Revision: 7502 $ + * + * Copyright (C) 2005 The Jmol Development Team + * + * Contact: jmol-developers@lists.sf.net + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +package javajs.util; + +import java.util.ArrayList; + +/** + * created to remove ambiguities in add and remove + * + * @param + */ +public class Lst extends ArrayList { + + public Lst() { + super(); + } + + /** + * @j2sIgnore + * + */ + @Override + @Deprecated + public boolean add(V v) { + throw new NullPointerException("use addLast(value), not add(value) in List for JavaScript compatibility"); + } + + public boolean addLast(V v) { + /** + * no overloading of add(Object) in JavaScript + * + * @j2sNative + * + * return this.add1(v); + * + */ + { + return super.add(v); + } + } + + /** + * @j2sIgnore + * + */ + @Override + @Deprecated + public boolean remove(Object v) { + throw new NullPointerException("use removeObj(obj), not remove(obj) in List for JavaScript compatibility"); + } + + public boolean removeObj(Object v) { + /** + * no overloading of remove(Object) in JavaScript + * + * @j2sNative + * + * return this.removeObject(v); + * + */ + { + return super.remove(v); + } + } + +} diff --git a/src/javajs/util/M3.java b/src/javajs/util/M3.java new file mode 100644 index 0000000..8d46569 --- /dev/null +++ b/src/javajs/util/M3.java @@ -0,0 +1,638 @@ +/* + Copyright (C) 1997,1998,1999 + Kenji Hiranabe, Eiwa System Management, Inc. + + This program is free software. + Implemented by Kenji Hiranabe(hiranabe@esm.co.jp), + conforming to the Java(TM) 3D API specification by Sun Microsystems. + + Permission to use, copy, modify, distribute and sell this software + and its documentation for any purpose is hereby granted without fee, + provided that the above copyright notice appear in all copies and + that both that copyright notice and this permission notice appear + in supporting documentation. Kenji Hiranabe and Eiwa System Management,Inc. + makes no representations about the suitability of this software for any + purpose. It is provided "AS IS" with NO WARRANTY. +*/ +package javajs.util; + +import java.io.Serializable; + + + +/** + * A single precision floating point 3 by 3 matrix. + * + * @author Kenji hiranabe + * + * additions by Bob Hanson hansonr@stolaf.edu 9/30/2012 for unique + * constructor and method names for the optimization of compiled + * JavaScript using Java2Script + * + * + */ +public class M3 extends M34 implements Serializable { + + /** + * Constructs and initializes a Matrix3f to all zeros. + * @j2sIgnore + */ + public M3() { + } + + /** + * Constructs and initializes a Matrix3f from the specified 9 element array. + * this.m00 =v[0], this.m01=v[1], etc. + * + * @param v + * the array of length 9 containing in order + * @return m + */ + public static M3 newA9(float[] v) { + M3 m = new M3(); + m.setA(v); + return m; + } + + /** + * Constructs a new matrix with the same values as the Matrix3f parameter. + * + * @param m1 + * The source matrix. + * @return m + */ + public static M3 newM3(M3 m1) { + M3 m = new M3(); + if (m1 == null) { + m.setScale(1); + return m; + } + m.m00 = m1.m00; + m.m01 = m1.m01; + m.m02 = m1.m02; + + m.m10 = m1.m10; + m.m11 = m1.m11; + m.m12 = m1.m12; + + m.m20 = m1.m20; + m.m21 = m1.m21; + m.m22 = m1.m22; + return m; + } + + /** + * Sets this Matrix3f to a scalar * Identity. + * @param scale + */ + public void setScale(float scale) { + clear33(); + m00 = m11 = m22 = scale; + } + + /** + * Sets the value of this matrix to the double value of the Matrix3f argument. + * + * @param m1 + * the matrix3f + */ + public void setM3(M34 m1) { + setM33(m1); + } + /** + * Sets the values in this Matrix3f equal to the row-major array parameter + * (ie, the first four elements of the array will be copied into the first row + * of this matrix, etc.). + * + * @param m + */ + public void setA(float m[]) { + m00 = m[0]; + m01 = m[1]; + m02 = m[2]; + m10 = m[3]; + m11 = m[4]; + m12 = m[5]; + m20 = m[6]; + m21 = m[7]; + m22 = m[8]; + } + + /** + * Sets the specified element of this matrix3d to the value provided. + * + * @param row + * the row number to be modified (zero indexed) + * @param col + * the column number to be modified (zero indexed) + * @param v + * the new value + */ + public void setElement(int row, int col, float v) { + set33(row, col, v); + } + + /** + * Retrieves the value at the specified row and column of this matrix. + * + * @param row + * the row number to be retrieved (zero indexed) + * @param col + * the column number to be retrieved (zero indexed) + * @return the value at the indexed element + */ + public float getElement(int row, int col) { + return get33(row, col); + } + + /** + * Sets the specified row of this matrix3d to the three values provided. + * + * @param row + * the row number to be modified (zero indexed) + * @param x + * the first column element + * @param y + * the second column element + * @param z + * the third column element + */ + public void setRow(int row, float x, float y, float z) { + switch (row) { + case 0: + m00 = x; + m01 = y; + m02 = z; + return; + case 1: + m10 = x; + m11 = y; + m12 = z; + return; + case 2: + m20 = x; + m21 = y; + m22 = z; + return; + default: + err(); + } + } + + /** + * Sets the specified row of this matrix3d to the Vector provided. + * + * @param row + * the row number to be modified (zero indexed) + * @param v + * the replacement row + */ + public void setRowV(int row, T3 v) { + switch (row) { + case 0: + m00 = v.x; + m01 = v.y; + m02 = v.z; + return; + case 1: + m10 = v.x; + m11 = v.y; + m12 = v.z; + return; + case 2: + m20 = v.x; + m21 = v.y; + m22 = v.z; + return; + default: + err(); + } + } + + /** + * Sets the specified row of this matrix3d to the four values provided. + * + * @param row + * the row number to be modified (zero indexed) + * @param v + * the replacement row + */ + public void setRowA(int row, float v[]) { + setRow33(row, v); + } + + /** + * Copies the matrix values in the specified row into the array parameter. + * + * @param row + * the matrix row + * @param v + * The array into which the matrix row values will be copied + */ + @Override + public void getRow(int row, float v[]) { + getRow33(row, v); + } + + /** + * Sets the specified column of this matrix3d to the three values provided. + * + * @param column + * the column number to be modified (zero indexed) + * @param x + * the first row element + * @param y + * the second row element + * @param z + * the third row element + */ + public void setColumn3(int column, float x, float y, float z) { + switch (column) { + case 0: + m00 = x; + m10 = y; + m20 = z; + break; + case 1: + m01 = x; + m11 = y; + m21 = z; + break; + case 2: + m02 = x; + m12 = y; + m22 = z; + break; + default: + err(); + } + } + + /** + * Sets the specified column of this matrix3d to the vector provided. + * + * @param column + * the column number to be modified (zero indexed) + * @param v + * the replacement column + */ + public void setColumnV(int column, T3 v) { + switch (column) { + case 0: + m00 = v.x; + m10 = v.y; + m20 = v.z; + break; + case 1: + m01 = v.x; + m11 = v.y; + m21 = v.z; + break; + case 2: + m02 = v.x; + m12 = v.y; + m22 = v.z; + break; + default: + err(); + } + } + + /** + * Copies the matrix values in the specified column into the vector parameter. + * + * @param column + * the matrix column + * @param v + * The vector into which the matrix row values will be copied + */ + public void getColumnV(int column, T3 v) { + switch (column) { + case 0: + v.x = m00; + v.y = m10; + v.z = m20; + break; + case 1: + v.x = m01; + v.y = m11; + v.z = m21; + break; + case 2: + v.x = m02; + v.y = m12; + v.z = m22; + break; + default: + err(); + } + } + + /** + * Sets the specified column of this matrix3d to the four values provided. + * + * @param column + * the column number to be modified (zero indexed) + * @param v + * the replacement column + */ + public void setColumnA(int column, float v[]) { + setColumn33(column, v); + } + + /** + * Copies the matrix values in the specified column into the array parameter. + * + * @param column + * the matrix column + * @param v + * The array into which the matrix row values will be copied + */ + public void getColumn(int column, float v[]) { + getColumn33(column, v); + } + + /** + * Sets the value of this matrix to sum of itself and matrix m1. + * + * @param m1 + * the other matrix + */ + public void add(M3 m1) { + add33(m1); + } + + /** + * Sets the value of this matrix to the matrix difference of itself and matrix + * m1 (this = this - m1). + * + * @param m1 + * the other matrix + */ + public void sub(M3 m1) { + sub33(m1); + } + + /** + * Sets the value of this matrix to its transpose. + */ + public void transpose() { + transpose33(); + } + + /** + * Sets the value of this matrix to the transpose of the argument matrix + * + * @param m1 + * the matrix to be transposed + */ + public void transposeM(M3 m1) { + // alias-safe + setM33(m1); + transpose33(); + } + + /** + * Sets the value of this matrix to the matrix inverse of the passed matrix + * m1. + * + * @param m1 + * the matrix to be inverted + */ + public void invertM(M3 m1) { + setM33(m1); + invert(); + } + + /** + * Sets the value of this matrix to its inverse. + */ + public void invert() { + double s = determinant3(); + if (s == 0.0) + return; + s = 1 / s; + // alias-safe way. + set9(m11 * m22 - m12 * m21, m02 * m21 - m01 * m22, m01 * m12 - m02 * m11, + m12 * m20 - m10 * m22, m00 * m22 - m02 * m20, m02 * m10 - m00 * m12, + m10 * m21 - m11 * m20, m01 * m20 - m00 * m21, m00 * m11 - m01 * m10); + scale((float) s); + } + + /** + * Sets the value of this matrix to a rotation matrix about the x axis by the + * passed angle. + * + * @param angle + * the angle to rotate about the X axis in radians + * @return this + */ + public M3 setAsXRotation(float angle) { + setXRot(angle); + return this; + } + + /** + * Sets the value of this matrix to a rotation matrix about the y axis by the + * passed angle. + * + * @param angle + * the angle to rotate about the Y axis in radians + * @return this + */ + public M3 setAsYRotation(float angle) { + setYRot(angle); + return this; + } + + /** + * Sets the value of this matrix to a rotation matrix about the z axis by the + * passed angle. + * + * @param angle + * the angle to rotate about the Z axis in radians + * @return this + */ + public M3 setAsZRotation(float angle) { + setZRot(angle); + return this; + } + + /** + * Multiplies each element of this matrix by a scalar. + * + * @param scalar + * The scalar multiplier. + */ + public void scale(float scalar) { + mul33(scalar); + } + + /** + * Sets the value of this matrix to the result of multiplying itself with + * matrix m1. + * + * @param m1 + * the other matrix + */ + public void mul(M3 m1) { + mul2(this, m1); + } + + /** + * Sets the value of this matrix to the result of multiplying the two argument + * matrices together. + * + * @param m1 + * the first matrix + * @param m2 + * the second matrix + */ + public void mul2(M3 m1, M3 m2) { + // alias-safe way. + set9(m1.m00 * m2.m00 + m1.m01 * m2.m10 + m1.m02 * m2.m20, m1.m00 * m2.m01 + + m1.m01 * m2.m11 + m1.m02 * m2.m21, m1.m00 * m2.m02 + m1.m01 * m2.m12 + + m1.m02 * m2.m22, + + m1.m10 * m2.m00 + m1.m11 * m2.m10 + m1.m12 * m2.m20, m1.m10 * m2.m01 + + m1.m11 * m2.m11 + m1.m12 * m2.m21, m1.m10 * m2.m02 + m1.m11 * m2.m12 + + m1.m12 * m2.m22, + + m1.m20 * m2.m00 + m1.m21 * m2.m10 + m1.m22 * m2.m20, m1.m20 * m2.m01 + + m1.m21 * m2.m11 + m1.m22 * m2.m21, m1.m20 * m2.m02 + m1.m21 * m2.m12 + + m1.m22 * m2.m22); + } + + /** + * Returns true if the Object o is of type Matrix3f and all of the data + * members of t1 are equal to the corresponding data members in this Matrix3f. + * + * @param o + * the object with which the comparison is made. + */ + @Override + public boolean equals(Object o) { + if (!(o instanceof M3)) + return false; + M3 m = (M3) o; + return m00 == m.m00 && m01 == m.m01 && m02 == m.m02 && m10 == m.m10 + && m11 == m.m11 && m12 == m.m12 && m20 == m.m20 && m21 == m.m21 + && m22 == m.m22; + } + + /** + * Returns a hash number based on the data values in this object. Two + * different Matrix3f objects with identical data values (ie, returns true for + * equals(Matrix3f) ) will return the same hash number. Two objects with + * different data members may return the same hash value, although this is not + * likely. + * + * @return the integer hash value + */ + @Override + public int hashCode() { + return T3.floatToIntBits0(m00) ^ T3.floatToIntBits0(m01) + ^ T3.floatToIntBits0(m02) ^ T3.floatToIntBits0(m10) + ^ T3.floatToIntBits0(m11) ^ T3.floatToIntBits0(m12) + ^ T3.floatToIntBits0(m20) ^ T3.floatToIntBits0(m21) + ^ T3.floatToIntBits0(m22); + } + + /** + * Sets this matrix to all zeros. + */ + public void setZero() { + clear33(); + } + + /** + * Sets 9 values + * + * @param m00 + * @param m01 + * @param m02 + * @param m10 + * @param m11 + * @param m12 + * @param m20 + * @param m21 + * @param m22 + */ + private void set9(float m00, float m01, float m02, float m10, float m11, + float m12, float m20, float m21, float m22) { + this.m00 = m00; + this.m01 = m01; + this.m02 = m02; + this.m10 = m10; + this.m11 = m11; + this.m12 = m12; + this.m20 = m20; + this.m21 = m21; + this.m22 = m22; + } + + /** + * Returns a string that contains the values of this Matrix3f. + * + * @return the String representation + */ + @Override + public String toString() { + return "[\n [" + m00 + "\t" + m01 + "\t" + m02 + "]" + "\n [" + m10 + + "\t" + m11 + "\t" + m12 + "]" + "\n [" + m20 + "\t" + m21 + "\t" + + m22 + "] ]"; + } + + /** + * Sets the value of this matrix to the matrix conversion of the single + * precision axis and angle argument. + * + * @param a + * the axis and angle to be converted + * @return this + */ + public M3 setAA(A4 a) { + setAA33(a); + return this; + } + + /** + * 3D ball rotation from dx dy in-plane mouse motion + * adapted from Andrew Hanson + * Computer Graphics beyond the Third Dimension: + * Geometry, Orientation Control, and Rendering for + * Graphics in Dimensions Greater than Three + * Course Notes for SIGGRAPH ’98 + * http://www.cse.ohio-state.edu/~hwshen/888_su02/hanson_note.pdf + * + * @param responseFactor Jmol uses 0.02 here + * @param dx + * @param dy + * @return true if successful; false if not; + */ + public boolean setAsBallRotation(float responseFactor, float dx, float dy) { + float r = (float) Math.sqrt(dx * dx + dy * dy); + float th = r * responseFactor; + if (th == 0) { + setScale(1); + return false; + } + float c = (float) Math.cos(th); + float s = (float) Math.sin(th); + float nx = -dy / r; + float ny = dx / r; + float c1 = c - 1; + m00 = 1 + c1 * nx * nx; + m01 = m10 = c1 * nx * ny; + m20 = -(m02 = s * nx); + m11 = 1 + c1 * ny * ny; + m21 = -(m12 = s * ny); + m22 = c; + return true; + } + + public boolean isRotation() { + return (Math.abs(determinant3() - 1) < 0.001f); + } + +} diff --git a/src/javajs/util/M34.java b/src/javajs/util/M34.java new file mode 100644 index 0000000..260a82c --- /dev/null +++ b/src/javajs/util/M34.java @@ -0,0 +1,416 @@ +package javajs.util; + +/** + * A base class for both M3 and M4 to conserve code size. + * + * @author Kenji hiranabe + * + * additions by Bob Hanson hansonr@stolaf.edu 9/30/2012 for unique + * constructor and method names for the optimization of compiled + * JavaScript using Java2Script and for subclassing to M3 and M4 + * + */ +public abstract class M34 { + + /** + * The first element of the first row + */ + public float m00; + + /** + * The second element of the first row. + */ + public float m01; + + /** + * third element of the first row. + */ + public float m02; + + /** + * The first element of the second row. + */ + public float m10; + + /** + * The second element of the second row. + */ + public float m11; + + /** + * The third element of the second row. + */ + public float m12; + + /** + * The first element of the third row. + */ + public float m20; + + /** + * The second element of the third row. + */ + public float m21; + + /** + * The third element of the third row. + */ + public float m22; + + protected void setAA33(A4 a) { + double x = a.x; + double y = a.y; + double z = a.z; + double angle = a.angle; + // Taken from Rick's which is taken from Wertz. pg. 412 + // Bug Fixed and changed into right-handed by hiranabe + double n = Math.sqrt(x * x + y * y + z * z); + // zero-div may occur + n = 1 / n; + x *= n; + y *= n; + z *= n; + double c = Math.cos(angle); + double s = Math.sin(angle); + double omc = 1.0 - c; + m00 = (float) (c + x * x * omc); + m11 = (float) (c + y * y * omc); + m22 = (float) (c + z * z * omc); + + double tmp1 = x * y * omc; + double tmp2 = z * s; + m01 = (float) (tmp1 - tmp2); + m10 = (float) (tmp1 + tmp2); + + tmp1 = x * z * omc; + tmp2 = y * s; + m02 = (float) (tmp1 + tmp2); + m20 = (float) (tmp1 - tmp2); + + tmp1 = y * z * omc; + tmp2 = x * s; + m12 = (float) (tmp1 - tmp2); + m21 = (float) (tmp1 + tmp2); + } + + public void rotate(T3 t) { + // alias-safe + rotate2(t, t); + } + + /** + * Transform the vector vec using this Matrix3f and place the result into + * vecOut. + * + * @param t + * the single precision vector to be transformed + * @param result + * the vector into which the transformed values are placed + */ + public void rotate2(T3 t, T3 result) { + // alias-safe + result.set(m00 * t.x + m01 * t.y + m02 * t.z, m10 * t.x + m11 * t.y + m12 + * t.z, m20 * t.x + m21 * t.y + m22 * t.z); + } + + + /** + * Sets the value of this matrix to the double value of the Matrix3f argument. + * + * @param m1 + * the matrix3f + */ + protected void setM33(M34 m1) { + m00 = m1.m00; + m01 = m1.m01; + m02 = m1.m02; + m10 = m1.m10; + m11 = m1.m11; + m12 = m1.m12; + m20 = m1.m20; + m21 = m1.m21; + m22 = m1.m22; + } + + protected void clear33() { + m00 = m01 = m02 = m10 = m11 = m12 = m20 = m21 = m22 = 0.0f; + } + + protected void set33(int row, int col, float v) { + switch (row) { + case 0: + switch (col) { + case 0: + m00 = v; + return; + case 1: + m01 = v; + return; + case 2: + m02 = v; + return; + } + break; + case 1: + switch (col) { + case 0: + m10 = v; + return; + case 1: + m11 = v; + return; + case 2: + m12 = v; + return; + } + break; + case 2: + switch (col) { + case 0: + m20 = v; + return; + case 1: + m21 = v; + return; + case 2: + m22 = v; + return; + } + break; + } + err(); + } + + protected float get33(int row, int col) { + switch (row) { + case 0: + switch (col) { + case 0: + return m00; + case 1: + return m01; + case 2: + return m02; + } + break; + case 1: + switch (col) { + case 0: + return m10; + case 1: + return m11; + case 2: + return m12; + } + break; + case 2: + switch (col) { + case 0: + return m20; + case 1: + return m21; + case 2: + return m22; + } + break; + } + err(); + return 0; + } + + protected void setRow33(int row, float v[]) { + switch (row) { + case 0: + m00 = v[0]; + m01 = v[1]; + m02 = v[2]; + return; + case 1: + m10 = v[0]; + m11 = v[1]; + m12 = v[2]; + return; + case 2: + m20 = v[0]; + m21 = v[1]; + m22 = v[2]; + return; + default: + err(); + } + } + + public abstract void getRow(int row, float v[]); + + protected void getRow33(int row, float v[]) { + switch (row) { + case 0: + v[0] = m00; + v[1] = m01; + v[2] = m02; + return; + case 1: + v[0] = m10; + v[1] = m11; + v[2] = m12; + return; + case 2: + v[0] = m20; + v[1] = m21; + v[2] = m22; + return; + } + err(); + } + + protected void setColumn33(int column, float v[]) { + switch(column) { + case 0: + m00 = v[0]; + m10 = v[1]; + m20 = v[2]; + break; + case 1: + m01 = v[0]; + m11 = v[1]; + m21 = v[2]; + break; + case 2: + m02 = v[0]; + m12 = v[1]; + m22 = v[2]; + break; + default: + err(); + } + } + + protected void getColumn33(int column, float v[]) { + switch(column) { + case 0: + v[0] = m00; + v[1] = m10; + v[2] = m20; + break; + case 1: + v[0] = m01; + v[1] = m11; + v[2] = m21; + break; + case 2: + v[0] = m02; + v[1] = m12; + v[2] = m22; + break; + default: + err(); + } + } + + protected void add33(M34 m1) { + m00 += m1.m00; + m01 += m1.m01; + m02 += m1.m02; + m10 += m1.m10; + m11 += m1.m11; + m12 += m1.m12; + m20 += m1.m20; + m21 += m1.m21; + m22 += m1.m22; + } + + protected void sub33(M34 m1) { + m00 -= m1.m00; + m01 -= m1.m01; + m02 -= m1.m02; + m10 -= m1.m10; + m11 -= m1.m11; + m12 -= m1.m12; + m20 -= m1.m20; + m21 -= m1.m21; + m22 -= m1.m22; + } + + protected void mul33(float x) { + m00 *= x; + m01 *= x; + m02 *= x; + m10 *= x; + m11 *= x; + m12 *= x; + m20 *= x; + m21 *= x; + m22 *= x; + } + + protected void transpose33() { + float tmp = m01; + m01 = m10; + m10 = tmp; + + tmp = m02; + m02 = m20; + m20 = tmp; + + tmp = m12; + m12 = m21; + m21 = tmp; + } + + protected void setXRot(float angle) { + double c = Math.cos(angle); + double s = Math.sin(angle); + m00 = 1.0f; + m01 = 0.0f; + m02 = 0.0f; + m10 = 0.0f; + m11 = (float) c; + m12 = (float) -s; + m20 = 0.0f; + m21 = (float) s; + m22 = (float) c; + } + + protected void setYRot(float angle) { + double c = Math.cos(angle); + double s = Math.sin(angle); + m00 = (float) c; + m01 = 0.0f; + m02 = (float) s; + m10 = 0.0f; + m11 = 1.0f; + m12 = 0.0f; + m20 = (float) -s; + m21 = 0.0f; + m22 = (float) c; + } + + protected void setZRot(float angle) { + double c = Math.cos(angle); + double s = Math.sin(angle); + m00 = (float) c; + m01 = (float) -s; + m02 = 0.0f; + m10 = (float) s; + m11 = (float) c; + m12 = 0.0f; + m20 = 0.0f; + m21 = 0.0f; + m22 = 1.0f; + } + + /** + * @return 3x3 determinant + */ + public float determinant3() { + return m00 * (m11 * m22 - m21 * m12) - m01 * (m10 * m22 - m20 * m12) + m02 + * (m10 * m21 - m20 * m11); + } + + protected void err() { + throw new ArrayIndexOutOfBoundsException( + "matrix column/row out of bounds"); + } + + +} diff --git a/src/javajs/util/M4.java b/src/javajs/util/M4.java new file mode 100644 index 0000000..c19ed88 --- /dev/null +++ b/src/javajs/util/M4.java @@ -0,0 +1,943 @@ +/* + Copyright (C) 1997,1998,1999 + Kenji Hiranabe, Eiwa System Management, Inc. + + This program is free software. + Implemented by Kenji Hiranabe(hiranabe@esm.co.jp), + conforming to the Java(TM) 3D API specification by Sun Microsystems. + + Permission to use, copy, modify, distribute and sell this software + and its documentation for any purpose is hereby granted without fee, + provided that the above copyright notice appear in all copies and + that both that copyright notice and this permission notice appear + in supporting documentation. Kenji Hiranabe and Eiwa System Management,Inc. + makes no representations about the suitability of this software for any + purpose. It is provided "AS IS" with NO WARRANTY. +*/ +package javajs.util; + +/** + * A single precision floating point 4 by 4 matrix. + * + * @author Kenji hiranabe + * + * additions by Bob Hanson hansonr@stolaf.edu 9/30/2012 for unique + * constructor and method names for the optimization of compiled + * JavaScript using Java2Script + */ +public class M4 extends M34 { + + /** + * The fourth element of the first row. + */ + public float m03; + + /** + * The fourth element of the second row. + */ + public float m13; + + /** + * The fourth element of the third row. + */ + public float m23; + + /** + * The first element of the fourth row. + */ + public float m30; + + /** + * The second element of the fourth row. + */ + public float m31; + + /** + * The third element of the fourth row. + */ + public float m32; + + /** + * The fourth element of the fourth row. + */ + public float m33 = 0; + + /** + * all zeros + * @j2sIgnore + */ + public M4() { + } + /** + * Constructs and initializes a Matrix4f from the specified 16 element array. + * this.m00 =v[0], this.m01=v[1], etc. + * + * @param v + * the array of length 16 containing in order + * @return m + */ + public static M4 newA16(float[] v) { + M4 m = new M4(); + m.m00 = v[0]; + m.m01 = v[1]; + m.m02 = v[2]; + m.m03 = v[3]; + + m.m10 = v[4]; + m.m11 = v[5]; + m.m12 = v[6]; + m.m13 = v[7]; + + m.m20 = v[8]; + m.m21 = v[9]; + m.m22 = v[10]; + m.m23 = v[11]; + + m.m30 = v[12]; + m.m31 = v[13]; + m.m32 = v[14]; + m.m33 = v[15]; + + return m; + } + + /** + * Constructs a new matrix with the same values as the Matrix4f parameter. + * + * @param m1 + * the source matrix + * @return m + */ + public static M4 newM4(M4 m1) { + M4 m = new M4(); + if (m1 == null) { + m.setIdentity(); + return m; + } + m.setToM3(m1); + m.m03 = m1.m03; + m.m13 = m1.m13; + m.m23 = m1.m23; + m.m30 = m1.m30; + m.m31 = m1.m31; + m.m32 = m1.m32; + m.m33 = m1.m33; + return m; + } + + /** + * Constructs and initializes a Matrix4f from the rotation matrix and + * translation. + * + * @param m1 + * The rotation matrix representing the rotational components + * @param t + * The translational components of the matrix + * @return m + */ + public static M4 newMV(M3 m1, T3 t) { + M4 m = new M4(); + m.setMV(m1, t); + return m; + } + + /** + * Sets this matrix to all zeros. + */ + public void setZero() { + clear33(); + m03 = m13 = m23 = m30 = m31 = m32 = m33 = 0.0f; + } + + /** + * Sets this Matrix4f to identity. + */ + public void setIdentity() { + setZero(); + m00 = m11 = m22 = m33 = 1.0f; + } + + /** + * Sets the value of this matrix to a copy of the passed matrix m1. + * + * @param m1 + * the matrix to be copied + * @return this + */ + public M4 setM4(M4 m1) { + setM33(m1); + m03 = m1.m03; + m13 = m1.m13; + m23 = m1.m23; + m30 = m1.m30; + m31 = m1.m31; + m32 = m1.m32; + m33 = m1.m33; + return this; + } + + /** + * Initializes a Matrix4f from the rotation matrix and translation. + * + * @param m1 + * The rotation matrix representing the rotational components + * @param t + * The translational components of the matrix + */ + public void setMV(M3 m1, T3 t) { + setM33(m1); + setTranslation(t); + m33 = 1; + } + + /** + * Sets the rotational component (upper 3x3) of this matrix to the matrix + * values in the single precision Matrix3f argument; the other elements of + * this matrix are initialized as if this were an identity matrix (ie, affine + * matrix with no translational component). + * + * @param m1 + * the 3x3 matrix + */ + public void setToM3(M34 m1) { + setM33(m1); + m03 = m13 = m23 = m30 = m31 = m32 = 0.0f; + m33 = 1.0f; + } + + /** + * Sets the rotational component (upper 3x3) of this matrix + * to a rotation given by an axis angle + * + * @param a + * the axis and angle to be converted + */ + public void setToAA(A4 a) { + setIdentity(); + setAA33(a); + } + + /** + * Sets the values in this Matrix4f equal to the row-major array parameter + * (ie, the first four elements of the array will be copied into the first row + * of this matrix, etc.). + * + * @param m + */ + public void setA(float m[]) { + m00 = m[0]; + m01 = m[1]; + m02 = m[2]; + m03 = m[3]; + m10 = m[4]; + m11 = m[5]; + m12 = m[6]; + m13 = m[7]; + m20 = m[8]; + m21 = m[9]; + m22 = m[10]; + m23 = m[11]; + m30 = m[12]; + m31 = m[13]; + m32 = m[14]; + m33 = m[15]; + } + + /** + * Modifies the translational components of this matrix to the values of the + * Vector3f argument; the other values of this matrix are not modified. + * + * @param trans + * the translational component + */ + public void setTranslation(T3 trans) { + m03 = trans.x; + m13 = trans.y; + m23 = trans.z; + } + + /** + * Sets the specified element of this matrix4f to the value provided. + * + * @param row + * the row number to be modified (zero indexed) + * @param col + * the column number to be modified (zero indexed) + * @param v + * the new value + */ + public void setElement(int row, int col, float v) { + if (row < 3 && col < 3) { + set33(row, col, v); + return; + } + if (row > 3 || col > 3) + err(); + switch (row) { + case 0: + m03 = v; + return; + case 1: + m13 = v; + return; + case 2: + m23 = v; + return; + } + switch (col) { + case 0: + m30 = v; + return; + case 1: + m31 = v; + return; + case 2: + m32 = v; + return; + case 3: + m33 = v; + return; + } + } + + /** + * Retrieves the value at the specified row and column of this matrix. + * + * @param row + * the row number to be retrieved (zero indexed) + * @param col + * the column number to be retrieved (zero indexed) + * @return the value at the indexed element + */ + public float getElement(int row, int col) { + if (row < 3 && col < 3) + return get33(row, col); + if (row > 3 || col > 3) { + err(); + return 0; + } + switch (row) { + case 0: + return m03; + case 1: + return m13; + case 2: + return m23; + default: + switch (col) { + case 0: + return m30; + case 1: + return m31; + case 2: + return m32; + default: + return m33; + } + } + } + + /** + * Retrieves the translational components of this matrix. + * + * @param trans + * the vector that will receive the translational component + */ + public void getTranslation(T3 trans) { + trans.x = m03; + trans.y = m13; + trans.z = m23; + } + + /** + * Gets the upper 3x3 values of this matrix and places them into the matrix + * m1. + * + * @param m1 + * The matrix that will hold the values + */ + public void getRotationScale(M3 m1) { + m1.m00 = m00; + m1.m01 = m01; + m1.m02 = m02; + m1.m10 = m10; + m1.m11 = m11; + m1.m12 = m12; + m1.m20 = m20; + m1.m21 = m21; + m1.m22 = m22; + } + + /** + * Replaces the upper 3x3 matrix values of this matrix with the values in the + * matrix m1. + * + * @param m1 + * The matrix that will be the new upper 3x3 + */ + public void setRotationScale(M3 m1) { + m00 = m1.m00; + m01 = m1.m01; + m02 = m1.m02; + m10 = m1.m10; + m11 = m1.m11; + m12 = m1.m12; + m20 = m1.m20; + m21 = m1.m21; + m22 = m1.m22; + } + + /** + * Sets the specified row of this matrix4f to the four values provided. + * + * @param row + * the row number to be modified (zero indexed) + * @param v + * the replacement row + */ + public void setRowA(int row, float v[]) { + if (row < 3) + setRow33(row, v); + switch (row) { + case 0: + m03 = v[3]; + return; + case 1: + m13 = v[3]; + return; + case 2: + m23 = v[3]; + return; + case 3: + m30 = v[0]; + m31 = v[1]; + m32 = v[2]; + m33 = v[3]; + return; + } + err(); + } + + /** + * Copies the matrix values in the specified row into the array parameter. + * + * @param row + * the matrix row + * @param v + * The array into which the matrix row values will be copied + */ + @Override + public void getRow(int row, float v[]) { + if (row < 3) + getRow33(row, v); + switch (row) { + case 0: + v[3] = m03; + return; + case 1: + v[3] = m13; + return; + case 2: + v[3] = m23; + return; + case 3: + v[0] = m30; + v[1] = m31; + v[2] = m32; + v[3] = m33; + return; + } + err(); + } + + /** + * Sets the specified column of this matrix4f to the four values provided. + * + * @param column + * the column number to be modified (zero indexed) + * @param x + * the first row element + * @param y + * the second row element + * @param z + * the third row element + * @param w + * the fourth row element + */ + public void setColumn4(int column, float x, float y, float z, float w) { + if (column == 0) { + m00 = x; + m10 = y; + m20 = z; + m30 = w; + } else if (column == 1) { + m01 = x; + m11 = y; + m21 = z; + m31 = w; + } else if (column == 2) { + m02 = x; + m12 = y; + m22 = z; + m32 = w; + } else if (column == 3) { + m03 = x; + m13 = y; + m23 = z; + m33 = w; + } else { + err(); + } + } + + /** + * Sets the specified column of this matrix4f to the four values provided. + * + * @param column + * the column number to be modified (zero indexed) + * @param v + * the replacement column + */ + public void setColumnA(int column, float v[]) { + if (column < 3) + setColumn33(column, v); + switch (column) { + case 0: + m30 = v[3]; + return; + case 1: + m31 = v[3]; + return; + case 2: + m32 = v[3]; + return; + case 3: + m03 = v[0]; + m13 = v[1]; + m23 = v[2]; + m33 = v[3]; + return; + default: + err(); + } + } + + /** + * Copies the matrix values in the specified column into the array parameter. + * + * @param column + * the matrix column + * @param v + * The array into which the matrix column values will be copied + */ + public void getColumn(int column, float v[]) { + if (column < 3) + getColumn33(column, v); + switch (column) { + case 0: + v[3] = m30; + return; + case 1: + v[3] = m31; + return; + case 2: + v[3] = m32; + return; + case 3: + v[0] = m03; + v[1] = m13; + v[2] = m23; + v[3] = m33; + return; + default: + err(); + } + } + + /** + * Sets the value of this matrix to the matrix difference of itself and matrix + * m1 (this = this - m1). + * + * @param m1 + * the other matrix + */ + public void sub(M4 m1) { + sub33(m1); + m03 -= m1.m03; + m13 -= m1.m13; + m23 -= m1.m23; + m30 -= m1.m30; + m31 -= m1.m31; + m32 -= m1.m32; + m33 -= m1.m33; + } + + /** + * Sets the value of this matrix to its transpose. + */ + public void transpose() { + transpose33(); + float tmp = m03; + m03 = m30; + m30 = tmp; + + tmp = m13; + m13 = m31; + m31 = tmp; + + tmp = m23; + m23 = m32; + m32 = tmp; + } + + /** + * Sets the value of this matrix to its inverse. + * @return this + */ + public M4 invert() { + float s = determinant4(); + if (s == 0.0) + return this; + s = 1 / s; + // alias-safe way. + // less *,+,- calculation than expanded expression. + set(m11 * (m22 * m33 - m23 * m32) + m12 * (m23 * m31 - m21 * m33) + m13 + * (m21 * m32 - m22 * m31), m21 * (m02 * m33 - m03 * m32) + m22 + * (m03 * m31 - m01 * m33) + m23 * (m01 * m32 - m02 * m31), m31 + * (m02 * m13 - m03 * m12) + m32 * (m03 * m11 - m01 * m13) + m33 + * (m01 * m12 - m02 * m11), m01 * (m13 * m22 - m12 * m23) + m02 + * (m11 * m23 - m13 * m21) + m03 * (m12 * m21 - m11 * m22), + + m12 * (m20 * m33 - m23 * m30) + m13 * (m22 * m30 - m20 * m32) + m10 + * (m23 * m32 - m22 * m33), m22 * (m00 * m33 - m03 * m30) + m23 + * (m02 * m30 - m00 * m32) + m20 * (m03 * m32 - m02 * m33), m32 + * (m00 * m13 - m03 * m10) + m33 * (m02 * m10 - m00 * m12) + m30 + * (m03 * m12 - m02 * m13), m02 * (m13 * m20 - m10 * m23) + m03 + * (m10 * m22 - m12 * m20) + m00 * (m12 * m23 - m13 * m22), + + m13 * (m20 * m31 - m21 * m30) + m10 * (m21 * m33 - m23 * m31) + m11 + * (m23 * m30 - m20 * m33), m23 * (m00 * m31 - m01 * m30) + m20 + * (m01 * m33 - m03 * m31) + m21 * (m03 * m30 - m00 * m33), m33 + * (m00 * m11 - m01 * m10) + m30 * (m01 * m13 - m03 * m11) + m31 + * (m03 * m10 - m00 * m13), m03 * (m11 * m20 - m10 * m21) + m00 + * (m13 * m21 - m11 * m23) + m01 * (m10 * m23 - m13 * m20), + + m10 * (m22 * m31 - m21 * m32) + m11 * (m20 * m32 - m22 * m30) + m12 + * (m21 * m30 - m20 * m31), m20 * (m02 * m31 - m01 * m32) + m21 + * (m00 * m32 - m02 * m30) + m22 * (m01 * m30 - m00 * m31), m30 + * (m02 * m11 - m01 * m12) + m31 * (m00 * m12 - m02 * m10) + m32 + * (m01 * m10 - m00 * m11), m00 * (m11 * m22 - m12 * m21) + m01 + * (m12 * m20 - m10 * m22) + m02 * (m10 * m21 - m11 * m20)); + scale(s); + return this; + } + + /** + * Sets 16 values + * + * @param m00 + * @param m01 + * @param m02 + * @param m03 + * @param m10 + * @param m11 + * @param m12 + * @param m13 + * @param m20 + * @param m21 + * @param m22 + * @param m23 + * @param m30 + * @param m31 + * @param m32 + * @param m33 + */ + private void set(float m00, float m01, float m02, float m03, float m10, + float m11, float m12, float m13, float m20, float m21, + float m22, float m23, float m30, float m31, float m32, + float m33) { + this.m00 = m00; + this.m01 = m01; + this.m02 = m02; + this.m03 = m03; + this.m10 = m10; + this.m11 = m11; + this.m12 = m12; + this.m13 = m13; + this.m20 = m20; + this.m21 = m21; + this.m22 = m22; + this.m23 = m23; + this.m30 = m30; + this.m31 = m31; + this.m32 = m32; + this.m33 = m33; + } + /** + * Computes the determinant of this matrix. + * + * @return the determinant of the matrix + */ + public float determinant4() { + // less *,+,- calculation than expanded expression. + return (m00 * m11 - m01 * m10) * (m22 * m33 - m23 * m32) + - (m00 * m12 - m02 * m10) * (m21 * m33 - m23 * m31) + + (m00 * m13 - m03 * m10) * (m21 * m32 - m22 * m31) + + (m01 * m12 - m02 * m11) * (m20 * m33 - m23 * m30) + - (m01 * m13 - m03 * m11) * (m20 * m32 - m22 * m30) + + (m02 * m13 - m03 * m12) * (m20 * m31 - m21 * m30); + + } + + /** + * Multiplies each element of this matrix by a scalar. + * + * @param scalar + * The scalar multiplier. + */ + private void scale(float scalar) { + mul33(scalar); + m03 *= scalar; + m13 *= scalar; + m23 *= scalar; + m30 *= scalar; + m31 *= scalar; + m32 *= scalar; + m33 *= scalar; + } + + /** + * Sets the value of this matrix to the result of multiplying itself with + * matrix m1. + * + * @param m1 + * the other matrix + */ + public void mul(M4 m1) { + mul2(this, m1); + } + + /** + * Sets the value of this matrix to the result of multiplying the two argument + * matrices together. + * + * @param m1 + * the first matrix + * @param m2 + * the second matrix + */ + public void mul2(M4 m1, M4 m2) { + // alias-safe way. + set(m1.m00 * m2.m00 + m1.m01 * m2.m10 + m1.m02 * m2.m20 + m1.m03 * m2.m30, + m1.m00 * m2.m01 + m1.m01 * m2.m11 + m1.m02 * m2.m21 + m1.m03 * m2.m31, + m1.m00 * m2.m02 + m1.m01 * m2.m12 + m1.m02 * m2.m22 + m1.m03 * m2.m32, + m1.m00 * m2.m03 + m1.m01 * m2.m13 + m1.m02 * m2.m23 + m1.m03 * m2.m33, + + m1.m10 * m2.m00 + m1.m11 * m2.m10 + m1.m12 * m2.m20 + m1.m13 * m2.m30, + m1.m10 * m2.m01 + m1.m11 * m2.m11 + m1.m12 * m2.m21 + m1.m13 * m2.m31, + m1.m10 * m2.m02 + m1.m11 * m2.m12 + m1.m12 * m2.m22 + m1.m13 * m2.m32, + m1.m10 * m2.m03 + m1.m11 * m2.m13 + m1.m12 * m2.m23 + m1.m13 * m2.m33, + + m1.m20 * m2.m00 + m1.m21 * m2.m10 + m1.m22 * m2.m20 + m1.m23 * m2.m30, + m1.m20 * m2.m01 + m1.m21 * m2.m11 + m1.m22 * m2.m21 + m1.m23 * m2.m31, + m1.m20 * m2.m02 + m1.m21 * m2.m12 + m1.m22 * m2.m22 + m1.m23 * m2.m32, + m1.m20 * m2.m03 + m1.m21 * m2.m13 + m1.m22 * m2.m23 + m1.m23 * m2.m33, + + m1.m30 * m2.m00 + m1.m31 * m2.m10 + m1.m32 * m2.m20 + m1.m33 * m2.m30, + m1.m30 * m2.m01 + m1.m31 * m2.m11 + m1.m32 * m2.m21 + m1.m33 * m2.m31, + m1.m30 * m2.m02 + m1.m31 * m2.m12 + m1.m32 * m2.m22 + m1.m33 * m2.m32, + m1.m30 * m2.m03 + m1.m31 * m2.m13 + m1.m32 * m2.m23 + m1.m33 * m2.m33); + } + + /** + * Transform the vector vec using this Matrix4f and place the result back into + * vec. + * + * @param vec + * the single precision vector to be transformed + */ + public void transform(T4 vec) { + transform2(vec, vec); + } + + /** + * Transform the vector vec using this Matrix4f and place the result into + * vecOut. + * + * @param vec + * the single precision vector to be transformed + * @param vecOut + * the vector into which the transformed values are placed + */ + public void transform2(T4 vec, T4 vecOut) { + // alias-safe + vecOut.set4(m00 * vec.x + m01 * vec.y + m02 * vec.z + m03 * vec.w, m10 + * vec.x + m11 * vec.y + m12 * vec.z + m13 * vec.w, m20 * vec.x + m21 + * vec.y + m22 * vec.z + m23 * vec.w, m30 * vec.x + m31 * vec.y + m32 + * vec.z + m33 * vec.w); + } + + /** + * Transforms the point parameter with this Matrix4f and places the result + * back into point. The fourth element of the point input parameter is assumed + * to be one. + * + * @param point + * the input point to be transformed. + */ + public void rotTrans(T3 point) { + rotTrans2(point, point); + } + + /** + * Transforms the point parameter with this Matrix4f and places the result + * into pointOut. The fourth element of the point input parameter is assumed to + * be one. point may be pointOut + * + * @param point + * the input point to be transformed. + * @param pointOut + * the transformed point + * @return pointOut + */ + public T3 rotTrans2(T3 point, T3 pointOut) { + pointOut.set( + m00 * point.x + m01 * point.y + m02 * point.z + m03, + m10 * point.x + m11 * point.y + m12 * point.z + m13, + m20 * point.x + m21 * point.y + m22 * point.z + m23); + return pointOut; + } + + /** + * Sets the value of this matrix to a rotation matrix about the w axis by the + * passed angle. + * + * @param angle + * the angle to rotate about the W axis in radians + * @return this + */ + public M4 setAsXYRotation(float angle) { + setIdentity(); + double c = Math.cos(angle); + double s = Math.sin(angle); + m22 = (float) c; + m23 = (float) -s; + m32 = (float) s; + m33 = (float) c; + return this; + } + + /** + * Sets the value of this matrix to a rotation matrix about the w axis by the + * passed angle. + * + * @param angle + * the angle to rotate about the W axis in radians + * @return this + */ + public M4 setAsYZRotation(float angle) { + setIdentity(); + double c = Math.cos(angle); + double s = Math.sin(angle); + m00 = (float) c; + m03 = (float) -s; + m30 = (float) s; + m33 = (float) c; + return this; + } + + /** + * Sets the value of this matrix to a rotation matrix about the w axis by the + * passed angle. + * + * @param angle + * the angle to rotate about the W axis in radians + * @return this + */ + public M4 setAsXZRotation(float angle) { + setIdentity(); + double c = Math.cos(angle); + double s = Math.sin(angle); + m11 = (float) c; + m13 = (float) -s; + m31 = (float) s; + m33 = (float) c; + return this; + } + + /** + * Returns true if the Object o is of type Matrix4f and all of the data + * members of t1 are equal to the corresponding data members in this Matrix4f. + * + * @param o + * the object with which the comparison is made. + */ + @Override + public boolean equals(Object o) { + if (!(o instanceof M4)) + return false; + M4 m = (M4) o; + return (this.m00 == m.m00 && this.m01 == m.m01 && this.m02 == m.m02 + && this.m03 == m.m03 && this.m10 == m.m10 && this.m11 == m.m11 + && this.m12 == m.m12 && this.m13 == m.m13 && this.m20 == m.m20 + && this.m21 == m.m21 && this.m22 == m.m22 && this.m23 == m.m23 + && this.m30 == m.m30 && this.m31 == m.m31 && this.m32 == m.m32 && this.m33 == m.m33); + } + + /** + * Returns a hash number based on the data values in this object. Two + * different Matrix4f objects with identical data values (ie, returns true for + * equals(Matrix4f) ) will return the same hash number. Two objects with + * different data members may return the same hash value, although this is not + * likely. + * + * @return the integer hash value + */ + @Override + public int hashCode() { + return T3.floatToIntBits0(m00) ^ T3.floatToIntBits0(m01) + ^ T3.floatToIntBits0(m02) ^ T3.floatToIntBits0(m03) + ^ T3.floatToIntBits0(m10) ^ T3.floatToIntBits0(m11) + ^ T3.floatToIntBits0(m12) ^ T3.floatToIntBits0(m13) + ^ T3.floatToIntBits0(m20) ^ T3.floatToIntBits0(m21) + ^ T3.floatToIntBits0(m22) ^ T3.floatToIntBits0(m23) + ^ T3.floatToIntBits0(m30) ^ T3.floatToIntBits0(m31) + ^ T3.floatToIntBits0(m32) ^ T3.floatToIntBits0(m33); + } + + /** + * Returns a string that contains the values of this Matrix4f. + * + * @return the String representation + */ + @Override + public String toString() { + return "[\n [" + m00 + "\t" + m01 + "\t" + m02 + "\t" + m03 + "]" + + "\n [" + m10 + "\t" + m11 + "\t" + m12 + "\t" + m13 + "]" + "\n [" + + m20 + "\t" + m21 + "\t" + m22 + "\t" + m23 + "]" + "\n [" + m30 + + "\t" + m31 + "\t" + m32 + "\t" + m33 + "] ]"; + } + public M4 round(float f) { + m00 = rnd(m00, f); + m01 = rnd(m01, f); + m02 = rnd(m02, f); + m03 = rnd(m03, f); + m10 = rnd(m10, f); + m11 = rnd(m11, f); + m12 = rnd(m12, f); + m13 = rnd(m13, f); + m20 = rnd(m20, f); + m21 = rnd(m21, f); + m22 = rnd(m22, f); + m23 = rnd(m23, f); + m30 = rnd(m30, f); + m31 = rnd(m31, f); + m32 = rnd(m32, f); + m33 = rnd(m33, f); + return this; + } + + private float rnd(float n, float f) { + return (Math.abs(n) < f ? 0 : n); + } +} diff --git a/src/javajs/util/Matrix.java b/src/javajs/util/Matrix.java new file mode 100644 index 0000000..cea5a04 --- /dev/null +++ b/src/javajs/util/Matrix.java @@ -0,0 +1,457 @@ +package javajs.util; + +/** + * + * streamlined and refined for Jmol by Bob Hanson + * + * from http://math.nist.gov/javanumerics/jama/ + * + * Jama = Java Matrix class. + * + * @author The MathWorks, Inc. and the National Institute of Standards and + * Technology. + * @version 5 August 1998 + */ + +public class Matrix implements Cloneable { + + public double[][] a; + protected int m, n; + + /** + * Construct a matrix quickly without checking arguments. + * + * @param a + * Two-dimensional array of doubles or null + * @param m + * Number of rows. + * @param n + * Number of colums. + */ + + public Matrix(double[][] a, int m, int n) { + this.a = (a == null ? new double[m][n] : a); + this.m = m; + this.n = n; + } + + /** + * 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; + } + + /** + * 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[][] x = new double[m][n]; + for (int i = m; --i >= 0;) + for (int j = n; --j >= 0;) + x[i][j] = a[i][j]; + return x; + } + + /** + * Make a deep copy of a matrix + * + * @return copy + */ + + public Matrix copy() { + Matrix x = new Matrix(null, m, n); + double[][] c = x.a; + for (int i = m; --i >= 0;) + for (int j = n; --j >= 0;) + c[i][j] = a[i][j]; + return x; + } + + /** + * Clone the Matrix object. + */ + + @Override + public Object clone() { + return copy(); + } + + /** + * Get a submatrix. + * + * @param i0 + * Initial row index + * @param j0 + * Initial column index + * @param nrows + * Number of rows + * @param ncols + * Number of columns + * @return submatrix + * + */ + + public Matrix getSubmatrix(int i0, int j0, int nrows, int ncols) { + Matrix x = new Matrix(null, nrows, ncols); + double[][] xa = x.a; + for (int i = nrows; --i >= 0;) + for (int j = ncols; --j >= 0;) + xa[i][j] = a[i0 + i][j0 + j]; + return x; + } + + /** + * Get a submatrix for a give number of columns and selected row set. + * + * @param r + * Array of row indices. + * @param n + * number of rows + * @return submatrix + */ + + public Matrix getMatrixSelected(int[] r, int n) { + Matrix x = new Matrix(null, r.length, n); + double[][] xa = x.a; + for (int i = r.length; --i >= 0;) { + double[] b = a[r[i]]; + for (int j = n; --j >= 0;) + xa[i][j] = b[j]; + } + return x; + } + + /** + * Matrix transpose. + * + * @return A' + */ + + public Matrix transpose() { + Matrix x = new Matrix(null, n, m); + double[][] c = x.a; + for (int i = m; --i >= 0;) + for (int j = n; --j >= 0;) + c[j][i] = a[i][j]; + return x; + } + + /** + * add two matrices + * @param b + * @return new Matrix this + b + */ + public Matrix add(Matrix b) { + return scaleAdd(b, 1); + } + + /** + * subtract two matrices + * @param b + * @return new Matrix this - b + */ + public Matrix sub(Matrix b) { + return scaleAdd(b, -1); + } + + /** + * X = A + B*scale + * @param b + * @param scale + * @return X + * + */ + public Matrix scaleAdd(Matrix b, double scale) { + Matrix x = new Matrix(null, m, n); + double[][] xa = x.a; + double[][] ba = b.a; + for (int i = m; --i >= 0;) + for (int j = n; --j >= 0;) + xa[i][j] = ba[i][j] * scale + a[i][j]; + return x; + } + + /** + * Linear algebraic matrix multiplication, A * B + * + * @param b + * another matrix + * @return Matrix product, A * B or null for wrong dimension + */ + + public Matrix mul(Matrix b) { + if (b.m != n) + return null; + Matrix x = new Matrix(null, m, b.n); + double[][] xa = x.a; + double[][] ba = b.a; + for (int j = b.n; --j >= 0;) + for (int i = m; --i >= 0;) { + double[] arowi = a[i]; + double s = 0; + for (int k = n; --k >= 0;) + s += arowi[k] * ba[k][j]; + xa[i][j] = s; + } + return x; + } + + /** + * Matrix inverse or pseudoinverse + * + * @return inverse (m == n) or pseudoinverse (m != n) + */ + + public Matrix inverse() { + return new LUDecomp(m, n).solve(identity(m, m), n); + } + + /** + * Matrix trace. + * + * @return sum of the diagonal elements. + */ + + public double trace() { + double t = 0; + for (int i = Math.min(m, n); --i >= 0;) + t += a[i][i]; + return t; + } + + /** + * Generate identity matrix + * + * @param m + * Number of rows. + * @param n + * Number of columns. + * @return An m-by-n matrix with ones on the diagonal and zeros elsewhere. + */ + + public static Matrix identity(int m, int n) { + Matrix x = new Matrix(null, m, n); + double[][] xa = x.a; + for (int i = Math.min(m, n); --i >= 0;) + xa[i][i] = 1; + return x; + } + + /** + * similarly to M3/M4 standard rotation/translation matrix + * we set a rotationTranslation matrix to be: + * + * [ nxn rot nx1 trans + * + * 1xn 0 1x1 1 ] + * + * + * @return rotation matrix + */ + public Matrix getRotation() { + return getSubmatrix(0, 0, m - 1, n - 1); + } + + public Matrix getTranslation() { + return getSubmatrix(0, n - 1, m - 1, 1); + } + + public static Matrix newT(T3 r, boolean asColumn) { + return (asColumn ? new Matrix(new double[][] { new double[] { r.x }, + new double[] { r.y }, new double[] { r.z } }, 3, 1) : new Matrix( + new double[][] { new double[] { r.x, r.y, r.z } }, 1, 3)); + } + + @Override + public String toString() { + String s = "[\n"; + for (int i = 0; i < m; i++) { + s += " ["; + for (int j = 0; j < n; j++) + s += " " + a[i][j]; + s += "]\n"; + } + s += "]"; + return s; + } + + /** + * + * Edited down by Bob Hanson for minimum needed by Jmol -- just constructor + * and solve + * + * LU Decomposition. + *

    + * 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. + *

    + * 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. + */ + + private class LUDecomp { + + /* ------------------------ + Class variables + * ------------------------ */ + + /** + * Array for internal storage of decomposition. + * + */ + private double[][] LU; + + /** + * Internal storage of pivot vector. + * + */ + private int[] piv; + + private int pivsign; + + /* ------------------------ + Constructor + * ------------------------ */ + + /** + * LU Decomposition Structure to access L, U and piv. + * @param m + * @param n + * + */ + + protected LUDecomp(int m, int n) { + + // Use a "left-looking", dot-product, Crout/Doolittle algorithm. + + LU = getArrayCopy(); + piv = new int[m]; + for (int i = m; --i >= 0;) + 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 = m; --i >= 0;) + LUcolj[i] = LU[i][j]; + + // Apply previous transformations. + + for (int i = m; --i >= 0;) { + 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 = kmax; --k >= 0;) + s += LUrowi[k] * LUcolj[k]; + + LUrowi[j] = LUcolj[i] -= s; + } + + // Find pivot and exchange if necessary. + + int p = j; + for (int i = m; --i > j;) + if (Math.abs(LUcolj[i]) > Math.abs(LUcolj[p])) + p = i; + if (p != j) { + for (int k = n; --k >= 0;) { + 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 = m; --i > j;) + LU[i][j] /= LU[j][j]; + } + } + + /* ------------------------ + default Methods + * ------------------------ */ + + /** + * Solve A*X = B + * + * @param b + * A Matrix with as many rows as A and any number of columns. + * @param n + * @return X so that L*U*X = B(piv,:) or null for wrong size or singular matrix + */ + + protected Matrix solve(Matrix b, int n) { + for (int j = 0; j < n; j++) + if (LU[j][j] == 0) + return null; // matrix is singular + + // Copy right hand side with pivoting + int nx = b.n; + Matrix x = b.getMatrixSelected(piv, nx); + double[][] a = x.a; + + // 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++) + a[i][j] -= a[k][j] * LU[i][k]; + + // Solve U*X = Y; + for (int k = n; --k >= 0;) { + for (int j = nx; --j >= 0;) + a[k][j] /= LU[k][k]; + for (int i = k; --i >= 0;) + for (int j = nx; --j >= 0;) + a[i][j] -= a[k][j] * LU[i][k]; + } + return x; + } + } + +} diff --git a/src/javajs/util/Measure.java b/src/javajs/util/Measure.java new file mode 100644 index 0000000..09b9807 --- /dev/null +++ b/src/javajs/util/Measure.java @@ -0,0 +1,733 @@ +/* $RCSfile$ + * $Author: egonw $ + * $Date: 2005-11-10 09:52:44 -0600 (Thu, 10 Nov 2005) $ + * $Revision: 4255 $ + * + * Copyright (C) 2003-2005 The Jmol Development Team + * + * Contact: jmol-developers@lists.sf.net + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + */ +package javajs.util; + +import javajs.api.EigenInterface; + +import javajs.api.Interface; + + + + +//import org.jmol.script.T; + +final public class Measure { + + public final static float radiansPerDegree = (float) (2 * Math.PI / 360); + + public static float computeAngle(T3 pointA, T3 pointB, T3 pointC, V3 vectorBA, V3 vectorBC, boolean asDegrees) { + vectorBA.sub2(pointA, pointB); + vectorBC.sub2(pointC, pointB); + float angle = vectorBA.angle(vectorBC); + return (asDegrees ? angle / radiansPerDegree : angle); + } + + public static float computeAngleABC(T3 pointA, T3 pointB, T3 pointC, boolean asDegrees) { + V3 vectorBA = new V3(); + V3 vectorBC = new V3(); + return computeAngle(pointA, pointB, pointC, vectorBA, vectorBC, asDegrees); + } + + public static float computeTorsion(T3 p1, T3 p2, T3 p3, T3 p4, boolean asDegrees) { + + float ijx = p1.x - p2.x; + float ijy = p1.y - p2.y; + float ijz = p1.z - p2.z; + + float kjx = p3.x - p2.x; + float kjy = p3.y - p2.y; + float kjz = p3.z - p2.z; + + float klx = p3.x - p4.x; + float kly = p3.y - p4.y; + float klz = p3.z - p4.z; + + float ax = ijy * kjz - ijz * kjy; + float ay = ijz * kjx - ijx * kjz; + float az = ijx * kjy - ijy * kjx; + float cx = kjy * klz - kjz * kly; + float cy = kjz * klx - kjx * klz; + float cz = kjx * kly - kjy * klx; + + float ai2 = 1f / (ax * ax + ay * ay + az * az); + float ci2 = 1f / (cx * cx + cy * cy + cz * cz); + + float ai = (float) Math.sqrt(ai2); + float ci = (float) Math.sqrt(ci2); + float denom = ai * ci; + float cross = ax * cx + ay * cy + az * cz; + float cosang = cross * denom; + if (cosang > 1) { + cosang = 1; + } + if (cosang < -1) { + cosang = -1; + } + + float torsion = (float) Math.acos(cosang); + float dot = ijx * cx + ijy * cy + ijz * cz; + float absDot = Math.abs(dot); + torsion = (dot / absDot > 0) ? torsion : -torsion; + return (asDegrees ? torsion / radiansPerDegree : torsion); + } + + /** + * This method calculates measures relating to two points in space + * with related quaternion frame difference. It is used in Jmol for + * calculating straightness and many other helical quantities. + * + * @param a + * @param b + * @param dq + * @return new T3[] { pt_a_prime, n, r, P3.new3(theta, pitch, residuesPerTurn), pt_b_prime }; + */ + public static T3[] computeHelicalAxis(P3 a, P3 b, Quat dq) { + + // b + // | /| + // | / | + // | / | + // |/ c + // b'+ / \ + // | / \ Vcb = Vab . n + // n | / \d Vda = (Vcb - Vab) / 2 + // |/theta \ + // a'+---------a + // r + + V3 vab = new V3(); + vab.sub2(b, a); + /* + * testing here to see if directing the normal makes any difference -- oddly + * enough, it does not. When n = -n and theta = -theta vab.n is reversed, + * and that magnitude is multiplied by n in generating the A'-B' vector. + * + * a negative angle implies a left-handed axis (sheets) + */ + float theta = dq.getTheta(); + V3 n = dq.getNormal(); + float v_dot_n = vab.dot(n); + if (Math.abs(v_dot_n) < 0.0001f) + v_dot_n = 0; + V3 va_prime_d = new V3(); + va_prime_d.cross(vab, n); + if (va_prime_d.dot(va_prime_d) != 0) + va_prime_d.normalize(); + V3 vda = new V3(); + V3 vcb = V3.newV(n); + if (v_dot_n == 0) + v_dot_n = PT.FLOAT_MIN_SAFE; // allow for perpendicular axis to vab + vcb.scale(v_dot_n); + vda.sub2(vcb, vab); + vda.scale(0.5f); + va_prime_d.scale(theta == 0 ? 0 : (float) (vda.length() / Math.tan(theta + / 2 / 180 * Math.PI))); + V3 r = V3.newV(va_prime_d); + if (theta != 0) + r.add(vda); + P3 pt_a_prime = P3.newP(a); + pt_a_prime.sub(r); + // already done this. ?? + if (v_dot_n != PT.FLOAT_MIN_SAFE) + n.scale(v_dot_n); + // must calculate directed angle: + P3 pt_b_prime = P3.newP(pt_a_prime); + pt_b_prime.add(n); + theta = computeTorsion(a, pt_a_prime, pt_b_prime, b, true); + if (Float.isNaN(theta) || r.length() < 0.0001f) + theta = dq.getThetaDirectedV(n); // allow for r = 0 + // anything else is an array + float residuesPerTurn = Math.abs(theta == 0 ? 0 : 360f / theta); + float pitch = Math.abs(v_dot_n == PT.FLOAT_MIN_SAFE ? 0 : n.length() + * (theta == 0 ? 1 : 360f / theta)); + return new T3[] { pt_a_prime, n, r, P3.new3(theta, pitch, residuesPerTurn), pt_b_prime }; + } + + public static P4 getPlaneThroughPoints(T3 pointA, + T3 pointB, + T3 pointC, V3 vNorm, + V3 vAB, P4 plane) { + float w = getNormalThroughPoints(pointA, pointB, pointC, vNorm, vAB); + plane.set4(vNorm.x, vNorm.y, vNorm.z, w); + return plane; + } + + public static void getPlaneThroughPoint(T3 pt, V3 normal, P4 plane) { + plane.set4(normal.x, normal.y, normal.z, -normal.dot(pt)); + } + + public static float distanceToPlane(P4 plane, T3 pt) { + return (plane == null ? Float.NaN + : (plane.dot(pt) + plane.w) / (float) Math.sqrt(plane.dot(plane))); + } + + public static float directedDistanceToPlane(P3 pt, P4 plane, P3 ptref) { + float f = plane.dot(pt) + plane.w; + float f1 = plane.dot(ptref) + plane.w; + return Math.signum(f1) * f / (float) Math.sqrt(plane.dot(plane)); + } + + public static float distanceToPlaneD(P4 plane, float d, P3 pt) { + return (plane == null ? Float.NaN : (plane.dot(pt) + plane.w) / d); + } + + public static float distanceToPlaneV(V3 norm, float w, P3 pt) { + return (norm == null ? Float.NaN + : (norm.dot(pt) + w) / (float) Math.sqrt(norm.dot(norm))); + } + + /** + * note that if vAB or vAC is dispensible, vNormNorm can be one of them + * @param pointA + * @param pointB + * @param pointC + * @param vNormNorm + * @param vAB + */ + public static void calcNormalizedNormal(T3 pointA, T3 pointB, + T3 pointC, V3 vNormNorm, V3 vAB) { + vAB.sub2(pointB, pointA); + vNormNorm.sub2(pointC, pointA); + vNormNorm.cross(vAB, vNormNorm); + vNormNorm.normalize(); + } + + public static float getDirectedNormalThroughPoints(T3 pointA, + T3 pointB, T3 pointC, T3 ptRef, V3 vNorm, + V3 vAB) { + // for x = plane({atomno=1}, {atomno=2}, {atomno=3}, {atomno=4}) + float nd = getNormalThroughPoints(pointA, pointB, pointC, vNorm, vAB); + if (ptRef != null) { + P3 pt0 = P3.newP(pointA); + pt0.add(vNorm); + float d = pt0.distance(ptRef); + pt0.sub2(pointA, vNorm); + if (d > pt0.distance(ptRef)) { + vNorm.scale(-1); + nd = -nd; + } + } + return nd; + } + + /** + * if vAC is dispensible vNorm can be vAC + * @param pointA + * @param pointB + * @param pointC + * @param vNorm + * @param vTemp + * @return w + */ + public static float getNormalThroughPoints(T3 pointA, T3 pointB, + T3 pointC, V3 vNorm, V3 vTemp) { + // for Polyhedra + calcNormalizedNormal(pointA, pointB, pointC, vNorm, vTemp); + // ax + by + cz + d = 0 + // so if a point is in the plane, then N dot X = -d + vTemp.setT(pointA); + return -vTemp.dot(vNorm); + } + + public static void getPlaneProjection(P3 pt, P4 plane, P3 ptProj, V3 vNorm) { + float dist = distanceToPlane(plane, pt); + vNorm.set(plane.x, plane.y, plane.z); + vNorm.normalize(); + vNorm.scale(-dist); + ptProj.add2(pt, vNorm); + } + + public final static V3 axisY = V3.new3(0, 1, 0); + + public static void getNormalToLine(P3 pointA, P3 pointB, + V3 vNormNorm) { + // vector in xy plane perpendicular to a line between two points RMH + vNormNorm.sub2(pointA, pointB); + vNormNorm.cross(vNormNorm, axisY); + vNormNorm.normalize(); + if (Float.isNaN(vNormNorm.x)) + vNormNorm.set(1, 0, 0); + } + + public static void getBisectingPlane(P3 pointA, V3 vAB, + T3 ptTemp, V3 vTemp, P4 plane) { + ptTemp.scaleAdd2(0.5f, vAB, pointA); + vTemp.setT(vAB); + vTemp.normalize(); + getPlaneThroughPoint(ptTemp, vTemp, plane); + } + + public static void projectOntoAxis(P3 point, P3 axisA, + V3 axisUnitVector, + V3 vectorProjection) { + vectorProjection.sub2(point, axisA); + float projectedLength = vectorProjection.dot(axisUnitVector); + point.scaleAdd2(projectedLength, axisUnitVector, axisA); + vectorProjection.sub2(point, axisA); + } + + public static void calcBestAxisThroughPoints(P3[] points, P3 axisA, + V3 axisUnitVector, + V3 vectorProjection, + int nTriesMax) { + // just a crude starting point. + + int nPoints = points.length; + axisA.setT(points[0]); + axisUnitVector.sub2(points[nPoints - 1], axisA); + axisUnitVector.normalize(); + + /* + * We now calculate the least-squares 3D axis + * through the helix alpha carbons starting with Vo + * as a first approximation. + * + * This uses the simple 0-centered least squares fit: + * + * Y = M cross Xi + * + * minimizing R^2 = SUM(|Y - Yi|^2) + * + * where Yi is the vector PERPENDICULAR of the point onto axis Vo + * and Xi is the vector PROJECTION of the point onto axis Vo + * and M is a vector adjustment + * + * M = SUM_(Xi cross Yi) / sum(|Xi|^2) + * + * from which we arrive at: + * + * V = Vo + (M cross Vo) + * + * Basically, this is just a 3D version of a + * standard 2D least squares fit to a line, where we would say: + * + * y = m xi + b + * + * D = n (sum xi^2) - (sum xi)^2 + * + * m = [(n sum xiyi) - (sum xi)(sum yi)] / D + * b = [(sum yi) (sum xi^2) - (sum xi)(sum xiyi)] / D + * + * but here we demand that the line go through the center, so we + * require (sum xi) = (sum yi) = 0, so b = 0 and + * + * m = (sum xiyi) / (sum xi^2) + * + * In 3D we do the same but + * instead of x we have Vo, + * instead of multiplication we use cross products + * + * A bit of iteration is necessary. + * + * Bob Hanson 11/2006 + * + */ + + calcAveragePointN(points, nPoints, axisA); + + int nTries = 0; + while (nTries++ < nTriesMax + && findAxis(points, nPoints, axisA, axisUnitVector, vectorProjection) > 0.001) { + } + + /* + * Iteration here gets the job done. + * We now find the projections of the endpoints onto the axis + * + */ + + P3 tempA = P3.newP(points[0]); + projectOntoAxis(tempA, axisA, axisUnitVector, vectorProjection); + axisA.setT(tempA); + } + + public static float findAxis(P3[] points, int nPoints, P3 axisA, + V3 axisUnitVector, V3 vectorProjection) { + V3 sumXiYi = new V3(); + V3 vTemp = new V3(); + P3 pt = new P3(); + P3 ptProj = new P3(); + V3 a = V3.newV(axisUnitVector); + + float sum_Xi2 = 0; + for (int i = nPoints; --i >= 0;) { + pt.setT(points[i]); + ptProj.setT(pt); + projectOntoAxis(ptProj, axisA, axisUnitVector, + vectorProjection); + vTemp.sub2(pt, ptProj); + //sum_Yi2 += vTemp.lengthSquared(); + vTemp.cross(vectorProjection, vTemp); + sumXiYi.add(vTemp); + sum_Xi2 += vectorProjection.lengthSquared(); + } + V3 m = V3.newV(sumXiYi); + m.scale(1 / sum_Xi2); + vTemp.cross(m, axisUnitVector); + axisUnitVector.add(vTemp); + axisUnitVector.normalize(); + //check for change in direction by measuring vector difference length + vTemp.sub2(axisUnitVector, a); + return vTemp.length(); + } + + + public static void calcAveragePoint(P3 pointA, P3 pointB, + P3 pointC) { + pointC.set((pointA.x + pointB.x) / 2, (pointA.y + pointB.y) / 2, + (pointA.z + pointB.z) / 2); + } + + public static void calcAveragePointN(P3[] points, int nPoints, + P3 averagePoint) { + averagePoint.setT(points[0]); + for (int i = 1; i < nPoints; i++) + averagePoint.add(points[i]); + averagePoint.scale(1f / nPoints); + } + + public static Lst transformPoints(Lst vPts, M4 m4, P3 center) { + Lst v = new Lst(); + for (int i = 0; i < vPts.size(); i++) { + P3 pt = P3.newP(vPts.get(i)); + pt.sub(center); + m4.rotTrans(pt); + pt.add(center); + v.addLast(pt); + } + return v; + } + + public static boolean isInTetrahedron(P3 pt, P3 ptA, P3 ptB, + P3 ptC, P3 ptD, + P4 plane, V3 vTemp, + V3 vTemp2, boolean fullyEnclosed) { + boolean b = (distanceToPlane(getPlaneThroughPoints(ptC, ptD, ptA, vTemp, vTemp2, plane), pt) >= 0); + if (b != (distanceToPlane(getPlaneThroughPoints(ptA, ptD, ptB, vTemp, vTemp2, plane), pt) >= 0)) + return false; + if (b != (distanceToPlane(getPlaneThroughPoints(ptB, ptD, ptC, vTemp, vTemp2, plane), pt) >= 0)) + return false; + float d = distanceToPlane(getPlaneThroughPoints(ptA, ptB, ptC, vTemp, vTemp2, plane), pt); + if (fullyEnclosed) + return (b == (d >= 0)); + float d1 = distanceToPlane(plane, ptD); + return d1 * d <= 0 || Math.abs(d1) > Math.abs(d); + } + + + /** + * + * @param plane1 + * @param plane2 + * @return [ point, vector ] or [] + */ + public static Lst getIntersectionPP(P4 plane1, P4 plane2) { + float a1 = plane1.x; + float b1 = plane1.y; + float c1 = plane1.z; + float d1 = plane1.w; + float a2 = plane2.x; + float b2 = plane2.y; + float c2 = plane2.z; + float d2 = plane2.w; + V3 norm1 = V3.new3(a1, b1, c1); + V3 norm2 = V3.new3(a2, b2, c2); + V3 nxn = new V3(); + nxn.cross(norm1, norm2); + float ax = Math.abs(nxn.x); + float ay = Math.abs(nxn.y); + float az = Math.abs(nxn.z); + float x, y, z, diff; + int type = (ax > ay ? (ax > az ? 1 : 3) : ay > az ? 2 : 3); + switch(type) { + case 1: + x = 0; + diff = (b1 * c2 - b2 * c1); + if (Math.abs(diff) < 0.01) return null; + y = (c1 * d2 - c2 * d1) / diff; + z = (b2 * d1 - d2 * b1) / diff; + break; + case 2: + diff = (a1 * c2 - a2 * c1); + if (Math.abs(diff) < 0.01) return null; + x = (c1 * d2 - c2 * d1) / diff; + y = 0; + z = (a2 * d1 - d2 * a1) / diff; + break; + case 3: + default: + diff = (a1 * b2 - a2 * b1); + if (Math.abs(diff) < 0.01) return null; + x = (b1 * d2 - b2 * d1) / diff; + y = (a2 * d1 - d2 * a1) / diff; + z = 0; + } + Lstlist = new Lst(); + list.addLast(P3.new3(x, y, z)); + nxn.normalize(); + list.addLast(nxn); + return list; + } + + /** + * + * @param pt1 point on line + * @param v unit vector of line + * @param plane + * @param ptRet point of intersection of line with plane + * @param tempNorm + * @param vTemp + * @return ptRtet + */ + public static P3 getIntersection(P3 pt1, V3 v, + P4 plane, P3 ptRet, V3 tempNorm, V3 vTemp) { + getPlaneProjection(pt1, plane, ptRet, tempNorm); + tempNorm.set(plane.x, plane.y, plane.z); + tempNorm.normalize(); + if (v == null) + v = V3.newV(tempNorm); + float l_dot_n = v.dot(tempNorm); + if (Math.abs(l_dot_n) < 0.01) return null; + vTemp.sub2(ptRet, pt1); + ptRet.scaleAdd2(vTemp.dot(tempNorm) / l_dot_n, v, pt1); + return ptRet; + } + + /* + public static Point3f getTriangleIntersection(Point3f a1, Point3f a2, + Point3f a3, Point4f plane, + Point3f b1, + Point3f b2, Point3f b3, + Vector3f vNorm, Vector3f vTemp, + Point3f ptRet, Point3f ptTemp, Vector3f vTemp2, Point4f pTemp, Vector3f vTemp3) { + + if (getTriangleIntersection(b1, b2, a1, a2, a3, vTemp, plane, vNorm, vTemp2, vTemp3, ptRet, ptTemp)) + return ptRet; + if (getTriangleIntersection(b2, b3, a1, a2, a3, vTemp, plane, vNorm, vTemp2, vTemp3, ptRet, ptTemp)) + return ptRet; + if (getTriangleIntersection(b3, b1, a1, a2, a3, vTemp, plane, vNorm, vTemp2, vTemp3, ptRet, ptTemp)) + return ptRet; + return null; + } + */ + /* + public static boolean getTriangleIntersection(Point3f b1, Point3f b2, + Point3f a1, Point3f a2, + Point3f a3, Vector3f vTemp, + Point4f plane, Vector3f vNorm, + Vector3f vTemp2, Vector3f vTemp3, + Point3f ptRet, + Point3f ptTemp) { + if (distanceToPlane(plane, b1) * distanceToPlane(plane, b2) >= 0) + return false; + vTemp.sub(b2, b1); + vTemp.normalize(); + if (getIntersection(b1, vTemp, plane, ptRet, vNorm, vTemp2) != null) { + if (isInTriangle(ptRet, a1, a2, a3, vTemp, vTemp2, vTemp3)) + return true; + } + return false; + } + private static boolean isInTriangle(Point3f p, Point3f a, Point3f b, + Point3f c, Vector3f v0, Vector3f v1, + Vector3f v2) { + // from http://www.blackpawn.com/texts/pointinpoly/default.html + // Compute barycentric coordinates + v0.sub(c, a); + v1.sub(b, a); + v2.sub(p, a); + float dot00 = v0.dot(v0); + float dot01 = v0.dot(v1); + float dot02 = v0.dot(v2); + float dot11 = v1.dot(v1); + float dot12 = v1.dot(v2); + float invDenom = 1 / (dot00 * dot11 - dot01 * dot01); + float u = (dot11 * dot02 - dot01 * dot12) * invDenom; + float v = (dot00 * dot12 - dot01 * dot02) * invDenom; + return (u > 0 && v > 0 && u + v < 1); + } + */ + + /** + * Closed-form solution of absolute orientation requiring 1:1 mapping of + * positions. + * + * @param centerAndPoints + * @param retStddev + * @return unit quaternion representation rotation + * + * @author hansonr Bob Hanson + * + */ + public static Quat calculateQuaternionRotation(P3[][] centerAndPoints, + float[] retStddev) { + + retStddev[1] = Float.NaN; + Quat q = new Quat(); + if (centerAndPoints[0].length == 1 + || centerAndPoints[0].length != centerAndPoints[1].length) + return q; + + /* + * see Berthold K. P. Horn, + * "Closed-form solution of absolute orientation using unit quaternions" J. + * Opt. Soc. Amer. A, 1987, Vol. 4, pp. 629-642 + * http://www.opticsinfobase.org/viewmedia.cfm?uri=josaa-4-4-629&seq=0 + * + * + * A similar treatment was developed independently (and later!) + * by G. Kramer, in G. R. Kramer, + * "Superposition of Molecular Structures Using Quaternions" + * Molecular Simulation, 1991, Vol. 7, pp. 113-119. + * + * In that treatment there is a lot of unnecessary calculation + * along the trace of matrix M (eqn 20). + * I'm not sure why the extra x^2 + y^2 + z^2 + x'^2 + y'^2 + z'^2 + * is in there, but they are unnecessary and only contribute to larger + * numerical averaging errors and additional processing time, as far as + * I can tell. Adding aI, where a is a scalar and I is the 4x4 identity + * just offsets the eigenvalues but doesn't change the eigenvectors. + * + * and Lydia E. Kavraki, "Molecular Distance Measures" + * http://cnx.org/content/m11608/latest/ + * + */ + + int n = centerAndPoints[0].length - 1; + if (n < 2) + return q; + + double Sxx = 0, Sxy = 0, Sxz = 0, Syx = 0, Syy = 0, Syz = 0, Szx = 0, Szy = 0, Szz = 0; + P3 ptA = new P3(); + P3 ptB = new P3(); + for (int i = n + 1; --i >= 1;) { + P3 aij = centerAndPoints[0][i]; + P3 bij = centerAndPoints[1][i]; + ptA.sub2(aij, centerAndPoints[0][0]); + ptB.sub2(bij, centerAndPoints[0][1]); + Sxx += (double) ptA.x * (double) ptB.x; + Sxy += (double) ptA.x * (double) ptB.y; + Sxz += (double) ptA.x * (double) ptB.z; + Syx += (double) ptA.y * (double) ptB.x; + Syy += (double) ptA.y * (double) ptB.y; + Syz += (double) ptA.y * (double) ptB.z; + Szx += (double) ptA.z * (double) ptB.x; + Szy += (double) ptA.z * (double) ptB.y; + Szz += (double) ptA.z * (double) ptB.z; + } + retStddev[0] = getRmsd(centerAndPoints, q); + double[][] N = new double[4][4]; + N[0][0] = Sxx + Syy + Szz; + N[0][1] = N[1][0] = Syz - Szy; + N[0][2] = N[2][0] = Szx - Sxz; + N[0][3] = N[3][0] = Sxy - Syx; + + N[1][1] = Sxx - Syy - Szz; + N[1][2] = N[2][1] = Sxy + Syx; + N[1][3] = N[3][1] = Szx + Sxz; + + N[2][2] = -Sxx + Syy - Szz; + N[2][3] = N[3][2] = Syz + Szy; + + N[3][3] = -Sxx - Syy + Szz; + + //this construction prevents JavaScript from requiring preloading of Eigen + + float[] v = ((EigenInterface) Interface.getInterface("javajs.util.Eigen")) + .setM(N).getEigenvectorsFloatTransposed()[3]; + q = Quat.newP4(P4.new4(v[1], v[2], v[3], v[0])); + retStddev[1] = getRmsd(centerAndPoints, q); + return q; + } + + /** + * Fills a 4x4 matrix with rotation-translation of mapped points A to B. + * If centerA is null, this is a standard 4x4 rotation-translation matrix; + * otherwise, this 4x4 matrix is a rotation around a vector through the center of ptsA, + * and centerA is filled with that center; + * Prior to Jmol 14.3.12_2014.02.14, when used from the JmolScript compare() function, + * this method returned the second of these options instead of the first. + * + * @param ptsA + * @param ptsB + * @param m 4x4 matrix to be returned + * @param centerA return center of rotation; if null, then standard 4x4 matrix is returned + * @return stdDev + */ + public static float getTransformMatrix4(Lst ptsA, Lst ptsB, M4 m, + P3 centerA) { + P3[] cptsA = getCenterAndPoints(ptsA); + P3[] cptsB = getCenterAndPoints(ptsB); + float[] retStddev = new float[2]; + Quat q = calculateQuaternionRotation(new P3[][] { cptsA, cptsB }, + retStddev); + M3 r = q.getMatrix(); + if (centerA == null) + r.rotate(cptsA[0]); + else + centerA.setT(cptsA[0]); + V3 t = V3.newVsub(cptsB[0], cptsA[0]); + m.setMV(r, t); + return retStddev[1]; + } + + /** + * from a list of points, create an array that includes the center + * point as the first point. This array is used as a starting point for + * a quaternion analysis of superposition. + * + * @param vPts + * @return array of points with first point center + */ + public static P3[] getCenterAndPoints(Lst vPts) { + int n = vPts.size(); + P3[] pts = new P3[n + 1]; + pts[0] = new P3(); + if (n > 0) { + for (int i = 0; i < n; i++) { + pts[0].add(pts[i + 1] = vPts.get(i)); + } + pts[0].scale(1f / n); + } + return pts; + } + + public static float getRmsd(P3[][] centerAndPoints, Quat q) { + double sum2 = 0; + P3[] ptsA = centerAndPoints[0]; + P3[] ptsB = centerAndPoints[1]; + P3 cA = ptsA[0]; + P3 cB = ptsB[0]; + int n = ptsA.length - 1; + P3 ptAnew = new P3(); + + for (int i = n + 1; --i >= 1;) { + ptAnew.sub2(ptsA[i], cA); + q.transform2(ptAnew, ptAnew).add(cB); + sum2 += ptAnew.distanceSquared(ptsB[i]); + } + return (float) Math.sqrt(sum2 / n); + } + +} diff --git a/src/javajs/util/OC.java b/src/javajs/util/OC.java new file mode 100644 index 0000000..97f7ddb --- /dev/null +++ b/src/javajs/util/OC.java @@ -0,0 +1,386 @@ +package javajs.util; + +import java.io.BufferedWriter; +import java.io.ByteArrayOutputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.io.OutputStreamWriter; + + + +import javajs.J2SIgnoreImport; +import javajs.api.BytePoster; +import javajs.api.JmolObjectInterface; + +/** + * + * A generic output method. JmolOutputChannel can be used to: + * + * add characters to a StringBuffer + * using fileName==null, append() and toString() + * + * add bytes utilizing ByteArrayOutputStream + * using writeBytes(), writeByteAsInt(), append()*, and bytesAsArray() + * *append() can be used as long as os==ByteArrayOutputStream + * or it is not used before one of the writeByte methods. + * + * output characters to a FileOutputStream + * using os==FileOutputStream, asWriter==true, append(), and closeChannel() + * + * output bytes to a FileOutputStream + * using os==FileOutputStream, writeBytes(), writeByteAsInt(), append(), and closeChannel() + * + * post characters or bytes to a remote server + * using fileName=="http://..." or "https://...", + * writeBytes(), writeByteAsInt(), append(), and closeChannel() + * + * send characters or bytes to a JavaScript function + * when JavaScript and (typeof fileName == "function") + * + * if fileName equals ";base64,", then the data are base64-encoded + * prior to writing, and closeChannel() returns the data. + * + * @author hansonr Bob Hanson hansonr@stolaf.edu 9/2013 + * + * + */ + +@J2SIgnoreImport({ java.io.FileOutputStream.class }) +public class OC extends OutputStream { + + private BytePoster bytePoster; // only necessary for writing to http:// or https:// + private String fileName; + private BufferedWriter bw; + private boolean isLocalFile; + private int byteCount; + private boolean isCanceled; + private boolean closed; + private OutputStream os; + private SB sb; + private String type; + private boolean isBase64; + private OutputStream os0; + private byte[] bytes; // preset bytes; output only + + public OC setParams(BytePoster bytePoster, String fileName, + boolean asWriter, OutputStream os) { + this.bytePoster = bytePoster; + this.fileName = fileName; + isBase64 = ";base64,".equals(fileName); + if (isBase64) { + fileName = null; + os0 = os; + os = null; + } + this.os = os; + isLocalFile = (fileName != null && !isRemote(fileName)); + if (asWriter && !isBase64 && os != null) + bw = new BufferedWriter(new OutputStreamWriter(os)); + return this; + } + + public OC setBytes(byte[] b) { + bytes = b; + return this; + } + + public String getFileName() { + return fileName; + } + + public String getName() { + return (fileName == null ? null : fileName.substring(fileName.lastIndexOf("/") + 1)); + } + + public int getByteCount() { + return byteCount; + } + + /** + * + * @param type user-identified type (PNG, JPG, etc) + */ + public void setType(String type) { + this.type = type; + } + + public String getType() { + return type; + } + + /** + * will go to string buffer if bw == null and os == null + * + * @param s + * @return this, for chaining like a standard StringBuffer + * + */ + public OC append(String s) { + try { + if (bw != null) { + bw.write(s); + } else if (os == null) { + if (sb == null) + sb = new SB(); + sb.append(s); + } else { + byte[] b = s.getBytes(); + os.write(b, 0, b.length); + byteCount += b.length; + return this; + } + } catch (IOException e) { + // ignore + } + byteCount += s.length(); // not necessarily exactly correct if unicode + return this; + } + + public void reset() { + sb = null; + initOS(); + } + + + private void initOS() { + if (sb != null) { + String s = sb.toString(); + reset(); + append(s); + return; + } + try { + /** + * @j2sNative + * + * this.os = null; + */ + { + if (os instanceof FileOutputStream) { + os.close(); + os = new FileOutputStream(fileName); + } else { + os = null; + } + } + if (os == null) + os = new ByteArrayOutputStream(); + if (bw != null) { + bw.close(); + bw = new BufferedWriter(new OutputStreamWriter(os)); + } + } catch (Exception e) { + // not perfect here. + System.out.println(e.toString()); + } + byteCount = 0; + } + + /** + * @j2sOverride + */ + @Override + public void write(byte[] buf, int i, int len) { + if (os == null) + initOS(); + try { + os.write(buf, i, len); + } catch (IOException e) { + } + byteCount += len; + } + + /** + * @param b + */ + public void writeByteAsInt(int b) { + if (os == null) + initOS(); + /** + * @j2sNative + * + * this.os.writeByteAsInt(b); + * + */ + { + try { + os.write(b); + } catch (IOException e) { + } + } + byteCount++; + } + + /** + * Will break JavaScript if used. + * + * @j2sIgnore + * + * @param b + */ + @Override + @Deprecated + public void write(int b) { + // required by standard ZipOutputStream -- do not use, as it will break JavaScript methods + if (os == null) + initOS(); + try { + os.write(b); + } catch (IOException e) { + } + byteCount++; + } + +// /** +// * Will break if used; no equivalent in JavaScript. +// * +// * @j2sIgnore +// * +// * @param b +// */ +// @Override +// @Deprecated +// public void write(byte[] b) { +// // not used in JavaScript due to overloading problem there +// write(b, 0, b.length); +// } + + public void cancel() { + isCanceled = true; + closeChannel(); + } + + @SuppressWarnings({ "null", "unused" }) + public String closeChannel() { + if (closed) + return null; + // can't cancel file writers + try { + if (bw != null) { + bw.flush(); + bw.close(); + } else if (os != null) { + os.flush(); + os.close(); + } + if (os0 != null && isCanceled) { + os0.flush(); + os0.close(); + } + } catch (Exception e) { + // ignore closing issues + } + if (isCanceled) { + closed = true; + return null; + } + if (fileName == null) { + if (isBase64) { + String s = getBase64(); + if (os0 != null) { + os = os0; + append(s); + } + sb = new SB(); + sb.append(s); + isBase64 = false; + return closeChannel(); + } + return (sb == null ? null : sb.toString()); + } + closed = true; + JmolObjectInterface jmol = null; + Object _function = null; + /** + * @j2sNative + * + * jmol = Jmol; _function = (typeof this.fileName == "function" ? + * this.fileName : null); + * + */ + { + if (!isLocalFile) { + String ret = postByteArray(); // unsigned applet could do this + if (ret.startsWith("java.net")) + byteCount = -1; + return ret; + } + } + if (jmol != null) { + Object data = (sb == null ? toByteArray() : sb.toString()); + if (_function == null) + jmol._doAjax(fileName, null, data); + else + jmol._apply(fileName, data); + } + return null; + } + + public boolean isBase64() { + return isBase64; + } + + public String getBase64() { + return Base64.getBase64(toByteArray()).toString(); + } + + public byte[] toByteArray() { + return (bytes != null ? bytes : os instanceof ByteArrayOutputStream ? ((ByteArrayOutputStream)os).toByteArray() : null); + } + + @Override + @Deprecated + public void close() { + closeChannel(); + } + + @Override + public String toString() { + if (bw != null) + try { + bw.flush(); + } catch (IOException e) { + // TODO + } + if (sb != null) + return closeChannel(); + return byteCount + " bytes"; + } + + private String postByteArray() { + byte[] bytes = (sb == null ? toByteArray() : sb.toString().getBytes()); + return bytePoster.postByteArray(fileName, bytes); + } + + public final static String[] urlPrefixes = { "http:", "https:", "sftp:", "ftp:", + "file:" }; + // note that SFTP is not supported + public final static int URL_LOCAL = 4; + + public static boolean isRemote(String fileName) { + if (fileName == null) + return false; + int itype = urlTypeIndex(fileName); + return (itype >= 0 && itype != URL_LOCAL); + } + + public static boolean isLocal(String fileName) { + if (fileName == null) + return false; + int itype = urlTypeIndex(fileName); + return (itype < 0 || itype == URL_LOCAL); + } + + public static int urlTypeIndex(String name) { + if (name == null) + return -2; // local unsigned applet + for (int i = 0; i < urlPrefixes.length; ++i) { + if (name.startsWith(urlPrefixes[i])) { + return i; + } + } + return -1; + } + +} diff --git a/src/javajs/util/P3.java b/src/javajs/util/P3.java new file mode 100644 index 0000000..3917159 --- /dev/null +++ b/src/javajs/util/P3.java @@ -0,0 +1,65 @@ +/* + Copyright (C) 1997,1998,1999 + Kenji Hiranabe, Eiwa System Management, Inc. + + This program is free software. + Implemented by Kenji Hiranabe(hiranabe@esm.co.jp), + conforming to the Java(TM) 3D API specification by Sun Microsystems. + + Permission to use, copy, modify, distribute and sell this software + and its documentation for any purpose is hereby granted without fee, + provided that the above copyright notice appear in all copies and + that both that copyright notice and this permission notice appear + in supporting documentation. Kenji Hiranabe and Eiwa System Management,Inc. + makes no representations about the suitability of this software for any + purpose. It is provided "AS IS" with NO WARRANTY. +*/ +package javajs.util; + + + +/** + * A 3 element point that is represented by single precision floating point + * x,y,z coordinates. + * + * @version specification 1.1, implementation $Revision: 1.10 $, $Date: + * 2006/09/08 20:20:20 $ + * @author Kenji hiranabe + * + * additions by Bob Hanson hansonr@stolaf.edu 9/30/2012 + * for unique constructor and method names + * for the optimization of compiled JavaScript using Java2Script + * + */ +public class P3 extends T3 { + + /** + * @j2sIgnore + */ + public P3() { + // ignore T3 + } + + public static P3 newP(T3 t) { + P3 p = new P3(); + p.x = t.x; + p.y = t.y; + p.z = t.z; + return p; + } + + private static P3 unlikely; + + public static P3 getUnlikely() { + return (unlikely == null ? unlikely = new3((float) Math.PI, (float) Math.E, (float) (Math.PI * Math.E)) : unlikely); + } + + public static P3 new3(float x, float y, float z) { + P3 p = new P3(); + p.x = x; + p.y = y; + p.z = z; + return p; + } + +} diff --git a/src/javajs/util/P3i.java b/src/javajs/util/P3i.java new file mode 100644 index 0000000..8f39550 --- /dev/null +++ b/src/javajs/util/P3i.java @@ -0,0 +1,43 @@ +/* + Copyright (C) 1997,1998,1999 + Kenji Hiranabe, Eiwa System Management, Inc. + + This program is free software. + Implemented by Kenji Hiranabe(hiranabe@esm.co.jp), + conforming to the Java(TM) 3D API specification by Sun Microsystems. + + Permission to use, copy, modify, distribute and sell this software + and its documentation for any purpose is hereby granted without fee, + provided that the above copyright notice appear in all copies and + that both that copyright notice and this permission notice appear + in supporting documentation. Kenji Hiranabe and Eiwa System Management,Inc. + makes no representations about the suitability of this software for any + purpose. It is provided "AS IS" with NO WARRANTY. +*/ +package javajs.util; + + + +/** + * A 3 element point that is represented by signed integer x,y,z coordinates. + * + * @since Java 3D 1.2 + * @version specification 1.2, implementation $Revision: 1.9 $, $Date: + * 2006/07/28 17:01:33 $ + * @author Kenji hiranabe + * + * + * additions by Bob Hanson hansonr@stolaf.edu 9/30/2012 for unique + * constructor and method names for the optimization of compiled + * JavaScript using Java2Script + */ +public class P3i extends T3i { + + public static P3i new3(int x, int y, int z) { + P3i pt = new P3i(); + pt.x = x; + pt.y = y; + pt.z = z; + return pt; + } +} diff --git a/src/javajs/util/P4.java b/src/javajs/util/P4.java new file mode 100644 index 0000000..a434f53 --- /dev/null +++ b/src/javajs/util/P4.java @@ -0,0 +1,70 @@ +/* + Copyright (C) 1997,1998,1999 + Kenji Hiranabe, Eiwa System Management, Inc. + + This program is free software. + Implemented by Kenji Hiranabe(hiranabe@esm.co.jp), + conforming to the Java(TM) 3D API specification by Sun Microsystems. + + Permission to use, copy, modify, distribute and sell this software + and its documentation for any purpose is hereby granted without fee, + provided that the above copyright notice appear in all copies and + that both that copyright notice and this permission notice appear + in supporting documentation. Kenji Hiranabe and Eiwa System Management,Inc. + makes no representations about the suitability of this software for any + purpose. It is provided "AS IS" with NO WARRANTY. +*/ +package javajs.util; + + + +/** + * A 4 element point that is represented by single precision floating point + * x,y,z,w coordinates. + * + * @version specification 1.1, implementation $Revision: 1.9 $, $Date: + * 2006/07/28 17:01:32 $ + * @author Kenji hiranabe + * + * additions by Bob Hanson hansonr@stolaf.edu 9/30/2012 + * for unique constructor and method names + * for the optimization of compiled JavaScript using Java2Script + */ +public class P4 extends T4 { + + /** + * + * @j2sIgnore * + */ + public P4() { + // skip T4() constructor + } + + public static P4 new4(float x, float y, float z, float w) { + P4 pt = new P4(); + pt.set4(x, y, z, w); + return pt; + } + + public static P4 newPt(P4 value) { + P4 pt = new P4(); + pt.set4(value.x, value.y, value.z, value.w); + return pt; + } + + /** + * Returns the distance between this point and point p1. + * + * @param p1 + * the other point + * @return the distance between these two points + */ + public final float distance4(P4 p1) { + double dx = x - p1.x; + double dy = y - p1.y; + double dz = z - p1.z; + double dw = w - p1.w; + return (float) Math.sqrt(dx * dx + dy * dy + dz * dz + dw * dw); + } + +} diff --git a/src/javajs/util/PT.java b/src/javajs/util/PT.java new file mode 100644 index 0000000..e6a27b4 --- /dev/null +++ b/src/javajs/util/PT.java @@ -0,0 +1,1540 @@ +/* $RCSfile$ + * $Author: hansonr $ + * $Date: 2007-04-26 16:57:51 -0500 (Thu, 26 Apr 2007) $ + * $Revision: 7502 $ + * + * Copyright (C) 2005 The Jmol Development Team + * + * Contact: jmol-developers@lists.sf.net + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +package javajs.util; + +import java.lang.reflect.Array; +import java.util.Map; +import java.util.Map.Entry; + +import javajs.J2SIgnoreImport; +import javajs.api.JSONEncodable; + +/** + * a combination of Parsing and Text-related utility classes + * + * @author hansonr + * + */ + +@J2SIgnoreImport(value = { java.lang.reflect.Array.class }) +public class PT { + + public static int parseInt(String str) { + return parseIntNext(str, new int[] {0}); + } + + public static int parseIntNext(String str, int[] next) { + int cch = str.length(); + if (next[0] < 0 || next[0] >= cch) + return Integer.MIN_VALUE; + return parseIntChecked(str, cch, next); + } + + public static int parseIntChecked(String str, int ichMax, int[] next) { + boolean digitSeen = false; + int value = 0; + int ich = next[0]; + if (ich < 0) + return Integer.MIN_VALUE; + int ch; + while (ich < ichMax && isWhiteSpace(str, ich)) + ++ich; + boolean negative = false; + if (ich < ichMax && str.charAt(ich) == 45) { //"-" + negative = true; + ++ich; + } + while (ich < ichMax && (ch = str.charAt(ich)) >= 48 && ch <= 57) { + value = value * 10 + (ch - 48); + digitSeen = true; + ++ich; + } + if (!digitSeen)// || !checkTrailingText(str, ich, ichMax)) + value = Integer.MIN_VALUE; + else if (negative) + value = -value; + next[0] = ich; + return value; + } + + public static boolean isWhiteSpace(String str, int ich) { + char ch; + return (ich >= 0 && ((ch = str.charAt(ich)) == ' ' || ch == '\t' || ch == '\n')); + } + + /** + * A float parser that is 30% faster than Float.parseFloat(x) and also accepts + * x.yD+-n + * + * @param str + * @param ichMax + * @param next + * pointer; incremented + * @param isStrict + * @return value or Float.NaN + */ + public static float parseFloatChecked(String str, int ichMax, int[] next, + boolean isStrict) { + boolean digitSeen = false; + int ich = next[0]; + if (isStrict && str.indexOf('\n') != str.lastIndexOf('\n')) + return Float.NaN; + while (ich < ichMax && isWhiteSpace(str, ich)) + ++ich; + boolean negative = false; + if (ich < ichMax && str.charAt(ich) == '-') { + ++ich; + negative = true; + } + // looks crazy, but if we don't do this, Google Closure Compiler will + // write code that Safari will misinterpret in a VERY nasty way -- + // getting totally confused as to long integers and double values + + // This is Safari figuring out the values of the numbers on the line (x, y, then z): + + // ATOM 1241 CD1 LEU A 64 -2.206 36.532 31.576 1.00 60.60 C + // e=1408749273 + // -e =-1408749273 + // ATOM 1241 CD1 LEU A 64 -2.206 36.532 31.576 1.00 60.60 C + // e=-1821066134 + // e=36.532 + // ATOM 1241 CD1 LEU A 64 -2.206 36.532 31.576 1.00 60.60 C + // e=-1133871366 + // e=31.576 + // + // "e" values are just before and after the "value = -value" statement. + + int ch = 0; + float ival = 0f; + float ival2 = 0f; + while (ich < ichMax && (ch = str.charAt(ich)) >= 48 && ch <= 57) { + ival = (ival * 10f) + (ch - 48)*1f; + ++ich; + digitSeen = true; + } + boolean isDecimal = false; + int iscale = 0; + int nzero = (ival == 0 ? -1 : 0); + if (ch == '.') { + isDecimal = true; + while (++ich < ichMax && (ch = str.charAt(ich)) >= 48 && ch <= 57) { + digitSeen = true; + if (nzero < 0) { + if (ch == 48) { + nzero--; + continue; + } + nzero = -nzero; + } + if (iscale < decimalScale.length) { + ival2 = (ival2 * 10f) + (ch - 48)*1f; + iscale++; + } + } + } + float value; + + // Safari breaks here intermittently converting integers to floats + + if (!digitSeen) { + value = Float.NaN; + } else if (ival2 > 0) { + value = ival2 * decimalScale[iscale - 1]; + if (nzero > 1) { + if (nzero - 2 < decimalScale.length) { + value *= decimalScale[nzero - 2]; + } else { + value *= Math.pow(10, 1 - nzero); + } + } else { + value += ival; + } + } else { + value = ival; + } + boolean isExponent = false; + if (ich < ichMax && (ch == 69 || ch == 101 || ch == 68)) { // E e D + isExponent = true; + if (++ich >= ichMax) + return Float.NaN; + ch = str.charAt(ich); + if ((ch == '+') && (++ich >= ichMax)) + return Float.NaN; + next[0] = ich; + int exponent = parseIntChecked(str, ichMax, next); + if (exponent == Integer.MIN_VALUE) + return Float.NaN; + if (exponent > 0 && exponent <= tensScale.length) + value *= tensScale[exponent - 1]; + else if (exponent < 0 && -exponent <= decimalScale.length) + value *= decimalScale[-exponent - 1]; + else if (exponent != 0) + value *= Math.pow(10, exponent); + } else { + next[0] = ich; // the exponent code finds its own ichNextParse + } + // believe it or not, Safari reports the long-equivalent of the + // float value here, then later the float value, after no operation! + if (negative) + value = -value; + if (value == Float.POSITIVE_INFINITY) + value = Float.MAX_VALUE; + return (!isStrict || (!isExponent || isDecimal) + && checkTrailingText(str, next[0], ichMax) ? value : Float.NaN); + } + + public final static float[] tensScale = { 10f, 100f, 1000f, 10000f, 100000f, 1000000f }; + public final static float[] decimalScale = { + 0.1f, + 0.01f, + 0.001f, + 0.0001f, + 0.00001f, + 0.000001f, + 0.0000001f, + 0.00000001f, + 0.000000001f + }; + public static boolean checkTrailingText(String str, int ich, int ichMax) { + //number must be pure -- no additional characters other than white space or ; + char ch; + while (ich < ichMax && (isWhitespace(ch = str.charAt(ich)) || ch == ';')) + ++ich; + return (ich == ichMax); + } + + public static float[] parseFloatArray(String str) { + return parseFloatArrayNext(str, new int[1], null, null, null); + } + + public static int parseFloatArrayInfested(String[] tokens, float[] data) { + int len = data.length; + int nTokens = tokens.length; + int n = 0; + int max = 0; + for (int i = 0; i >= 0 && i < len && n < nTokens; i++) { + float f; + while (Float.isNaN(f = parseFloat(tokens[n++])) + && n < nTokens) { + } + if (!Float.isNaN(f)) + data[(max = i)] = f; + if (n == nTokens) + break; + } + return max + 1; + } + + /** + * @param str + * @param next + * @param f + * @param strStart or null + * @param strEnd or null + * @return array of float values + * + */ + public static float[] parseFloatArrayNext(String str, int[] next, float[] f, + String strStart, String strEnd) { + int n = 0; + int pt = next[0]; + if (pt >= 0) { + if (strStart != null) { + int p = str.indexOf(strStart, pt); + if (p >= 0) + next[0] = p + strStart.length(); + } + str = str.substring(next[0]); + pt = (strEnd == null ? -1 : str.indexOf(strEnd)); + if (pt < 0) + pt = str.length(); + else + str = str.substring(0, pt); + next[0] += pt + 1; + String[] tokens = getTokens(str); + if (f == null) + f = new float[tokens.length]; + n = parseFloatArrayInfested(tokens, f); + } + if (f == null) + return new float[0]; + for (int i = n; i < f.length; i++) + f[i] = Float.NaN; + return f; + } + + public static float parseFloatRange(String str, int ichMax, int[] next) { + int cch = str.length(); + if (ichMax > cch) + ichMax = cch; + if (next[0] < 0 || next[0] >= ichMax) + return Float.NaN; + return parseFloatChecked(str, ichMax, next, false); + } + + public static float parseFloatNext(String str, int[] next) { + int cch = (str == null ? -1 : str.length()); + return (next[0] < 0 || next[0] >= cch ? Float.NaN : parseFloatChecked(str, cch, next, false)); + } + + public static float parseFloatStrict(String str) { + // checks trailing characters and does not allow "1E35" to be float + int cch = str.length(); + if (cch == 0) + return Float.NaN; + return parseFloatChecked(str, cch, new int[] {0}, true); + } + + public static float parseFloat(String str) { + return parseFloatNext(str, new int[] {0}); + } + + public static int parseIntRadix(String s, int i) throws NumberFormatException { + /** + * + * JavaScript uses parseIntRadix + * + * @j2sNative + * + * return Integer.parseIntRadix(s, i); + * + */ + { + return Integer.parseInt(s, i); + } + } + + public static String[] getTokens(String line) { + return getTokensAt(line, 0); + } + + public static String parseToken(String str) { + return parseTokenNext(str, new int[] {0}); + } + + public static String parseTrimmed(String str) { + return parseTrimmedRange(str, 0, str.length()); + } + + public static String parseTrimmedAt(String str, int ichStart) { + return parseTrimmedRange(str, ichStart, str.length()); + } + + public static String parseTrimmedRange(String str, int ichStart, int ichMax) { + int cch = str.length(); + if (ichMax < cch) + cch = ichMax; + if (cch < ichStart) + return ""; + return parseTrimmedChecked(str, ichStart, cch); + } + + public static String[] getTokensAt(String line, int ich) { + if (line == null) + return null; + int cchLine = line.length(); + if (ich < 0 || ich > cchLine) + return null; + int tokenCount = countTokens(line, ich); + String[] tokens = new String[tokenCount]; + int[] next = new int[1]; + next[0] = ich; + for (int i = 0; i < tokenCount; ++i) + tokens[i] = parseTokenChecked(line, cchLine, next); + return tokens; + } + + public static int countChar(String line, char c) { + int tokenCount = 0; + int pt = -1; + while ((pt = line.indexOf(c, pt + 1)) >= 0) + tokenCount++; + return tokenCount; + } + + public static int countTokens(String line, int ich) { + int tokenCount = 0; + if (line != null) { + int ichMax = line.length(); + while (true) { + while (ich < ichMax && isWhiteSpace(line, ich)) + ++ich; + if (ich == ichMax) + break; + ++tokenCount; + do { + ++ich; + } while (ich < ichMax && !isWhiteSpace(line, ich)); + } + } + return tokenCount; + } + + public static String parseTokenNext(String str, int[] next) { + int cch = str.length(); + return (next[0] < 0 || next[0] >= cch ? null : parseTokenChecked(str, cch, next)); + } + + public static String parseTokenRange(String str, int ichMax, int[] next) { + int cch = str.length(); + if (ichMax > cch) + ichMax = cch; + return (next[0] < 0 || next[0] >= ichMax ? null : parseTokenChecked(str, ichMax, next)); + } + + public static String parseTokenChecked(String str, int ichMax, int[] next) { + int ich = next[0]; + while (ich < ichMax && isWhiteSpace(str, ich)) + ++ich; + int ichNonWhite = ich; + while (ich < ichMax && !isWhiteSpace(str, ich)) + ++ich; + next[0] = ich; + return (ichNonWhite == ich ? null : str.substring(ichNonWhite, ich)); + } + + public static String parseTrimmedChecked(String str, int ich, int ichMax) { + while (ich < ichMax && isWhiteSpace(str, ich)) + ++ich; + int ichLast = ichMax - 1; + while (ichLast >= ich && isWhiteSpace(str, ichLast)) + --ichLast; + return (ichLast < ich ? "" : str.substring(ich, ichLast + 1)); + } + + public static double dVal(String s) throws NumberFormatException { + /** + * @j2sNative + * + * if(s==null) + * throw new NumberFormatException("null"); + * var d=parseFloat(s); + * if(isNaN(d)) + * throw new NumberFormatException("Not a Number : "+s); + * return d + * + */ + { + return Double.valueOf(s).doubleValue(); + } + } + + public static float fVal(String s) throws NumberFormatException { + /** + * @j2sNative + * + * return this.dVal(s); + */ + { + return Float.parseFloat(s); + } + } + + public static int parseIntRange(String str, int ichMax, int[] next) { + int cch = str.length(); + if (ichMax > cch) + ichMax = cch; + return (next[0] < 0 || next[0] >= ichMax ? Integer.MIN_VALUE : parseIntChecked(str, ichMax, next)); + } + + /** + * parses a string array for floats. Returns NaN for nonfloats. + * + * @param tokens the strings to parse + * @param data the array to fill + */ + public static void parseFloatArrayData(String[] tokens, float[] data) { + parseFloatArrayDataN(tokens, data, data.length); + } + + /** + * parses a string array for floats. Returns NaN for nonfloats or missing data. + * + * @param tokens the strings to parse + * @param data the array to fill + * @param nData the number of elements + */ + public static void parseFloatArrayDataN(String[] tokens, float[] data, int nData) { + for (int i = nData; --i >= 0;) + data[i] = (i >= tokens.length ? Float.NaN : parseFloat(tokens[i])); + } + + /** + * + * proper splitting, even for Java 1.3 -- if the text ends in the run, + * no new line is appended. + * + * @param text + * @param run + * @return String array + */ + public static String[] split(String text, String run) { + if (text.length() == 0) + return new String[0]; + int n = 1; + int i = text.indexOf(run); + String[] lines; + int runLen = run.length(); + if (i < 0 || runLen == 0) { + lines = new String[1]; + lines[0] = text; + return lines; + } + int len = text.length() - runLen; + for (; i >= 0 && i < len; n++) + i = text.indexOf(run, i + runLen); + lines = new String[n]; + i = 0; + int ipt = 0; + int pt = 0; + for (; (ipt = text.indexOf(run, i)) >= 0 && pt + 1 < n;) { + lines[pt++] = text.substring(i, ipt); + i = ipt + runLen; + } + if (text.indexOf(run, len) != len) + len += runLen; + lines[pt] = text.substring(i, len); + return lines; + } + + public final static float FLOAT_MIN_SAFE = 2E-45f; + // Float.MIN_VALUE (1.45E-45) is not reliable with JavaScript because of the float/double difference there + + /// general static string-parsing class /// + + // next[0] tracks the pointer within the string so these can all be static. + // but the methods parseFloat, parseInt, parseToken, parseTrimmed, and getTokens do not require this. + +// public static String concatTokens(String[] tokens, int iFirst, int iEnd) { +// String str = ""; +// String sep = ""; +// for (int i = iFirst; i < iEnd; i++) { +// if (i < tokens.length) { +// str += sep + tokens[i]; +// sep = " "; +// } +// } +// return str; +// } + + public static String getQuotedStringAt(String line, int ipt0) { + int[] next = new int[] { ipt0 }; + return getQuotedStringNext(line, next); + } + + /** + * + * @param line + * @param next passes [current pointer] + * @return quoted string -- does NOT unescape characters + */ + public static String getQuotedStringNext(String line, int[] next) { + int i = next[0]; + if (i < 0 || (i = line.indexOf("\"", i)) < 0) + return ""; + int pt = i + 1; + int len = line.length(); + while (++i < len && line.charAt(i) != '"') + if (line.charAt(i) == '\\') + i++; + next[0] = i + 1; + return line.substring(pt, i); + } + + /** + * CSV format -- escaped quote is "" WITHIN "..." + * + * + * @param line + * @param next int[2] filled with [ptrQuote1, ptrAfterQuote2] + * next[1] will be -1 if unmatched quotes are found (continuation on next line) + * @return unescaped string or null + */ + public static String getCSVString(String line, int[] next) { + int i = next[1]; + if (i < 0 || (i = line.indexOf("\"", i)) < 0) + return null; + int pt = next[0] = i; + int len = line.length(); + boolean escaped = false; + boolean haveEscape = false; + while (++i < len + && (line.charAt(i) != '"' || (escaped = (i + 1 < len && line.charAt(i + 1) == '"')))) + if (escaped) { + escaped = false; + haveEscape = true; + i++; + } + if (i >= len) { + next[1] = -1; + return null; // unmatched + } + next[1] = i + 1; + String s = line.substring(pt + 1, i); + return (haveEscape ? rep(rep(s, "\"\"", "\0"), "\0","\"") : s); + } + + public static boolean isOneOf(String key, String semiList) { + if (semiList.length() == 0) + return false; + if (semiList.charAt(0) != ';') + semiList = ";" + semiList + ";"; + return key.indexOf(";") < 0 && semiList.indexOf(';' + key + ';') >= 0; + } + + public static String getQuotedAttribute(String info, String name) { + int i = info.indexOf(name + "="); + return (i < 0 ? null : getQuotedStringAt(info, i)); + } + + public static float approx(float f, float n) { + return Math.round (f * n) / n; + } + + /** + * Does a clean ITERATIVE replace of strFrom in str with strTo. + * Thus, rep("Testttt", "tt","t") becomes "Test". + * + * @param str + * @param strFrom + * @param strTo + * @return replaced string + */ + public static String rep(String str, String strFrom, String strTo) { + if (str == null || strFrom.length() == 0 || str.indexOf(strFrom) < 0) + return str; + boolean isOnce = (strTo.indexOf(strFrom) >= 0); + do { + str = str.replace(strFrom, strTo); + } while (!isOnce && str.indexOf(strFrom) >= 0); + return str; + } + + public static String formatF(float value, int width, int precision, + boolean alignLeft, boolean zeroPad) { + return formatS(DF.formatDecimal(value, precision), width, 0, alignLeft, zeroPad); + } + + /** + * + * @param value + * @param width + * @param precision + * @param alignLeft + * @param zeroPad + * @param allowOverflow IGNORED + * @return formatted string + */ + public static String formatD(double value, int width, int precision, + boolean alignLeft, boolean zeroPad, boolean allowOverflow) { + return formatS(DF.formatDecimal((float)value, -1 - precision), width, 0, alignLeft, zeroPad); + } + + /** + * + * @param value + * @param width number of columns + * @param precision precision > 0 ==> precision = number of characters max from left + * precision < 0 ==> -1 - precision = number of char. max from right + * @param alignLeft + * @param zeroPad generally for numbers turned strings + * @return formatted string + */ + public static String formatS(String value, int width, int precision, + boolean alignLeft, boolean zeroPad) { + if (value == null) + return ""; + int len = value.length(); + if (precision != Integer.MAX_VALUE && precision > 0 + && precision < len) + value = value.substring(0, precision); + else if (precision < 0 && len + precision >= 0) + value = value.substring(len + precision + 1); + + int padLength = width - value.length(); + if (padLength <= 0) + return value; + boolean isNeg = (zeroPad && !alignLeft && value.charAt(0) == '-'); + char padChar = (zeroPad ? '0' : ' '); + char padChar0 = (isNeg ? '-' : padChar); + + SB sb = new SB(); + if (alignLeft) + sb.append(value); + sb.appendC(padChar0); + for (int i = padLength; --i > 0;) + // this is correct, not >= 0 + sb.appendC(padChar); + if (!alignLeft) + sb.append(isNeg ? padChar + value.substring(1) : value); + return sb.toString(); + } + + /** + * Does a clean replace of any of the characters in str with chrTo + * If strTo contains strFrom, then only a single pass is done. + * Otherwise, multiple passes are made until no more replacements can be made. + * + * @param str + * @param strFrom + * @param chTo + * @return replaced string + */ + public static String replaceWithCharacter(String str, String strFrom, + char chTo) { + if (str == null) + return null; + for (int i = strFrom.length(); --i >= 0;) + str = str.replace(strFrom.charAt(i), chTo); + return str; + } + + /** + * Does a clean replace of any of the characters in str with strTo + * If strTo contains strFrom, then only a single pass is done. + * Otherwise, multiple passes are made until no more replacements can be made. + * + * @param str + * @param strFrom + * @param strTo + * @return replaced string + */ + public static String replaceAllCharacters(String str, String strFrom, + String strTo) { + for (int i = strFrom.length(); --i >= 0;) { + String chFrom = strFrom.substring(i, i + 1); + str = rep(str, chFrom, strTo); + } + return str; + } + + public static String trim(String str, String chars) { + if (str == null || str.length() == 0) + return str; + if (chars.length() == 0) + return str.trim(); + int len = str.length(); + int k = 0; + while (k < len && chars.indexOf(str.charAt(k)) >= 0) + k++; + int m = str.length() - 1; + while (m > k && chars.indexOf(str.charAt(m)) >= 0) + m--; + return str.substring(k, m + 1); + } + + public static String trimQuotes(String value) { + return (value != null && value.length() > 1 && value.startsWith("\"") + && value.endsWith("\"") ? value.substring(1, value.length() - 1) + : value); + } + + public static boolean isNonStringPrimitive(Object info) { + // note that we don't use Double, Float, or Integer here + // because in JavaScript those would be false for unwrapped primitives + // coming from equivalent of Array.get() + // Strings will need their own escaped processing + + return info instanceof Number || info instanceof Boolean; + } + + private static Object arrayGet(Object info, int i) { + /** + * + * Note that info will be a primitive in JavaScript + * but a wrapped primitive in Java. + * + * @j2sNative + * + * return info[i]; + */ + { + return Array.get(info, i); + } + } + + @SuppressWarnings("unchecked") + public static String toJSON(String infoType, Object info) { + if (info == null) + return packageJSON(infoType, null); + if (isNonStringPrimitive(info)) + return packageJSON(infoType, info.toString()); + String s = null; + SB sb = null; + while (true) { + if (info instanceof String) { + s = (String) info; + /** + * @j2sNative + * + * if (typeof s == "undefined") s = "null" + * + */ + {} + if (s.indexOf("{\"") != 0) { + //don't doubly fix JSON strings when retrieving status + s = rep(s, "\"", "\\\""); + s = rep(s, "\n", "\\n"); + s = "\"" + s + "\""; + } + break; + } + if (info instanceof JSONEncodable) { + // includes javajs.util.BS, org.jmol.script.SV + if ((s = ((JSONEncodable) info).toJSON()) == null) + s = "null"; // perhaps a list has a null value (group3List, for example) + break; + } + sb = new SB(); + if (info instanceof Map) { + sb.append("{ "); + String sep = ""; + for (String key : ((Map) info).keySet()) { + sb.append(sep).append( + packageJSON(key, toJSON(null, ((Map) info).get(key)))); + sep = ","; + } + sb.append(" }"); + break; + } + if (info instanceof Lst) { + sb.append("[ "); + int n = ((Lst) info).size(); + for (int i = 0; i < n; i++) { + if (i > 0) + sb.appendC(','); + sb.append(toJSON(null, ((Lst) info).get(i))); + } + sb.append(" ]"); + break; + } + if (info instanceof M34) { + // M4 extends M3 + int len = (info instanceof M4 ? 4 : 3); + float[] x = new float[len]; + M34 m = (M34) info; + sb.appendC('['); + for (int i = 0; i < len; i++) { + if (i > 0) + sb.appendC(','); + m.getRow(i, x); + sb.append(toJSON(null, x)); + } + sb.appendC(']'); + break; + } + s = nonArrayString(info); + if (s == null) { + sb.append("["); + int n = AU.getLength(info); + for (int i = 0; i < n; i++) { + if (i > 0) + sb.appendC(','); + sb.append(toJSON(null, arrayGet(info, i))); + } + sb.append("]"); + break; + } + info = info.toString(); + } + return packageJSON(infoType, (s == null ? sb.toString() : s)); + } + + /** + * Checks to see if an object is an array, and if it is, returns null; + * otherwise it returns the string equivalent of that object. + * + * @param x + * @return String or null + */ + public static String nonArrayString(Object x) { + /** + * @j2sNative + * + * var s = x.toString(); return (s.startsWith("[object") && + * s.endsWith("Array]") ? null : s); + * + */ + { + try { + Array.getLength(x); + return null; + } catch (Exception e) { + return x.toString(); + } + } + } + + public static String byteArrayToJSON(byte[] data) { + SB sb = new SB(); + sb.append("["); + int n = data.length; + for (int i = 0; i < n; i++) { + if (i > 0) + sb.appendC(','); + sb.appendI(data[i] & 0xFF); + } + sb.append("]"); + return sb.toString(); + } + + public static String packageJSON(String infoType, String info) { + return (infoType == null ? info : "\"" + infoType + "\": " + info); + } + + public static String escapeUrl(String url) { + url = rep(url, "\n", ""); + url = rep(url, "%", "%25"); + url = rep(url, "#", "%23"); + url = rep(url, "[", "%5B"); + url = rep(url, "]", "%5D"); + url = rep(url, " ", "%20"); + return url; + } + + private final static String escapable = "\\\\\tt\rr\nn\"\""; + + public static String esc(String str) { + if (str == null || str.length() == 0) + return "\"\""; + boolean haveEscape = false; + int i = 0; + for (; i < escapable.length(); i += 2) + if (str.indexOf(escapable.charAt(i)) >= 0) { + haveEscape = true; + break; + } + if (haveEscape) + while (i < escapable.length()) { + int pt = -1; + char ch = escapable.charAt(i++); + char ch2 = escapable.charAt(i++); + SB sb = new SB(); + int pt0 = 0; + while ((pt = str.indexOf(ch, pt + 1)) >= 0) { + sb.append(str.substring(pt0, pt)).appendC('\\').appendC(ch2); + pt0 = pt + 1; + } + sb.append(str.substring(pt0, str.length())); + str = sb.toString(); + } + return "\"" + escUnicode(str) + "\""; + } + + public static String escUnicode(String str) { + for (int i = str.length(); --i >= 0;) + if (str.charAt(i) > 0x7F) { + String s = "0000" + Integer.toHexString(str.charAt(i)); + str = str.substring(0, i) + "\\u" + s.substring(s.length() - 4) + + str.substring(i + 1); + } + return str; + } + + /** + * ensures that a float turned to string has a decimal point + * + * @param f + * @return string version of float + */ + public static String escF(float f) { + String sf = "" + f; + /** + * @j2sNative + * + * if (sf.indexOf(".") < 0 && sf.indexOf("e") < 0) + * sf += ".0"; + */ + { + } + return sf; + } + public static String join(String[] s, char c, int i0) { + if (s.length < i0) + return null; + SB sb = new SB(); + sb.append(s[i0++]); + for (int i = i0; i < s.length; i++) + sb.appendC(c).append(s[i]); + return sb.toString(); + } + + /** + * a LIKE "x" a is a string and equals x + * + * a LIKE "*x" a is a string and ends with x + * + * a LIKE "x*" a is a string and starts with x + * + * a LIKE "*x*" a is a string and contains x + * + * @param a + * @param b + * @return a LIKE b + */ + public static boolean isLike(String a, String b) { + boolean areEqual = a.equals(b); + if (areEqual) + return true; + boolean isStart = b.startsWith("*"); + boolean isEnd = b.endsWith("*"); + return (!isStart && !isEnd) ? areEqual + : isStart && isEnd ? b.length() == 1 || a.contains(b.substring(1, b.length() - 1)) + : isStart ? a.endsWith(b.substring(1)) + : a.startsWith(b.substring(0, b.length() - 1)); + } + + public static Object getMapValueNoCase(Map h, String key) { + if ("this".equals(key)) + return h; + Object val = h.get(key); + if (val == null) + for (Entry e : h.entrySet()) + if (e.getKey().equalsIgnoreCase(key)) + return e.getValue(); + return val; + } + + public static String clean(String s) { + return rep(replaceAllCharacters(s, " \t\n\r", " "), " ", " ").trim(); + } + + /** + * + * fdup duplicates p or q formats for formatCheck + * and the format() function. + * + * @param f + * @param pt + * @param n + * @return %3.5q%3.5q%3.5q%3.5q or %3.5p%3.5p%3.5p + */ + public static String fdup(String f, int pt, int n) { + char ch; + int count = 0; + for (int i = pt; --i >= 1; ) { + if (isDigit(ch = f.charAt(i))) + continue; + switch (ch) { + case '.': + if (count++ != 0) + return f; + continue; + case '-': + if (i != 1 && f.charAt(i - 1) != '.') + return f; + continue; + default: + return f; + } + } + String s = f.substring(0, pt + 1); + SB sb = new SB(); + for (int i = 0; i < n; i++) + sb.append(s); + sb.append(f.substring(pt + 1)); + return sb.toString(); + } + + /** + * generic string formatter based on formatLabel in Atom + * + * + * @param strFormat .... %width.precisionKEY.... + * @param key any string to match + * @param strT replacement string or null + * @param floatT replacement float or Float.NaN + * @param doubleT replacement double or Double.NaN -- for exponential + * @param doOne mimic sprintf + * @return formatted string + */ + + public static String formatString(String strFormat, String key, String strT, + float floatT, double doubleT, boolean doOne) { + if (strFormat == null) + return null; + if ("".equals(strFormat)) + return ""; + int len = key.length(); + if (strFormat.indexOf("%") < 0 || len == 0 || strFormat.indexOf(key) < 0) + return strFormat; + + String strLabel = ""; + int ich, ichPercent, ichKey; + for (ich = 0; (ichPercent = strFormat.indexOf('%', ich)) >= 0 + && (ichKey = strFormat.indexOf(key, ichPercent + 1)) >= 0;) { + if (ich != ichPercent) + strLabel += strFormat.substring(ich, ichPercent); + ich = ichPercent + 1; + if (ichKey > ichPercent + 6) { + strLabel += '%'; + continue;//%12.10x + } + try { + boolean alignLeft = false; + if (strFormat.charAt(ich) == '-') { + alignLeft = true; + ++ich; + } + boolean zeroPad = false; + if (strFormat.charAt(ich) == '0') { + zeroPad = true; + ++ich; + } + char ch; + int width = 0; + while ((ch = strFormat.charAt(ich)) >= '0' && (ch <= '9')) { + width = (10 * width) + (ch - '0'); + ++ich; + } + int precision = Integer.MAX_VALUE; + boolean isExponential = false; + if (strFormat.charAt(ich) == '.') { + ++ich; + if ((ch = strFormat.charAt(ich)) == '-') { + isExponential = true; + ++ich; + } + if ((ch = strFormat.charAt(ich)) >= '0' && ch <= '9') { + precision = ch - '0'; + ++ich; + } + if (isExponential) + precision = -precision - (strT == null ? 1 : 0); + } + String st = strFormat.substring(ich, ich + len); + if (!st.equals(key)) { + ich = ichPercent + 1; + strLabel += '%'; + continue; + } + ich += len; + if (!Float.isNaN(floatT)) + strLabel += formatF(floatT, width, precision, alignLeft, + zeroPad); + else if (strT != null) + strLabel += formatS(strT, width, precision, alignLeft, + zeroPad); + else if (!Double.isNaN(doubleT)) + strLabel += formatD(doubleT, width, precision, alignLeft, + zeroPad, true); + if (doOne) + break; + } catch (IndexOutOfBoundsException ioobe) { + ich = ichPercent; + break; + } + } + strLabel += strFormat.substring(ich); + //if (strLabel.length() == 0) + //return null; + return strLabel; + } + + public static String formatStringS(String strFormat, String key, String strT) { + return formatString(strFormat, key, strT, Float.NaN, Double.NaN, false); + } + + public static String formatStringF(String strFormat, String key, float floatT) { + return formatString(strFormat, key, null, floatT, Double.NaN, false); + } + + public static String formatStringI(String strFormat, String key, int intT) { + return formatString(strFormat, key, "" + intT, Float.NaN, Double.NaN, false); + } + + /** + * sprintf emulation uses (almost) c++ standard string formats + * + * 's' string 'i' or 'd' integer, 'e' double, 'f' float, 'p' point3f 'q' + * quaternion/plane/axisangle with added "i" (equal to the insipid "d" -- + * digits?) + * + * @param strFormat + * @param list + * a listing of what sort of data will be found in Object[] values, in + * order: s string, f float, i integer, d double, p point3f, q + * quaternion/point4f, S String[], F float[], I int[], and D double[] + * @param values + * Object[] containing above types + * @return formatted string + */ + public static String sprintf(String strFormat, String list, Object[] values) { + if (values == null) + return strFormat; + int n = list.length(); + if (n == values.length) + try { + for (int o = 0; o < n; o++) { + if (values[o] == null) + continue; + switch (list.charAt(o)) { + case 's': + strFormat = formatString(strFormat, "s", (String) values[o], + Float.NaN, Double.NaN, true); + break; + case 'f': + strFormat = formatString(strFormat, "f", null, ((Float) values[o]) + .floatValue(), Double.NaN, true); + break; + case 'i': + strFormat = formatString(strFormat, "d", "" + values[o], Float.NaN, + Double.NaN, true); + strFormat = formatString(strFormat, "i", "" + values[o], Float.NaN, + Double.NaN, true); + break; + case 'd': + strFormat = formatString(strFormat, "e", null, Float.NaN, + ((Double) values[o]).doubleValue(), true); + break; + case 'p': + T3 pVal = (T3) values[o]; + strFormat = formatString(strFormat, "p", null, pVal.x, Double.NaN, + true); + strFormat = formatString(strFormat, "p", null, pVal.y, Double.NaN, + true); + strFormat = formatString(strFormat, "p", null, pVal.z, Double.NaN, + true); + break; + case 'q': + T4 qVal = (T4) values[o]; + strFormat = formatString(strFormat, "q", null, qVal.x, Double.NaN, + true); + strFormat = formatString(strFormat, "q", null, qVal.y, Double.NaN, + true); + strFormat = formatString(strFormat, "q", null, qVal.z, Double.NaN, + true); + strFormat = formatString(strFormat, "q", null, qVal.w, Double.NaN, + true); + break; + case 'S': + String[] sVal = (String[]) values[o]; + for (int i = 0; i < sVal.length; i++) + strFormat = formatString(strFormat, "s", sVal[i], Float.NaN, + Double.NaN, true); + break; + case 'F': + float[] fVal = (float[]) values[o]; + for (int i = 0; i < fVal.length; i++) + strFormat = formatString(strFormat, "f", null, fVal[i], + Double.NaN, true); + break; + case 'I': + int[] iVal = (int[]) values[o]; + for (int i = 0; i < iVal.length; i++) + strFormat = formatString(strFormat, "d", "" + iVal[i], Float.NaN, + Double.NaN, true); + for (int i = 0; i < iVal.length; i++) + strFormat = formatString(strFormat, "i", "" + iVal[i], Float.NaN, + Double.NaN, true); + break; + case 'D': + double[] dVal = (double[]) values[o]; + for (int i = 0; i < dVal.length; i++) + strFormat = formatString(strFormat, "e", null, Float.NaN, + dVal[i], true); + } + + } + return rep(strFormat, "%%", "%"); + } catch (Exception e) { + // + } + System.out.println("TextFormat.sprintf error " + list + " " + strFormat); + return rep(strFormat, "%", "?"); + } + + /** + * + * formatCheck checks p and q formats and duplicates if necessary + * "%10.5p xxxx" ==> "%10.5p%10.5p%10.5p xxxx" + * + * @param strFormat + * @return f or dupicated format + */ + public static String formatCheck(String strFormat) { + if (strFormat == null || strFormat.indexOf('p') < 0 && strFormat.indexOf('q') < 0) + return strFormat; + strFormat = rep(strFormat, "%%", "\1"); + strFormat = rep(strFormat, "%p", "%6.2p"); + strFormat = rep(strFormat, "%q", "%6.2q"); + String[] format = split(strFormat, "%"); + SB sb = new SB(); + sb.append(format[0]); + for (int i = 1; i < format.length; i++) { + String f = "%" + format[i]; + int pt; + if (f.length() >= 3) { + if ((pt = f.indexOf('p')) >= 0) + f = fdup(f, pt, 3); + if ((pt = f.indexOf('q')) >= 0) + f = fdup(f, pt, 4); + } + sb.append(f); + } + return sb.toString().replace('\1', '%'); + } + + public static void leftJustify(SB s, String s1, String s2) { + s.append(s2); + int n = s1.length() - s2.length(); + if (n > 0) + s.append(s1.substring(0, n)); + } + + public static void rightJustify(SB s, String s1, String s2) { + int n = s1.length() - s2.length(); + if (n > 0) + s.append(s1.substring(0, n)); + s.append(s2); + } + + public static String safeTruncate(float f, int n) { + if (f > -0.001 && f < 0.001) + f = 0; + return (f + " ").substring(0,n); + } + + public static boolean isWild(String s) { + return s != null && (s.indexOf("*") >= 0 || s.indexOf("?") >= 0); + } + + /** + * A general non-regex (for performance) text matcher that utilizes ? and *. + * + * ??? means "at most three" characters if at beginning or end; + * "exactly three" otherwise + * \1 in search is a stand-in for actual ? + * + * @param search + * the string to search + * @param match + * the match string + * @param checkStar + * @param allowInitialStar + * @return true if found + */ + public static boolean isMatch(String search, String match, boolean checkStar, + boolean allowInitialStar) { + // search == match --> true + if (search.equals(match)) + return true; + int mLen = match.length(); + // match == "" --> false + if (mLen == 0) + return false; + boolean isStar0 = (checkStar && allowInitialStar ? match.charAt(0) == '*' + : false); + // match == "*" --> true + if (mLen == 1 && isStar0) + return true; + boolean isStar1 = (checkStar && match.endsWith("*")); + boolean haveQ = (match.indexOf('?') >= 0); + // match == "**" --> true + // match == "*xxx*" --> search contains "xxx" + // match == "*xxx" --> search ends with "xxx" + // match == "xxx*" --> search starts with "xxx" + if (!haveQ) { + if (isStar0) + return (isStar1 ? (mLen < 3 || search.indexOf(match.substring(1, + mLen - 1)) >= 0) : search.endsWith(match.substring(1))); + else if (isStar1) + return search.startsWith(match.substring(0, mLen - 1)); + } + int sLen = search.length(); + // pad match with "?" -- same as * + String qqqq = "????"; + int nq = 4; + while (nq < sLen) { + qqqq += qqqq; + nq += 4; + } + if (checkStar) { + if (isStar0) { + match = qqqq + match.substring(1); + mLen += nq - 1; + } + if (isStar1) { + match = match.substring(0, mLen - 1) + qqqq; + mLen += nq - 1; + } + } + // length of match < length of search --> false + if (mLen < sLen) + return false; + + // -- each ? matches ONE character if not at end + // -- extra ? at end ignored + + // (allowInitialStar == true) + // -- extra ? at beginning reduced to match length + + int ich = 0; + while (mLen > sLen) { + if (allowInitialStar && match.charAt(ich) == '?') { + ++ich; + } else if (match.charAt(ich + mLen - 1) != '?') { + return false; + } + --mLen; + } + + // both are effectively same length now. + // \1 is stand-in for "?" + + for (int i = sLen; --i >= 0;) { + char chm = match.charAt(ich + i); + if (chm == '?') + continue; + char chs = search.charAt(i); + if (chm != chs && (chm != '\1' || chs != '?')) + return false; + } + return true; + } + + public static String replaceQuotedStrings(String s, Lst list, + Lst newList) { + int n = list.size(); + for (int i = 0; i < n; i++) { + String name = list.get(i); + String newName = newList.get(i); + if (!newName.equals(name)) + s = rep(s, "\"" + name + "\"", "\"" + newName + + "\""); + } + return s; + } + + public static String replaceStrings(String s, Lst list, + Lst newList) { + int n = list.size(); + for (int i = 0; i < n; i++) { + String name = list.get(i); + String newName = newList.get(i); + if (!newName.equals(name)) + s = rep(s, name, newName); + } + return s; + } + + public static boolean isDigit(char ch) { + // just way simpler code than Character.isDigit(ch); + int c = ch; + return (48 <= c && c <= 57); + } + + public static boolean isUpperCase(char ch) { + int c = ch; + return (65 <= c && c <= 90); + } + + public static boolean isLowerCase(char ch) { + int c = ch; + return (97 <= c && c <= 122); + } + + public static boolean isLetter(char ch) { + // just way simpler code than Character.isLetter(ch); + int c = ch; + return (65 <= c && c <= 90 || 97 <= c && c <= 122); + } + + public static boolean isLetterOrDigit(char ch) { + // just way simpler code than Character.isLetterOrDigit(ch); + int c = ch; + return (65 <= c && c <= 90 || 97 <= c && c <= 122 || 48 <= c && c <= 57); + } + + public static boolean isWhitespace(char ch) { + int c = ch; + return (c >= 0x1c && c <= 0x20 || c >= 0x9 && c <= 0xd); + } + + public static final float FRACTIONAL_PRECISION = 100000f; + public static final float CARTESIAN_PRECISION = 10000f; + + public static void fixPtFloats(T3 pt, float f) { + //this will equate float and double as long as -256 <= x <= 256 + pt.x = Math.round(pt.x * f) / f; + pt.y = Math.round(pt.y * f) / f; + pt.z = Math.round(pt.z * f) / f; + } + + public static double fixDouble(double d, double f) { + return Math.round(d * f) / f; + } + + /** + * parse a float or "float/float" + * @param s + * @return a/b + */ + public static float parseFloatFraction(String s) { + int pt = s.indexOf("/"); + return (pt < 0 ? parseFloat(s) : parseFloat(s.substring(0, pt)) + / parseFloat(s.substring(pt + 1))); + } + +//static { +// +// double d = 790.8999998888; +// float x = 790.8999998888f; +// for (int i = 0; i < 50; i++) { +// System.out.println(x + " " + d); +// System.out.println(Math.round(x * 100000) / 100000f); +// System.out.println(Math.round(d * 100000) / 100000.); +// System.out.println(Math.round(x * 10000) / 10000f); +// System.out.println(Math.round(d * 10000) / 10000.); +// x+=1; +// d+=1; +// } +// System.out.println(100.123456789f); +//} + +// static { +// long t; +// char c = '0'; +// t = System.currentTimeMillis(); +// for (int i = 0; i < 10000000; i++) { +// boolean b = PT.isUpperCase(c); +// } +// System.out.println(System.currentTimeMillis() - t); +// +// t = System.currentTimeMillis(); +// for (int i = 0; i < 10000000; i++) { +// boolean b = Character.isUpperCase(c); +// } +// System.out.println(System.currentTimeMillis() - t); +// +// t = System.currentTimeMillis(); +// for (int i = 0; i < 10000000; i++) { +// boolean b = PT.isUpperCase(c); +// } +// System.out.println(System.currentTimeMillis() - t); +// +// System.out.println("PT test"); +// } +} diff --git a/src/javajs/util/Quat.java b/src/javajs/util/Quat.java new file mode 100644 index 0000000..6b93578 --- /dev/null +++ b/src/javajs/util/Quat.java @@ -0,0 +1,815 @@ +/* $RCSfile$ + * $Author: hansonr $ + * $Date: 2007-04-05 09:07:28 -0500 (Thu, 05 Apr 2007) $ + * $Revision: 7326 $ + * + * Copyright (C) 2003-2005 The Jmol Development Team + * + * Contact: jmol-developers@lists.sf.net + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + */ +package javajs.util; + +/* + * Standard UNIT quaternion math -- for rotation. + * + * All rotations can be represented as two identical quaternions. + * This is because any rotation can be considered from either end of the + * rotational axis -- either as a + rotation or a - rotation. This code + * is designed to always maintain the quaternion with a rotation in the + * [0, PI) range. + * + * This ensures that the reported theta is always positive, and the normal + * reported is always associated with a positive theta. + * + * @author Bob Hanson, hansonr@stolaf.edu 6/2008 + * + */ + +public class Quat { + public float q0, q1, q2, q3; + private M3 mat; + + private final static P4 qZero = new P4(); + private static final double RAD_PER_DEG = Math.PI / 180; + + public Quat() { + q0 = 1; + } + + public static Quat newQ(Quat q) { + Quat q1 = new Quat(); + q1.set(q); + return q1; + } + + public static Quat newVA(T3 v, float theta) { + Quat q = new Quat(); + q.setTA(v, theta); + return q; + } + + public static Quat newM(M3 mat) { + Quat q = new Quat(); + q.setM(M3.newM3(mat)); + return q; + } + + public static Quat newAA(A4 a) { + Quat q = new Quat(); + q.setAA(a); + return q; + } + + public static Quat newP4(P4 pt) { + Quat q = new Quat(); + q.setP4(pt); + return q; + } + + /** + * Note that q0 is the last parameter here + * + * @param q1 + * @param q2 + * @param q3 + * @param q0 + * @return {q1 q2 q3 q0} + */ + public static Quat new4(float q1, float q2, float q3, float q0) { + Quat q = new Quat(); + if (q0 < -1) { + q.q0 = -1; + return q; + } + if (q0 > 1) { + q.q0 = 1; + return q; + } + q.q0 = q0; + q.q1 = q1; + q.q2 = q2; + q.q3 = q3; + return q; + } + + public void set(Quat q) { + q0 = q.q0; + q1 = q.q1; + q2 = q.q2; + q3 = q.q3; + } + + /** + * {x y z w} --> {q1 q2 q3 q0} and factored + * + * @param pt + */ + private void setP4(P4 pt) { + float factor = (pt == null ? 0 : pt.distance4(qZero)); + if (factor == 0) { + q0 = 1; + return; + } + q0 = pt.w / factor; + q1 = pt.x / factor; + q2 = pt.y / factor; + q3 = pt.z / factor; + } + + /** + * q = (cos(theta/2), sin(theta/2) * n) + * + * @param pt + * @param theta + */ + public void setTA(T3 pt, float theta) { + if (pt.x == 0 && pt.y == 0 && pt.z == 0) { + q0 = 1; + return; + } + double fact = (Math.sin(theta / 2 * RAD_PER_DEG) / Math.sqrt(pt.x + * pt.x + pt.y * pt.y + pt.z * pt.z)); + q0 = (float) (Math.cos(theta / 2 * RAD_PER_DEG)); + q1 = (float) (pt.x * fact); + q2 = (float) (pt.y * fact); + q3 = (float) (pt.z * fact); + } + + public void setAA(A4 a) { + A4 aa = A4.newAA(a); + if (aa.angle == 0) + aa.y = 1; + setM(new M3().setAA(aa)); + } + + private void setM(M3 mat) { + + /* + * Changed 7/16/2008 to double precision for 11.5.48. + * + * + * + * RayTrace Software Package, release 3.0. May 3, 2006. + * + * Mathematics Subpackage (VrMath) + * + * Author: Samuel R. Buss + * + * Software is "as-is" and carries no warranty. It may be used without + * restriction, but if you modify it, please change the filenames to + * prevent confusion between different versions. Please acknowledge + * all use of the software in any publications or products based on it. + * + * Bug reports: Sam Buss, sbuss@ucsd.edu. + * Web page: http://math.ucsd.edu/~sbuss/MathCG + + // Use Shepperd's algorithm, which is stable, does not lose + // significant precision and uses only one sqrt. + // J. Guidance and Control, 1 (1978) 223-224. + + * + * + * Except, that code has errors. + * + * CORRECTIONS (as noted below) of Quaternion.cpp. I have reported the bug. + * + * -- Bob Hanson + * + * theory: + * cos(theta/2)^2 = (cos(theta) + 1)/2 + * and + * trace = (1-x^2)ct + (1-y^2)ct + (1-z^2)ct + 1 = 2cos(theta) + 1 + * or + * cos(theta) = (trace - 1)/2 + * + * so in general, + * + * w = cos(theta/2) + * = sqrt((cos(theta)+1)/2) + * = sqrt((trace-1)/4+1/2) + * = sqrt((trace+1)/4) + * = sqrt(trace+1)/2 + * + * but there are precision issues, so we allow for other situations. + * note -- trace >= 0.5 when cos(theta) >= -0.25 (-104.48 <= theta <= 104.48). + * this code cleverly matches the precision in all four options. + * + */ + + this.mat = mat; + + double trace = mat.m00 + mat.m11 + mat.m22; + double temp; + double w, x, y, z; + if (trace >= 0.5) { + w = Math.sqrt(1.0 + trace); + x = (mat.m21 - mat.m12) / w; + y = (mat.m02 - mat.m20) / w; + z = (mat.m10 - mat.m01) / w; + } else if ((temp = mat.m00 + mat.m00 - trace) >= 0.5) { + x = Math.sqrt(1.0 + temp); + w = (mat.m21 - mat.m12) / x; + y = (mat.m10 + mat.m01) / x; + z = (mat.m20 + mat.m02) / x; + } else if ((temp = mat.m11 + mat.m11 - trace) >= 0.5 + || mat.m11 > mat.m22) { + y = Math.sqrt(1.0 + temp); + w = (mat.m02 - mat.m20) / y; + x = (mat.m10 + mat.m01) / y; + z = (mat.m21 + mat.m12) / y; + } else { + z = Math.sqrt(1.0 + mat.m22 + mat.m22 - trace); + w = (mat.m10 - mat.m01) / z; + x = (mat.m20 + mat.m02) / z; // was - + y = (mat.m21 + mat.m12) / z; // was - + } + + q0 = (float) (w * 0.5); + q1 = (float) (x * 0.5); + q2 = (float) (y * 0.5); + q3 = (float) (z * 0.5); + + /* + * Originally from http://www.gamedev.net/community/forums/topic.asp?topic_id=448380 + * later algorithm was adapted from Visualizing Quaternions, by Andrew J. Hanson + * (Morgan Kaufmann, 2006), page 446 + * + * HOWEVER, checking with AxisAngle4f and Quat4f equivalents, it was found that + * BOTH of these sources produce inverted quaternions. So here we do an inversion. + * + * This correction was made in 11.5.42 6/19/2008 -- Bob Hanson + * + * former algorithm used: + * / + + double tr = mat.m00 + mat.m11 + mat.m22; //Matrix trace + double s; + double[] q = new double[4]; + if (tr > 0) { + s = Math.sqrt(tr + 1); + q0 = (float) (0.5 * s); + s = 0.5 / s; // = 1/q0 + q1 = (float) ((mat.m21 - mat.m12) * s); + q2 = (float) ((mat.m02 - mat.m20) * s); + q3 = (float) ((mat.m10 - mat.m01) * s); + } else { + float[][] m = new float[][] { new float[3], new float[3], new float[3] }; + mat.getRow(0, m[0]); + mat.getRow(1, m[1]); + mat.getRow(2, m[2]); + + //Find out the biggest element along the diagonal + float max = Math.max(mat.m11, mat.m00); + int i = (mat.m22 > max ? 2 : max == mat.m11 ? 1 : 0); + int j = (i + 1) % 3; + int k = (j + 1) % 3; + s = -Math.sqrt(1 + m[i][i] - m[j][j] - m[k][k]); + // 0 = 1 + (1-x^2)ct + x^2 -(1-y^2)ct - y^2 - (1-z^2)ct - z^2 + // 0 = 1 - ct + (x^2 - y^2 - z^2) - (x^2 - y^2 - z^2)ct + // 0 = 1 - ct + 2x^2 - 1 - (2x^2)ct + ct + // 0 = 2x^2(1 - ct) + // theta = 0 (but then trace = 1 + 1 + 1 = 3) + // or x = 0. + q[i] = s * 0.5; + if (s != 0) + s = 0.5 / s; // = 1/q[i] + q[j] = (m[i][j] + m[j][i]) * s; + q[k] = (m[i][k] + m[k][i]) * s; + q0 = (float) ((m[k][j] - m[j][k]) * s); + q1 = (float) q[0]; // x + q2 = (float) q[1]; // y + q3 = (float) q[2]; // z + } + + */ + } + + /* + * if qref is null, "fix" this quaternion + * otherwise, return a quaternion that is CLOSEST to the given quaternion + * that is, one that gives a positive dot product + * + */ + public void setRef(Quat qref) { + if (qref == null) { + mul(getFixFactor()); + return; + } + if (dot(qref) >= 0) + return; + q0 *= -1; + q1 *= -1; + q2 *= -1; + q3 *= -1; + } + + /** + * returns a quaternion frame based on three points (center, x, and any point in xy plane) + * or two vectors (vA, vB). + * + * @param center (null for vA/vB option) + * @param x + * @param xy + * @return quaternion for frame + */ + public static final Quat getQuaternionFrame(P3 center, T3 x, + T3 xy) { + V3 vA = V3.newV(x); + V3 vB = V3.newV(xy); + if (center != null) { + vA.sub(center); + vB.sub(center); + } + return getQuaternionFrameV(vA, vB, null, false); + } + + /** + * Create a quaternion based on a frame + * @param vA + * @param vB + * @param vC + * @param yBased + * @return quaternion + */ + public static final Quat getQuaternionFrameV(V3 vA, V3 vB, + V3 vC, boolean yBased) { + if (vC == null) { + vC = new V3(); + vC.cross(vA, vB); + if (yBased) + vA.cross(vB, vC); + } + V3 vBprime = new V3(); + vBprime.cross(vC, vA); + vA.normalize(); + vBprime.normalize(); + vC.normalize(); + M3 mat = new M3(); + mat.setColumnV(0, vA); + mat.setColumnV(1, vBprime); + mat.setColumnV(2, vC); + + /* + * + * Verification tests using Quat4f and AngleAxis4f: + * + System.out.println("quaternion frame matrix: " + mat); + + Point3f pt2 = new Point3f(); + mat.transform(Point3f.new3(1, 0, 0), pt2); + System.out.println("vA=" + vA + " M(100)=" + pt2); + mat.transform(Point3f.new3(0, 1, 0), pt2); + System.out.println("vB'=" + vBprime + " M(010)=" + pt2); + mat.transform(Point3f.new3(0, 0, 1), pt2); + System.out.println("vC=" + vC + " M(001)=" + pt2); + Quat4f q4 = new Quat4f(); + q4.set(mat); + System.out.println("----"); + System.out.println("Quat4f: {" + q4.w + " " + q4.x + " " + q4.y + " " + q4.z + "}"); + System.out.println("Quat4f: 2xy + 2wz = m10: " + (2 * q4.x * q4.y + 2 * q4.w * q4.z) + " = " + mat.m10); + + */ + + Quat q = newM(mat); + + /* + System.out.println("Quaternion mat from q \n" + q.getMatrix()); + System.out.println("Quaternion: " + q.getNormal() + " " + q.getTheta()); + AxisAngle4f a = new AxisAngle4f(); + a.set(mat); + Vector3f v = Vector3f.new3(a.x, a.y, a.z); + v.normalize(); + System.out.println("angleAxis: " + v + " "+(a.angle/Math.PI * 180)); + */ + + return q; + } + + public M3 getMatrix() { + if (mat == null) + setMatrix(); + return mat; + } + + private void setMatrix() { + mat = new M3(); + // q0 = w, q1 = x, q2 = y, q3 = z + mat.m00 = q0 * q0 + q1 * q1 - q2 * q2 - q3 * q3; + mat.m01 = 2 * q1 * q2 - 2 * q0 * q3; + mat.m02 = 2 * q1 * q3 + 2 * q0 * q2; + mat.m10 = 2 * q1 * q2 + 2 * q0 * q3; + mat.m11 = q0 * q0 - q1 * q1 + q2 * q2 - q3 * q3; + mat.m12 = 2 * q2 * q3 - 2 * q0 * q1; + mat.m20 = 2 * q1 * q3 - 2 * q0 * q2; + mat.m21 = 2 * q2 * q3 + 2 * q0 * q1; + mat.m22 = q0 * q0 - q1 * q1 - q2 * q2 + q3 * q3; + } + + public Quat add(float x) { + // scalar theta addition (degrees) + return newVA(getNormal(), getTheta() + x); + } + + public Quat mul(float x) { + // scalar theta multiplication + return (x == 1 ? new4(q1, q2, q3, q0) : + newVA(getNormal(), getTheta() * x)); + } + + public Quat mulQ(Quat p) { + return new4( + q0 * p.q1 + q1 * p.q0 + q2 * p.q3 - q3 * p.q2, + q0 * p.q2 + q2 * p.q0 + q3 * p.q1 - q1 * p.q3, + q0 * p.q3 + q3 * p.q0 + q1 * p.q2 - q2 * p.q1, + q0 * p.q0 - q1 * p.q1 - q2 * p.q2 - q3 * p.q3); + } + + public Quat div(Quat p) { + // unit quaternions assumed -- otherwise would scale by 1/p.dot(p) + return mulQ(p.inv()); + } + + public Quat divLeft(Quat p) { + // unit quaternions assumed -- otherwise would scale by 1/p.dot(p) + return this.inv().mulQ(p); + } + + public float dot(Quat q) { + return this.q0 * q.q0 + this.q1 * q.q1 + this.q2 * q.q2 + this.q3 * q.q3; + } + + public Quat inv() { + return new4(-q1, -q2, -q3, q0); + } + + public Quat negate() { + return new4(-q1, -q2, -q3, -q0); + } + + /** + * ensures + * + * 1) q0 > 0 + * or + * 2) q0 = 0 and q1 > 0 + * or + * 3) q0 = 0 and q1 = 0 and q2 > 0 + * or + * 4) q0 = 0 and q1 = 0 and q2 = 0 and q3 > 0 + * + * @return 1 or -1 + * + */ + + private float getFixFactor() { + return (q0 < 0 || + q0 == 0 && (q1 < 0 || q1 == 0 && (q2 < 0 || q2 == 0 && q3 < 0)) ? -1 : 1); + } + + public V3 getVector(int i) { + return getVectorScaled(i, 1f); + } + + public V3 getVectorScaled(int i, float scale) { + if (i == -1) { + scale *= getFixFactor(); + return V3.new3(q1 * scale, q2 * scale, q3 * scale); + } + if (mat == null) + setMatrix(); + V3 v = new V3(); + mat.getColumnV(i, v); + if (scale != 1f) + v.scale(scale); + return v; + } + + /** + * + * @return vector such that 0 <= angle <= 180 + */ + public V3 getNormal() { + V3 v = getRawNormal(this); + v.scale(getFixFactor()); + return v; + } + + private static V3 getRawNormal(Quat q) { + V3 v = V3.new3(q.q1, q.q2, q.q3); + if (v.length() == 0) + return V3.new3(0, 0, 1); + v.normalize(); + return v; + } + + /** + * + * @return 0 <= angle <= 180 in degrees + */ + public float getTheta() { + return (float) (Math.acos(Math.abs(q0)) * 2 * 180 / Math.PI); + } + + public float getThetaRadians() { + return (float) (Math.acos(Math.abs(q0)) * 2); + } + + /** + * + * @param v0 + * @return vector option closest to v0 + * + */ + public V3 getNormalDirected(V3 v0) { + V3 v = getNormal(); + if (v.x * v0.x + v.y * v0.y + v.z * v0.z < 0) { + v.scale(-1); + } + return v; + } + + public V3 get3dProjection(V3 v3d) { + v3d.set(q1, q2, q3); + return v3d; + } + + /** + * + * @param axisAngle + * @return fill in theta of axisAngle such that + */ + public P4 getThetaDirected(P4 axisAngle) { + //fills in .w; + float theta = getTheta(); + V3 v = getNormal(); + if (axisAngle.x * q1 + axisAngle.y * q2 + axisAngle.z * q3 < 0) { + v.scale(-1); + theta = -theta; + } + axisAngle.set4(v.x, v.y, v.z, theta); + return axisAngle; + } + + /** + * + * @param vector a vector, same as for getNormalDirected + * @return return theta + */ + public float getThetaDirectedV(V3 vector) { + //fills in .w; + float theta = getTheta(); + V3 v = getNormal(); + if (vector.x * q1 + vector.y * q2 + vector.z * q3 < 0) { + v.scale(-1); + theta = -theta; + } + return theta; + } + + /** + * Quaternions are saved as {q1, q2, q3, q0} + * + * While this may seem odd, it is so that for any point4 -- + * planes, axisangles, and quaternions -- we can use the + * first three coordinates to determine the relavent axis + * the fourth then gives us offset to {0,0,0} (plane), + * rotation angle (axisangle), and cos(theta/2) (quaternion). + * @return {x y z w} (unnormalized) + */ + public P4 toPoint4f() { + return P4.new4(q1, q2, q3, q0); // x,y,z,w + } + + public A4 toAxisAngle4f() { + double theta = 2 * Math.acos(Math.abs(q0)); + double sinTheta2 = Math.sin(theta/2); + V3 v = getNormal(); + if (sinTheta2 < 0) { + v.scale(-1); + theta = Math.PI - theta; + } + return A4.newVA(v, (float) theta); + } + + public T3 transform2(T3 pt, T3 ptNew) { + if (mat == null) + setMatrix(); + mat.rotate2(pt, ptNew); + return ptNew; + } + + public Quat leftDifference(Quat q2) { + //dq = q.leftDifference(qnext);//q.inv().mul(qnext); + Quat q2adjusted = (this.dot(q2) < 0 ? q2.negate() : q2); + return inv().mulQ(q2adjusted); + } + + public Quat rightDifference(Quat q2) { + //dq = qnext.rightDifference(q);//qnext.mul(q.inv()); + Quat q2adjusted = (this.dot(q2) < 0 ? q2.negate() : q2); + return mulQ(q2adjusted.inv()); + } + + /** + * + * Java axisAngle / plane / Point4f format + * all have the format {x y z w} + * so we go with that here as well + * + * @return "{q1 q2 q3 q0}" + */ + @Override + public String toString() { + return "{" + q1 + " " + q2 + " " + q3 + " " + q0 + "}"; + } + + /** + * + * @param data1 + * @param data2 + * @param nMax > 0 --> limit to this number + * @param isRelative + * + * @return pairwise array of data1 / data2 or data1 \ data2 + */ + public static Quat[] div(Quat[] data1, Quat[] data2, int nMax, boolean isRelative) { + int n; + if (data1 == null || data2 == null || (n = Math.min(data1.length, data2.length)) == 0) + return null; + if (nMax > 0 && n > nMax) + n = nMax; + Quat[] dqs = new Quat[n]; + for (int i = 0; i < n; i++) { + if (data1[i] == null || data2[i] == null) + return null; + dqs[i] = (isRelative ? data1[i].divLeft(data2[i]) : data1[i].div(data2[i])); + } + return dqs; + } + + public static Quat sphereMean(Quat[] data, float[] retStddev, float criterion) { + // Samuel R. Buss, Jay P. Fillmore: + // Spherical averages and applications to spherical splines and interpolation. + // ACM Trans. Graph. 20(2): 95-126 (2001) + if (data == null || data.length == 0) + return new Quat(); + if (retStddev == null) + retStddev = new float[1]; + if (data.length == 1) { + retStddev[0] = 0; + return newQ(data[0]); + } + float diff = Float.MAX_VALUE; + float lastStddev = Float.MAX_VALUE; + Quat qMean = simpleAverage(data); + int maxIter = 100; // typically goes about 5 iterations + int iter = 0; + while (diff > criterion && lastStddev != 0 && iter < maxIter) { + qMean = newMean(data, qMean); + retStddev[0] = stdDev(data, qMean); + diff = Math.abs(retStddev[0] - lastStddev); + lastStddev = retStddev[0]; + //Logger.info(++iter + " sphereMean " + qMean + " stddev=" + lastStddev + " diff=" + diff); + } + return qMean; + } + + /** + * Just a starting point. + * get average normal vector + * scale normal by average projection of vectors onto it + * create quaternion from this 3D projection + * + * @param ndata + * @return approximate average + */ + private static Quat simpleAverage(Quat[] ndata) { + V3 mean = V3.new3(0, 0, 1); + // using the directed normal ensures that the mean is + // continually added to and never subtracted from + V3 v = ndata[0].getNormal(); + mean.add(v); + for (int i = ndata.length; --i >= 0;) + mean.add(ndata[i].getNormalDirected(mean)); + mean.sub(v); + mean.normalize(); + float f = 0; + // the 3D projection of the quaternion is [sin(theta/2)]*n + // so dotted with the normalized mean gets us an approximate average for sin(theta/2) + for (int i = ndata.length; --i >= 0;) + f += Math.abs(ndata[i].get3dProjection(v).dot(mean)); + if (f != 0) + mean.scale(f / ndata.length); + // now convert f to the corresponding cosine instead of sine + f = (float) Math.sqrt(1 - mean.lengthSquared()); + if (Float.isNaN(f)) + f = 0; + return newP4(P4.new4(mean.x, mean.y, mean.z, f)); + } + + private static Quat newMean(Quat[] data, Quat mean) { + /* quaternion derivatives nicely take care of producing the necessary + * metric. Since dq gives us the normal with the smallest POSITIVE angle, + * we just scale by that -- using degrees. + * No special normalization is required. + * + * The key is that the mean has been set up already, and dq.getTheta() + * will always return a value between 0 and 180. True, for groupings + * where dq swings wildly -- 178, 182, 178, for example -- there will + * be problems, but the presumption here is that there is a REASONABLE + * set of data. Clearly there are spherical data sets that simply cannot + * be assigned a mean. (For example, where the three projected points + * are equally distant on the sphere. We just can't worry about those + * cases here. Rather, if there is any significance to the data, + * there will be clusters of projected points, and the analysis will + * be meaningful. + * + * Note that the hemisphere problem drops out because dq.getNormal() and + * dq.getTheta() will never return (n, 182 degrees) but will + * instead return (-n, 2 degrees). That's just what we want in that case. + * + * Note that the projection in this case is to 3D -- a set of vectors + * in space with lengths proportional to theta (not the sin(theta/2) + * that is associated with a quaternion map). + * + * This is officially an "exponential" or "hyperbolic" projection. + * + */ + V3 sum = new V3(); + V3 v; + Quat q, dq; + //System.out.println("newMean mean " + mean); + for (int i = data.length; --i >= 0;) { + q = data[i]; + dq = q.div(mean); + v = dq.getNormal(); + v.scale(dq.getTheta()); + sum.add(v); + } + sum.scale(1f/data.length); + Quat dqMean = newVA(sum, sum.length()); + //System.out.println("newMean dqMean " + dqMean + " " + dqMean.getNormal() + " " + dqMean.getTheta()); + return dqMean.mulQ(mean); + } + + /** + * @param data + * @param mean + * @return standard deviation in units of degrees + */ + private static float stdDev(Quat[] data, Quat mean) { + // the quaternion dot product gives q0 for dq (i.e. q / mean) + // that is, cos(theta/2) for theta between them + double sum2 = 0; + int n = data.length; + for (int i = n; --i >= 0;) { + float theta = data[i].div(mean).getTheta(); + sum2 += theta * theta; + } + return (float) Math.sqrt(sum2 / n); + } + + public float[] getEulerZYZ() { + // http://www.swarthmore.edu/NatSci/mzucker1/e27/diebel2006attitude.pdf + double rA, rB, rG; + if (q1 == 0 && q2 == 0) { + float theta = getTheta(); + // pure Z rotation - ambiguous + return new float[] { q3 < 0 ? -theta : theta , 0, 0 }; + } + rA = Math.atan2(2 * (q2 * q3 + q0 * q1), 2 * (-q1 * q3 + q0 * q2 )); + rB = Math.acos(q3 * q3 - q2 * q2 - q1 * q1 + q0 * q0); + rG = Math.atan2( 2 * (q2 * q3 - q0 * q1), 2 * (q0 * q2 + q1 * q3)); + return new float[] {(float) (rA / RAD_PER_DEG), (float) (rB / RAD_PER_DEG), (float) (rG / RAD_PER_DEG)}; + } + + public float[] getEulerZXZ() { + // NOT http://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles + // http://www.swarthmore.edu/NatSci/mzucker1/e27/diebel2006attitude.pdf + double rA, rB, rG; + if (q1 == 0 && q2 == 0) { + float theta = getTheta(); + // pure Z rotation - ambiguous + return new float[] { q3 < 0 ? -theta : theta , 0, 0 }; + } + rA = Math.atan2(2 * (q1 * q3 - q0 * q2), 2 * (q0 * q1 + q2 * q3 )); + rB = Math.acos(q3 * q3 - q2 * q2 - q1 * q1 + q0 * q0); + rG = Math.atan2( 2 * (q1 * q3 + q0 * q2), 2 * (-q2 * q3 + q0 * q1)); + return new float[] {(float) (rA / RAD_PER_DEG), (float) (rB / RAD_PER_DEG), (float) (rG / RAD_PER_DEG)}; + } + +} diff --git a/src/javajs/util/Rdr.java b/src/javajs/util/Rdr.java new file mode 100644 index 0000000..5296964 --- /dev/null +++ b/src/javajs/util/Rdr.java @@ -0,0 +1,509 @@ +/* $RCSfile$ + * $Author: hansonr $ + * $Date: 2007-04-05 09:07:28 -0500 (Thu, 05 Apr 2007) $ + * $Revision: 7326 $ + * + * Copyright (C) 2003-2005 The Jmol Development Team + * + * Contact: jmol-developers@lists.sf.net + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + */ +package javajs.util; + +import java.io.BufferedInputStream; +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.StringReader; +import java.io.UnsupportedEncodingException; + +import java.util.Map; + + +import javajs.api.GenericCifDataParser; +import javajs.api.GenericLineReader; +import javajs.api.GenericZipTools; + +/** + * A general helper class for a variety of stream and reader functionality + * including: + * + * stream and byte magic-number decoding for PNG, PNGJ, ZIP, and GZIP streams + * + * various stream/reader methods, including UTF-encoded stream reading + * + * reflection-protected access to a CIF parser and ZIP tools + * + * + * + * + */ +public class Rdr implements GenericLineReader { + + BufferedReader reader; + + public Rdr(BufferedReader reader) { + this.reader = reader; + } + + @Override + public String readNextLine() throws Exception { + return reader.readLine(); + } + + public static Map readCifData(GenericCifDataParser parser, BufferedReader br) { + return parser.set(null, br).getAllCifData(); + } + + + /////////// + + public static String fixUTF(byte[] bytes) { + Encoding encoding = getUTFEncoding(bytes); + if (encoding != Encoding.NONE) + try { + String s = new String(bytes, encoding.name().replace('_', '-')); + switch (encoding) { + case UTF8: + case UTF_16BE: + case UTF_16LE: + // extra byte at beginning removed + s = s.substring(1); + break; + default: + break; + } + return s; + } catch (UnsupportedEncodingException e) { + System.out.println(e); + } + return new String(bytes); + } + + private static Encoding getUTFEncoding(byte[] bytes) { + if (bytes.length >= 3 && bytes[0] == (byte) 0xEF && bytes[1] == (byte) 0xBB && bytes[2] == (byte) 0xBF) + return Encoding.UTF8; + if (bytes.length >= 4 && bytes[0] == (byte) 0 && bytes[1] == (byte) 0 + && bytes[2] == (byte) 0xFE && bytes[3] == (byte) 0xFF) + return Encoding.UTF_32BE; + if (bytes.length >= 4 && bytes[0] == (byte) 0xFF && bytes[1] == (byte) 0xFE + && bytes[2] == (byte) 0 && bytes[3] == (byte) 0) + return Encoding.UTF_32LE; + if (bytes.length >= 2 && bytes[0] == (byte) 0xFF && bytes[1] == (byte) 0xFE) + return Encoding.UTF_16LE; + if (bytes.length >= 2 && bytes[0] == (byte) 0xFE && bytes[1] == (byte) 0xFF) + return Encoding.UTF_16BE; + return Encoding.NONE; + + } + + ////////// stream type checking ////////// + + + private static Encoding getUTFEncodingForStream(BufferedInputStream is) throws IOException { + /** + * @j2sNative + * + * is.resetStream(); + * + */ + { + } + byte[] abMagic = new byte[4]; + abMagic[3] = 1; + try{ + is.mark(5); + } catch (Exception e) { + return Encoding.NONE; + } + is.read(abMagic, 0, 4); + is.reset(); + return getUTFEncoding(abMagic); + } + + public static boolean isBase64(SB sb) { + return (sb.indexOf(";base64,") == 0); + } + + public static boolean isCompoundDocumentS(InputStream is) { + return isCompoundDocumentB(getMagic(is, 8)); + } + + public static boolean isCompoundDocumentB(byte[] bytes) { + return (bytes.length >= 8 && bytes[0] == (byte) 0xD0 + && bytes[1] == (byte) 0xCF && bytes[2] == (byte) 0x11 + && bytes[3] == (byte) 0xE0 && bytes[4] == (byte) 0xA1 + && bytes[5] == (byte) 0xB1 && bytes[6] == (byte) 0x1A + && bytes[7] == (byte) 0xE1); + } + + public static boolean isGzipS(InputStream is) { + return isGzipB(getMagic(is, 2)); + } + + public static boolean isGzipB(byte[] bytes) { + return (bytes != null && bytes.length >= 2 + && bytes[0] == (byte) 0x1F && bytes[1] == (byte) 0x8B); + } + + public static boolean isPickleS(InputStream is) { + return Rdr.isPickleB(getMagic(is, 2)); + } + + public static boolean isPickleB(byte[] bytes) { + return (bytes != null && bytes.length >= 2 + && bytes[0] == (byte) 0x7D && bytes[1] == (byte) 0x71); + } + + public static boolean isPngZipStream(InputStream is) { + return isPngZipB(getMagic(is, 55)); + } + + public static boolean isPngZipB(byte[] bytes) { + // \0PNGJ starting at byte 50 + return (bytes[50] == 0 && bytes[51] == 0x50 && bytes[52] == 0x4E && bytes[53] == 0x47 && bytes[54] == 0x4A); + } + + public static boolean isZipS(InputStream is) { + return isZipB(getMagic(is, 4)); + } + + public static boolean isZipB(byte[] bytes) { + return (bytes.length >= 4 + && bytes[0] == 0x50 //PK<03><04> + && bytes[1] == 0x4B + && bytes[2] == 0x03 + && bytes[3] == 0x04); + } + + private static byte[] getMagic(InputStream is, int n) { + byte[] abMagic = new byte[n]; + /** + * @j2sNative + * + * is.resetStream(); + * + */ + { + } + try { + is.mark(n + 1); + is.read(abMagic, 0, n); + } catch (IOException e) { + } + try { + is.reset(); + } catch (IOException e) { + } + return abMagic; + } + + public static String guessMimeTypeForBytes(byte[] bytes) { + // only options here are JPEG, PNG, GIF, and BMP + switch (bytes.length < 2 ? -1 : bytes[1]) { + case 0: + return "image/jpg"; // 0xFF 0x00 ... + case 0x49: + return "image/gif"; // GIF89a... + case 0x4D: + return "image/BMP"; // BM... + case 0x50: + return "image/png"; + default: + return "image/unknown"; + } + } + + + ////////// stream/byte methods /////////// + + public static BufferedInputStream getBIS(byte[] bytes) { + return new BufferedInputStream(new ByteArrayInputStream(bytes)); + } + + public static BufferedReader getBR(String string) { + return new BufferedReader(new StringReader(string)); + } + + /** + * Drill down into a GZIP stack until no more layers. + * @param jzt + * + * @param bis + * @return non-gzipped buffered input stream. + * + * @throws IOException + */ + public static BufferedInputStream getUnzippedInputStream(GenericZipTools jzt, BufferedInputStream bis) throws IOException { + while (isGzipS(bis)) + bis = new BufferedInputStream(jzt.newGZIPInputStream(bis)); + return bis; + } + + /** + * Allow for base64-encoding check. + * + * @param sb + * @return byte array + */ + public static byte[] getBytesFromSB(SB sb) { + return (isBase64(sb) ? Base64.decodeBase64(sb.substring(8)) : sb.toBytes(0, -1)); + } + + /** + * Read a an entire BufferedInputStream for its bytes, and + * either return them or leave them in the designated output channel. + * + * @param bis + * @param out a destination output channel, or null + * @return byte[] (if out is null) or a message indicating length (if not) + * + * @throws IOException + */ + public static Object getStreamAsBytes(BufferedInputStream bis, + OC out) throws IOException { + byte[] buf = new byte[1024]; + byte[] bytes = (out == null ? new byte[4096] : null); + int len = 0; + int totalLen = 0; + while ((len = bis.read(buf, 0, 1024)) > 0) { + totalLen += len; + if (out == null) { + if (totalLen >= bytes.length) + bytes = AU.ensureLengthByte(bytes, totalLen * 2); + System.arraycopy(buf, 0, bytes, totalLen - len, len); + } else { + out.write(buf, 0, len); + } + } + bis.close(); + if (out == null) { + return AU.arrayCopyByte(bytes, totalLen); + } + return totalLen + " bytes"; + } + + /** + * Read an input stream fully, saving a byte array, then + * return a buffered reader to those bytes converted to string form. + * + * @param bis + * @param charSet + * @return Reader + * @throws IOException + */ + public static BufferedReader getBufferedReader(BufferedInputStream bis, String charSet) + throws IOException { + // could also just make sure we have a buffered input stream here. + if (getUTFEncodingForStream(bis) == Encoding.NONE) + return new BufferedReader(new InputStreamReader(bis, (charSet == null ? "UTF-8" : charSet))); + byte[] bytes = getLimitedStreamBytes(bis, -1); + bis.close(); + return getBR(charSet == null ? fixUTF(bytes) : new String(bytes, charSet)); + } + + /** + * Read a possibly limited number of bytes (when n > 0) from a stream, + * leaving the stream open. + * + * @param is an input stream, not necessarily buffered. + * @param n the maximum number of bytes to read, or -1 for all + * @return the bytes read + * + * @throws IOException + */ + public static byte[] getLimitedStreamBytes(InputStream is, long n) + throws IOException { + + //Note: You cannot use InputStream.available() to reliably read + // zip data from the web. + + int buflen = (n > 0 && n < 1024 ? (int) n : 1024); + byte[] buf = new byte[buflen]; + byte[] bytes = new byte[n < 0 ? 4096 : (int) n]; + int len = 0; + int totalLen = 0; + if (n < 0) + n = Integer.MAX_VALUE; + while (totalLen < n && (len = is.read(buf, 0, buflen)) > 0) { + totalLen += len; + if (totalLen > bytes.length) + bytes = AU.ensureLengthByte(bytes, totalLen * 2); + System.arraycopy(buf, 0, bytes, totalLen - len, len); + if (n != Integer.MAX_VALUE && totalLen + buflen > bytes.length) + buflen = bytes.length - totalLen; + + } + if (totalLen == bytes.length) + return bytes; + buf = new byte[totalLen]; + System.arraycopy(bytes, 0, buf, 0, totalLen); + return buf; + } + + /** + * + * Read a UTF-8 stream fully, converting it to a String. + * Called by Jmol's XMLReaders + * + * @param bis + * @return a UTF-8 string + */ + public static String StreamToUTF8String(BufferedInputStream bis) { + String[] data = new String[1]; + try { + readAllAsString(getBufferedReader(bis, "UTF-8"), -1, true, data, 0); + } catch (IOException e) { + } + return data[0]; + } + + /** + * This method fills data[i] with string data from a file that may or may not + * be binary even though it is being read by a reader. It is meant to be used + * simple text-based files only. + * + * @param br + * @param nBytesMax + * @param allowBinary + * @param data + * @param i + * @return true if data[i] holds the data; false if data[i] holds an error message. + */ + public static boolean readAllAsString(BufferedReader br, int nBytesMax, boolean allowBinary, String[] data, int i) { + try { + SB sb = SB.newN(8192); + String line; + if (nBytesMax < 0) { + line = br.readLine(); + if (allowBinary || line != null && line.indexOf('\0') < 0 + && (line.length() != 4 || line.charAt(0) != 65533 + || line.indexOf("PNG") != 1)) { + sb.append(line).appendC('\n'); + while ((line = br.readLine()) != null) + sb.append(line).appendC('\n'); + } + } else { + int n = 0; + int len; + while (n < nBytesMax && (line = br.readLine()) != null) { + if (nBytesMax - n < (len = line.length()) + 1) + line = line.substring(0, nBytesMax - n - 1); + sb.append(line).appendC('\n'); + n += len + 1; + } + } + br.close(); + data[i] = sb.toString(); + return true; + } catch (Exception ioe) { + data[i] = ioe.toString(); + return false; + } + } + + + /////////// PNGJ support ///////////// + + + /** + * Look at byte 50 for "\0PNGJxxxxxxxxx+yyyyyyyyy" where xxxxxxxxx is a byte + * offset to the JMOL data and yyyyyyyyy is the length of the data. + * + * @param bis + * @return same stream or byte stream + */ + + /** + * Retrieve the two numbers in a PNG iTXt tag indicating the + * file pointer for the start of the ZIP data as well as its length. + * + * @param bis + * @param pt_count + */ + static void getPngZipPointAndCount(BufferedInputStream bis, int[] pt_count) { + bis.mark(75); + try { + byte[] data = getLimitedStreamBytes(bis, 74); + bis.reset(); + int pt = 0; + for (int i = 64, f = 1; --i > 54; f *= 10) + pt += (data[i] - '0') * f; + int n = 0; + for (int i = 74, f = 1; --i > 64; f *= 10) + n += (data[i] - '0') * f; + pt_count[0] = pt; + pt_count[1] = n; + } catch (Throwable e) { + pt_count[1] = 0; + } + } + + /** + * Either advance a PNGJ stream to its zip file data or pull out the ZIP data + * bytes and create a new stream for them from which a ZIP utility can start + * extracting files. + * + * @param bis + * @param asNewStream + * @return new buffered ByteArrayInputStream, possibly with no data if there is an error + */ + public static BufferedInputStream getPngZipStream(BufferedInputStream bis, boolean asNewStream) { + if (!isPngZipStream(bis)) + return bis; + byte[] data = new byte[0]; + bis.mark(75); + try { + int pt_count[] = new int[2]; + getPngZipPointAndCount(bis, pt_count); + if (pt_count[1] != 0) { + int pt = pt_count[0]; + while (pt > 0) + pt -= bis.skip(pt); + if (!asNewStream) + return bis; + data = getLimitedStreamBytes(bis, pt_count[1]); + } + } catch (Throwable e) { + } finally { + try { + if (asNewStream) + bis.close(); + } catch (Exception e) { + // ignore + } + } + return getBIS(data); + } + + /** We define a request for zip file extraction by vertical bar: + * zipName|interiorFileName. These may be nested if there is a + * zip file contained in a zip file. + * + * @param fileName + * @return filename trimmed of interior fileName + * + */ + public static String getZipRoot(String fileName) { + int pt = fileName.indexOf("|"); + return (pt < 0 ? fileName : fileName.substring(0, pt)); + } + + +} + diff --git a/src/javajs/util/SB.java b/src/javajs/util/SB.java new file mode 100644 index 0000000..2b9efa6 --- /dev/null +++ b/src/javajs/util/SB.java @@ -0,0 +1,342 @@ + +package javajs.util; + +import javajs.J2SIgnoreImport; + +/** + * Interesting thing here is that JavaScript is 3x faster than Java in handling strings. + * + * Java StringBuilder is final, unfortunately. I guess they weren't thinking about Java2Script! + * + * The reason we have to do this that several overloaded append methods is WAY too expensive + * + */ + +@J2SIgnoreImport({java.lang.StringBuilder.class}) +public class SB { + + private java.lang.StringBuilder sb; + String s; // used by JavaScript only; no Java references + + //TODO: JS experiment with using array and .push() here + + public SB() { + /** + * @j2sNative + * + * this.s = ""; + * + */ + { + sb = new java.lang.StringBuilder(); + } + } + + public static SB newN(int n) { + /** + * @j2sNative + * return new javajs.util.SB(); + */ + { + // not perfect, because it requires defining sb twice. + // We can do better... + SB sb = new SB(); + sb.sb = new java.lang.StringBuilder(n); + return sb; + } + } + + public static SB newS(String s) { + /** + * @j2sNative + * + * var sb = new javajs.util.SB(); + * sb.s = s; + * return sb; + * + */ + { + SB sb = new SB(); + sb.sb = new java.lang.StringBuilder(s); + return sb; + } + } + + public SB append(String s) { + /** + * @j2sNative + * + * this.s += s + * + */ + { + sb.append(s); + } + return this; + } + + public SB appendC(char c) { + /** + * @j2sNative + * + * this.s += c; + */ + { + sb.append(c); + } + return this; + + } + + public SB appendI(int i) { + /** + * @j2sNative + * + * this.s += i + * + */ + { + sb.append(i); + } + return this; + } + + public SB appendB(boolean b) { + /** + * @j2sNative + * + * this.s += b + * + */ + { + sb.append(b); + } + return this; + } + + /** + * note that JavaScript could drop off the ".0" in "1.0" + * @param f + * @return this + */ + public SB appendF(float f) { + /** + * @j2sNative + * + * var sf = "" + f; + * if (sf.indexOf(".") < 0 && sf.indexOf("e") < 0) + * sf += ".0" ; + * this.s += sf; + * + */ + { + sb.append(f); + } + return this; + } + + public SB appendD(double d) { + /** + * @j2sNative + * + * var sf = "" + d; + * if (sf.indexOf(".") < 0 && sf.indexOf("e") < 0) + * sf += ".0" ; + * this.s += sf; + * + */ + { + sb.append(d); + } + return this; + } + + public SB appendSB(SB buf) { + /** + * @j2sNative + * + * this.s += buf.s; + * + */ + { + sb.append(buf.sb); + } + return this; + } + + public SB appendO(Object data) { + if (data != null) { + /** + * @j2sNative + * + * this.s += data.toString(); + * + */ + { + sb.append(data); + } + } + return this; + } + + public void appendCB(char[] cb, int off, int len) { + /** + * @j2sNative + * + * for (var i = len,j=off; --i >= 0;) + * this.s += cb[j++]; + * + */ + { + sb.append(cb, off, len); + } + } + + @Override + public String toString() { + /** + * @j2sNative + * + * return this.s; + * + */ + { + return sb.toString(); + } + } + + public int length() { + /** + * @j2sNative + * + * return this.s.length; + * + */ + { + return sb.length(); + } + } + + public int indexOf(String s) { + /** + * @j2sNative + * + * return this.s.indexOf(s); + * + */ + { + return sb.indexOf(s); + } + } + + public char charAt(int i) { + /** + * @j2sNative + * + * return this.s.charAt(i); + * + */ + { + return sb.charAt(i); + } + } + + public int charCodeAt(int i) { + /** + * @j2sNative + * + * return this.s.charCodeAt(i); + * + */ + { + return sb.codePointAt(i); + } + } + + public void setLength(int n) { + /** + * @j2sNative + * + * this.s = this.s.substring(0, n); + */ + { + sb.setLength(n); + } + } + + public int lastIndexOf(String s) { + /** + * @j2sNative + * + * return this.s.lastIndexOf(s); + */ + { + return sb.lastIndexOf(s); + } + } + + public int indexOf2(String s, int i) { + /** + * @j2sNative + * + * return this.s.indexOf(s, i); + */ + { + return sb.indexOf(s, i); + } + } + + public String substring(int i) { + /** + * @j2sNative + * + * return this.s.substring(i); + */ + { + return sb.substring(i); + } + } + + public String substring2(int i, int j) { + /** + * @j2sNative + * + * return this.s.substring(i, j); + */ + { + return sb.substring(i, j); + } + } + + /** + * simple byte conversion not allowing for unicode. + * Used for base64 conversion and allows for offset + * @param off + * @param len or -1 for full length (then off must = 0) + * @return byte[] + */ + public byte[] toBytes(int off, int len) { + if (len < 0) + len = length() - off; + byte[] b = new byte[len]; + for (int i = off + len, j = i - off; --i >= off;) + b[--j] = (byte) charAt(i); + return b; + } + + public void replace(int start, int end, String str) { + /** + * @j2sNative + * + * this.s = this.s.substring(0, start) + str + this.s.substring(end); + */ + { + sb.replace(start, end, str); + } + } + + public void insert(int offset, String str) { + replace(offset, offset, str); + } + +} diff --git a/src/javajs/util/StringDataReader.java b/src/javajs/util/StringDataReader.java new file mode 100644 index 0000000..32e87e1 --- /dev/null +++ b/src/javajs/util/StringDataReader.java @@ -0,0 +1,48 @@ +/* $RCSfile$ + * $Author$ + * $Date$ + * $Revision$ + * + * Copyright (C) 2011 The Jmol Development Team + * + * Contact: jmol-developers@lists.sf.net + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +package javajs.util; + +import java.io.StringReader; + + + + + +public class StringDataReader extends DataReader { + + public StringDataReader() { + super(); + } + + public StringDataReader(String data) { + super(new StringReader(data)); + } + + @Override + public DataReader setData(Object data) { + return new StringDataReader((String) data); + } +} \ No newline at end of file diff --git a/src/javajs/util/T3.java b/src/javajs/util/T3.java new file mode 100644 index 0000000..4412565 --- /dev/null +++ b/src/javajs/util/T3.java @@ -0,0 +1,341 @@ +/* + Copyright (C) 1997,1998,1999 + Kenji Hiranabe, Eiwa System Management, Inc. + + This program is free software. + Implemented by Kenji Hiranabe(hiranabe@esm.co.jp), + conforming to the Java(TM) 3D API specification by Sun Microsystems. + + Permission to use, copy, modify, distribute and sell this software + and its documentation for any purpose is hereby granted without fee, + provided that the above copyright notice appear in all copies and + that both that copyright notice and this permission notice appear + in supporting documentation. Kenji Hiranabe and Eiwa System Management,Inc. + makes no representations about the suitability of this software for any + purpose. It is provided "AS IS" with NO WARRANTY. +*/ +package javajs.util; + +import java.io.Serializable; + +import javajs.api.JSONEncodable; + +/** + * A generic 3 element tuple that is represented by single precision floating + * point x,y and z coordinates. + * + * @version specification 1.1, implementation $Revision: 1.10 $, $Date: + * 2006/09/08 20:20:20 $ + * @author Kenji hiranabe + * + * additions by Bob Hanson hansonr@stolaf.edu 9/30/2012 + * for unique constructor and method names + * for the optimization of compiled JavaScript using Java2Script + */ +public abstract class T3 implements JSONEncodable, Serializable { + + public float x, y, z; + + /** + * @j2sIgnore + * + */ + public T3() { + } + + /** + * Sets the value of this tuple to the specified xyz coordinates. + * + * @param x + * the x coordinate + * @param y + * the y coordinate + * @param z + * the z coordinate + */ + public final void set(float x, float y, float z) { + this.x = x; + this.y = y; + this.z = z; + } + + /** + * Sets the value of this tuple from the 3 values specified in the array. + * + * @param t + * the array of length 3 containing xyz in order + */ + public final void setA(float t[]) { + // ArrayIndexOutOfBounds is thrown if t.length < 3 + x = t[0]; + y = t[1]; + z = t[2]; + } + + /** + * Sets the value of this tuple to the value of the Tuple3f argument. + * + * @param t1 + * the tuple to be copied + */ + public final void setT(T3 t1) { + x = t1.x; + y = t1.y; + z = t1.z; + } + + /** + * Sets the value of this tuple to the vector sum of tuples t1 and t2. + * + * @param t1 + * the first tuple + * @param t2 + * the second tuple + */ + public final void add2(T3 t1, T3 t2) { + x = t1.x + t2.x; + y = t1.y + t2.y; + z = t1.z + t2.z; + } + + /** + * Sets the value of this tuple to the vector sum of itself and tuple t1. + * + * @param t1 + * the other tuple + */ + public final void add(T3 t1) { + x += t1.x; + y += t1.y; + z += t1.z; + } + + /** + * Computes the square of the distance between this point and point p1. + * + * @param p1 + * the other point + * @return the square of distance between these two points as a float + */ + public final float distanceSquared(T3 p1) { + double dx = x - p1.x; + double dy = y - p1.y; + double dz = z - p1.z; + return (float) (dx * dx + dy * dy + dz * dz); + } + + /** + * Returns the distance between this point and point p1. + * + * @param p1 + * the other point + * @return the distance between these two points + */ + public final float distance(T3 p1) { + return (float) Math.sqrt(distanceSquared(p1)); + } + + /** + * Sets the value of this tuple to the vector difference of tuple t1 and t2 + * (this = t1 - t2). + * + * @param t1 + * the first tuple + * @param t2 + * the second tuple + */ + public final void sub2(T3 t1, T3 t2) { + x = t1.x - t2.x; + y = t1.y - t2.y; + z = t1.z - t2.z; + } + + /** + * Sets the value of this tuple to the vector difference of itself and tuple + * t1 (this = this - t1). + * + * @param t1 + * the other tuple + */ + public final void sub(T3 t1) { + x -= t1.x; + y -= t1.y; + z -= t1.z; + } + + /** + * Sets the value of this tuple to the scalar multiplication of itself. + * + * @param s + * the scalar value + */ + public final void scale(float s) { + x *= s; + y *= s; + z *= s; + } + + /** + * Add {a b c} + * + * @param a + * @param b + * @param c + */ + public final void add3(float a, float b, float c) { + x += a; + y += b; + z += c; + } + + + /** + * {x*p.x, y*p.y, z*p.z) used for three-way scaling + * + * @param p + */ + public final void scaleT(T3 p) { + x *= p.x; + y *= p.y; + z *= p.z; + } + + + /** + * Sets the value of this tuple to the scalar multiplication of tuple t1 and + * then adds tuple t2 (this = s*t1 + t2). + * + * @param s + * the scalar value + * @param t1 + * the tuple to be multipled + * @param t2 + * the tuple to be added + */ + public final void scaleAdd2(float s, T3 t1, T3 t2) { + x = s * t1.x + t2.x; + y = s * t1.y + t2.y; + z = s * t1.z + t2.z; + } + + + /** + * average of two tuples + * + * @param a + * @param b + */ + public void ave(T3 a, T3 b) { + x = (a.x + b.x) / 2f; + y = (a.y + b.y) / 2f; + z = (a.z + b.z) / 2f; + } + + /** + * Vector dot product. Was in Vector3f; more useful here, though. + * + * @param v + * the other vector + * @return this.dot.v + */ + public final float dot(T3 v) { + return x * v.x + y * v.y + z * v.z; + } + + /** + * Returns the squared length of this vector. + * Was in Vector3f; more useful here, though. + * + * @return the squared length of this vector + */ + public final float lengthSquared() { + return x * x + y * y + z * z; + } + + /** + * Returns the length of this vector. + * Was in Vector3f; more useful here, though. + * + * @return the length of this vector + */ + public final float length() { + return (float) Math.sqrt(lengthSquared()); + } + + /** + * Normalizes this vector in place. + * Was in Vector3f; more useful here, though. + */ + public final void normalize() { + double d = length(); + + // zero-div may occur. + x /= d; + y /= d; + z /= d; + } + + /** + * Sets this tuple to be the vector cross product of vectors v1 and v2. + * + * @param v1 + * the first vector + * @param v2 + * the second vector + */ + public final void cross(T3 v1, T3 v2) { + set(v1.y * v2.z - v1.z * v2.y, v1.z * v2.x - v1.x * v2.z, v1.x * v2.y + - v1.y * v2.x); + } + + /** + * Returns a hash number based on the data values in this object. Two + * different Tuple3f objects with identical data values (ie, returns true for + * equals(Tuple3f) ) will return the same hash number. Two vectors with + * different data members may return the same hash value, although this is not + * likely. + */ + @Override + public int hashCode() { + long bits = 1L; + bits = 31L * bits + floatToIntBits0(x); + bits = 31L * bits + floatToIntBits0(y); + bits = 31L * bits + floatToIntBits0(z); + return (int) (bits ^ (bits >> 32)); + } + + public static int floatToIntBits0(float f) { + return (f == 0 ? 0 : Float.floatToIntBits(f)); + } + + /** + * Returns true if all of the data members of Tuple3f t1 are equal to the + * corresponding data members in this + * + * @param t1 + * the vector with which the comparison is made. + */ + @Override + public boolean equals(Object t1) { + if (!(t1 instanceof T3)) + return false; + T3 t2 = (T3) t1; + return (x == t2.x && y == t2.y && z == t2.z); + } + + /** + * Returns a string that contains the values of this Tuple3f. The form is + * (x,y,z). + * + * @return the String representation + */ + @Override + public String toString() { + return "{" + x + ", " + y + ", " + z + "}"; + } + + @Override + public String toJSON() { + return "[" + x + "," + y + "," + z + "]"; + } +} diff --git a/src/javajs/util/T3d.java b/src/javajs/util/T3d.java new file mode 100644 index 0000000..08d02d7 --- /dev/null +++ b/src/javajs/util/T3d.java @@ -0,0 +1,225 @@ +/* + Copyright (C) 1997,1998,1999 + Kenji Hiranabe, Eiwa System Management, Inc. + + This program is free software. + Implemented by Kenji Hiranabe(hiranabe@esm.co.jp), + conforming to the Java(TM) 3D API specification by Sun Microsystems. + + Permission to use, copy, modify, distribute and sell this software + and its documentation for any purpose is hereby granted without fee, + provided that the above copyright notice appear in all copies and + that both that copyright notice and this permission notice appear + in supporting documentation. Kenji Hiranabe and Eiwa System Management,Inc. + makes no representations about the suitability of this software for any + purpose. It is provided "AS IS" with NO WARRANTY. +*/ +package javajs.util; + +import java.io.Serializable; + +/** + * A generic 3 element tuple that is represented by double precision floating + * point x,y and z coordinates. + * + * @version specification 1.1, implementation $Revision: 1.9 $, $Date: + * 2006/07/28 17:01:32 $ + * @author Kenji hiranabe + * + * additions by Bob Hanson hansonr@stolaf.edu 9/30/2012 + * for unique constructor and method names + * for the optimization of compiled JavaScript using Java2Script + */ +public abstract class T3d implements Serializable { + /** + * The x coordinate. + */ + public double x; + + /** + * The y coordinate. + */ + public double y; + + /** + * The z coordinate. + */ + public double z; + + /** + * Constructs and initializes a Tuple3d to (0,0,0). + */ + public T3d() { + } + + /** + * Sets the value of this tuple to the specified xyz coordinates. + * + * @param x + * the x coordinate + * @param y + * the y coordinate + * @param z + * the z coordinate + */ + public final void set(double x, double y, double z) { + this.x = x; + this.y = y; + this.z = z; + } + + /** + * Sets the value of this tuple from the 3 values specified in the array. + * + * @param t + * the array of length 3 containing xyz in order + */ + public final void setA(double t[]) { + // ArrayIndexOutOfBounds is thrown if t.length < 3 + x = t[0]; + y = t[1]; + z = t[2]; + } + + /** + * Sets the value of this tuple to the value of the Tuple3d argument. + * + * @param t1 + * the tuple to be copied + */ + public final void setT(T3d t1) { + x = t1.x; + y = t1.y; + z = t1.z; + } + + /** + * Sets the value of this tuple to the vector sum of tuples t1 and t2. + * + * @param t1 + * the first tuple + * @param t2 + * the second tuple + */ + public final void add2(T3d t1, T3d t2) { + x = t1.x + t2.x; + y = t1.y + t2.y; + z = t1.z + t2.z; + } + + /** + * Sets the value of this tuple to the vector sum of itself and tuple t1. + * + * @param t1 + * the other tuple + */ + public final void add(T3d t1) { + x += t1.x; + y += t1.y; + z += t1.z; + } + + /** + * Sets the value of this tuple to the vector difference of tuple t1 and t2 + * (this = t1 - t2). + * + * @param t1 + * the first tuple + * @param t2 + * the second tuple + */ + public final void sub2(T3d t1, T3d t2) { + x = t1.x - t2.x; + y = t1.y - t2.y; + z = t1.z - t2.z; + } + + /** + * Sets the value of this tuple to the vector difference of itself and tuple + * t1 (this = this - t1). + * + * @param t1 + * the other tuple + */ + public final void sub(T3d t1) { + x -= t1.x; + y -= t1.y; + z -= t1.z; + } + + /** + * Sets the value of this tuple to the scalar multiplication of itself. + * + * @param s + * the scalar value + */ + public final void scale(double s) { + x *= s; + y *= s; + z *= s; + } + + /** + * Sets the value of this tuple to the scalar multiplication of tuple t1 and + * then adds tuple t2 (this = s*t1 + t2). + * + * @param s + * the scalar value + * @param t1 + * the tuple to be multipled + * @param t2 + * the tuple to be added + */ + public final void scaleAdd(double s, T3d t1, T3d t2) { + x = s * t1.x + t2.x; + y = s * t1.y + t2.y; + z = s * t1.z + t2.z; + } + + /** + * Returns a hash number based on the data values in this object. Two + * different Tuple3d objects with identical data values (ie, returns true for + * equals(Tuple3d) ) will return the same hash number. Two vectors with + * different data members may return the same hash value, although this is not + * likely. + */ + @Override + public int hashCode() { + long xbits = doubleToLongBits0(x); + long ybits = doubleToLongBits0(y); + long zbits = doubleToLongBits0(z); + return (int) (xbits ^ (xbits >> 32) ^ ybits ^ (ybits >> 32) ^ zbits ^ (zbits >> 32)); + } + + static long doubleToLongBits0(double d) { + // Check for +0 or -0 + return (d == 0 ? 0 : Double.doubleToLongBits(d)); + } + + /** + * Returns true if all of the data members of Tuple3d t1 are equal to the + * corresponding data members in this + * + * @param t1 + * the vector with which the comparison is made. + */ + @Override + public boolean equals(Object t1) { + if (!(t1 instanceof T3d)) + return false; + T3d t2 = (T3d) t1; + return (this.x == t2.x && this.y == t2.y && this.z == t2.z); + } + + /** + * Returns a string that contains the values of this Tuple3d. The form is + * (x,y,z). + * + * @return the String representation + */ + @Override + public String toString() { + return "{" + x + ", " + y + ", " + z + "}"; + } + +} diff --git a/src/javajs/util/T3i.java b/src/javajs/util/T3i.java new file mode 100644 index 0000000..7fbd3bb --- /dev/null +++ b/src/javajs/util/T3i.java @@ -0,0 +1,151 @@ +/* + Copyright (C) 1997,1998,1999 + Kenji Hiranabe, Eiwa System Management, Inc. + + This program is free software. + Implemented by Kenji Hiranabe(hiranabe@esm.co.jp), + conforming to the Java(TM) 3D API specification by Sun Microsystems. + + Permission to use, copy, modify, distribute and sell this software + and its documentation for any purpose is hereby granted without fee, + provided that the above copyright notice appear in all copies and + that both that copyright notice and this permission notice appear + in supporting documentation. Kenji Hiranabe and Eiwa System Management,Inc. + makes no representations about the suitability of this software for any + purpose. It is provided "AS IS" with NO WARRANTY. +*/ +package javajs.util; + +import java.io.Serializable; + +/** + * A 3-element tuple represented by signed integer x,y,z coordinates. + * + * @since Java 3D 1.2 + * @version specification 1.2, implementation $Revision: 1.9 $, $Date: + * 2006/07/28 17:01:32 $ + * @author Kenji hiranabe + * + * additions by Bob Hanson hansonr@stolaf.edu 9/30/2012 for unique + * constructor and method names for the optimization of compiled + * JavaScript using Java2Script + */ +public abstract class T3i implements Serializable { + + /** + * The x coordinate. + */ + public int x; + + /** + * The y coordinate. + */ + public int y; + + /** + * The z coordinate. + */ + public int z; + + /** + * Constructs and initializes a Tuple3i to (0,0,0). + */ + public T3i() { + } + + /** + * Sets the value of this tuple to to the specified x, y, and z coordinates. + * + * @param x + * the x coordinate. + * @param y + * the y coordinate. + * @param z + * the z coordinate. + */ + public final void set(int x, int y, int z) { + this.x = x; + this.y = y; + this.z = z; + } + + /** + * Sets the value of this tuple to the value of tuple t1. + * + * @param t1 + * the tuple to be copied. + */ + public final void setT(T3i t1) { + x = t1.x; + y = t1.y; + z = t1.z; + } + + /** + * Sets the value of this tuple to the sum of itself and t1. + * + * @param t + * is the other tuple + */ + public final void add(T3i t) { + x += t.x; + y += t.y; + z += t.z; + } + + /** + * Sets the value of this tuple to the scalar multiplication of tuple t1 plus + * tuple t2 (this = s*t1 + t2). + * + * @param s + * the scalar value + * @param t1 + * the tuple to be multipled + * @param t2 + * the tuple to be added + */ + public final void scaleAdd(int s, T3i t1, T3i t2) { + x = s * t1.x + t2.x; + y = s * t1.y + t2.y; + z = s * t1.z + t2.z; + } + + /** + * Returns a hash number based on the data values in this object. Two + * different Tuple3i objects with identical data values (ie, returns true for + * equals(Tuple3i) ) will return the same hash number. Two vectors with + * different data members may return the same hash value, although this is not + * likely. + */ + @Override + public int hashCode() { + return x ^ y ^ z; + } + + /** + * Returns true if the Object o is of type Tuple3i and all of the data members + * of t are equal to the corresponding data members in this Tuple3i. + * + * @param o + * the object with which the comparison is made. + */ + @Override + public boolean equals(Object o) { + if (!(o instanceof T3i)) + return false; + T3i t = (T3i) o; + return (this.x == t.x && this.y == t.y && this.z == t.z); + } + + /** + * Returns a string that contains the values of this Tuple3i. The form is + * (x,y,z). + * + * @return the String representation + */ + @Override + public String toString() { + return "(" + x + ", " + y + ", " + z + ")"; + } + +} diff --git a/src/javajs/util/T4.java b/src/javajs/util/T4.java new file mode 100644 index 0000000..1309fa3 --- /dev/null +++ b/src/javajs/util/T4.java @@ -0,0 +1,120 @@ +/* + Copyright (C) 1997,1998,1999 + Kenji Hiranabe, Eiwa System Management, Inc. + + This program is free software. + Implemented by Kenji Hiranabe(hiranabe@esm.co.jp), + conforming to the Java(TM) 3D API specification by Sun Microsystems. + + Permission to use, copy, modify, distribute and sell this software + and its documentation for any purpose is hereby granted without fee, + provided that the above copyright notice appear in all copies and + that both that copyright notice and this permission notice appear + in supporting documentation. Kenji Hiranabe and Eiwa System Management,Inc. + makes no representations about the suitability of this software for any + purpose. It is provided "AS IS" with NO WARRANTY. +*/ +package javajs.util; + +/** + * A generic 4 element tuple that is represented by single precision floating + * point x,y,z and w coordinates. + * + * @version specification 1.1, implementation $Revision: 1.9 $, $Date: + * 2006/07/28 17:01:32 $ + * @author Kenji hiranabe + * + * additions by Bob Hanson hansonr@stolaf.edu 9/30/2012 + * for unique constructor and method names + * for the optimization of compiled JavaScript using Java2Script + */ +public abstract class T4 extends T3 { + + /** + * The w coordinate. + */ + public float w; + + /** + * Constructs and initializes a Tuple4f to (0,0,0,0). + * + * @j2sIgnore * + */ + public T4() { + } + + /** + * Sets the value of this tuple to the specified xyzw coordinates. + * + * @param x + * the x coordinate + * @param y + * the y coordinate + * @param z + * the z coordinate + * @param w + * the w coordinate + */ + public final void set4(float x, float y, float z, float w) { + this.x = x; + this.y = y; + this.z = z; + this.w = w; + } + + /** + * Sets the value of this tuple to the scalar multiplication of itself. + * + * @param s + * the scalar value + */ + public final void scale4(float s) { + scale(s); + w *= s; + } + + /** + * Returns a hash number based on the data values in this object. Two + * different Tuple4f objects with identical data values (ie, returns true for + * equals(Tuple4f) ) will return the same hash number. Two vectors with + * different data members may return the same hash value, although this is not + * likely. + */ + @Override + public int hashCode() { + return floatToIntBits0(x) ^ floatToIntBits0(y) + ^ floatToIntBits0(z) ^ floatToIntBits0(w); + } + + /** + * Returns true if all of the data members of Object are equal to the + * corresponding data members in this + * + * @param o + * the vector with which the comparison is made. + */ + @Override + public boolean equals(Object o) { + if (!(o instanceof T4)) + return false; + T4 t = (T4) o; + return (this.x == t.x && this.y == t.y && this.z == t.z && this.w == t.w); + } + + /** + * Returns a string that contains the values of this Tuple4f. The form is + * (x,y,z,w). + * + * @return the String representation + */ + @Override + public String toString() { + return "(" + x + ", " + y + ", " + z + ", " + w + ")"; + } + + @Override + public String toJSON() { + return "[" + x + ", " + y + ", " + z + ", " + w + "]"; + } + +} diff --git a/src/javajs/util/V3.java b/src/javajs/util/V3.java new file mode 100644 index 0000000..12c0ce8 --- /dev/null +++ b/src/javajs/util/V3.java @@ -0,0 +1,77 @@ +/* + Copyright (C) 1997,1998,1999 + Kenji Hiranabe, Eiwa System Management, Inc. + + This program is free software. + Implemented by Kenji Hiranabe(hiranabe@esm.co.jp), + conforming to the Java(TM) 3D API specification by Sun Microsystems. + + Permission to use, copy, modify, distribute and sell this software + and its documentation for any purpose is hereby granted without fee, + provided that the above copyright notice appear in all copies and + that both that copyright notice and this permission notice appear + in supporting documentation. Kenji Hiranabe and Eiwa System Management,Inc. + makes no representations about the suitability of this software for any + purpose. It is provided "AS IS" with NO WARRANTY. + */ +package javajs.util; + + +/** + * A 3-element vector that is represented by single precision floating point + * x,y,z coordinates. If this value represents a normal, then it should be + * normalized. + * + * @version specification 1.1, implementation $Revision: 1.10 $, $Date: + * 2006/10/03 19:52:30 $ + * @author Kenji hiranabe + * + * additions by Bob Hanson hansonr@stolaf.edu 9/30/2012 + * for unique constructor and method names + * for the optimization of compiled JavaScript using Java2Script + */ +public class V3 extends T3 { + + /** + * @j2sIgnoreSuperConstructor + */ + public V3() { + // ignore T3 + } + public static V3 newV(T3 t) { + return V3.new3(t.x, t.y, t.z); + } + + public static V3 newVsub(T3 t1, T3 t2) { + return V3.new3(t1.x - t2.x, t1.y - t2.y,t1.z - t2.z); + } + + public static V3 new3(float x, float y, float z) { + V3 v = new V3(); + v.x = x; + v.y = y; + v.z = z; + return v; + } + + /** + * Returns the angle in radians between this vector and the vector parameter; + * the return value is constrained to the range [0,PI]. + * + * @param v1 + * the other vector + * @return the angle in radians in the range [0,PI] + */ + public final float angle(V3 v1) { + // return (double)Math.acos(dot(v1)/v1.length()/v.length()); + // Numerically, near 0 and PI are very bad condition for acos. + // In 3-space, |atan2(sin,cos)| is much stable. + + double xx = y * v1.z - z * v1.y; + double yy = z * v1.x - x * v1.z; + double zz = x * v1.y - y * v1.x; + double cross = Math.sqrt(xx * xx + yy * yy + zz * zz); + + return (float) Math.abs(Math.atan2(cross, dot(v1))); + } +} diff --git a/src/javajs/util/V3d.java b/src/javajs/util/V3d.java new file mode 100644 index 0000000..9060575 --- /dev/null +++ b/src/javajs/util/V3d.java @@ -0,0 +1,93 @@ +/* + Copyright (C) 1997,1998,1999 + Kenji Hiranabe, Eiwa System Management, Inc. + + This program is free software. + Implemented by Kenji Hiranabe(hiranabe@esm.co.jp), + conforming to the Java(TM) 3D API specification by Sun Microsystems. + + Permission to use, copy, modify, distribute and sell this software + and its documentation for any purpose is hereby granted without fee, + provided that the above copyright notice appear in all copies and + that both that copyright notice and this permission notice appear + in supporting documentation. Kenji Hiranabe and Eiwa System Management,Inc. + makes no representations about the suitability of this software for any + purpose. It is provided "AS IS" with NO WARRANTY. +*/ +package javajs.util; + + + + +/** + * A 3 element vector that is represented by double precision floating point + * x,y,z coordinates. If this value represents a normal, then it should be + * normalized. + * + * @version specification 1.1, implementation $Revision: 1.9 $, $Date: + * 2006/07/28 17:01:32 $ + * @author Kenji hiranabe + * + * additions by Bob Hanson hansonr@stolaf.edu 9/30/2012 + * for unique constructor and method names + * for the optimization of compiled JavaScript using Java2Script + */ +public class V3d extends T3d { + + /** + * Sets this vector to be the vector cross product of vectors v1 and v2. + * + * @param v1 + * the first vector + * @param v2 + * the second vector + */ + public final void cross(V3d v1, V3d v2) { + // store on stack once for aliasing-safty + // i.e. safe when a.cross(a, b) + set(v1.y * v2.z - v1.z * v2.y, v1.z * v2.x - v1.x * v2.z, v1.x * v2.y + - v1.y * v2.x); + } + + /** + * Normalizes this vector in place. + */ + public final void normalize() { + double d = length(); + + // zero-div may occur. + x /= d; + y /= d; + z /= d; + } + + /** + * Computes the dot product of the this vector and vector v. + * + * @param v + * the other vector + * @return this.dot.v + */ + public final double dot(V3d v) { + return x * v.x + y * v.y + z * v.z; + } + + /** + * Returns the squared length of this vector. + * + * @return the squared length of this vector + */ + public final double lengthSquared() { + return x * x + y * y + z * z; + } + + /** + * Returns the length of this vector. + * + * @return the length of this vector + */ + public final double length() { + return Math.sqrt(lengthSquared()); + } + +} diff --git a/src/javajs/util/XmlUtil.java b/src/javajs/util/XmlUtil.java new file mode 100644 index 0000000..d2194cd --- /dev/null +++ b/src/javajs/util/XmlUtil.java @@ -0,0 +1,165 @@ +/* $RCSfile$ + * $Author$ + * $Date$ + * $Revision$ + * + * Copyright (C) 2006 The Jmol Development Team + * + * Contact: jmol-developers@lists.sf.net + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +package javajs.util; + +public class XmlUtil { + + public XmlUtil() { + // Jmol's PropertyManager class uses reflection + } + // / simple Xml parser/generator /// + + public static void openDocument(SB data) { + data.append("\n"); + } + + public static void openTag(SB sb, String name) { + sb.append("<").append(name).append(">\n"); + } + + public static void openTagAttr(SB sb, String name, Object[] attributes) { + appendTagAll(sb, name, attributes, null, false, false); + sb.append("\n"); + } + + public static void closeTag(SB sb, String name) { + sb.append("\n"); + } + + public static void appendTagAll(SB sb, String name, + Object[] attributes, Object data, + boolean isCdata, boolean doClose) { + String closer = ">"; + if (name.endsWith("/")){ + name = name.substring(0, name.length() - 1); + if (data == null) { + closer = "/>\n"; + doClose = false; + } + } + sb.append("<").append(name); + if (attributes != null) + for (int i = 0; i < attributes.length; i++) { + Object o = attributes[i]; + if (o == null) + continue; + if (o instanceof Object[]) + for (int j = 0; j < ((Object[]) o).length; j+= 2) + appendAttrib(sb, ((Object[]) o)[j], ((Object[]) o)[j + 1]); + else + appendAttrib(sb, o, attributes[++i]); + } + sb.append(closer); + if (data != null) { + if (isCdata) + data = wrapCdata(data); + sb.appendO(data); + } + if (doClose) + closeTag(sb, name); + } + + /** + * wrap the string as character data, with replacements for [ noted + * as a list starting with * after the CDATA termination + * + * @param data + * @return wrapped text + */ + public static String wrapCdata(Object data) { + String s = "" + data; + return (s.indexOf("&") < 0 && s.indexOf("<") < 0 ? (s.startsWith("\n") ? "" : "\n") + s + : "", "]]]]>") + "]]>"); + } + + /** + * @param s + * @return unwrapped text + */ + public static String unwrapCdata(String s) { + return (s.startsWith("") ? + PT.rep(s.substring(9, s.length()-3),"]]]]>", "]]>") : s); + } + + /** + * standard data" + * + * @param sb + * @param name + * @param attributes + * @param data + */ + public static void appendTagObj(SB sb, String name, + Object[] attributes, Object data) { + appendTagAll(sb, name, attributes, data, false, true); + } + + /** + * standard data" + * standard " + * + * @param sb + * @param name + * @param data + */ + public static void appendTag(SB sb, String name, Object data) { + if (data instanceof Object[]) + appendTagAll(sb, name, (Object[]) data, null, false, true); + else + appendTagAll(sb, name, null, data, false, true); + } + + /** + * " + * + * will convert ]]> to ]] > + * + * @param sb + * @param name + * @param attributes + * @param data + */ + public static void appendCdata(SB sb, String name, + Object[] attributes, String data) { + appendTagAll(sb, name, attributes, data, true, true); + } + + /** + * + * @param sb + * @param name + * @param value + */ + public static void appendAttrib(SB sb, Object name, Object value) { + if (value == null) + return; + + // note: <&" are disallowed but not checked for here + + sb.append(" ").appendO(name).append("=\"").appendO(value).append("\""); + } + +} diff --git a/src/javajs/util/ZipData.java b/src/javajs/util/ZipData.java new file mode 100644 index 0000000..f20715f --- /dev/null +++ b/src/javajs/util/ZipData.java @@ -0,0 +1,76 @@ +/* $RCSfile$ + * $Author$ + * $Date$ + * $Revision$ + * + * Copyright (C) 2006 The Jmol Development Team + * + * Contact: jmol-developers@lists.sf.net + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +package javajs.util; + +import java.io.BufferedInputStream; + +import javajs.api.GenericZipTools; + + + + +public class ZipData { + boolean isEnabled = true; + byte[] buf; + int pt; + int nBytes; + + public ZipData(int nBytes) { + this.nBytes = nBytes; + } + + public int addBytes(byte[] byteBuf, int nSectorBytes, int nBytesRemaining) { + if (pt == 0) { + if (!Rdr.isGzipB(byteBuf)) { + isEnabled = false; + return -1; + } + buf = new byte[nBytesRemaining]; + } + int nToAdd = Math.min(nSectorBytes, nBytesRemaining); + System.arraycopy(byteBuf, 0, buf, pt, nToAdd); + pt += nToAdd; + return nBytesRemaining - nToAdd; + } + + public void addTo(GenericZipTools jzt, SB data) { + data.append(getGzippedBytesAsString(jzt, buf)); + } + + static String getGzippedBytesAsString(GenericZipTools jzt, byte[] bytes) { + try { + BufferedInputStream bis = jzt.getUnGzippedInputStream(bytes); + String s = ZipTools.getStreamAsString(bis); + bis.close(); + return s; + } catch (Exception e) { + return ""; + } + } + + +} + diff --git a/src/javajs/util/ZipTools.java b/src/javajs/util/ZipTools.java new file mode 100644 index 0000000..deed8c8 --- /dev/null +++ b/src/javajs/util/ZipTools.java @@ -0,0 +1,432 @@ +/* $RCSfile$ + * $Author$ + * $Date$ + * $Revision$ + * + * Copyright (C) 2006 The Jmol Development Team + * + * Contact: jmol-developers@lists.sf.net + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +package javajs.util; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +import javajs.J2SIgnoreImport; +import javajs.api.GenericZipInputStream; +import javajs.api.GenericZipTools; +import javajs.api.ZInputStream; + +import java.util.Map; +import java.util.zip.CRC32; +import java.util.zip.GZIPInputStream; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; +import java.util.zip.ZipOutputStream; + + +/** + * Note the JSmol/HTML5 must use its own version of java.util.zip.ZipOutputStream. + * + */ +@J2SIgnoreImport({ java.util.zip.ZipOutputStream.class }) +public class ZipTools implements GenericZipTools { + + public ZipTools() { + // for reflection + } + + @Override + public ZInputStream newZipInputStream(InputStream is) { + return newZIS(is); + } + + @SuppressWarnings("resource") + private static ZInputStream newZIS(InputStream is) { + return (is instanceof ZInputStream ? (ZInputStream) is + : is instanceof BufferedInputStream ? new GenericZipInputStream(is) + : new GenericZipInputStream(new BufferedInputStream(is))); + } + + /** + * reads a ZIP file and saves all data in a Hashtable so that the files may be + * organized later in a different order. Also adds a #Directory_Listing entry. + * + * Files are bracketed by BEGIN Directory Entry and END Directory Entry lines, + * similar to CompoundDocument.getAllData. + * + * @param is + * @param subfileList + * @param name0 + * prefix for entry listing + * @param binaryFileList + * |-separated list of files that should be saved as xx xx xx hex byte + * strings. The directory listing is appended with ":asBinaryString" + * @param fileData + */ + @Override + public void getAllZipData(InputStream is, String[] subfileList, + String name0, String binaryFileList, + Map fileData) { + ZipInputStream zis = (ZipInputStream) newZIS(is); + ZipEntry ze; + SB listing = new SB(); + binaryFileList = "|" + binaryFileList + "|"; + String prefix = PT.join(subfileList, '/', 1); + String prefixd = null; + if (prefix != null) { + prefixd = prefix.substring(0, prefix.indexOf("/") + 1); + if (prefixd.length() == 0) + prefixd = null; + } + try { + while ((ze = zis.getNextEntry()) != null) { + String name = ze.getName(); + if (prefix != null && prefixd != null + && !(name.equals(prefix) || name.startsWith(prefixd))) + continue; + //System.out.println("ziputil: " + name); + listing.append(name).appendC('\n'); + String sname = "|" + name.substring(name.lastIndexOf("/") + 1) + "|"; + boolean asBinaryString = (binaryFileList.indexOf(sname) >= 0); + byte[] bytes = Rdr.getLimitedStreamBytes(zis, ze.getSize()); + String str; + if (asBinaryString) { + str = getBinaryStringForBytes(bytes); + name += ":asBinaryString"; + } else { + str = Rdr.fixUTF(bytes); + } + str = "BEGIN Directory Entry " + name + "\n" + str + + "\nEND Directory Entry " + name + "\n"; + fileData.put(name0 + "|" + name, str); + } + } catch (Exception e) { + } + fileData.put("#Directory_Listing", listing.toString()); + } + + private String getBinaryStringForBytes(byte[] bytes) { + SB ret = new SB(); + for (int i = 0; i < bytes.length; i++) + ret.append(Integer.toHexString(bytes[i] & 0xFF)).appendC(' '); + return ret.toString(); + } + + /** + * iteratively drills into zip files of zip files to extract file content or + * zip file directory. Also works with JAR files. + * + * Does not return "__MACOS" paths + * + * @param bis + * @param list + * @param listPtr + * @param asBufferedInputStream + * for Pmesh + * @return directory listing or subfile contents + */ + @Override + public Object getZipFileDirectory(BufferedInputStream bis, String[] list, + int listPtr, boolean asBufferedInputStream) { + SB ret; + if (list == null || listPtr >= list.length) + return getZipDirectoryAsStringAndClose(bis); + bis = Rdr.getPngZipStream(bis, true); + String fileName = list[listPtr]; + ZipInputStream zis = new ZipInputStream(bis); + ZipEntry ze; + //System.out.println("fname=" + fileName); + try { + boolean isAll = (fileName.equals(".")); + if (isAll || fileName.lastIndexOf("/") == fileName.length() - 1) { + ret = new SB(); + while ((ze = zis.getNextEntry()) != null) { + String name = ze.getName(); + if (isAll || name.startsWith(fileName)) + ret.append(name).appendC('\n'); + } + String str = ret.toString(); + return (asBufferedInputStream ? Rdr.getBIS(str.getBytes()) : str); + } + int pt = fileName.indexOf(":asBinaryString"); + boolean asBinaryString = (pt > 0); + if (asBinaryString) + fileName = fileName.substring(0, pt); + fileName = fileName.replace('\\', '/'); + while ((ze = zis.getNextEntry()) != null + && !fileName.equals(ze.getName())) { + } + byte[] bytes = (ze == null ? null : Rdr.getLimitedStreamBytes(zis, + ze.getSize())); + ze = null; + zis.close(); + if (bytes == null) + return ""; + if (Rdr.isZipB(bytes) || Rdr.isPngZipB(bytes)) + return getZipFileDirectory(Rdr.getBIS(bytes), list, ++listPtr, + asBufferedInputStream); + if (asBufferedInputStream) + return Rdr.getBIS(bytes); + if (asBinaryString) { + ret = new SB(); + for (int i = 0; i < bytes.length; i++) + ret.append(Integer.toHexString(bytes[i] & 0xFF)).appendC(' '); + return ret.toString(); + } + if (Rdr.isGzipB(bytes)) + bytes = Rdr.getLimitedStreamBytes(getUnGzippedInputStream(bytes), -1); + return Rdr.fixUTF(bytes); + } catch (Exception e) { + return ""; + } + } + + @Override + public byte[] getZipFileContentsAsBytes(BufferedInputStream bis, + String[] list, int listPtr) { + byte[] ret = new byte[0]; + String fileName = list[listPtr]; + if (fileName.lastIndexOf("/") == fileName.length() - 1) + return ret; + try { + bis = Rdr.getPngZipStream(bis, true); + ZipInputStream zis = new ZipInputStream(bis); + ZipEntry ze; + while ((ze = zis.getNextEntry()) != null) { + if (!fileName.equals(ze.getName())) + continue; + byte[] bytes = Rdr.getLimitedStreamBytes(zis, ze.getSize()); + return ((Rdr.isZipB(bytes) || Rdr.isPngZipB(bytes)) && ++listPtr < list.length ? getZipFileContentsAsBytes( + Rdr.getBIS(bytes), list, listPtr) : bytes); + } + } catch (Exception e) { + } + return ret; + } + + @Override + public String getZipDirectoryAsStringAndClose(BufferedInputStream bis) { + SB sb = new SB(); + String[] s = new String[0]; + try { + s = getZipDirectoryOrErrorAndClose(bis, null); + bis.close(); + } catch (Exception e) { + System.out.println(e.toString()); + } + for (int i = 0; i < s.length; i++) + sb.append(s[i]).appendC('\n'); + return sb.toString(); + } + + @Override + public String[] getZipDirectoryAndClose(BufferedInputStream bis, + String manifestID) { + String[] s = new String[0]; + try { + s = getZipDirectoryOrErrorAndClose(bis, manifestID); + bis.close(); + } catch (Exception e) { + System.out.println(e.toString()); + } + return s; + } + + private String[] getZipDirectoryOrErrorAndClose(BufferedInputStream bis, + String manifestID) + throws IOException { + bis = Rdr.getPngZipStream(bis, true); + Lst v = new Lst(); + ZipInputStream zis = new ZipInputStream(bis); + ZipEntry ze; + String manifest = null; + while ((ze = zis.getNextEntry()) != null) { + String fileName = ze.getName(); + if (manifestID != null && fileName.startsWith(manifestID)) + manifest = getStreamAsString(zis); + else if (!fileName.startsWith("__MACOS")) // resource fork not nec. + v.addLast(fileName); + } + zis.close(); + if (manifestID != null) + v.add(0, manifest == null ? "" : manifest + "\n############\n"); + return v.toArray(new String[v.size()]); + } + + public static String getStreamAsString(InputStream is) throws IOException { + return Rdr.fixUTF(Rdr.getLimitedStreamBytes(is, -1)); + } + + @Override + public InputStream newGZIPInputStream(InputStream is) throws IOException { + return new BufferedInputStream(new GZIPInputStream(is, 512)); + } + + @Override + public BufferedInputStream getUnGzippedInputStream(byte[] bytes) { + try { + return Rdr.getUnzippedInputStream(this, Rdr.getBIS(bytes)); + } catch (Exception e) { + return null; + } + } + + @Override + public void addZipEntry(Object zos, String fileName) throws IOException { + ((ZipOutputStream) zos).putNextEntry(new ZipEntry(fileName)); + } + + @Override + public void closeZipEntry(Object zos) throws IOException { + ((ZipOutputStream) zos).closeEntry(); + } + + @Override + public Object getZipOutputStream(Object bos) { + /** + * @j2sNative + * + * return javajs.api.Interface.getInterface( + * "java.util.zip.ZipOutputStream").setZOS(bos); + * + */ + { + return new ZipOutputStream((OutputStream) bos); + } + } + + @Override + public int getCrcValue(byte[] bytes) { + CRC32 crc = new CRC32(); + crc.update(bytes, 0, bytes.length); + return (int) crc.getValue(); + } + + @Override + public void readFileAsMap(BufferedInputStream bis, Map bdata, String name) { + int pt = (name == null ? -1 : name.indexOf("|")); + name = (pt >= 0 ? name.substring(pt + 1) : null); + try { + if (Rdr.isPngZipStream(bis)) { + boolean isImage = "_IMAGE_".equals(name); + if (name == null || isImage) + bdata.put((isImage ? "_DATA_" : "_IMAGE_"), new BArray(getPngImageBytes(bis))); + if (!isImage) + cacheZipContents(bis, name, bdata, true); + } else if (Rdr.isZipS(bis)) { + cacheZipContents(bis, name, bdata, true); + } else if (name == null){ + bdata.put("_DATA_", new BArray(Rdr.getLimitedStreamBytes(bis, -1))); + } else { + throw new IOException("ZIP file " + name + " not found"); + } + bdata.put("$_BINARY_$", Boolean.TRUE); + } catch (IOException e) { + bdata.clear(); + bdata.put("_ERROR_", e.getMessage()); + } + } + + @Override + public String cacheZipContents(BufferedInputStream bis, + String fileName, + Map cache, + boolean asByteArray) { + ZipInputStream zis = (ZipInputStream) newZIS(bis); + ZipEntry ze; + SB listing = new SB(); + long n = 0; + boolean oneFile = (asByteArray && fileName != null); + int pt = (oneFile ? fileName.indexOf("|") : -1); + String file0 = (pt >= 0 ? fileName : null); + if (pt >= 0) + fileName = fileName.substring(0, pt); + try { + while ((ze = zis.getNextEntry()) != null) { + String name = ze.getName(); + if (fileName != null) { + if (oneFile) { + if (!name.equalsIgnoreCase(fileName)) + continue; + } else { + listing.append(name).appendC('\n'); + } + } + long nBytes = ze.getSize(); + byte[] bytes = Rdr.getLimitedStreamBytes(zis, nBytes); + if (file0 != null) { + readFileAsMap(Rdr.getBIS(bytes), cache, file0); + return null; + } + n += bytes.length; + Object o = (asByteArray ? new BArray(bytes) : bytes); + cache.put((oneFile ? "_DATA_" : (fileName == null ? "" : fileName + "|") + name), o); + if (oneFile) + break; + } + zis.close(); + } catch (Exception e) { + try { + zis.close(); + } catch (IOException e1) { + } + return null; + } + if (n == 0 || fileName == null) + return null; + System.out.println("ZipTools cached " + n + " bytes from " + fileName); + return listing.toString(); + } + + private static byte[] getPngImageBytes(BufferedInputStream bis) { + try { + if (Rdr.isPngZipStream(bis)) { + int pt_count[] = new int[2]; + Rdr.getPngZipPointAndCount(bis, pt_count); + if (pt_count[1] != 0) + return deActivatePngZipB(Rdr.getLimitedStreamBytes(bis, pt_count[0])); + } + return Rdr.getLimitedStreamBytes(bis, -1); + } catch (IOException e) { + return null; + } + } + + /** + * Once a PNGJ image has been extracted, we want to red-line its + * iTXt "Jmol Type PNGJ" tag, since it is no longer associated with + * ZIP data. + * + * @param bytes + * @return disfigured bytes + * + */ + private static byte[] deActivatePngZipB(byte[] bytes) { + // \0PNGJ starting at byte 50 changed to \0 NGJ + if (Rdr.isPngZipB(bytes)) + bytes[51] = 32; + return bytes; + } + + + +} diff --git a/src/netscape/javascript/JSException.java b/src/netscape/javascript/JSException.java new file mode 100644 index 0000000..165cbda --- /dev/null +++ b/src/netscape/javascript/JSException.java @@ -0,0 +1,5 @@ +package netscape.javascript; + +public class JSException extends Exception { + +} diff --git a/src/netscape/javascript/JSObject.java b/src/netscape/javascript/JSObject.java new file mode 100644 index 0000000..4e84f89 --- /dev/null +++ b/src/netscape/javascript/JSObject.java @@ -0,0 +1,41 @@ +package netscape.javascript; + +import jalview.bin.JalviewLite; + +public class JSObject { + + public static JSObject getWindow(JalviewLite jvlite) { + /** + * @j2sNative + * + * return window; + * + */ + { + return null; + } + } + + public void call(String _listener, Object[] objects) { + /** + * @j2sNative + * + * alert("call " + _listener); + */ + {} + } + + public Object eval(String string) { + /** + * @j2sNative + * + * alert("evval " + string); + */ + { + + + } + return eval(string); + } + +} diff --git a/src/org/exolab/castor/mapping/Mapping.java b/src/org/exolab/castor/mapping/Mapping.java new file mode 100644 index 0000000..0bef0ce --- /dev/null +++ b/src/org/exolab/castor/mapping/Mapping.java @@ -0,0 +1,16 @@ +package org.exolab.castor.mapping; + +import java.net.URL; + +public class Mapping { + + public Mapping(ClassLoader classLoader) { + // TODO Auto-generated constructor stub + } + + public void loadMapping(URL url) { + // TODO Auto-generated method stub + + } + +} diff --git a/src/org/exolab/castor/xml/Unmarshaller.java b/src/org/exolab/castor/xml/Unmarshaller.java new file mode 100644 index 0000000..640328b --- /dev/null +++ b/src/org/exolab/castor/xml/Unmarshaller.java @@ -0,0 +1,44 @@ +package org.exolab.castor.xml; + +import java.io.PrintWriter; +import java.io.Reader; + +import org.exolab.castor.mapping.Mapping; + +public class Unmarshaller { + + public Unmarshaller(Object record) { + // TODO Auto-generated constructor stub + } + + public void setIgnoreExtraElements(boolean b) { + // TODO Auto-generated method stub + + } + + public void setIgnoreExtraAttributes(boolean b) { + // TODO Auto-generated method stub + + } + + public void setMapping(Mapping map) { + // TODO Auto-generated method stub + + } + + public void setLogWriter(PrintWriter printWriter) { + // TODO Auto-generated method stub + + } + + public Object unmarshal(Reader file) { + // TODO Auto-generated method stub + return null; + } + + public void setDebug(boolean debugEnabled) { + // TODO Auto-generated method stub + + } + +} diff --git a/src/org/jmol/viewer/Viewer.java b/src/org/jmol/viewer/Viewer.java new file mode 100644 index 0000000..1f6c399 --- /dev/null +++ b/src/org/jmol/viewer/Viewer.java @@ -0,0 +1,5 @@ +package org.jmol.viewer; + +public class Viewer { + +} diff --git a/src/swingjs/JSEvent.java b/src/swingjs/JSEvent.java new file mode 100644 index 0000000..5b2a6e6 --- /dev/null +++ b/src/swingjs/JSEvent.java @@ -0,0 +1,22 @@ +package swingjs; + +import java.awt.event.InvocationEvent; + +/** + * a custom implementation of java.awt.event.InvocationEvent for JSThread + * + * @author Bob Hanson + * + */ +public class JSEvent extends InvocationEvent { + + /** + * + */ + private static final long serialVersionUID = -8061376242084344200L; + + JSEvent(JSThread t, Runnable r) { + super(t, r); + } + +} diff --git a/src/swingjs/JSThread.java b/src/swingjs/JSThread.java new file mode 100644 index 0000000..b7e7f10 --- /dev/null +++ b/src/swingjs/JSThread.java @@ -0,0 +1,143 @@ +package swingjs; + +import java.awt.Toolkit; +import java.awt.event.InvocationEvent; +import swingjs.api.JSFunction; + +/** + * A class that takes care of simple threading. There are three states: INIT, LOOP, and DONE. + * These states are passed into run1 + * + * + * @author Bob Hanson + * + */ +public abstract class JSThread extends Thread implements JSFunction { + + public static final int INIT = 0; + public static final int LOOP = 1; + public static final int DONE = 2; + + protected boolean isJS; + protected boolean doDispatch = true; + protected int msDelay; + + public JSThread(ThreadGroup group, String name) { + super(group, name); + /** + * @j2sNative + * + * this.isJS = true; + */ + {} + } + + public void run() { + run1(INIT); + } + + @Override + public synchronized void start() { + + /** + * @j2sNative + * + * JSToolkit.setTimeout(this, 1, 0); + * + */ + { + super.start(); + } + + } + + /** + * set the delay time between run1 calls + * + * @param ms + */ + public void setDelayMillis(int ms) { + msDelay = ms; + } + + /** + * a generic method that loops until done, or in JavaScript, will reenter and + * continue at the appropriate spot. Example given here + * + * @param state + */ + protected abstract void run1(int state); + + + // protected void run1(int state) { + // try { + // while (true) + // switch (state) { + // case INIT: + // // once-through stuff here + // state = LOOP; + // break; + // case LOOP: + // if (!doDispatch || isInterrupted()) { + // state = DONE; + // } else { + // // put the loop code here + // }; + // dispatchAndReturn(state); + // if (isJS) + // return; + // } + // break; + // // add more cases as needed + // case DONE: + // // finish up here + // if (isInterrupted()) + // return; + // // or here + // break; + // } + // } finally { + // // stuff here to be executed after each loop in JS or at the end in Java + // } + // } + + /** + * + * @param r + * @param state + * @throws InterruptedException + */ + protected void dispatchAndReturn(final int state) + throws InterruptedException { + final int delay = msDelay; + if (isJS) { + // in JavaScript, we need to do this through the system event queue, + // which in JSToolkit takes care of all the "thread" handling. + + final JSThread me = this; + Runnable r = new Runnable() { + @Override + public void run() { + me.run1(state); + } + }; + /** + * @j2sNative + * + * setTimeout(function() { + * java.awt.Toolkit.getDefaultToolkit().getSystemEventQueue + * ().postEvent(new java.awt.event.InvocationEvent(me, r)), + * delay; } + * + */ + { + // for reference only + Toolkit.getDefaultToolkit().getSystemEventQueue() + .postEvent(new InvocationEvent(me, r)); + } + } else { + sleep(delay); + } + } + +} diff --git a/src/swingjs/api/JSFunction.java b/src/swingjs/api/JSFunction.java new file mode 100644 index 0000000..4dcc3ea --- /dev/null +++ b/src/swingjs/api/JSFunction.java @@ -0,0 +1,5 @@ +package swingjs.api; + +public interface JSFunction { + +} -- 1.7.10.2