[jabref] 50/459: Load /tmp/tmp.vjbgZ10456/jabref-2.2~b2 into jabref/branches/upstream/current.
gregor herrmann
gregoa at debian.org
Thu Sep 15 20:39:40 UTC 2016
This is an automated email from the git hooks/post-receive script.
gregoa pushed a commit to branch master
in repository jabref.
commit a872b88085ac404d82a5fefbcff00c0ffe43071c
Author: gregor herrmann <gregoa at debian.org>
Date: Sun Nov 26 20:29:57 2006 +0000
Load /tmp/tmp.vjbgZ10456/jabref-2.2~b2 into
jabref/branches/upstream/current.
---
.classpath | 28 -
.cvsignore | 15 -
build.number | 4 +-
build.xml | 966 +++--
lib/JempBox-0.1.0-dev.jar | Bin 0 -> 24974 bytes
lib/PDFBox-0.7.3-dev-reduced.jar | Bin 0 -> 634567 bytes
lib/antlr-3.0b5.jar | Bin 0 -> 664368 bytes
lib/glazedlists-1.5.0_java14.jar | Bin 341472 -> 0 bytes
lib/glazedlists-1.7.0_java14.jar | Bin 0 -> 525078 bytes
lib/spin-1.4.jar | Bin 23118 -> 0 bytes
lib/spin.jar | Bin 0 -> 21206 bytes
src/help/About.html | 6 +-
src/help/CiteSeerHelp.html | 3 +-
src/help/Contents.html | 21 +-
src/help/CustomExports.html | 92 +-
src/help/ExternalFiles.html | 36 +-
src/help/PreviewHelp.html | 2 +-
src/help/SearchHelp.html | 8 +-
src/help/XMPHelp.html | 114 +
src/help/credits.txt | 3 +
src/help/de/About.html | 2 +
src/help/de/PreviewHelp.html | 2 +-
src/help/fr/About.html | 2 +
src/help/fr/BaseFrameHelp.html | 11 +-
src/help/fr/Contents.html | 11 +-
src/help/fr/CustomExports.html | 13 +-
src/help/fr/ExternalFiles.html | 45 +-
src/help/fr/PreviewHelp.html | 4 +-
src/help/fr/XMPHelp.html | 114 +
src/images/JabRef-Logo.icns | Bin 31575 -> 35556 bytes
src/images/JabRef-icon.png | Bin 659 -> 0 bytes
src/images/JabRef-icon.svg | 207 --
src/images/JabRef.ico | Bin 0 -> 15086 bytes
src/images/crystal_16/Icons.properties~ | 69 -
src/images/font/ACTIVA.TTF | Bin 82984 -> 0 bytes
src/images/font/ASTROLYT.TTF | Bin 42020 -> 0 bytes
src/images/font/AUGIE.TTF | Bin 54108 -> 0 bytes
src/images/secondary_sorted_reverse.png | Bin 0 -> 214 bytes
src/images/splash-2.1.png | Bin 169994 -> 0 bytes
src/images/splash-2.1.svg | 244 --
src/images/splash.png | Bin 0 -> 223373 bytes
src/images/splash.svg | 229 --
src/java/net/sf/jabref/AuthorList.java | 1855 +++++-----
src/java/net/sf/jabref/BasePanel.java | 243 +-
src/java/net/sf/jabref/BibtexEntry.java | 40 +-
src/java/net/sf/jabref/EntryComparator.java | 1 -
src/java/net/sf/jabref/EntryEditor.java | 2582 +++++++-------
src/java/net/sf/jabref/EntryEditorTab.java | 695 ++--
src/java/net/sf/jabref/ExternalTab.java | 341 +-
src/java/net/sf/jabref/FieldComparator.java | 180 +-
src/java/net/sf/jabref/FieldContentSelector.java | 429 +--
src/java/net/sf/jabref/FieldEditor.java | 121 +-
src/java/net/sf/jabref/FieldNameLabel.java | 10 +-
src/java/net/sf/jabref/FieldTextArea.java | 370 +-
src/java/net/sf/jabref/FieldTextField.java | 169 +-
src/java/net/sf/jabref/GUIGlobals.java | 690 ++--
src/java/net/sf/jabref/Globals.java | 2593 +++++++-------
src/java/net/sf/jabref/Globals.java~ | 1324 -------
src/java/net/sf/jabref/HelpAction.java | 215 +-
src/java/net/sf/jabref/HelpContent.java | 411 ++-
src/java/net/sf/jabref/HelpDialog.java | 280 +-
src/java/net/sf/jabref/JabRef.java | 127 +-
src/java/net/sf/jabref/JabRefFrame.java | 1233 +++----
src/java/net/sf/jabref/JabRefPreferences.java | 93 +-
src/java/net/sf/jabref/MetaData.java | 27 +-
src/java/net/sf/jabref/NameFormatterTab.java | 307 ++
src/java/net/sf/jabref/PrefsDialog2.java | 9 +-
src/java/net/sf/jabref/PrefsDialog3.java | 33 +-
src/java/net/sf/jabref/PreviewPanel.java | 369 +-
src/java/net/sf/jabref/PreviewPrefsTab.java | 402 ++-
src/java/net/sf/jabref/ReplaceStringDialog.java | 7 +-
src/java/net/sf/jabref/SearchManager2.java | 9 +-
src/java/net/sf/jabref/SidePane.java | 201 +-
src/java/net/sf/jabref/SidePaneComponent.java | 199 +-
src/java/net/sf/jabref/SidePaneManager.java | 376 +-
src/java/net/sf/jabref/SplashScreen.java | 2 +-
src/java/net/sf/jabref/SplashScreen.java~ | 110 -
src/java/net/sf/jabref/StringDialog.java | 4 +-
src/java/net/sf/jabref/TablePrefsTab.java | 628 ++--
src/java/net/sf/jabref/Util.java | 3727 ++++++++++++--------
src/java/net/sf/jabref/bst/BibtexCaseChanger.java | 249 ++
.../net/sf/jabref/bst/BibtexNameFormatter.java | 304 ++
src/java/net/sf/jabref/bst/BibtexPurify.java | 84 +
src/java/net/sf/jabref/bst/BibtexTextPrefix.java | 78 +
src/java/net/sf/jabref/bst/BibtexWidth.java | 241 ++
src/java/net/sf/jabref/bst/Bst.java | 1943 ++++++++++
src/java/net/sf/jabref/bst/BstLexer.java | 1659 +++++++++
src/java/net/sf/jabref/bst/BstParser.java | 1344 +++++++
src/java/net/sf/jabref/bst/ChangeCaseFunction.java | 65 +
src/java/net/sf/jabref/bst/FormatNameFunction.java | 67 +
src/java/net/sf/jabref/bst/PurifyFunction.java | 47 +
src/java/net/sf/jabref/bst/TextPrefixFunction.java | 58 +
src/java/net/sf/jabref/bst/VM.java | 1377 ++++++++
src/java/net/sf/jabref/bst/VMException.java | 9 +
src/java/net/sf/jabref/bst/Warn.java | 5 +
src/java/net/sf/jabref/bst/WidthFunction.java | 48 +
src/java/net/sf/jabref/bst/bst.g | 88 +
src/java/net/sf/jabref/collab/ChangeScanner.java | 23 +-
src/java/net/sf/jabref/collab/FileUpdatePanel.java | 99 +-
.../net/sf/jabref/export/CustomExportList.java | 23 +
.../jabref/export/ExportCustomizationDialog.java | 6 +-
.../net/sf/jabref/export/ExportFileFilter.java | 38 +
src/java/net/sf/jabref/export/ExportFormat.java | 200 ++
src/java/net/sf/jabref/export/ExportFormats.java | 211 ++
src/java/net/sf/jabref/export/FieldFormatter.java | 57 +-
src/java/net/sf/jabref/export/FileActions.java | 221 +-
.../net/sf/jabref/export/ModsExportFormat.java | 52 +
src/java/net/sf/jabref/export/OOCalcDatabase.java | 30 +-
.../jabref/export/OpenDocumentRepresentation.java | 30 +-
.../export/OpenDocumentSpreadsheetCreator.java | 18 +-
.../jabref/export/OpenOfficeDocumentCreator.java | 21 +-
src/java/net/sf/jabref/export/SaveException.java | 2 +-
.../net/sf/jabref/export/layout/LayoutEntry.java | 851 +++--
.../sf/jabref/export/layout/LayoutFormatter.java | 72 +-
.../net/sf/jabref/export/layout/LayoutHelper.java | 102 +-
.../export/layout/format/AuthorAbbreviator.java | 152 +-
.../layout/format/AuthorAndsCommaReplacer.java | 2 +-
.../layout/format/AuthorFirstAbbrLastCommas.java | 44 +-
.../format/AuthorFirstAbbrLastOxfordCommas.java | 50 +
.../export/layout/format/AuthorFirstFirst.java | 65 +-
.../layout/format/AuthorFirstLastCommas.java | 12 +-
...ommas.java => AuthorFirstLastOxfordCommas.java} | 14 +-
.../export/layout/format/AuthorLastFirst.java | 12 +-
.../layout/format/AuthorLastFirstAbbrCommas.java | 38 +-
.../format/AuthorLastFirstAbbrOxfordCommas.java | 49 +
.../layout/format/AuthorLastFirstAbbreviator.java | 15 +-
.../layout/format/AuthorLastFirstCommas.java | 39 +-
.../layout/format/AuthorLastFirstOxfordCommas.java | 47 +
.../jabref/export/layout/format/AuthorOrgSci.java | 42 +
.../export/layout/format/CompositeFormat.java | 41 +
.../sf/jabref/export/layout/format/DOICheck.java | 34 +
.../export/layout/format/HTMLParagraphs.java | 48 +
.../sf/jabref/export/layout/format/NameFormat.java | 151 +
.../layout/format/NoSpaceBetweenAbbreviations.java | 37 +
.../sf/jabref/export/layout/format/RTFChars.java | 283 +-
.../sf/jabref/export/layout/format/ResolvePDF.java | 37 +-
.../jabref/export/layout/format/ToLowerCase.java | 25 +-
.../external/AutoSetExternalFileForEntries.java | 11 +-
.../net/sf/jabref/external/DroppedFileHandler.java | 411 +++
.../net/sf/jabref/external/ExternalFilePanel.java | 717 ++--
.../net/sf/jabref/external/ExternalFileType.java | 9 +
.../net/sf/jabref/external/PushToApplication.java | 3 +
.../jabref/external/PushToApplicationAction.java | 9 +-
.../jabref/external/PushToApplicationButton.java | 187 +
src/java/net/sf/jabref/external/PushToEmacs.java | 4 +
.../net/sf/jabref/external/PushToLatexEditor.java | 7 +-
src/java/net/sf/jabref/external/PushToLyx.java | 4 +
src/java/net/sf/jabref/external/PushToWinEdt.java | 4 +
.../net/sf/jabref/external/WriteXMPAction.java | 250 ++
.../jabref/groups/EntryTableTransferHandler.java | 650 ++--
src/java/net/sf/jabref/groups/GroupDialog.java | 2 +-
src/java/net/sf/jabref/groups/GroupSelector.java | 11 +-
.../sf/jabref/gui/DatabasePropertiesDialog.java | 18 +-
.../net/sf/jabref/gui/ImportInspectionDialog.java | 2 +-
src/java/net/sf/jabref/gui/MainTable.java | 63 +-
src/java/net/sf/jabref/gui/MainTableFormat.java | 6 +-
.../sf/jabref/gui/MainTableSelectionListener.java | 113 +-
.../net/sf/jabref/gui/date/DatePickerButton.java | 48 +-
src/java/net/sf/jabref/imports/BibtexParser.java | 1591 +++++----
.../net/sf/jabref/imports/CiteSeerFetcher.java | 2 +-
.../sf/jabref/imports/CiteSeerFetcherPanel.java | 37 +-
src/java/net/sf/jabref/imports/GeneralFetcher.java | 37 +-
.../net/sf/jabref/imports/ImportFileFilter.java | 38 +
.../net/sf/jabref/imports/ImportFormatReader.java | 55 +-
src/java/net/sf/jabref/imports/ImportFormats.java | 122 +
src/java/net/sf/jabref/imports/ImportMenuItem.java | 10 +-
src/java/net/sf/jabref/imports/IsiImporter.java | 639 ++--
src/java/net/sf/jabref/imports/OAI2Fetcher.java | 267 ++
src/java/net/sf/jabref/imports/OAI2Handler.java | 131 +
.../net/sf/jabref/imports/OpenDatabaseAction.java | 11 +-
src/java/net/sf/jabref/imports/PdfXmpImporter.java | 50 +
src/java/net/sf/jabref/mods/MODSDatabase.java | 19 +-
src/java/net/sf/jabref/search/BasicSearch.java | 146 +
.../sf/jabref/search/SearchExpressionParser.java | 22 +-
.../net/sf/jabref/undo/CountingUndoManager.java | 4 +-
src/java/net/sf/jabref/util/CaseChanger.java | 212 +-
.../util/EncryptionNotSupportedException.java | 13 +
src/java/net/sf/jabref/util/ErrorConsole.java | 1 -
.../net/sf/jabref/util/MassSetFieldAction.java | 171 +
src/java/net/sf/jabref/util/XMPSchemaBibtex.java | 280 ++
src/java/net/sf/jabref/util/XMPUtil.java | 506 +++
.../sf/jabref/wizard/integrity/IntegrityCheck.java | 11 +-
src/java/tests/net/sf/jabref/AllTests.java | 28 +
src/java/tests/net/sf/jabref/AuthorListTest.java | 547 +++
.../tests/net/sf/jabref/FileBasedTestCase.java | 222 ++
src/java/tests/net/sf/jabref/JabRefTestCase.java | 24 +
src/java/tests/net/sf/jabref/UtilFindFileTest.java | 191 +
src/java/tests/net/sf/jabref/UtilTest.java | 379 ++
src/java/tests/net/sf/jabref/bst/AllTests.java | 21 +
.../net/sf/jabref/bst/BibtexCaseChangerTest.java | 125 +
.../net/sf/jabref/bst/BibtexNameFormatterTest.java | 135 +
.../tests/net/sf/jabref/bst/BibtexPurifyTest.java | 27 +
.../tests/net/sf/jabref/bst/BibtexWidthTest.java | 78 +
src/java/tests/net/sf/jabref/bst/TestVM.java | 648 ++++
.../net/sf/jabref/bst/TextPrefixFunctionTest.java | 29 +
.../net/sf/jabref/export/layout/AllTests.java | 17 +
.../net/sf/jabref/export/layout/LayoutTest.java | 100 +
.../net/sf/jabref/export/layout/RTFCharsTest.java | 85 +
.../sf/jabref/export/layout/format/AllTests.java | 36 +
.../layout/format/AuthorAbbreviatorTest.java | 55 +
.../layout/format/AuthorAndsCommaReplacerTest.java | 61 +
.../layout/format/AuthorAndsReplacerTest.java | 64 +
.../format/AuthorFirstAbbrLastCommasTest.java | 61 +
.../AuthorFirstAbbrLastOxfordCommasTest.java | 63 +
.../export/layout/format/AuthorFirstFirstTest.java | 48 +
.../layout/format/AuthorFirstLastCommasTest.java | 63 +
.../format/AuthorFirstLastOxfordCommasTest.java | 64 +
.../format/AuthorLastFirstAbbrCommasTest.java | 64 +
.../AuthorLastFirstAbbrOxfordCommasTest.java | 63 +
.../format/AuthorLastFirstAbbreviatorTester.java | 28 +-
.../layout/format/AuthorLastFirstCommasTest.java | 65 +
.../format/AuthorLastFirstOxfordCommasTest.java | 63 +
.../export/layout/format/AuthorLastFirstTest.java | 30 +
.../export/layout/format/AuthorOrgSciTest.java | 33 +
.../format/BibtexNameLayoutFormatterTest.java | 61 +
.../export/layout/format/CompositeFormatTest.java | 60 +
.../jabref/export/layout/format/DOICheckTest.java | 37 +
.../export/layout/format/HTMLParagraphsTest.java | 21 +
.../format/NoSpaceBetweenAbbreviationsTest.java | 26 +
.../export/layout/format/ResolvePDFTest.java | 52 +
src/java/tests/net/sf/jabref/imports/AllTests.java | 19 +
.../net/sf/jabref/imports/AutoImportTest.java | 11 +
.../net/sf/jabref/imports/BibtexParserTest.java | 216 ++
.../tests/net/sf/jabref/imports/IEEEImport1.txt | 60 +
.../net/sf/jabref/imports/IsiImporterTest.java | 370 ++
.../net/sf/jabref/imports/IsiImporterTest1.isi | 25 +
.../sf/jabref/imports/IsiImporterTestInspec.isi | 122 +
.../sf/jabref/imports/IsiImporterTestMedline.isi | 27 +
.../net/sf/jabref/imports/IsiImporterTestWOS.isi | 135 +
.../net/sf/jabref/imports/OAI2ImportTest.java | 99 +
src/java/tests/net/sf/jabref/imports/RisTest.ris | 18 +
src/java/tests/net/sf/jabref/imports/oai2.xml | 30 +
src/java/tests/net/sf/jabref/imports/oai22.xml | 30 +
src/java/tests/net/sf/jabref/search/AllTests.java | 16 +
.../net/sf/jabref/search/BasicSearchTest.java | 60 +
src/java/tests/net/sf/jabref/util/AllTests.java | 18 +
.../tests/net/sf/jabref/util/CaseChangerTest.java | 58 +
.../net/sf/jabref/util/XMPSchemaBibtexTest.java | 245 ++
src/java/tests/net/sf/jabref/util/XMPUtilTest.java | 1122 ++++++
src/resource/IntegrityMessage_du.properties | 11 +
src/resource/JabRef_de.properties | 68 +-
src/resource/JabRef_du.properties | 2171 ++++++++++++
src/resource/JabRef_en.properties | 67 +
src/resource/JabRef_fr.properties | 79 +-
src/resource/JabRef_it.properties | 70 +-
src/resource/JabRef_no.properties | 69 +-
src/resource/Menu_de.properties | 16 +-
src/resource/Menu_du.properties | 203 ++
src/resource/Menu_en.properties | 10 +-
src/resource/Menu_fr.properties | 11 +-
src/resource/Menu_it.properties | 7 +
src/resource/Menu_no.properties | 9 +-
src/resource/build.properties | 6 +-
src/resource/fields/.cvsignore | 1 +
src/resource/journalList.txt | 1556 ++++++++
.../layout/tablerefs/tablerefs.begin.layout | 152 +
src/resource/layout/tablerefs/tablerefs.end.layout | 12 +
src/resource/layout/tablerefs/tablerefs.layout | 8 +
.../tablerefsabsbib/tablerefsabsbib.begin.layout | 221 ++
.../tablerefsabsbib/tablerefsabsbib.end.layout | 12 +
.../layout/tablerefsabsbib/tablerefsabsbib.layout | 36 +
src/resource/log4j.properties | 7 +
src/tests/encrypted.pdf | 51 +
src/tests/net/sf/jabref/bst/abbrv.bst | 1098 ++++++
src/txt/README | 65 +-
src/txt/TODO | 9 +
src/windows/nsis/.cvsignore | 2 +
src/windows/nsis/README.txt | 38 +
src/windows/nsis/fileassoc.nsh | 119 +
src/windows/nsis/launcher.nsi | 106 +
src/windows/nsis/setup.nsi | 159 +
271 files changed, 38801 insertions(+), 14629 deletions(-)
diff --git a/.classpath b/.classpath
deleted file mode 100644
index a0c016f..0000000
--- a/.classpath
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<classpath>
- <classpathentry kind="src" path="src/java"/>
- <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
- <classpathentry kind="lib" path="lib/aelfred-1.2.jar"/>
- <classpathentry kind="lib" path="lib/antlr.jar"/>
- <classpathentry kind="lib" path="lib/ccl.jar"/>
- <classpathentry kind="lib" path="lib/jalopy-1.0b10.jar"/>
- <classpathentry kind="lib" path="lib/jalopy-ant-0.6.1.jar"/>
- <classpathentry kind="lib" path="lib/javancss.jar"/>
- <classpathentry kind="lib" path="lib/jaxen-core-1.0-fcs.jar"/>
- <classpathentry kind="lib" path="lib/jaxp-1.2.jar"/>
- <classpathentry kind="lib" path="lib/jdom-1.0b8.jar"/>
- <classpathentry kind="lib" path="lib/log4j-1.2.6.jar"/>
- <classpathentry kind="lib" path="lib/looks-1.2.2.jar"/>
- <classpathentry kind="lib" path="lib/oro-2.0.6.jar"/>
- <classpathentry kind="lib" path="lib/plastic-1.2.1.jar"/>
- <classpathentry kind="lib" path="lib/sax-2.0.1.jar"/>
- <classpathentry kind="lib" path="lib/saxpath-1.0-fcs.jar"/>
- <classpathentry kind="lib" path="lib/vizant.jar"/>
- <classpathentry kind="lib" path="lib/spin.jar"/>
- <classpathentry kind="var" path="JUNIT_HOME/junit.jar"/>
- <classpathentry kind="lib" path="lib/pmd-2.0.jar"/>
- <classpathentry kind="lib" path="lib/forms-1.0.4.jar"/>
- <classpathentry kind="lib" path="lib/junit.jar"/>
- <classpathentry kind="lib" path="lib/log4j-1.2.9.jar"/>
- <classpathentry kind="output" path="build"/>
-</classpath>
diff --git a/.cvsignore b/.cvsignore
deleted file mode 100644
index 0a53838..0000000
--- a/.cvsignore
+++ /dev/null
@@ -1,15 +0,0 @@
-bak
-build
-.classpath
-.project
-work.jpx
-work.refactor
-.#build.xml.1.38
-.#jabref.log.1.2
-ini
-jabref.log
-jabref.log.lck
-build.number
-classes
-jabref.jpx
-jabref.oif
diff --git a/build.number b/build.number
index 691512d..135abb0 100644
--- a/build.number
+++ b/build.number
@@ -1,3 +1,3 @@
#Build Number for ANT. Do not edit!
-#Wed Aug 09 18:35:54 CEST 2006
-build.number=570
+#Sun Nov 26 20:22:40 CET 2006
+build.number=341
diff --git a/build.xml b/build.xml
index 36b8b76..0b8e3a2 100644
--- a/build.xml
+++ b/build.xml
@@ -22,11 +22,13 @@
Compiler: Ant
Authors: Joerg K. Wegner, wegnerj at informatik.uni-tuebingen.de
Morten O. Alver
- Version: $Revision: 1.62 $
- $Date: 2006/07/25 19:56:36 $
- $Author: mortenalver $
+ Version: $Revision: 1.77 $
+ $Date: 2006/11/23 22:37:19 $
+ $Author: coezbek $
modified:
+ 23.11.2006 c.oezbek
+ - tried to fix classpath issues
28.07.2005 r.nagel
- insert dynamic build info generation (resource/build.properties)
- copy fonts directory, used by the new about dialog
@@ -40,469 +42,444 @@
<project name="JabRef" default="jars" basedir=".">
- <!-- ==========================================================================================
+ <!-- ==========================================================================================
PROPERTY SETUP
========================================================================================== -->
- <!-- some version information -->
- <property name="jabref.bin" value="jabref" />
- <property name="jabref.version" value="2.1" />
- <property name="jabref.placeholder.version" value="@version@" /> <!-- used by replace task -->
-
-
- <!-- Set the properties for intermediate directory -->
- <property name="build.dir" value="build" />
- <property name="build.classes" value="${build.dir}/classes" />
- <property name="build.tmp" value="${build.dir}/tmp" />
- <property name="build.osx" value="${build.dir}/classes/osxadapter" />
- <property name="build.lib" value="${build.dir}/lib" />
- <property name="build.bin" value="${build.dir}/bin" />
- <property name="build.win" value="${build.dir}/windows" />
- <property name="build.images" value="${build.dir}/images" />
- <property name="build.fonts" value="${build.dir}/images/font" />
- <property name="build.resource" value="${build.dir}/resource" />
- <property name="build.help" value="${build.dir}/help" />
- <property name="build.javadocs" value="${build.dir}/docs/API" />
- <property name="build.extensions" value="${build.dir}/extensions" />
- <property name="build.extension-javadocs" value="${build.extensions}/API" />
- <property name="build.extension-layout" value="${build.extensions}/layout" />
- <property name="build.openoffice.meta" value="${build.resource}/openoffice"/>
-
- <!-- Set the properties for source directories -->
- <property name="src.dir" value="src" />
- <property name="src.tests" value="src/java/tests" />
- <property name="txt.dir" value="src/txt" />
- <property name="java.dir" value="${src.dir}/java" />
- <property name="osx.dir" value="${src.dir}/osx" />
- <property name="win.dir" value="${src.dir}/windows" />
- <property name="resource.dir" value="${src.dir}/resource" />
- <property name="bin.dir" value="${src.dir}/scripts" />
- <property name="images.dir" value="${src.dir}/images" />
- <property name="fonts.dir" value="${src.dir}/images/font" />
- <property name="help.dir" value="${src.dir}/help" />
- <property name="extensions.dir" value="${src.dir}/extensions" />
- <property name="layout.dir" value="${src.dir}/resource/layout" />
-
-
- <!-- Set the properties for library directories -->
- <property name="library.directory" value="lib" />
-
-
- <taskdef name="jarbundler"
- classpath="${library.directory}/jarbundler-1.4.jar"
- classname="com.loomcom.ant.tasks.jarbundler.JarBundler" />
-
-
- <!-- Build classpath -->
- <path id="classpath">
- <pathelement path="${build.classes}" />
- <!--<pathelement location="${library.directory}/commons-httpclient-2.0.jar" />
- <pathelement location="${library.directory}/commons-logging.jar" />-->
- <fileset dir="${library.directory}">
- <include name="*.jar" />
- </fileset>
- </path>
-
- <!-- Runs project (e.g. in NetBeans 4) -->
- <target name="run" depends="jars">
- <java classname="net.sf.jabref.JabRef" fork="true">
- <classpath>
- <pathelement location="${build.lib}/jabref.jar"/>
- <!--<pathelement location="${library.directory}/commons-httpclient-2.0.jar" />
- <pathelement location="${library.directory}/commons-logging.jar" />-->
- <pathelement location="${library.directory}/antlr.jar" />
- <pathelement location="${library.directory}/looks-2.0.4.jar" />
- <pathelement location="${library.directory}/forms-1.0.4.jar" />
- <pathelement location="${library.directory}/spin-1.4.jar" />
- <pathelement location="${library.directory}/glazedlists-1.5.0_java14.jar" />
- <pathelement location="${library.directory}/microba.jar" />
- </classpath>
- </java>
- </target>
-
- <!-- Target used for profiling with the Netbeans profiler. -->
- <!--<target name="profile" depends="jars">
- <nbprofile classname="net.sf.jabref.JabRef">
- <classpath>
- <pathelement location="${build.lib}/jabref.jar"/>
- <pathelement location="${library.directory}/antlr.jar" />
- <pathelement location="${library.directory}/looks-2.0.4.jar" />
- <pathelement location="${library.directory}/forms-1.0.4.jar" />
- <pathelement location="${library.directory}/spin.jar" />
- <pathelement location="${library.directory}/glazedlists-1.5.0_java14.jar" />
- </classpath>
- </nbprofile>
- </target>-->
- <target name="profile" depends="jars" description="Profile JabRef">
- <fail unless="netbeans.home">This target can only run inside the NetBeans IDE.</fail>
-
- <nbprofiledirect>
- <classpath>
- <pathelement location="${build.lib}/jabref.jar"/>
- <pathelement location="${library.directory}/antlr.jar" />
- <pathelement location="${library.directory}/looks-2.0.4.jar" />
- <pathelement location="${library.directory}/forms-1.0.4.jar" />
- <pathelement location="${library.directory}/spin-1.4.jar" />
- <pathelement location="${library.directory}/glazedlists-1.5.0_java14.jar" />
- </classpath>
- </nbprofiledirect>
-
- <property environment="env"/>
- <java fork="true" classname="net.sf.jabref.JabRef" dir="${build.dir}"
- jvm="${profiler.info.jvm}">
- <jvmarg value="${profiler.info.jvmargs.agent}"/>
- <jvmarg line="${profiler.info.jvmargs}"/>
- <env key="LD_LIBRARY_PATH" path="${profiler.info.agentpath}:${env.LD_LIBRARY_PATH}"/>
- <classpath>
- <pathelement location="${build.lib}/jabref.jar"/>
- <pathelement location="${library.directory}/antlr.jar" />
- <pathelement location="${library.directory}/looks-2.0.4.jar" />
- <pathelement location="${library.directory}/forms-1.0.4.jar" />
- <pathelement location="${library.directory}/spin-1.4.jar" />
- <pathelement location="${library.directory}/glazedlists-1.5.0_java14.jar" />
-
- </classpath>
- </java>
- </target>
- <!-- Compiles project -->
- <target name="compile">
- <mkdir dir="${build.classes}" />
- <!--deprecation="on"-->
- <javac debug="off" deprecation="on" destdir="${build.classes}" source="1.4" target="1.4">
- <src path="${java.dir}"/>
- <exclude name="tests/**"/>
- <classpath>
- <pathelement path="${build.classes}" />
- <!--<pathelement location="${library.directory}/commons-httpclient-2.0.jar" />
- <pathelement location="${library.directory}/commons-logging.jar" />-->
- <pathelement location="${library.directory}/antlr.jar" />
- <pathelement location="${library.directory}/looks-2.0.4.jar" />
- <pathelement location="${library.directory}/forms-1.0.4.jar" />
- <pathelement location="${library.directory}/spin-1.4.jar" />
- <pathelement location="${library.directory}/glazedlists-1.5.0_java14.jar" />
- <pathelement location="${library.directory}/microba.jar" />
- </classpath>
- </javac>
- </target>
-
- <!-- Compiles only the tests -->
- <target name="compiletest">
- <mkdir dir="${build.classes}" />
- <!--deprecation="on"-->
- <javac srcdir="${java.dir}/tests" debug="off" destdir="${build.classes}" source="1.4" target="1.4">
- <classpath>
- <pathelement path="${build.classes}" />
- <!--<pathelement location="${library.directory}/commons-httpclient-2.0.jar" />
- <pathelement location="${library.directory}/commons-logging.jar" />-->
- <pathelement location="${library.directory}/antlr.jar" />
- <pathelement location="${library.directory}/looks-2.0.4.jar" />
- <pathelement location="${library.directory}/spin-1.4.jar" />
- </classpath>
- </javac>
-
- </target>
- <!-- Builds the OSXAdapter -->
- <target name="osx">
- <mkdir dir="${build.classes}" />
-
- <javac srcdir="${osx.dir}" debug="off" destdir="${build.classes}" target="1.4">
- </javac>
- </target>
-
- <!-- Copies in the OSXAdapter class, which is compilable only on Mac -->
- <target name="non_osx">
- <mkdir dir="${build.osx}" />
- <copy file="${library.directory}/OSXAdapter.class" todir="${build.osx}" />
- </target>
-
-
- <!-- Jars up project -->
- <target name="jars" depends="build">
- <mkdir dir="${build.lib}" />
- <mkdir dir="${build.tmp}" />
- <jar destfile="${build.lib}/jabref.jar">
- <fileset dir="${build.classes}" />
- <fileset dir="${build.tmp}" />
- <fileset dir="${build.dir}">
- <include name="images/**" />
- <include name="help/**" />
- <include name="help/de/**" />
- <include name="help/no/**" />
- <include name="resource/**" />
- </fileset>
- <fileset dir="${library.directory}">
- <include name="EndNote.zip" />
- </fileset>
-
- <fileset dir="${txt.dir}">
- <include name="gpl.txt" />
- <include name="lesser.txt" />
- <include name="apache-license.txt" />
- <include name="jgoodies.txt" />
- <include name="README" />
- </fileset>
- <manifest>
- <attribute name="Main-Class" value="net.sf.jabref.JabRef" />
-<!-- <attribute name="Main-Class" value="net.sf.jabref.gui.FieldWeightDialog" /> -->
- </manifest>
- </jar>
-
- </target>
-
- <!-- copy all necessary files and insert version informations -->
- <target name="build" depends="compile, buildinfos" description="Build project">
- <mkdir dir="${build.bin}" />
-
- <mkdir dir="${build.resource}" />
- <copy todir="${build.resource}">
- <fileset dir="${resource.dir}">
- <include name="**" />
- </fileset>
- </copy>
- <mkdir dir="${build.images}" />
- <copy todir="${build.images}">
- <fileset dir="${images.dir}">
- <include name="**" />
- </fileset>
- </copy>
-
- <!-- the fonts are used by the new about dialog -->
- <mkdir dir="${build.fonts}" />
- <copy todir="${build.fonts}">
- <fileset dir="${fonts.dir}">
- <include name="*" />
- </fileset>
- </copy>
-
- <mkdir dir="${build.help}" />
- <copy todir="${build.help}">
- <fileset dir="${help.dir}">
- <!--<include name="*" />-->
- </fileset>
- </copy>
-
- <!-- Insert version informations -->
- <replace dir="${build.help}"
- token="${jabref.placeholder.version}"
- value="${jabref.version}">
- <include name="**/About.html"/>
- </replace>
- <replace dir="${build.openoffice.meta}"
- token="${jabref.placeholder.version}"
- value="${jabref.version}">
- <include name="meta.xml"/>
- </replace>
-
-<!-- WHY ???
- <mkdir dir="${build.win}" />
- <copy file="${build.lib}/${jabref.bin}.jar" todir="${build.win}" />
- <copy todir="${build.win}">
- <fileset dir="${win.dir}">
- <include name="*" />
- </fileset>
- </copy>
--->
- </target>
-
-<!-- generate and save some build infos !!! necessary for dynamic build infos !!! -->
-<!-- todo : replace it by the replace task :-),
+ <!-- some version information -->
+ <property name="jabref.bin" value="JabRef-2.2" />
+ <property name="jabref.version" value="2.2b2" />
+ <property name="jabref.placeholder.version" value="@version@" />
+ <!-- used by replace task -->
+
+
+ <!-- Set the properties for intermediate directory -->
+ <property name="build.dir" value="build" />
+ <property name="build.classes" value="${build.dir}/classes" />
+ <property name="build.tmp" value="${build.dir}/tmp" />
+ <property name="build.osx" value="${build.dir}/classes/osxadapter" />
+ <property name="build.lib" value="${build.dir}/lib" />
+ <property name="build.win" value="${build.dir}/windows" />
+ <property name="build.images" value="${build.dir}/images" />
+ <property name="build.fonts" value="${build.dir}/images/font" />
+ <property name="build.resource" value="${build.dir}/resource" />
+ <property name="build.help" value="${build.dir}/help" />
+ <property name="build.javadocs" value="${build.dir}/docs/API" />
+ <property name="build.extensions" value="${build.dir}/extensions" />
+ <property name="build.extension-javadocs" value="${build.extensions}/API" />
+ <property name="build.extension-layout" value="${build.extensions}/layout" />
+ <property name="build.openoffice.meta" value="${build.resource}/openoffice" />
+
+ <!-- Set the properties for source directories -->
+ <property name="src.dir" value="src" />
+ <property name="src.tests" value="src/java/tests" />
+ <property name="txt.dir" value="src/txt" />
+ <property name="java.dir" value="${src.dir}/java" />
+ <property name="osx.dir" value="${src.dir}/osx" />
+ <property name="win.installer.dir" value="${src.dir}/windows/nsis" />
+ <property name="resource.dir" value="${src.dir}/resource" />
+ <property name="bin.dir" value="${src.dir}/scripts" />
+ <property name="images.dir" value="${src.dir}/images" />
+ <property name="fonts.dir" value="${src.dir}/images/font" />
+ <property name="help.dir" value="${src.dir}/help" />
+ <property name="extensions.dir" value="${src.dir}/extensions" />
+ <property name="layout.dir" value="${src.dir}/resource/layout" />
+
+ <!-- Set the properties for library directories -->
+ <property name="library.directory" value="lib" />
+
+ <!-- Load user dependent properties -->
+ <property file="build.properties" />
+ <!--
+ * For instance define the NSIS-compiler:
+ * nsis.executable="d:\prog\dev\NSIS\makensis.exe"
+ *-->
+
+ <!-- win.installer can only be build under Windows -->
+ <condition property="is.windows">
+ <and>
+ <os family="windows" />
+ <isset property="nsis.executable" />
+ </and>
+ </condition>
+
+ <taskdef name="jarbundler" classpath="${library.directory}/jarbundler-1.4.jar" classname="com.loomcom.ant.tasks.jarbundler.JarBundler" />
+
+
+ <!-- Build classpath -->
+ <path id="classpath">
+ <pathelement path="${build.classes}" />
+ <pathelement path="${build.dir}" />
+ <pathelement location="${library.directory}/antlr.jar" />
+ <pathelement location="${library.directory}/antlr-3.0b5.jar" />
+ <pathelement location="${library.directory}/looks-2.0.4.jar" />
+ <pathelement location="${library.directory}/forms-1.0.4.jar" />
+ <pathelement location="${library.directory}/spin.jar" />
+ <pathelement location="${library.directory}/glazedlists-1.7.0_java14.jar" />
+ <pathelement location="${library.directory}/microba.jar" />
+ <pathelement location="${library.directory}/PDFBox-0.7.3-dev-reduced.jar" />
+ <pathelement location="${library.directory}/JempBox-0.1.0-dev.jar" />
+ </path>
+
+ <target name="run" depends="build">
+ <java classname="net.sf.jabref.JabRef" fork="true">
+ <classpath refid="classpath"/>
+ </java>
+ </target>
+
+ <!-- Runs project -->
+ <target name="runFromJar" depends="jars">
+ <java classname="net.sf.jabref.JabRef" fork="true">
+ <classpath>
+ <pathelement location="${build.lib}/jabref.jar" />
+ </classpath>
+ </java>
+ </target>
+
+ <target name="profile" depends="jars" description="Profile JabRef">
+ <fail unless="netbeans.home">This target can only run inside the NetBeans IDE.</fail>
+
+ <nbprofiledirect>
+ <classpath refid="classpath"/>
+ </nbprofiledirect>
+
+ <property environment="env" />
+ <java fork="true" classname="net.sf.jabref.JabRef" dir="${build.dir}" jvm="${profiler.info.jvm}">
+ <jvmarg value="${profiler.info.jvmargs.agent}" />
+ <jvmarg line="${profiler.info.jvmargs}" />
+ <env key="LD_LIBRARY_PATH" path="${profiler.info.agentpath}:${env.LD_LIBRARY_PATH}" />
+ <classpath refid="classpath"/>
+ </java>
+ </target>
+
+ <!-- Compiles project -->
+ <target name="compile">
+ <mkdir dir="${build.classes}" />
+ <javac debug="on" deprecation="on" destdir="${build.classes}" source="1.4" target="1.4">
+ <src path="${java.dir}" />
+ <exclude name="tests/**" />
+ <classpath refid="classpath"/>
+ </javac>
+ </target>
+
+ <!-- Compiles only the tests -->
+ <target name="compiletest">
+ <mkdir dir="${build.classes}" />
+ <!--deprecation="on"-->
+ <javac srcdir="${java.dir}/tests" debug="off" destdir="${build.classes}" source="1.4" target="1.4">
+ <classpath refid="classpath"/>
+ </javac>
+ </target>
+
+ <!-- Builds the OSXAdapter -->
+ <target name="osx">
+ <mkdir dir="${build.classes}" />
+
+ <javac srcdir="${osx.dir}" debug="on" destdir="${build.classes}" target="1.4">
+ </javac>
+ </target>
+
+ <!-- Copies in the OSXAdapter class, which is compilable only on Mac -->
+ <target name="non_osx">
+ <mkdir dir="${build.osx}" />
+ <copy file="${library.directory}/OSXAdapter.class" todir="${build.osx}" />
+ </target>
+
+ <!-- Jars up project -->
+ <target name="jars" depends="build, unjarlib">
+ <mkdir dir="${build.lib}" />
+ <mkdir dir="${build.tmp}" />
+ <jar destfile="${build.lib}/jabref.jar">
+
+ <fileset dir="${build.classes}" />
+ <fileset dir="${build.tmp}" />
+ <fileset dir="${build.dir}">
+ <include name="images/**" />
+ <include name="help/**" />
+ <include name="help/de/**" />
+ <include name="help/no/**" />
+ <include name="resource/**" />
+ </fileset>
+ <fileset dir="${library.directory}">
+ <include name="EndNote.zip" />
+ </fileset>
+ <fileset dir="${txt.dir}">
+ <include name="gpl.txt" />
+ <include name="lesser.txt" />
+ <include name="jgoodies.txt" />
+ <include name="README" />
+ </fileset>
+ <manifest>
+ <attribute name="Main-Class" value="net.sf.jabref.JabRef" />
+ </manifest>
+ </jar>
+
+ </target>
+
+ <!-- copy all necessary files and insert version informations -->
+ <target name="build" depends="compile, buildinfos" description="Build project">
+
+ <mkdir dir="${build.resource}" />
+
+ <copy todir="${build.resource}">
+ <fileset dir="${resource.dir}">
+ <include name="**" />
+ </fileset>
+ </copy>
+ <mkdir dir="${build.images}" />
+ <copy todir="${build.images}">
+ <fileset dir="${images.dir}">
+ <include name="**" />
+ </fileset>
+ </copy>
+
+ <!-- the fonts are used by the new about dialog
+ <mkdir dir="${build.fonts}" />
+ <copy todir="${build.fonts}">
+ <fileset dir="${fonts.dir}">
+ <include name="*" />
+ </fileset>
+ </copy> -->
+
+ <mkdir dir="${build.help}" />
+ <copy todir="${build.help}">
+ <fileset dir="${help.dir}">
+ <!--<include name="*" />-->
+ </fileset>
+ </copy>
+
+ <!-- Insert version informations -->
+ <replace dir="${build.help}" token="${jabref.placeholder.version}" value="${jabref.version}">
+ <include name="**/About.html" />
+ </replace>
+ <replace dir="${build.openoffice.meta}" token="${jabref.placeholder.version}" value="${jabref.version}">
+ <include name="meta.xml" />
+ </replace>
+
+ </target>
+
+ <!-- generate and save some build infos !!! necessary for dynamic build infos !!! -->
+ <!-- todo : replace it by the replace task :-),
src/resource/build.properties = template
build/resource/build.properties = real info file
--->
- <target name="buildinfos">
- <tstamp/> <!-- get date -->
- <buildnumber/> <!-- generate new build number -> build.number -->
- <echo message="build number = ${build.number}"/>
- <!-- write the file, please do not edit this lines -->
- <echo file="${resource.dir}/build.properties">builddate=${TODAY}
+ -->
+ <target name="buildinfos">
+ <tstamp />
+ <!-- get date -->
+ <buildnumber />
+ <!-- generate new build number -> build.number -->
+ <echo message="build number = ${build.number}" />
+ <!-- write the file, please do not edit this lines -->
+ <echo file="${resource.dir}/build.properties">builddate=${TODAY}
build=${build.number}
version=${jabref.version}</echo>
- </target>
-
-
- <!-- Creates all docs -->
- <target name="docs" depends="javadocs" description="Generates all the documentation" />
-
- <!-- Creates javadocs -->
- <target name="javadocs" depends="compile" description="Generates the javadocs">
- <mkdir dir="${build.javadocs}" />
- <javadoc sourcepath="${java.dir}" destdir="${build.javadocs}" author="true" version="true" windowtitle="JabRef API" link="http://java.sun.com/j2se/1.4.1/docs/api/">
-
- <fileset dir="${java.dir}" defaultexcludes="yes">
- <include name="**/*.java" />
- </fileset>
-
- <classpath refid="classpath" />
- </javadoc>
- </target>
-
- <!-- Creates javadocs for the extensions -->
- <target name="extension-javadocs" depends="build" description="Generates the javadocs for the extensions archive">
- <mkdir dir="${build.extension-javadocs}" />
- <copy todir="${build.extension-javadocs}">
- <fileset dir="${help.dir}" defaultexcludes="yes">
- <include name="CustomExports.html" />
- <include name="CustomImports.html" />
- </fileset>
- </copy>
-
- <javadoc sourcepath="${java.dir}"
- destdir="${build.extension-javadocs}"
- author="true"
- version="true"
- windowtitle="JabRef-Extensions API"
- link="http://java.sun.com/j2se/1.4.1/docs/api/"
- Overview="${extensions.dir}/API/overview.html"
- access="protected"
- >
- <!--
- create javadoc only selectively for classes that
- users extending JabRef are likely to use
- -->
- <fileset dir="${java.dir}" defaultexcludes="yes">
- <include name="net/sf/jabref/imports/ImportFormat.java" />
- <include name="net/sf/jabref/imports/ImportFormatReader.java" />
- <include name="net/sf/jabref/BibtexEntry.java" />
- <include name="net/sf/jabref/BibtexEntryType.java" />
- <include name="net/sf/jabref/AuthorList.java" />
- <include name="net/sf/jabref/AuthorList.java" />
- <include name="net/sf/jabref/export/layout/LayoutFormatter.java" />
- </fileset>
-
- <classpath refid="classpath" />
- </javadoc>
- </target>
-
- <!-- Creates javadocs for the extensions -->
- <target name="extensions" depends="extension-javadocs" description="Generates the extensions archive">
- <!-- copy examples -->
- <copy todir="${build.extensions}">
- <fileset dir="${java.dir}">
- <include name="net/sf/jabref/export/layout/format/CurrentDate.java"/>
- <include name="net/sf/jabref/export/layout/format/ToLowerCase.java"/>
- <include name="net/sf/jabref/export/layout/format/HTMLChars.java"/>
- <include name="net/sf/jabref/imports/*Importer.java"/>
- </fileset>
- </copy>
- <mkdir dir="${build.extension-layout}" />
- <copy todir="${build.extension-layout}">
- <fileset dir="${layout.dir}" />
- </copy>
- <copy todir="${build.extensions}">
- <fileset dir="${extensions.dir}" />
- <filterset>
- <filter token="version" value="${jabref.version}"/>
- </filterset>
- </copy>
- <!-- create extensions-zip file -->
- <zip destfile="${build.dir}/jabref-extensions.zip">
- <zipfileset dir="${build.extensions}" prefix="jabref-extensions"/>
- </zip>
- </target>
-
- <target name="clean" description="Clean project">
- <delete dir="${build.dir}" />
- </target>
-
- <!-- Unpacks jar needed jar files from lib directory into temp directory. -->
- <target name="unjarlib" description="Unpacks jars from library">
- <mkdir dir="${build.tmp}"/>
- <!--<unjar src="${library.directory}/commons-httpclient-2.0.jar" dest="${build.tmp}" />
- <unjar src="${library.directory}/commons-logging.jar" dest="${build.tmp}" />-->
- <unjar src="${library.directory}/antlr.jar" dest="${build.tmp}" />
- <!-- <unjar src="${library.directory}/plastic-1.2.1.jar" dest="${build.classes}" />-->
- <unjar src="${library.directory}/looks-2.0.4.jar" dest="${build.tmp}" />
- <unjar src="${library.directory}/forms-1.0.4.jar" dest="${build.tmp}" />
- <unjar src="${library.directory}/spin-1.4.jar" dest="${build.tmp}" />
- <unjar src="${library.directory}/glazedlists-1.5.0_java14.jar" dest="${build.tmp}" />
- <unjar src="${library.directory}/microba.jar" dest="${build.tmp}" />
- <delete dir="${build.tmp}/META-INF"/>
- <!-- rename the microba license file -->
- <move file="${build.tmp}/license.txt" tofile="${build.tmp}/microba-license.txt"/>
- </target>
-
-
- <target name="osxjar">
- <jarbundler dir="${build.lib}"
- name="JabRef"
- mainclass="net.sf.jabref.JabRef"
- jars="${build.lib}/${jabref.bin}.jar"
- icon="${images.dir}/JabRef-Logo.icns"
- version="${jabref.version}"
- jvmversion="1.4+"
- stubfile="${library.directory}/JavaApplicationStub" />
-
- </target>
-
-
- <!--++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ </target>
+
+
+ <!-- Creates all docs -->
+ <target name="docs" depends="javadocs" description="Generates all the documentation" />
+
+ <!-- Creates javadocs -->
+ <target name="javadocs" depends="compile" description="Generates the javadocs">
+ <mkdir dir="${build.javadocs}" />
+ <javadoc sourcepath="${java.dir}" destdir="${build.javadocs}" author="true" version="true" windowtitle="JabRef API" link="http://java.sun.com/j2se/1.4.1/docs/api/">
+
+ <fileset dir="${java.dir}" defaultexcludes="yes">
+ <include name="**/*.java" />
+ </fileset>
+
+ <classpath refid="classpath" />
+ </javadoc>
+ </target>
+
+ <!-- Creates javadocs for the extensions -->
+ <target name="extension-javadocs" depends="build" description="Generates the javadocs for the extensions archive">
+ <mkdir dir="${build.extension-javadocs}" />
+ <copy todir="${build.extension-javadocs}">
+ <fileset dir="${help.dir}" defaultexcludes="yes">
+ <include name="CustomExports.html" />
+ <include name="CustomImports.html" />
+ </fileset>
+ </copy>
+
+ <javadoc sourcepath="${java.dir}" destdir="${build.extension-javadocs}" author="true" version="true" windowtitle="JabRef-Extensions API" link="http://java.sun.com/j2se/1.4.1/docs/api/" Overview="${extensions.dir}/API/overview.html" access="protected">
+ <!--
+ create javadoc only selectively for classes that
+ users extending JabRef are likely to use
+ -->
+ <fileset dir="${java.dir}" defaultexcludes="yes">
+ <include name="net/sf/jabref/imports/ImportFormat.java" />
+ <include name="net/sf/jabref/imports/ImportFormatReader.java" />
+ <include name="net/sf/jabref/BibtexEntry.java" />
+ <include name="net/sf/jabref/BibtexEntryType.java" />
+ <include name="net/sf/jabref/AuthorList.java" />
+ <include name="net/sf/jabref/AuthorList.java" />
+ <include name="net/sf/jabref/export/layout/LayoutFormatter.java" />
+ </fileset>
+
+ <classpath refid="classpath" />
+ </javadoc>
+ </target>
+
+ <!-- Creates javadocs for the extensions -->
+ <target name="extensions" depends="extension-javadocs" description="Generates the extensions archive">
+ <!-- copy examples -->
+ <copy todir="${build.extensions}">
+ <fileset dir="${java.dir}">
+ <include name="net/sf/jabref/export/layout/format/CurrentDate.java" />
+ <include name="net/sf/jabref/export/layout/format/ToLowerCase.java" />
+ <include name="net/sf/jabref/export/layout/format/HTMLChars.java" />
+ <include name="net/sf/jabref/imports/*Importer.java" />
+ </fileset>
+ </copy>
+ <mkdir dir="${build.extension-layout}" />
+ <copy todir="${build.extension-layout}">
+ <fileset dir="${layout.dir}" />
+ </copy>
+ <copy todir="${build.extensions}">
+ <fileset dir="${extensions.dir}" />
+ <filterset>
+ <filter token="version" value="${jabref.version}" />
+ </filterset>
+ </copy>
+ <!-- create extensions-zip file -->
+ <zip destfile="${build.dir}/jabref-extensions.zip">
+ <zipfileset dir="${build.extensions}" prefix="jabref-extensions" />
+ </zip>
+ </target>
+
+ <target name="clean" depends="win.installer.clean" description="Clean project">
+ <delete dir="${build.dir}" />
+ </target>
+
+ <!-- Unpacks jar needed jar files from lib directory into temp directory. -->
+ <target name="unjarlib" description="Unpacks jars from library">
+ <mkdir dir="${build.tmp}" />
+ <unjar src="${library.directory}/antlr.jar" dest="${build.tmp}" />
+ <unjar src="${library.directory}/antlr-3.0b5.jar" dest="${build.tmp}" />
+ <unjar src="${library.directory}/looks-2.0.4.jar" dest="${build.tmp}" />
+ <unjar src="${library.directory}/forms-1.0.4.jar" dest="${build.tmp}" />
+ <unjar src="${library.directory}/spin.jar" dest="${build.tmp}" />
+ <unjar src="${library.directory}/glazedlists-1.7.0_java14.jar" dest="${build.tmp}" />
+ <unjar src="${library.directory}/microba.jar" dest="${build.tmp}" />
+ <unjar src="${library.directory}/PDFBox-0.7.3-dev-reduced.jar" dest="${build.tmp}" />
+ <unjar src="${library.directory}/JempBox-0.1.0-dev.jar" dest="${build.tmp}" />
+ <delete dir="${build.tmp}/META-INF" />
+ <!-- rename the microba license file -->
+ <move file="${build.tmp}/license.txt" tofile="${build.tmp}/microba-license.txt" />
+ </target>
+
+
+ <target name="osxjar">
+ <jarbundler dir="${build.lib}" name="JabRef" mainclass="net.sf.jabref.JabRef" jars="${build.lib}/jabref.jar" icon="${images.dir}/JabRef-Logo.icns" version="${jabref.version}" jvmversion="1.4+" stubfile="${library.directory}/JavaApplicationStub" />
+ </target>
+
+
+ <!--++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-->
+ <!-- Build Windows Installer -->
+ <!-- -->
+ <!-- Don't forget to set nsis.executable property -->
+ <!--++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-->
+
+ <target name="win.installer.clean" description="Delete Installer and Exe-Wrapper + Temp-files">
+ <delete dir="${win.installer.dir}/dist" />
+ <delete file="${win.installer.dir}/JabRefSetup.exe" />
+ </target>
+
+ <target name="win.installer.prepare" depends="jars" if="is.windows" description="Copy files in place to be used by the installer">
+ <!-- Gather everything that will go into the installer in dist -->
+ <mkdir dir="${win.installer.dir}/dist" />
+ <!-- <copy file="${build.lib}/${jabref.bin}.jar"
+ todir="${win.installer.dir}/dist" /> -->
+ <copy todir="${win.installer.dir}/dist">
+ <fileset dir="${txt.dir}">
+ <include name="gpl.txt" />
+ <include name="lesser.txt" />
+ <include name="README" />
+ </fileset>
+ </copy>
+ </target>
+
+ <target name="win.installer.exewrapper" depends="win.installer.prepare" if="is.windows" description="Create Exe-Wrapper">
+ <exec dir="." executable="${nsis.executable}" failonerror="true">
+ <arg line="'/DJARFILE=${jabref.bin}.jar' '/DVERSION=${jabref.version}' '/DAPPICON=../../../${images.dir}/JabRef.ico' ${win.installer.dir}/launcher.nsi" />
+ </exec>
+ </target>
+
+ <target name="win.installer.build" depends="win.installer.exewrapper" if="is.windows" description="Create Windows-Installer.">
+ <exec dir="." executable="${nsis.executable}" failonerror="true">
+ <arg line="'/DVERSION=${jabref.version}' ${win.installer.dir}/setup.nsi" />
+ </exec>
+ </target>
+
+ <!--++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
What's about the software design ?!;-)
-+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-->
-
- <target name="pmd" description="SOFTWAREDESIGN: Project Mess Detector !;-)">
- <echo>Checking Project Mess Detection (PMD) rulesets.</echo>
- <taskdef name="pmd" classname="net.sourceforge.pmd.ant.PMDTask">
- <classpath>
- <pathelement path="${classpath}" />
- <fileset dir="${library.directory}">
- <include name="*.jar" />
- </fileset>
- </classpath>
- </taskdef>
- <!-- allowed Pretty Much Done rulsets -->
- <!-- rulesets/basic.xml -->
- <!-- rulesets/braces.xml -->
- <!-- rulesets/codesize.xml-->
- <!-- rulesets/controversial.xml-->
- <!-- rulesets/coupling.xml-->
- <!-- rulesets/design.xml -->
- <!-- rulesets/experimental.xml -->
- <!-- rulesets/favorites.xml -->
- <!-- rulesets/imports.xml -->
- <!-- rulesets/naming.xml -->
- <!-- rulesets/javabean.xml -->
- <!-- rulesets/junit.xml -->
- <!-- rulesets/scratchpad.xml -->
- <!-- rulesets/strictexception.xml -->
- <!-- rulesets/strings.xml -->
- <!-- rulesets/unusedcode.xml -->
-
- <pmd rulesetfiles="rulesets/unusedcode.xml,rulesets/basic.xml" failonerror="no">
- <formatter type="html" toFile="${build.dir}/pmd_report.html" />
- <fileset dir="${src.dir}">
- <include name="**/*.java" />
- </fileset>
- </pmd>
-
- <!-- check for duplicated code -->
- <echo>WARNING: use environment variable: ANT_OPTS=-Xmx512m or this task will fail.</echo>
- <echo>Checking for duplicated code using the Copy/Paste Detector (CPD).</echo>
- <taskdef name="cpd" classname="net.sourceforge.pmd.cpd.CPDTask">
- <classpath>
- <pathelement path="${classpath}" />
- <fileset dir="${library.directory}">
- <include name="*.jar" />
- </fileset>
- </classpath>
- </taskdef>
- <cpd format="text" minimumTokenCount="100" outputFile="${build.dir}/duplicated_code_report.txt">
- <fileset dir="${src.dir}">
- <include name="**/*.java" />
- </fileset>
- </cpd>
- </target>
-
-
- <target name="javancss" description="SOFTWAREDESIGN: Determining the NCSS and CCN code metrics for JOELib.">
- <taskdef name="javancss" classname="javancss.JavancssAntTask">
- <classpath>
- <pathelement path="${classpath}" />
- <fileset dir="${library.directory}">
- <include name="*.jar" />
- </fileset>
- </classpath>
- </taskdef>
- <echo>Cyclomatic
+ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-->
+
+ <target name="pmd" description="SOFTWAREDESIGN: Project Mess Detector !;-)">
+ <echo>Checking Project Mess Detection (PMD) rulesets.</echo>
+ <taskdef name="pmd" classname="net.sourceforge.pmd.ant.PMDTask">
+ <classpath>
+ <pathelement path="${classpath}" />
+ <fileset dir="${library.directory}">
+ <include name="*.jar" />
+ </fileset>
+ </classpath>
+ </taskdef>
+ <!-- allowed Pretty Much Done rulsets -->
+ <!-- rulesets/basic.xml -->
+ <!-- rulesets/braces.xml -->
+ <!-- rulesets/codesize.xml-->
+ <!-- rulesets/controversial.xml-->
+ <!-- rulesets/coupling.xml-->
+ <!-- rulesets/design.xml -->
+ <!-- rulesets/experimental.xml -->
+ <!-- rulesets/favorites.xml -->
+ <!-- rulesets/imports.xml -->
+ <!-- rulesets/naming.xml -->
+ <!-- rulesets/javabean.xml -->
+ <!-- rulesets/junit.xml -->
+ <!-- rulesets/scratchpad.xml -->
+ <!-- rulesets/strictexception.xml -->
+ <!-- rulesets/strings.xml -->
+ <!-- rulesets/unusedcode.xml -->
+
+ <pmd rulesetfiles="rulesets/unusedcode.xml,rulesets/basic.xml" failonerror="no">
+ <formatter type="html" toFile="${build.dir}/pmd_report.html" />
+ <fileset dir="${src.dir}">
+ <include name="**/*.java" />
+ </fileset>
+ </pmd>
+
+ <!-- check for duplicated code -->
+ <echo>WARNING: use environment variable: ANT_OPTS=-Xmx512m or this task will fail.</echo>
+ <echo>Checking for duplicated code using the Copy/Paste Detector (CPD).</echo>
+ <taskdef name="cpd" classname="net.sourceforge.pmd.cpd.CPDTask">
+ <classpath>
+ <pathelement path="${classpath}" />
+ <fileset dir="${library.directory}">
+ <include name="*.jar" />
+ </fileset>
+ </classpath>
+ </taskdef>
+ <cpd format="text" minimumTokenCount="100" outputFile="${build.dir}/duplicated_code_report.txt">
+ <fileset dir="${src.dir}">
+ <include name="**/*.java" />
+ </fileset>
+ </cpd>
+ </target>
+
+
+ <target name="javancss" description="SOFTWAREDESIGN: Determining the NCSS and CCN code metrics for JOELib.">
+ <taskdef name="javancss" classname="javancss.JavancssAntTask">
+ <classpath>
+ <pathelement path="${classpath}" />
+ <fileset dir="${library.directory}">
+ <include name="*.jar" />
+ </fileset>
+ </classpath>
+ </taskdef>
+ <echo>Cyclomatic
Complexity Ease of Risk
Number (CCN) maintenance
(McCabe metric)
@@ -513,46 +490,35 @@ Number (CCN) maintenance
>50, unstable very hard very high
</echo>
- <javancss srcdir="${src.dir}" includes="**/*.java" excludes="jama/**/*.java, jmat/**/*.java, cformat/**/*.java" abortOnFail="false" ccnPerFuncMax="30" generateReport="true" outputfile="${build.dir}/javancss_report.plain" format="plain" packageMetrics="true" classMetrics="false" functionMetrics="false" />
- </target>
-
- <target name="jalopy" description="SOFTWAREDESIGN: source code formatter using the JOELib convention.">
- <taskdef name="jalopy" classname="de.hunsicker.jalopy.plugin.ant.AntPlugin">
- <classpath>
- <pathelement path="${classpath}" />
- <fileset dir="${library.directory}">
- <include name="*.jar" />
- </fileset>
- </classpath>
- </taskdef>
- <jalopy fileformat="unix" convention="${src.dir}/java/jalopy.format.convention.xml" history="file" historymethod="adler32" loglevel="error" threads="2" classpathref="classpath" backup="bak">
- <fileset dir="${src.dir}">
- <include name="java/net/sf/jabref/**/*.java" />
- </fileset>
- </jalopy>
- </target>
-
- <target name="test">
- <junit printsummary="yes" fork="yes" haltonfailure="no">
- <batchtest fork="yes" todir="/tmp/testres">
- <fileset dir="${build.classes}">
- <include name="**/*Tester.class" />
- <include name="**/*Test.class" />
- </fileset>
- </batchtest>
-
- <classpath>
- <pathelement location="${build.lib}/jabref.jar" />
- <!--<pathelement location="${library.directory}/commons-httpclient-2.0.jar" />
- <pathelement location="${library.directory}/commons-logging.jar" />-->
- <pathelement location="${library.directory}/antlr.jar" />
- <pathelement location="${library.directory}/looks-2.0.4.jar" />
- <pathelement location="${library.directory}/looks-2.0.4.jar" />
- <pathelement location="${library.directory}/spin-1.4.jar" />
- </classpath>
-
- <!--<test name="tests.net.sf.jabref.export.layout.format.AuthorLastFirstAbbreviatorTester"/>-->
- </junit>
- </target>
-
+ <javancss srcdir="${src.dir}" includes="**/*.java" excludes="jama/**/*.java, jmat/**/*.java, cformat/**/*.java" abortOnFail="false" ccnPerFuncMax="30" generateReport="true" outputfile="${build.dir}/javancss_report.plain" format="plain" packageMetrics="true" classMetrics="false" functionMetrics="false" />
+ </target>
+
+ <target name="jalopy" description="SOFTWAREDESIGN: source code formatter using the JOELib convention.">
+ <taskdef name="jalopy" classname="de.hunsicker.jalopy.plugin.ant.AntPlugin">
+ <classpath>
+ <pathelement path="${classpath}" />
+ <fileset dir="${library.directory}">
+ <include name="*.jar" />
+ </fileset>
+ </classpath>
+ </taskdef>
+ <jalopy fileformat="unix" convention="${src.dir}/java/jalopy.format.convention.xml" history="file" historymethod="adler32" loglevel="error" threads="2" classpathref="classpath" backup="bak">
+ <fileset dir="${src.dir}">
+ <include name="java/net/sf/jabref/**/*.java" />
+ </fileset>
+ </jalopy>
+ </target>
+
+ <target name="test">
+ <junit printsummary="yes" fork="yes" haltonfailure="no">
+ <batchtest fork="yes" todir="/tmp/testres">
+ <fileset dir="${build.classes}">
+ <include name="**/*Tester.class" />
+ <include name="**/*Test.class" />
+ </fileset>
+ </batchtest>
+ <classpath refid="classpath"/>
+ </junit>
+ </target>
+
</project>
diff --git a/lib/JempBox-0.1.0-dev.jar b/lib/JempBox-0.1.0-dev.jar
new file mode 100644
index 0000000..735639d
Binary files /dev/null and b/lib/JempBox-0.1.0-dev.jar differ
diff --git a/lib/PDFBox-0.7.3-dev-reduced.jar b/lib/PDFBox-0.7.3-dev-reduced.jar
new file mode 100644
index 0000000..ffb9019
Binary files /dev/null and b/lib/PDFBox-0.7.3-dev-reduced.jar differ
diff --git a/lib/antlr-3.0b5.jar b/lib/antlr-3.0b5.jar
new file mode 100644
index 0000000..5449eb2
Binary files /dev/null and b/lib/antlr-3.0b5.jar differ
diff --git a/lib/glazedlists-1.5.0_java14.jar b/lib/glazedlists-1.5.0_java14.jar
deleted file mode 100644
index 8af40f5..0000000
Binary files a/lib/glazedlists-1.5.0_java14.jar and /dev/null differ
diff --git a/lib/glazedlists-1.7.0_java14.jar b/lib/glazedlists-1.7.0_java14.jar
new file mode 100644
index 0000000..1d2611b
Binary files /dev/null and b/lib/glazedlists-1.7.0_java14.jar differ
diff --git a/lib/spin-1.4.jar b/lib/spin-1.4.jar
deleted file mode 100644
index a683361..0000000
Binary files a/lib/spin-1.4.jar and /dev/null differ
diff --git a/lib/spin.jar b/lib/spin.jar
new file mode 100644
index 0000000..9d7f0e4
Binary files /dev/null and b/lib/spin.jar differ
diff --git a/src/help/About.html b/src/help/About.html
index 9a88101..67e2be5 100755
--- a/src/help/About.html
+++ b/src/help/About.html
@@ -21,7 +21,9 @@ Michel Baylac,
Guillaume Gardey,
Cyrille d'Haese,
Raik Nagel,
+Christopher Oezbek,
Ellen Reitmayr,
+Gert Renckens,
Andreas Rudert,
Michael Spiegel,
Ulrik Stervbo,
@@ -43,15 +45,17 @@ Bernd Kalbfuss,
Martin Kähmer,
Ervin Kolenovic,
Krzysztof A. Kościuszkiewicz,
+Christian Kopf,
Jeffrey Kuhn,
Alex Montgomery,
-Christopher Oezbek,
John Relph,
Moritz Ringler,
Andreas Rudert,
+Mark Schenk,
Rudolf Seemann,
Toralf Senger,
Mike Smoot,
+Ulrich Stärk,
Martin Stolle,
David Weitzman,
Seb Wills,
diff --git a/src/help/CiteSeerHelp.html b/src/help/CiteSeerHelp.html
index 4c33cb1..cda4f08 100644
--- a/src/help/CiteSeerHelp.html
+++ b/src/help/CiteSeerHelp.html
@@ -46,4 +46,5 @@ at <p> http://java.sun.com/j2se/1.4.2/docs/guide/net/properties.html
<p>
-</HTML>
+</body>
+</html>
diff --git a/src/help/Contents.html b/src/help/Contents.html
index b503538..e2ae5b8 100755
--- a/src/help/Contents.html
+++ b/src/help/Contents.html
@@ -16,30 +16,23 @@
<a href="CustomEntriesHelp.html">Customizing entry types</a><br>
<a href="GeneralFields.html">Customizing general fields</a><br>
<a href="EndNoteFilters.html">The EndNote import/export filter set</a><br>
- <a href="OpenOfficeHelp.html">Using JabRef bibliographies in OpenOffice.org</a><br>
<a href="EntryEditorHelp.html">Entry editor</a><br>
+ <a href="TimeStampHelp.html">Entry time stamps</a><br>
<a href="CiteSeerHelp.html">Fetching entries from <em>CiteSeer</em></a><br>
<a href="MedlineHelp.html">Fetching entries from <em>Medline</em></a><br>
<a href="IEEEXploreHelp.html">Fetching entries from <em>IEEExplore</em></a><br>
<a href="ContentSelectorHelp.html">Field content selector</a><br>
- <a href="JournalAbbreviations.html">Journal abbreviations</a><br>
<a href="GroupsHelp.html">Help on using <em>Groups</em></a><br>
+ <a href="ImportInspectionDialog.html">Import inspection window</a><br>
+ <a href="JournalAbbreviations.html">Journal abbreviations</a><br>
<a href="BaseFrameHelp.html">The JabRef main window</a><br>
- <a href="MarkingHelp.html">Marking entries</a><br>
<a href="OwnerHelp.html">The 'owner' field</a><br>
+ <a href="MarkingHelp.html">Marking entries</a><br>
+ <a href="OpenOfficeHelp.html">Using JabRef bibliographies in OpenOffice.org</a><br>
<a href="ExternalFiles.html">PDF/PS/URL/DOI links in JabRef</a><br>
<a href="SearchHelp.html">Searching in JabRef</a><br>
<a href="StringEditorHelp.html">String editor</a><br>
- <a href="TimeStampHelp.html">Entry time stamps</a><br>
- <a href="ImportInspectionDialog.html">Import inspection window</a><br>
-
-
-
-
-
-
-
-
-
+ <a href="PreviewHelp.html">Entry preview setup</a><br>
+ <a href="XMPHelp.html">XMP metadata support in JabRef</a>
</HTML>
diff --git a/src/help/CustomExports.html b/src/help/CustomExports.html
index 07d468d..29d4f69 100644
--- a/src/help/CustomExports.html
+++ b/src/help/CustomExports.html
@@ -99,9 +99,13 @@ This can be useful for some fomatters, e.g. the CurrentDate formatter (described
<ul>
<li><code>HTMLChars</code> : replaces TeX-specific special characters (e.g. {\^a} or {\"{o}})
with their HTML representations.
+<li><code>HTMLParagraphs</code> : interprets two consecutive newlines (e.g. \n \n) as the beginning of a new paragraph and creates paragraph-html-tags accordingly.
<li><code>XMLChars</code> : replaces TeX-specific special characters (e.g. {\^a} or {\"{o}})
with their XML representations.
+
<li><code>CreateDocBookAuthors</code> : formats the author field in DocBook style.
+<li><code>CreateDocBookEditors</code> : to be documented.
+
<li><code>CurrentDate</code> : outputs the current date. With no argument, this formatter outputs the
current date and time in the format "yyyy.MM.dd hh:mm:ss z" (date, time and time zone). By giving a
different format string as argument, the date format can be customized. E.g.
@@ -109,17 +113,39 @@ This can be useful for some fomatters, e.g. the CurrentDate formatter (described
<li><code>AuthorFirstFirst</code> : formats author/editor fields with the first names first.
<li><code>AuthorFirstFirstCommas</code> : formats author/editor fields with the first names first, and deliminated by commas.
+<li><code>AuthorFirstAbbrLastCommas</code> : to be documented.
+<li><code>AuthorFirstAbbrLastOxfordCommas</code> : to be documented.
+<li><code>AuthorFirstLastOxfordCommas </code> : to be documented.
+
<li><code>AuthorLastFirst</code> : formats author/editor fields with the last names first.
<li><code>AuthorLastFirstAbbreviator</code> : abbreviates first and middle names of all authors. This formatter requires AuthorLastFirst
to have been run earlier.
-<li><code>AuthorAndsReplacer</code> : replaces "and" between names with ";", and "&" between the last two.
+<li><code>AuthorLastFirstCommas</code> : to be documented.
+<li><code>AuthorLastFirstOxfordCommas</code> : to be documented.
+<li><code>AuthorLastFirstAbbrCommas</code> : to be documented.
+<li><code>AuthorLastFirstAbbrOxfordCommas</code> : to be documented.
+
+<li><code>AuthorAndsReplacer</code> : replaces "and" between names with ";", and "&" between the last two.
<li><code>AuthorAndsCommaReplacer</code> : replaces "and" between names with ",", and "&" between the last two.
+<li><code>AuthorOrgSci</code> : first author is in "last, first" all others in "first last". First names are abbreviated.
+<li><code>AuthorAbbreviator : to be documented.
+
+<li><code>NoSpaceBetweenAbbreviations</code> : spaces between multiple abbreviated first names are removed.
<li><code>FormatPagesForHTML</code> : replaces "--" with "-".
<li><code>FormatPagesForXML</code> : replaces "--" with an XML en-dash.
+
<li><code>RemoveBrackets</code> : removes all curly brackets "{" or "}".
+<li><code>RemoveBracketsAddComma</code> : to be documented.
+<li><code>RemoveWhitespace</code> : to be documented.
<li><code>RemoveLatexCommands</code> : removes LaTeX commands like <code>\em</code>, <code>\textbf</code>, etc. If
used together with <code>HTMLChars</code> or <code>XMLChars</code>, this formatter should be called last.
<li><code>ToLowerCase</code> : turns all characters into lower case.
+
+<li><code>CompositeFormat</code> : to be documented.
+<li><code>GetOpenOfficeType</code> : to be documented.
+<li><code>RTFChars</code> : to be documented.
+<li><code>ResolvePDF</code> : to be documented.
+
</ul>
<p>If none of the available formatters can do what you want to achieve, you can add your own by implementing
@@ -127,7 +153,67 @@ to have been run earlier.
into the <code>net.sf.jabref.export.layout.format</code> package, you can call the formatter by its
class name only, like with the standard formatters. Otherwise, you must call the formatter by its fully
qualified name (including package name). In any case, the formatter must be in your classpath when running
- JabRef.
+ JabRef.</p>
+
+<a name="NameFormatter">
+<H2>Using Custom Name Formatters</H2>
+
+<p>With JabRef 2.2 it is now possible to define custom name formatters using the bibtex-sty-file syntax.
+This allows ultimate flexibility, but is a cumbersome to write</p>
+<p>You can define your own formatter in the preference tab "Name Formatter" using the following format
+and then use it with the name given to it as any other name formatter</p>
+
+<code>
+ <case1>@<range11>@<format>@<range12>@<format>@<range13>...@@<br>
+ <case2>@<range21>@... and so on.
+</code>
+
+<p>This format first splits the task to format a list of author into cases depending on
+how many authors there are (this is since some formats differ depending on how many authors there are).
+Each individual case is separated by @@ and contains instructions on how to format each author in the case.
+These instructions are separated by a @.</p>
+<p>Cases are identified using integers (1,2,3,etc.) or the character * (matches any number of authors) and will tell
+the formatter to apply the following instructions if there are a number of less or equal of authors given.
+</p>
+<p>
+ Ranges are either <code><integer>..<integer></code>, <code><integer></code> or the character <code>*</code> using a 1 based index for indexing
+ authors from the given list of authors. Integer indexes can be negative to denote them to start from
+ the end of the list where -1 is the last author.
+</p>
+
+<p>For instance with an authorlist of "Joe Doe and Mary Jane and Bruce Bar and Arthur Kay":</p>
+<ul>
+ <li> 1..3 will affect Joe, Mary and Bruce</li>
+ <li> 4..4 will affect Arthur </li>
+ <li> * will affect all of them</li>
+ <li> 2..-1 will affect Mary, Bruce and Arthur</li>
+</ul>
+
+<p>The <code><format></code>-strings use the Bibtex formatter format:</p>
+
+<p>
+ The four letter v, f, l, j indicate the name parts von, first, last, jr which
+ are used within curly braces. A single letter v, f, l, j indicates that the name should be abbreviated.
+ If one of these letters or letter pairs is encountered JabRef will output all the respective names
+ (possibly abbreviated), but the whole expression in curly braces is only printed if the name part exists.</p>
+
+<p>For instance if the format is "{ll} {vv {von Part}} {ff}" and the names are "Mary Kay and John von Neumann",
+ then JabRef will output "Kay Mary" (with two space between last and first) and "Neuman von von Part John".</p>
+
+<p>I give two examples but would rather point you to the bibtex documentation.</p>
+
+<p>Small example: <code>"{ll}, {f.}"</code> will turn <code>"Joe Doe"</code> into <code>"Doe, J."</code></p>
+
+<p>Large example:</p>
+<blockquote>
+<p> To turn: </p>
+<p><code>"Joe Doe and Mary Jane and Bruce Bar and Arthur Kay"</code></p>
+<p>into</p>
+<p><code>"Doe, J., Jane, M., Bar, B. and Kay, A."</code></p>
+<p>you would use</p>
+<p><code>1@*@{ll}, {f}.@@2 at 1@{ll}, {f}. at 2@ and {ll}, {f}.@@*@1..-3@{ll}, {f}., @-2@{ll}, {f}. at -1@ and {ll}, {f}.</code></p>
+</blockquote>
+<p>If somebody would like to write a better tutorial about this: Write a mail to one of the JabRef mailinglists!</p>
<H3>Conditional output</H3>
@@ -159,7 +245,7 @@ field referred in the curly braces has changed value.
your entries based on keyword. Now use the following commands to group by keyword:
<p><code>\begingroup{keywords}New Category: \format[HTMLChars]{\keywords}
-<br> \endgroup{keywords}</code>
+<br> \endgroup{keywords}</code>
<H2>Sharing your work</H2>
diff --git a/src/help/ExternalFiles.html b/src/help/ExternalFiles.html
index 91448bf..61ea300 100644
--- a/src/help/ExternalFiles.html
+++ b/src/help/ExternalFiles.html
@@ -49,5 +49,37 @@ You can set PDF and PS directories specific to a database (<b>File -> Database p
These directories will supersede the main directories.
</P>
-
-</HTML>
+<a name="RegularExpressionSearch">
+<H2>Using Regular Expression Search for Auto-Linking</H2>
+</a>
+<p>
+In the previous sections JabRef's auto-linking feature was described: If you choose names for your files
+corresponding to the bibtex-key + plus the extension, JabRef will automatically be able to find it.
+</p><p>
+Since JabRef 2.2 it is now possible to have greater flexibility in the naming scheme by using
+regular expression for the search. In most cases it should not be necessary though to adapt the given default.
+</p><p>
+If you open the external preferences
+(Options -> Preferences -> External Programs) you will find an option called "Use Regular Expression Search".
+Checking this option will allow you to enter your own regular expression for search in the PDF directories.
+</p><p>
+The following syntax is understood:
+</p>
+<ul>
+ <li><code>*</code> - Search in all immediate all subdirectories excluding the current
+ and any deeper subdirectories.</li>
+ <li><code>**</code> - Search in all subdirectories recursively AND the current directory.</li>
+ <li><code>.</code> and <code>..</code> - The current directory and the parent directory.</li>
+ <li><code>[title]</code> - All expressions in square brackets are replace by the corresponding field in the current
+ entry</li>
+ <li><code>[extension]</code> - Is replaced by the file-extension of the field you are using.</li>
+ <li>All other text is interpreted as a regular expression. But caution: You need to escape backslashes by putting
+ two backslashes after each other to not confuse them with the path-separator.</li>
+</ul>
+<p>
+The default for searches is <code>**/.*[bibtexkey].*\\.[extension]</code>. As you can see this will
+search in all subdirectories of the extension-based directory (for instance in the PDF directory) for any file that has the correct extension and
+contains the Bibtex-key somewhere.
+</p>
+</body>
+</html>
diff --git a/src/help/PreviewHelp.html b/src/help/PreviewHelp.html
index 491dd20..39b6b15 100644
--- a/src/help/PreviewHelp.html
+++ b/src/help/PreviewHelp.html
@@ -8,7 +8,7 @@
The entry preview is created using the same mechanism as used by the
<a href="CustomExports.html">Custom export filter</a> facility. When previewed,
an entry is processed using one of the two alternative layouts (you can switch between
-the two layouts by pressing CTRL-F9) to produce HTML code which is displayed by the
+the two layouts by pressing F9) to produce HTML code which is displayed by the
preview panel.
To modify the appearance and contents of the preview you need to edit the preview layouts
diff --git a/src/help/SearchHelp.html b/src/help/SearchHelp.html
index 6503489..f9ca60d 100644
--- a/src/help/SearchHelp.html
+++ b/src/help/SearchHelp.html
@@ -33,8 +33,12 @@ search".
<H2>Normal</H2>
-In a normal search, the program searches your database for all occurences of your
-search string, once you press ENTER. All entries that don't match are hidden, leaving for display the matching entries only (filter mode), or are grayed-out (float mode).
+In a normal search, the program searches your database for all occurences of the words in your
+search string, once you press ENTER. Only entries containing all words will be considered matches.
+To search for sequences of words, enclose the sequences in double quotes. For instance, the query
+<b>progress "marine aquaculture"</b> will match entries containing both the word "progress" and the
+phrase "marine aquaculture". All entries that don't match are hidden, leaving for display the
+matching entries only (filter mode), or are grayed-out (float mode).
To stop displaying the search results, press ESC or click "Clear search".
<a name="advanced"><H2>Field specification, logical operators</H2>
diff --git a/src/help/XMPHelp.html b/src/help/XMPHelp.html
new file mode 100644
index 0000000..d8d937f
--- /dev/null
+++ b/src/help/XMPHelp.html
@@ -0,0 +1,114 @@
+<HTML>
+
+<BODY text="#275856">
+<basefont size="4" color="#2F4958" face="arial">
+
+<H1>XMP metadata support in JabRef</H1>
+<p>
+XMP is a standard created by Adobe Systems for storing metadata (data about data) in files.
+An well known example for metadata are MP3 tags, which can be used to describe artist, album and song name
+of a MP3 file. Adding metadata to MP3 helps other people to identify the songs correctly independent of file-name
+and can provide means for software (MP3 players for instance) to sort and group songs.
+</p>
+<p>
+With XMP-support the JabRef team tries to bring the advantages of metadata to the world of reference managers.
+You can now choose to "Write XMP" metadata in the General Tab of JabRef, which will put all the Bibtex information
+into the PDF. If you then email this PDF to a collegue she can just drag the file into JabRef and all information
+that you entered will be available to her.
+</p>
+
+<H2>Usage</H2>
+
+To use the XMP-feature in JabRef you can do the following:
+
+<ul>
+ <li>To <b>import a single annotated PDF-file</b> that contains XMP you can select "File -> Import into... -> XMP-annotated PDF" or drag the file into the main view.</li>
+ <li>To <b>write the bibliographic information to the associated PDF</b> do the following: Double click the entry in the main view, go to the "General" tab and click on "Write XMP".</li>
+ <li>If you want <b>to annotate all the PDFs in a given database</b> you can select "Tools -> Write XMP for database"</li>
+ <li>To verify if it worked you can open the PDF in Adobe Acrobat and select
+ "File -> Document Properties -> Additional Metadata -> Advanced". In the tree to the right you should see an entry called "http://purl.org/net/bibteXMP"
+<ul>
+
+<h2>BibteXmp Fileformat</h2>
+
+<p>
+XMP uses a subset of the Resource Description Framework (RDF) to store data. For JabRef a new metadata
+format is used which maps very closely to BibTeX. Basically all fields and values are turned into
+nodes of an XML document. Only authors and editors are stored as rdf:Seq-structures, so users
+of the data can skip the splitting on 'and's. All strings and crossrefs will be resolved in the data.
+</p>
+<p>
+The following easy minimal schema is used:
+</p>
+<p>
+<ul>
+ <li>The BibTeX-key is stored as <code>bibtexkey</code>.</li>
+ <li>The type of the BibTeX-entry is stored as <code>entrytype</code>.</li>
+ <li><code>author</code> and <code>editor</code> are encoding as <code>rdf:Seq</code>s where the
+ individual authors are represented as <code>rdf:li</code>s.</li>
+ <li>All other fields are saved using their field-name as is.</li>
+</ul>
+</p>
+<p>
+The following is an example of the mapping
+</p>
+<pre>
+ at INPROCEEDINGS{CroAnnHow05,
+ author = {Crowston, K. and Annabi, H. and Howison, J. and Masango, C.},
+ title = {Effective work practices for floss development: A model and propositions},
+ booktitle = {Hawaii International Conference On System Sciences (HICSS)},
+ year = {2005},
+ owner = {oezbek},
+ timestamp = {2006.05.29},
+ url = {http://james.howison.name/publications.html}
+}
+</pre>
+
+will be transformed into
+
+<pre>
+<rdf:Description xmlns:bibtex="http://jabref.sourceforge.net/bibteXMP/"
+ bibtex:bibtexkey="CroAnnHow05"
+ bibtex:year="2005"
+ bibtex:title="Effective work practices for floss development: A model and propositions"
+ bibtex:owner="oezbek"
+ bibtex:url="http://james.howison.name/publications.html"
+ bibtex:booktitle="Hawaii International Conference On System Sciences (HICSS)"
+ bibtex:timestamp="2006.05.29">
+ <bibtex:author>
+ <rdf:Seq>
+ <rdf:li>K. Crowston</rdf:li>
+ <rdf:li>H. Annabi</rdf:li>
+ <rdf:li>J. Howison</rdf:li>
+ <rdf:li>C. Masango</rdf:li>
+ </rdf:Seq>
+ </bibtex:author>
+ <bibtex:entrytype>Inproceedings</bibtex:entrytype>
+</rdf:Description>
+</pre></td></tr>
+</table>
+
+<p>
+Beware of the following caveats if you trying to parse bibteXMP:
+</p>
+<p>
+<ul>
+ <li>In RDF attribute-value pairs can also be expressed as nodes and vice versa.</li>
+</ul>
+</p>
+<H2>Related Links:</H2>
+<p>
+Some links about XMP and annotating PDFs:
+</p>
+<p>
+<ul>
+ <li><a href="http://freelancepropaganda.com/themp/">James Howison's blog "Themp---Managing Academic Papers like MP3s"</a></li>
+ <li><a href="http://www.xml.com/pub/a/2004/09/22/xmp.html">XML.com article about XMP</a></li>
+ <li><a href="http://jempbox.org">JempBox</a> and <a href="http://pdfbox.org">PDFBox</a> by Ben Litchfield are the Jaba libraries
+ used to access the PDFs and the metadata stream.</a></li>
+ <li><a href="http://episteme.arstechnica.com/eve/ubb.x/a/tpc/f/8300945231/m/377001889631">Good thread on ArsTechnica discussing the management of PDFs.</a></li>
+ <li><a href="http://partners.adobe.com/public/developer/en/xmp/sdk/xmpspecification.pdf">Adobe XMP Specification</a></li>
+</ul>
+</p>
+</body>
+</HTML>
\ No newline at end of file
diff --git a/src/help/credits.txt b/src/help/credits.txt
index 62fd992..f60fac9 100644
--- a/src/help/credits.txt
+++ b/src/help/credits.txt
@@ -5,6 +5,7 @@ Michel Baylac
Guillaume Gardey
Cyrille d'Haese
Raik Nagel
+Christopher Oezbek
Ellen Reitmayr
Michael Spiegel
Ulrik Stervbo
@@ -24,11 +25,13 @@ Alexis Gallagher
Sascha Hunold
Bernd Kalbfuss
Martin K�hmer
+Christian Kopf
Alex Montgomery
John Relph
Moritz Ringler
Rudolf Seemann
Mike Smoot
+Ulrich St�rk
Martin Stolle
David Weitzman
Seb Wills
diff --git a/src/help/de/About.html b/src/help/de/About.html
index 2bfe7ed..0f2f79a 100644
--- a/src/help/de/About.html
+++ b/src/help/de/About.html
@@ -23,6 +23,7 @@ Guillaume Gardey,
Cyrille d'Haese,
Raik Nagel,
Ellen Reitmayr,
+Gert Renckens,
Andreas Rudert,
Michael Spiegel,
Ulrik Stervbo,
@@ -49,6 +50,7 @@ Alex Montgomery,
Christopher Oezbek,
John Relph,
Moritz Ringler,
+Mark Schenk,
Rudolf Seemann,
Toralf Senger,
Mike Smoot,
diff --git a/src/help/de/PreviewHelp.html b/src/help/de/PreviewHelp.html
index 3515df0..7f3535d 100644
--- a/src/help/de/PreviewHelp.html
+++ b/src/help/de/PreviewHelp.html
@@ -5,7 +5,7 @@
<H1>Eintragsvorschau einstellen</H1>
-Die Eintragsvorschau wird mit denselben Mechanismen erstellt, die auch bei den <a href="CustomExports.html">Exportfiltern</a> angewendet werden. Bei der Vorschau durchläuft ein Eintrag eins von zwei möglichen Layouts (die sie mit STRG-F9 wechseln können) und erstellt HTML-Code, der im Vorschaudialog angezeigt wird.
+Die Eintragsvorschau wird mit denselben Mechanismen erstellt, die auch bei den <a href="CustomExports.html">Exportfiltern</a> angewendet werden. Bei der Vorschau durchläuft ein Eintrag eins von zwei möglichen Layouts (die sie mit F9 wechseln können) und erstellt HTML-Code, der im Vorschaudialog angezeigt wird.
Aussehen und Inhalt der Vorschau können mit derselben Syntax verändert werden, die in der Hilfe zur Anpassung der <a href="CustomExports.html">Exportfilter</a> beschrieben wird.
diff --git a/src/help/fr/About.html b/src/help/fr/About.html
index b891a34..6479a3c 100644
--- a/src/help/fr/About.html
+++ b/src/help/fr/About.html
@@ -22,6 +22,7 @@ Guillaume Gardey,
Cyrille d'Haese,
Raik Nagel,
Ellen Reitmayr,
+Gert Renckens,
Andreas Rudert,
Michael Spiegel,
Ulrik Stervbo,
@@ -48,6 +49,7 @@ Alex Montgomery,
Christopher Oezbek,
John Relph,
Moritz Ringler,
+Mark Schenk,
Rudolf Seemann,
Toralf Senger,
Mike Smoot,
diff --git a/src/help/fr/BaseFrameHelp.html b/src/help/fr/BaseFrameHelp.html
index a3cf5ce..1d7b662 100644
--- a/src/help/fr/BaseFrameHelp.html
+++ b/src/help/fr/BaseFrameHelp.html
@@ -22,7 +22,14 @@ données, ainsi qu'une sélection configurable de leurs champs.
<li>Vous décidez des champs affichés dans ce tableau en cochant les
champs que vous voulez voir dans la fenêtre de dialogue <strong>Préférences</strong>.</li>
<li>Pour éditér la valeur d'un champ, double-cliquez sur la ligne que vous voulez modifiez. Vous pouvez naviguer dans le tableau en utilisant les flèches du clavier.</li>
-<li>Le tableau est trié selon une série de champs de votre choix. L'ordre de tri par défaut est configuré dans <strong>Options -> Préférences -> Table des entrées</strong> mais vous pouvez changer rapidement et simplement cet ordre en double-cliquant sur le titre d'une colonne pour définir le critère de tri principal et en simple-cliquant sur le titre pour ajouter un nouveau sous-critère de tri. Si vous cliquez sur le [...]
+<li>Le tableau est trié selon une série de champs de votre choix.
+L'ordre de tri par défaut est configuré dans <strong>Options -> Préférences -> Table des entrées</strong>
+mais pour changer rapidement cet ordre,
+ cliquez l'entête d'une colonne pour la définir comme critère de tri principal, ou
+ inverser l'ordre du tri s'il est déj� défini. Un clic supplémentaire désélectionnera la colonne
+ comme critère de tri. Maintenez la touche <b>CONTROL</b> enfoncée et cliquez sur un autre entête de colonne pour l'ajouter, l'inverser
+ ou l'enlever comme critère de tri auxiliaire. Vous pouvez ajouter un nombre arbitraire
+ de critères auxiliaires.
<li>Vous pouvez ajuster la largeur des colonnes en faisant glisser les limites
entre les entêtes.</li>
<li>Dans la fenêtre de dialogue <strong>Préférences</strong>, choisissez si le tableau
@@ -66,7 +73,7 @@ tel que CTRL-SHIFT-A pour l'ajout d'une entrée <em>article</em>.
<H2>Editer une entrée</H2> Pour ouvrir la <a
href="EntryEditorHelp.html">fenêtre d'édition</a> sur une entrée existante,
-double-cliquez simplement sur la ligne correspondant à l'entrée (ou appuyez sur ENTREE apr�s avoir sélectionner l'entrée).
+double-cliquez simplement sur la ligne correspondant à l'entrée (ou appuyez sur ENTREE après avoir sélectionner l'entrée).
<H2>Référencer une chaîne <em>BibTeX</em> dans un champ</H2>
Dans JabRef vous écrivez le contenu de tous les champs de la même
diff --git a/src/help/fr/Contents.html b/src/help/fr/Contents.html
index 5f97116..451c0ae 100644
--- a/src/help/fr/Contents.html
+++ b/src/help/fr/Contents.html
@@ -16,23 +16,24 @@
<a href="CustomEntriesHelp.html">Personnalisation des types d'entrées</a><br>
<a href="GeneralFields.html">Personnalisation des champs généraux</a><br>
<a href="EndNoteFilters.html">Filtres d'importation/exportation d'EndNote</a><br>
- <a href="OpenOfficeHelp.html">Utiliser les bibliographies JabRef dans OpenOffice.org</a><br>
<a href="EntryEditorHelp.html">�diteur d'entrées</a><br>
+ <a href="TimeStampHelp.html">Horodatage des entrées</a><br>
<a href="CiteSeerHelp.html">Récupération des entrées depuis <em>CiteSeer</em></a><br>
<a href="MedlineHelp.html">Récupération des entrées depuis <em>Medline</em></a><br>
<a href="IEEEXploreHelp.html">Récupération des entrées depuis <em>IEEExplore</em></a><br>
<a href="ContentSelectorHelp.html">Sélecteur de contenu de champ</a><br>
- <a href="JournalAbbreviations.html">Abréviations de journaux</a><br>
<a href="GroupsHelp.html">Utilisation des <em>Groupes</em></a><br>
+ <a href="ImportInspectionDialog.html">Fenêtre de vérification des importations</a><br>
+ <a href="JournalAbbreviations.html">Abréviations de journaux</a><br>
<a href="BaseFrameHelp.html">La fenêtre principale de JabRef</a><br>
- <a href="MarkingHelp.html">�tiqueter des entrées</a><br>
<a href="OwnerHelp.html">Le champ 'owner' (propriétaire)</a><br>
+ <a href="MarkingHelp.html">�tiqueter des entrées</a><br>
+ <a href="OpenOfficeHelp.html">Utiliser les bibliographies JabRef dans OpenOffice.org</a><br>
<a href="ExternalFiles.html">Liens PDF/PS/URL/DOI dans JabRef</a><br>
<a href="SearchHelp.html">Recherche dans JabRef</a><br>
<a href="StringEditorHelp.html">�diteur de chaînes</a><br>
- <a href="TimeStampHelp.html">Horodatage des entrées</a><br>
- <a href="ImportInspectionDialog.html">Fenêtre de vérification des importations</a><br>
<a href="PreviewHelp.html">Configuration de l'aperçu des entrées</a><br>
+ <a href="XMPHelp.html">Support des metadonn�es XMP dans JabRef</a>
diff --git a/src/help/fr/CustomExports.html b/src/help/fr/CustomExports.html
index eafd922..68ae7a9 100644
--- a/src/help/fr/CustomExports.html
+++ b/src/help/fr/CustomExports.html
@@ -36,7 +36,7 @@ Il faut noter que ces fichiers doivent être dans le même répe
</p>
<p>
-Dans notre exemple de fichier d'exportation, cela pourrait ressembler à
+Dans notre exemple de fichier d'exportation, cela pourrait ressembler à
</p>
<p>
@@ -89,7 +89,7 @@ Le formateur est utilisé en insérant la commande <code>\format</co
</p>
<p>
-Vous pouvez aussi indiquer plusieurs formateurs séparés par des virgules. Ils seront alors appelés séquentiellement de la gauche vers la droite, par exemple :
+Vous pouvez aussi indiquer plusieurs formateurs séparés par des virgules. Ils seront alors appelés séquentiellement de la gauche vers la droite, par exemple :
</p>
<p>
<code>\format[ToLowerCase,HTMLChars]{\author}</code>
@@ -109,14 +109,15 @@ JabRef fournit les formateurs suivants, certains d'entre eux dépendant d'
<li><code>HTMLChars</code> : remplace les caractères spéciaux spécifiques à TeX (par exemple : {\^a} ou {\"{o}}) par leur représentation HTML.
<li><code>XMLChars</code> : remplace les caractères spéciaux spécifiques à TeX (par exemple : {\^a} ou {\"{o}}) par leur représentation XML.
<li><code>CreateDocBookAuthors</code> : formate le contenu du champ author selon le style DocBook.
-<li><code>CurrentDate</code> : renvoie la date actuelle. Sans argument, ce formateur renvoie la date et l'heure actuelle au format "yyyy.MM.dd hh:mm:ss z" (date, heure et fuseau horaire). En donnant une chaîne de format différent comme argument, le format de la date peut-être adapté. Par exemple,
+<li><code>CurrentDate</code> : renvoie la date actuelle. Sans argument, ce formateur renvoie la date et l'heure actuelle au format "yyyy.MM.dd hh:mm:ss z" (date, heure et fuseau horaire). En donnant une chaîne de format différent comme argument, le format de la date peut-être adapté. Par exemple,
<code>\format[CurrentDate]{yyyy.MM.dd}</code> renverra uniquement la date, comme par exemple 2005.11.30.
<li><code>AuthorFirstFirst</code> : formate le contenu des champs author/editor en mettant les prénoms en premier.
<li><code>AuthorFirstFirstCommas</code> : formate le contenu des champs author/editor en mettant les prénoms en premier et des virgules comme séparateurs.
<li><code>AuthorLastFirst</code> : formate le contenu des champs author/editor en mettant le nom de famille en premier.
<li><code>AuthorLastFirstAbbreviator</code> : réduit les prénoms de tous les auteurs à leurs initiales. Ce formateur nécessite d'avoir préalablement utilisé AuthorLastFirst.
-<li><code>AuthorAndsReplacer</code> : remplace "and" par ";" entre les premiers noms et par "&" entre les deux derniers.
-<li><code>AuthorAndsCommaReplacer</code> : remplace "and" entre les noms par une virgule (",") et "&" entre les deux derniers.
+<li><code>AuthorAndsReplacer</code> : remplace "and" par ";" entre les premiers noms et par "&" entre les deux derniers.
+<li><code>AuthorAndsCommaReplacer</code> : remplace "and" entre les noms par une virgule (",") et "&" entre les deux derniers.
+<li><code>AuthorOrgSci</code> : premier auteur selon "nom, pr�nom" et tous les autres selon "pr�nom nom". Les pr�noms sont abr�g�s.
<li><code>FormatPagesForHTML</code> : remplace "--" par "-".
<li><code>FormatPagesForXML</code> : remplace "--" par un tiret XML.
<li><code>RemoveBrackets</code> : supprime toutes les accolades "{" ou "}".
@@ -164,7 +165,7 @@ Par exemple, on suppose que l'on désire faire des groupes à partir
</p>
<p>
<code>\begingroup{keywords}New Category: \format[HTMLChars]{\keywords}
-<br> \endgroup{keywords}</code>
+<br> \endgroup{keywords}</code>
</p>
<h2>Partage de votre travail </h2>
diff --git a/src/help/fr/ExternalFiles.html b/src/help/fr/ExternalFiles.html
index 1592cb1..d0896df 100644
--- a/src/help/fr/ExternalFiles.html
+++ b/src/help/fr/ExternalFiles.html
@@ -75,5 +75,46 @@ Vous pouvez définir des répertoires PDF et PS spécifiques &
Ces répertoires remplacent alors les répertoires principaux.
</P>
-
-</HTML>
+<a name="RegularExpressionSearch">
+<H2>Utiliser la recherche d'expressions régulières pour les liaisons automatiques</H2>
+</a>
+<p>
+Dans les sections précédentes, la fonction de liaison automatique de JabRef était décrite : si vous
+choisissiez des noms de fichiers qui correspondaient à la clef BibTex suivi de l'extension,
+JabRef était capable de trouver les fichiers automatiquement.
+
+</p><p>
+A partir de JabRef 2.2, il est possible d'avoir une plus grande flexibilité dans la forme du nom grâce à l'utilisation
+d'une expression régulière pour la recherche. Dans la plupart des cas, adapter l'expression régulière donnée par défaut devrait suffire.
+
+</p><p>
+Si vous ouvrez les préférences pour les programmes externes (Options -> Préférences -> Programmes externes),
+vous y trouverez une option nommée "Rechercher l'expression régulière".
+Cocher cette option vous permettra d'entrer votre propre expression régulière pour la recherche dans les
+répertoires PDF.
+
+</p><p>
+Voici la syntaxe à utiliser :
+</p>
+<ul>
+ <li><code>*</code> - Rechercher dans tous les sous-répertoires directs en excluant le répertoire courant
+ et tout autre sous-répertoire.</li>
+ <li><code>**</code> - Rechercher récursivement dans tous les sous-répertoires ET dans le répertoire courant.</li>
+ <li><code>.</code> et <code>..</code> - Le répertoire courant et le répertoire parent.</li>
+ <li><code>[title]</code> - Toutes les expressions entre crochets sont remplacées par le champ correspondant dans l'entrée courante.</li>
+ <li><code>[extension]</code> - Remplacement par l'extension de fichier du champ que vous utilisez.</li>
+ <li>Tout autre texte est interprété comme une expression régulière. Mais attention : vous devez remplacer
+ chaque caractère anti-slash (\) par deux anti-slashs (\\) afin d'éviter la confusion avec un séparateur de répertoire .</li>
+</ul>
+<p>
+Par défaut, l'expression régulière de recherche est <code>**/.*[bibtexkey].*\\.[extension]</code>. Comme vous pouvez le voir cela effectuera
+la recherche dans tous les sous-répertoires du répertoire défini pour l'extension (par exemple dans le répertoire PDF) de tout nom de fichier qui possède la bonne extension et
+qui contient quelque part la clef BibTeX.
+
+
+
+
+
+</p>
+</body>
+</html>
diff --git a/src/help/fr/PreviewHelp.html b/src/help/fr/PreviewHelp.html
index f396b63..2f261f6 100644
--- a/src/help/fr/PreviewHelp.html
+++ b/src/help/fr/PreviewHelp.html
@@ -8,9 +8,9 @@
L'aperçu des entrées est créé en utilisant le même mécanisme que pour les
<a href="CustomExports.html">filtres d'exportation personnalisés</a>.
En mode aperçu, une entrée est traitée en utilisant l'une des deux mises en page disponibles
-(vous pouvez basculer entre les deux mises en page en pressant CTRL-F9) afin de produire du code HTML qui est affiché dans le panneau d'aperçu.
+(vous pouvez basculer entre les deux mises en page en pressant F9) afin de produire du code HTML qui est affiché dans le panneau d'aperçu.
-Pour modifier l'apparence et le contenu de l'aperçu vous devez éditer les mises en page de l'aperçu en utilisant la
+Pour modifier l'apparence et le contenu de l'aperçu vous devez éditer les mises en page de l'aperçu en utilisant la
syntaxe décrite dans le fichier d'aide portant sur les
<a href="CustomExports.html">filtres d'exportation personnalisés</a>.
diff --git a/src/help/fr/XMPHelp.html b/src/help/fr/XMPHelp.html
new file mode 100644
index 0000000..e5bf6c1
--- /dev/null
+++ b/src/help/fr/XMPHelp.html
@@ -0,0 +1,114 @@
+<HTML>
+
+<BODY text="#275856">
+<basefont size="4" color="#2F4958" face="arial">
+
+<H1>Support des metadonnées XMP dans JabRef</H1>
+
+NdT : Menus à vérifier !!!
+
+<p>
+XMP est un standard créé par Adobe Systems pour stocker des métadonnées (des données sur les données) dans des fichiers.
+A exemple bien connu de métadonnées sont les balises MP3 qui peuvent être utilisées pour décrire l'artiste, l'album et le nom de la chanson
+dans un fichier MP3. Ajouter des métadonnées à des fichiers MP3 aide les autres utilisateurs à identifier correctement les chansons indépendamment du nom du fichier
+et permet aux logiciels (lecteurs MP3 par exemple) de trier et de grouper les chansons.
+</p>
+<p>
+Avec le support de XMP, l'équipe de développement de JabRef introduit les avantages des métadonnées au monde des gestionnaires de références.
+Vous avez maintenant la possibilité d'"écrire des métadonnées XMP" dans l'onglet General de Jabref, ce qui mettra toutes les informations BibTex dans un fichier PDF. En transférant ce fichier à un collègue, il aura simplement à faire glisser le fichier dans JabRef pour que toutes les informations que vous y avez entrées lui soient disponibles.
+</p>
+
+<H2>Utilisation</H2>
+
+Pour utiliser la fonction XMP dans JabRef, vous pouvez faire les choses suivantes :
+
+<ul>
+ <li><b>Importer un unique fichier PDF annoté</b> contenant les métadonnées XMP. Vous pouvez sélectionner "Fichier -> Importer dans... -> PDF avec annotations XMP" ou faire glisser le fichier dans la fenêtre principale.</li>
+ <li><b>Ecrire les informations bibliographiques dans le fichier PDF associé.</b> Pour cela, double-cliquez sur l'entrée dans
+ la fenêtre principale, allez dans l'onglet "General" et cliquer sur "Ecrire XMP".</li>
+ <li>Si vous voulez <b>annoter tous les PDFs dans une base de données déterminée</b> vous pouvez sélectionner "Outils -> Ecrire XMP pour la base de données"</li>
+ <li>Pour vérifier si cela a fonctionné, vous pouvez ouvrir le PDF dans Adobe Acrobat et sélectionner
+ "Fichier -> Propriétés du Document -> Métadonnées additionnelles -> Avancé". Dans l'arborescence sur la droite vous devriez voir une entrée nommée "http://purl.org/net/bibteXMP".
+</ul>
+
+<h2>Format de fichier BibteXmp</h2>
+
+<p>
+XMP utilise un sous-ensemble du Schéma de Description des Ressources (Resource Description Framework - RDF) pour stocker les données. Pour JabRef, un nouveau format de métadonnées
+est utilisé ; il ressemble beaucoup au format BibTeX. Fondamentalement, tous les champs et valeurs sont transformés en
+noeuds dans un document XML. Seuls les auteurs et les éditeurs sont stockés comme des rdf:Seq-structures, aussi les utilisateurs
+des données peuvent éviter la séparation basées sur des 'and'. Toutes les chaînes et les références croisées seront présentes dans les données.
+</p>
+<p>
+Le schéma suivant, facile et minimal, est utilisé :
+</p>
+<p>
+<ul>
+ <li>La clef BibTeX est stockée comme une <code>bibtexkey</code>.</li>
+ <li>Le type d'entrée BibTeX est stocké comme une <code>entrytype</code>.</li>
+ <li>les champs <code>author</code> et <code>editor</code> sont encodés comme des <code>rdf:Seq</code>s où les auteurs individuels sont représentés par des <code>rdf:li</code>s.</li>
+ <li>Tous les autres champs sont sauvés en utilisant directement le nom de leur champ.</li>
+</ul>
+</p>
+<p>
+Ci-dessous, un exemple de mise en correspondance
+</p>
+<pre>
+ at INPROCEEDINGS{CroAnnHow05,
+ author = {Crowston, K. and Annabi, H. and Howison, J. and Masango, C.},
+ title = {Effective work practices for floss development: A model and propositions},
+ booktitle = {Hawaii International Conference On System Sciences (HICSS)},
+ year = {2005},
+ owner = {oezbek},
+ timestamp = {2006.05.29},
+ url = {http://james.howison.name/publications.html}
+}
+</pre>
+
+sera transformé en
+<pre>
+<rdf:Description xmlns:bibtex="http://jabref.sourceforge.net/bibteXMP/"
+ bibtex:bibtexkey="CroAnnHow05"
+ bibtex:year="2005"
+ bibtex:title="Effective work practices for floss development: A model and propositions"
+ bibtex:owner="oezbek"
+ bibtex:url="http://james.howison.name/publications.html"
+ bibtex:booktitle="Hawaii International Conference On System Sciences (HICSS)"
+ bibtex:timestamp="2006.05.29">
+ <bibtex:author>
+ <rdf:Seq>
+ <rdf:li>K. Crowston</rdf:li>
+ <rdf:li>H. Annabi</rdf:li>
+ <rdf:li>J. Howison</rdf:li>
+ <rdf:li>C. Masango</rdf:li>
+ </rdf:Seq>
+ </bibtex:author>
+ <bibtex:entrytype>Inproceedings</bibtex:entrytype>
+</rdf:Description>
+</pre></td></tr>
+</table>
+
+<p>
+Faites attention aux pi�ges suivants si vous essayer de traiter les m�tadonn�es bibtexXMP :
+</p>
+<p>
+<ul>
+ <li>Selon RDF, les couples attribut-valeur peuvent aussi être exprimés comme des noeuds, et vice-versa.</li>
+</ul>
+</p>
+<H2>Liens :</H2>
+<p>
+Quelques liens (en anglais) à propos de XMP et de l'annotation des PDFs :
+</p>
+<p>
+<ul>
+ <li><a href="http://freelancepropaganda.com/themp/">James Howison's blog "Themp---Managing Academic Papers like MP3s"</a></li>
+ <li><a href="http://www.xml.com/pub/a/2004/09/22/xmp.html">XML.com article about XMP</a></li>
+ <li><a href="http://jempbox.org">JempBox</a> and <a href="http://pdfbox.org">PDFBox</a> by Ben Litchfield are the Jaba libraries
+ used to access the PDFs and the metadata stream.</a></li>
+ <li><a href="http://episteme.arstechnica.com/eve/ubb.x/a/tpc/f/8300945231/m/377001889631">Good thread on ArsTechnica discussing the management of PDFs.</a></li>
+ <li><a href="http://partners.adobe.com/public/developer/en/xmp/sdk/xmpspecification.pdf">Adobe XMP Specification</a></li>
+</ul>
+</p>
+</body>
+</HTML>
diff --git a/src/images/JabRef-Logo.icns b/src/images/JabRef-Logo.icns
index ff51d59..7f30a50 100644
Binary files a/src/images/JabRef-Logo.icns and b/src/images/JabRef-Logo.icns differ
diff --git a/src/images/JabRef-icon.png b/src/images/JabRef-icon.png
deleted file mode 100644
index ca11220..0000000
Binary files a/src/images/JabRef-icon.png and /dev/null differ
diff --git a/src/images/JabRef-icon.svg b/src/images/JabRef-icon.svg
deleted file mode 100644
index 1204858..0000000
--- a/src/images/JabRef-icon.svg
+++ /dev/null
@@ -1,207 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-<svg
- xmlns:dc="http://purl.org/dc/elements/1.1/"
- xmlns:cc="http://web.resource.org/cc/"
- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
- xmlns:svg="http://www.w3.org/2000/svg"
- xmlns="http://www.w3.org/2000/svg"
- xmlns:xlink="http://www.w3.org/1999/xlink"
- xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
- width="744.09448819"
- height="1052.3622047"
- id="svg2"
- sodipodi:version="0.32"
- inkscape:version="0.44"
- sodipodi:docbase="/home/alver/Documents"
- sodipodi:docname="jabrefIkon.svg">
- <defs
- id="defs4">
- <linearGradient
- id="linearGradient2915">
- <stop
- id="stop2917"
- offset="0"
- style="stop-color:white;stop-opacity:1;" />
- <stop
- id="stop2919"
- offset="1"
- style="stop-color:#dadce0;stop-opacity:1;" />
- </linearGradient>
- <linearGradient
- id="linearGradient2909">
- <stop
- id="stop2911"
- offset="0"
- style="stop-color:white;stop-opacity:1;" />
- <stop
- id="stop2913"
- offset="1"
- style="stop-color:#cfd1d7;stop-opacity:1;" />
- </linearGradient>
- <linearGradient
- id="linearGradient2897">
- <stop
- style="stop-color:#dadee7;stop-opacity:1;"
- offset="0"
- id="stop2899" />
- <stop
- style="stop-color:#1e68c6;stop-opacity:1;"
- offset="1"
- id="stop2901" />
- </linearGradient>
- <linearGradient
- id="linearGradient2889">
- <stop
- style="stop-color:#e0e4ee;stop-opacity:1;"
- offset="0"
- id="stop2891" />
- <stop
- style="stop-color:#e0e4ee;stop-opacity:0;"
- offset="1"
- id="stop2893" />
- </linearGradient>
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient2915"
- id="linearGradient2971"
- gradientUnits="userSpaceOnUse"
- gradientTransform="matrix(1.115225,0,0,1,-1.889007,46.1244)"
- x1="329.18756"
- y1="289.87192"
- x2="598.66205"
- y2="548.62866" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient2909"
- id="linearGradient2974"
- gradientUnits="userSpaceOnUse"
- gradientTransform="matrix(1.082601,0,0,1,-1.374219,40)"
- x1="145.45497"
- y1="332.74286"
- x2="326.12537"
- y2="576.18854" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient2909"
- id="linearGradient2983"
- gradientUnits="userSpaceOnUse"
- gradientTransform="matrix(8.119652e-2,0,0,7.966468e-2,422.1323,954.272)"
- x1="145.45497"
- y1="332.74286"
- x2="326.12537"
- y2="576.18854" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient2915"
- id="linearGradient2985"
- gradientUnits="userSpaceOnUse"
- gradientTransform="matrix(8.119652e-2,0,0,7.966468e-2,424.2434,954.7598)"
- x1="329.18756"
- y1="289.87192"
- x2="598.66205"
- y2="548.62866" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient2909"
- id="linearGradient3878"
- gradientUnits="userSpaceOnUse"
- gradientTransform="matrix(3.824753e-2,0,0,3.538487e-2,403.2956,1005.814)"
- x1="145.45497"
- y1="332.74286"
- x2="326.12537"
- y2="576.18854" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient2915"
- id="linearGradient3880"
- gradientUnits="userSpaceOnUse"
- gradientTransform="matrix(3.863231e-2,4.140938e-3,-3.672702e-3,3.351102e-2,404.9189,1005.265)"
- x1="329.18756"
- y1="289.87192"
- x2="598.66205"
- y2="548.62866" />
- </defs>
- <sodipodi:namedview
- id="base"
- pagecolor="#ffffff"
- bordercolor="#666666"
- borderopacity="1.0"
- gridtolerance="50"
- guidetolerance="10"
- objecttolerance="10"
- inkscape:pageopacity="0.0"
- inkscape:pageshadow="2"
- inkscape:zoom="21.286454"
- inkscape:cx="416.46054"
- inkscape:cy="31.511436"
- inkscape:document-units="px"
- inkscape:current-layer="layer1"
- showgrid="false"
- inkscape:guide-bbox="false"
- showguides="true"
- inkscape:window-width="1118"
- inkscape:window-height="944"
- inkscape:window-x="0"
- inkscape:window-y="0" />
- <metadata
- id="metadata7">
- <rdf:RDF>
- <cc:Work
- rdf:about="">
- <dc:format>image/svg+xml</dc:format>
- <dc:type
- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- </cc:Work>
- </rdf:RDF>
- </metadata>
- <g
- inkscape:label="Layer 1"
- inkscape:groupmode="layer"
- id="layer1">
- <rect
- style="opacity:1;fill:#4f5f8f;fill-opacity:1"
- id="rect2905"
- width="716.55713"
- height="730.3371"
- x="10.717734"
- y="89.297173" />
- <path
- style="fill:url(#linearGradient2974);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
- d="M 122.04224,150.95548 C 208.65029,150.95548 286.97046,184.73542 286.97046,184.73542 C 286.97046,184.73542 372.48612,237.27117 327.52453,611.24332 C 314.57556,683.68157 250.81542,747.98797 172.90939,747.98797 C 95.003363,747.98797 50.24884,702.05483 50.24884,648.46615 C 119.867,694.3993 168.69957,681.54848 189.48514,672.96384 C 199.45516,668.84613 251.63441,636.1731 257.44572,548.94433 C 264.07602,449.42251 247.50026,297.84312 122.04224,150.95548 z "
- id="path1972"
- sodipodi:nodetypes="cccscssc" />
- <path
- style="fill:url(#linearGradient2971);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.05348015px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
- d="M 322.49657,164.88378 C 533.15821,196.83799 712.94701,311.87314 516.81377,452.47165 C 462.33232,497.20754 627.59274,671.35798 692.97048,751.2435 C 544.0545,717.69157 402.40271,580.28849 400.58666,476.43731 C 398.77062,401.34492 516.81377,393.35637 516.81377,347.02276 C 516.81377,300.68916 344.28916,262.34411 322.49657,164.88378 z "
- id="path1993"
- sodipodi:nodetypes="cccc" />
- <rect
- style="opacity:1;fill:#4f5f8f;fill-opacity:1"
- id="rect3872"
- width="24.96747"
- height="24.892717"
- x="403.74191"
- y="1008.134"
- inkscape:export-xdpi="173.03"
- inkscape:export-ydpi="173.03"
- inkscape:export-filename="/home/alver/div/smalltheme/jabrefIkon-48.png" />
- <path
- style="fill:url(#linearGradient3878);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
- d="M 407.84626,1010.4236 C 410.90607,1010.4236 413.43489,1010.4972 413.43489,1010.4972 C 413.43489,1010.4972 416.50376,1012.7951 414.91528,1026.0281 C 414.45779,1028.5913 412.2052,1030.8669 409.45284,1030.8669 C 406.70046,1030.8669 405.11931,1029.2413 405.11931,1027.3453 C 407.95995,1028.6292 410.06622,1027.9794 410.80057,1027.6755 C 411.15281,1027.5298 412.46165,1026.9172 412.43944,1023.8236 C 412.38788,1016.6442 413.08837,1015.0847 407.84626,1010.4236 z "
- id="path3874"
- sodipodi:nodetypes="cccscssc"
- inkscape:export-filename="/home/alver/div/smalltheme/jabrefIkon-48.png"
- inkscape:export-xdpi="173.03"
- inkscape:export-ydpi="173.03" />
- <path
- style="fill:url(#linearGradient3880);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.05348015px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
- d="M 415.71976,1010.449 C 423.13477,1010.8154 428.70544,1016.8245 421.39485,1020.8079 C 419.34326,1022.1048 424.42839,1028.5544 426.39975,1031.4741 C 421.3644,1029.7968 416.96212,1024.6664 417.28063,1021.1794 C 417.49352,1018.6562 421.61195,1018.8269 421.78212,1017.2742 C 421.95228,1015.7216 419.07637,1015.8865 415.71976,1010.449 z "
- id="path3876"
- sodipodi:nodetypes="ccccsc"
- inkscape:export-filename="/home/alver/div/smalltheme/jabrefIkon-48.png"
- inkscape:export-xdpi="173.03"
- inkscape:export-ydpi="173.03" />
- </g>
-</svg>
diff --git a/src/images/JabRef.ico b/src/images/JabRef.ico
new file mode 100644
index 0000000..21cb443
Binary files /dev/null and b/src/images/JabRef.ico differ
diff --git a/src/images/crystal_16/Icons.properties~ b/src/images/crystal_16/Icons.properties~
deleted file mode 100644
index bc48561..0000000
--- a/src/images/crystal_16/Icons.properties~
+++ /dev/null
@@ -1,69 +0,0 @@
-#jabrefIcon=JabRef-icon.png
-jabrefIcon=ikon.gif
-about=JabRef-icon.png
-
-new=filenew.png
-open=fileopen.png
-loadSession=fileimport.png
-save=filesave.png
-saveAs=filesaveas.png
-copy=editcopy.png
-paste=editpaste.png
-cut=editcut.png
-undo=undo.png
-redo=redo.png
-refresh=reload.png
-left=1leftarrow.png
-right=1rightarrow.png
-up=1uparrow.png
-down=1downarrow.png
-add=edit_add.png
-remove=edit_remove.png
-delete=trash.png
-edit=edit.png
-help=help.png
-helpSmall=help.png
-helpContents=contents2.png
-search=search.png
-incSearch=search.png
-toggleSearch=search.png
-complete=button_ok.png
-wrong=cancel.png
-makeKey=wizard.png
-psSmall=ps.png
-pdfSmall=pdf-document.png
-openFile=pdf-document.png
-preferences=advancedsettings.png
-openUrl=agt_internet.png
-www=agt_internet.png
-wwwSmall=agt_internet_small.png
-medline=agt_internet.png
-integrityWarn=status_unknown.png
-integrityInfo=documentinfo.png
-integrityFail=gg_ignored.png
-
-togglePreview=text_bottom.png
-toggleGroups=queue.png
-editPreamble=preamble.png
-editStrings=strings.png
-emacs=emacs.png
-lyx=lyx2.png
-winedt=winedt.png
-required=reqIcon.png
-optional=optIcon.png
-general=genIcon.png
-abstract=absIcon.png
-source=viewsource.gif
-duplicate=duplicate.png
-autoGroup=run.png
-markEntries=mark.png
-unmarkEntries=unmark.png
-citeseer=wwwciteseer.png
-doiSmall=doismall.png
-groupsHighlightAny=groupsHighlightAny.png
-groupsHighlightAll=groupsHighlightAll.png
-close=fileclose.png
-close2=fileclose2.png
-integrityCheck=integrity.png
-groupIncluding=groupIncluding.png
-groupRefining=groupRefining.png
diff --git a/src/images/font/ACTIVA.TTF b/src/images/font/ACTIVA.TTF
deleted file mode 100644
index c973b2c..0000000
Binary files a/src/images/font/ACTIVA.TTF and /dev/null differ
diff --git a/src/images/font/ASTROLYT.TTF b/src/images/font/ASTROLYT.TTF
deleted file mode 100644
index 9a92497..0000000
Binary files a/src/images/font/ASTROLYT.TTF and /dev/null differ
diff --git a/src/images/font/AUGIE.TTF b/src/images/font/AUGIE.TTF
deleted file mode 100644
index 175d7ce..0000000
Binary files a/src/images/font/AUGIE.TTF and /dev/null differ
diff --git a/src/images/secondary_sorted_reverse.png b/src/images/secondary_sorted_reverse.png
new file mode 100644
index 0000000..b7fb00a
Binary files /dev/null and b/src/images/secondary_sorted_reverse.png differ
diff --git a/src/images/splash-2.1.png b/src/images/splash-2.1.png
deleted file mode 100644
index 1ddced9..0000000
Binary files a/src/images/splash-2.1.png and /dev/null differ
diff --git a/src/images/splash-2.1.svg b/src/images/splash-2.1.svg
deleted file mode 100644
index bf20ab2..0000000
--- a/src/images/splash-2.1.svg
+++ /dev/null
@@ -1,244 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-<svg
- xmlns:dc="http://purl.org/dc/elements/1.1/"
- xmlns:cc="http://web.resource.org/cc/"
- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
- xmlns:svg="http://www.w3.org/2000/svg"
- xmlns="http://www.w3.org/2000/svg"
- xmlns:xlink="http://www.w3.org/1999/xlink"
- xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd"
- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
- inkscape:export-ydpi="90.000000"
- inkscape:export-xdpi="90.000000"
- inkscape:export-filename="/home/alver/jabref-2.1b/src/images/splash-2.1beta.png"
- sodipodi:docname="splash-2.1.svg"
- sodipodi:docbase="/home/alver/jabref/src/images"
- inkscape:version="0.42+0.43pre1"
- sodipodi:version="0.32"
- id="svg2138"
- height="1052.3622047"
- width="744.09448819">
- <defs
- id="defs2140">
- <pattern
- patternTransform="translate(316.0000,1046.362)"
- id="pattern9054"
- xlink:href="#pattern9048"
- inkscape:collect="always" />
- <linearGradient
- id="linearGradient5361"
- inkscape:collect="always">
- <stop
- id="stop5363"
- offset="0"
- style="stop-color:#000000;stop-opacity:1;" />
- <stop
- id="stop5365"
- offset="1"
- style="stop-color:#000000;stop-opacity:0;" />
- </linearGradient>
- <marker
- style="overflow:visible;"
- id="Arrow2Send"
- refX="0.0"
- refY="0.0"
- orient="auto"
- inkscape:stockid="Arrow2Send">
- <path
- transform="scale(0.3) rotate(180) translate(-5,0)"
- d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
- style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
- id="path3046"
- sodipodi:nodetypes="cccc" />
- </marker>
- <linearGradient
- gradientUnits="userSpaceOnUse"
- y2="300.91277"
- x2="491.20592"
- y1="300.91277"
- x1="445.01770"
- id="linearGradient5367"
- xlink:href="#linearGradient5361"
- inkscape:collect="always" />
- <pattern
- id="pattern9048"
- patternTransform="translate(231.0000,284.3622)"
- height="428.00000"
- width="572.00000"
- patternUnits="userSpaceOnUse">
- <image
- transform="translate(-231.0000,-284.3622)"
- style="opacity:1.0000000;stroke:#000000;stroke-width:5.0000000;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-opacity:1.0000000"
- inkscape:export-ydpi="90.000000"
- inkscape:export-xdpi="90.000000"
- inkscape:export-filename="/home/alver/Desktop/bilder/jabref/splash4.png"
- y="284.36218"
- x="231.00000"
- xlink:href="behandlet.png"
- sodipodi:absref="/home/alver/Desktop/bilder/jabref/behandlet.png"
- width="572.00000"
- height="428.00000"
- id="image9050" />
- </pattern>
- </defs>
- <sodipodi:namedview
- inkscape:window-y="53"
- inkscape:window-x="15"
- inkscape:window-height="856"
- inkscape:window-width="750"
- inkscape:current-layer="layer1"
- inkscape:document-units="px"
- inkscape:cy="698.1925"
- inkscape:cx="364.52617"
- inkscape:zoom="1"
- inkscape:pageshadow="2"
- inkscape:pageopacity="0.0"
- borderopacity="1.0"
- bordercolor="#666666"
- pagecolor="#ffffff"
- id="base" />
- <metadata
- id="metadata2143">
- <rdf:RDF>
- <cc:Work
- rdf:about="">
- <dc:format>image/svg+xml</dc:format>
- <dc:type
- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- </cc:Work>
- </rdf:RDF>
- </metadata>
- <g
- id="layer1"
- inkscape:groupmode="layer"
- inkscape:label="Layer 1">
- <rect
- inkscape:export-ydpi="75.000000"
- inkscape:export-xdpi="75.000000"
- inkscape:export-filename="/home/alver/jabref-2.1b/src/images/splash-2.1beta.png"
- y="170.36218"
- x="77.500000"
- height="432.00000"
- width="576.00000"
- id="rect6833"
- style="opacity:1.0000000;fill:#6b6b75;fill-opacity:1.0000000;stroke:none;stroke-width:5.0000000;stroke-linecap:round;stroke-linejoin:bevel;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000" />
- <image
- id="image1821"
- height="428"
- width="572"
- sodipodi:absref="/home/alver/jabref/src/images/splashBackground.png"
- xlink:href="splashBackground.png"
- x="79"
- y="172.36218"
- inkscape:export-filename="/home/alver/jabref-2.1b/src/images/splash-2.1beta.png"
- inkscape:export-xdpi="75"
- inkscape:export-ydpi="75" />
- <flowRoot
- inkscape:export-ydpi="75.000000"
- inkscape:export-xdpi="75.000000"
- inkscape:export-filename="/home/alver/jabref_beta/jabref/jabref-2.0-splash.png"
- style="opacity:1.0000000;fill:#635578;fill-opacity:1.0000000;stroke:#b5b5c7;stroke-width:0.48137558;stroke-linejoin:bevel;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000"
- transform="matrix(1.875133,0.000000,0.000000,2.542210,-129.6969,-372.8897)"
- id="flowRoot2189"
- xml:space="preserve">
- <flowRegion
- id="flowRegion2191">
- <rect
- style="fill:#635578;fill-opacity:1.0000000;stroke:#b5b5c7;stroke-opacity:1.0000000;stroke-width:0.48137557;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-linejoin:bevel"
- y="199.10532"
- x="128.49385"
- height="127.49445"
- width="283.51782"
- id="rect2193" />
- </flowRegion>
- <flowPara
- style="font-size:90.000000px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125.00000%;writing-mode:lr-tb;text-anchor:start;fill:#635578;fill-opacity:1.0000000;stroke:#b5b5c7;stroke-width:0.48137558;stroke-linejoin:bevel;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;font-family:AR PL KaitiM GB"
- id="flowPara2201">JabRef</flowPara>
- </flowRoot> <flowRoot
- inkscape:export-ydpi="75.000000"
- inkscape:export-xdpi="75.000000"
- inkscape:export-filename="/home/alver/jabref-2.1b/src/images/splash-2.1beta.png"
- style="font-size:34.96500015px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:104.16220427%;writing-mode:lr-tb;text-anchor:start;opacity:1;fill:#ffffff;fill-opacity:1;stroke:#5cc757;stroke-width:0.64448702;stroke-linecap:round;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:0.64448701 0.64448701 ;stroke-dashoffset:0.45114091;stroke-opacity:1;font-family:FreeSans"
- transform="matrix(2.869197,-1.415830e-2,2.234317e-2,3.356271,-832.1435,-652.0185)"
- id="flowRoot2203"
- xml:space="preserve">
- <flowRegion
- style="stroke:url(#linearGradient5367);stroke-width:0.64448702;stroke-miterlimit:4;stroke-dasharray:0.64448701 0.64448701 ;stroke-dashoffset:0.45114091"
- id="flowRegion2205">
- <rect
- style="font-size:34.96500015px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:104.16220427%;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:#322b5b;stroke-width:0.64448702;stroke-linecap:round;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:0.64448701 0.64448701 ;stroke-dashoffset:0.45114091;stroke-opacity:1;font-family:FreeSans"
- y="286.45224"
- x="443.95346"
- height="119.83134"
- width="173.972"
- id="rect2207" />
- </flowRegion>
- <flowPara
- style="font-size:34.96500015px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:104.16220427%;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:#322b5b;stroke-width:0.64448702;stroke-linecap:round;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:0.64448701 0.64448701 ;stroke-dashoffset:0.45114091;stroke-opacity:1;font-family:FreeSans"
- id="flowPara2211">2.1</flowPara>
- </flowRoot> <flowRoot
- inkscape:export-ydpi="75.000000"
- inkscape:export-xdpi="75.000000"
- inkscape:export-filename="/home/alver/jabref-2.1b/src/images/splash-2.1beta.png"
- transform="matrix(0.972246,0.000000,0.000000,1.325301,6.054966,-126.1181)"
- style="font-size:11.9999996;font-style:oblique;font-variant:normal;font-weight:bold;font-stretch:normal;fill:#797580;fill-opacity:1.0000000;font-family:Bitstream Vera Sans;text-anchor:middle;writing-mode:lr;text-align:center;line-height:100%"
- id="flowRoot3076"
- xml:space="preserve"><flowRegion
- id="flowRegion3078">
- <rect
- style="fill:#797580;fill-opacity:1.0000000;font-family:Bitstream Vera Sans;font-weight:bold;font-style:oblique;font-stretch:normal;font-variant:normal;font-size:11.9999996;text-anchor:middle;text-align:center;writing-mode:lr;line-height:100%"
- y="514.56494"
- x="115.50008"
- height="78.684433"
- width="506.03476"
- id="rect3080" />
- </flowRegion><flowPara
- id="flowPara1339">This program is distributed under the terms of the General Public License.</flowPara><flowPara
- id="flowPara1341">Copyright (2003-2006) Morten O. Alver, Nizar Batada and all contributors.</flowPara></flowRoot> <text
- inkscape:export-ydpi="75.000000"
- inkscape:export-xdpi="75.000000"
- inkscape:export-filename="/home/alver/jabref-2.1b/src/images/splash-2.1beta.png"
- transform="scale(0.853277,1.171952)"
- sodipodi:linespacing="100%"
- id="text1393"
- y="315.20035"
- x="163.38908"
- style="font-size:183.29680;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;fill:#413b62;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Nimbus Roman No9 L;text-anchor:start;writing-mode:lr-tb"
- xml:space="preserve"><tspan
- y="315.20035"
- x="163.38908"
- id="tspan1395"
- sodipodi:role="line">JabRef</tspan></text>
- <text
- inkscape:export-ydpi="75.000000"
- inkscape:export-xdpi="75.000000"
- inkscape:export-filename="/home/alver/jabref-2.1b/src/images/splash-2.1beta.png"
- transform="scale(0.853347,1.171856)"
- sodipodi:linespacing="100%"
- id="text2179"
- y="397.84811"
- x="149.99753"
- style="font-size:44.00000436;font-style:italic;font-variant:normal;font-weight:bold;font-stretch:normal;fill:#805b41;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Nimbus Roman No9 L;text-anchor:start;writing-mode:lr;text-align:start;line-height:100%"
- xml:space="preserve"><tspan
- y="397.84811"
- x="149.99753"
- id="tspan2181"
- sodipodi:role="line">reference manager</tspan></text>
- <text
- xml:space="preserve"
- style="font-size:68.76833344px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;opacity:0.66853937;fill:#cf5953;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Nimbus Sans L"
- x="288.67255"
- y="712.21191"
- id="text1343"
- sodipodi:linespacing="125%"
- transform="matrix(0.950669,-0.326025,0.330198,0.938651,0.000000,0.000000)"
- inkscape:export-filename="/home/alver/jabref-2.1b/src/images/splash-2.1beta.png"
- inkscape:export-xdpi="75"
- inkscape:export-ydpi="75"><tspan
- sodipodi:role="line"
- id="tspan1345"
- x="288.67255"
- y="712.21191">beta</tspan></text>
- </g>
-</svg>
diff --git a/src/images/splash.png b/src/images/splash.png
new file mode 100644
index 0000000..55bce92
Binary files /dev/null and b/src/images/splash.png differ
diff --git a/src/images/splash.svg b/src/images/splash.svg
deleted file mode 100644
index 628543b..0000000
--- a/src/images/splash.svg
+++ /dev/null
@@ -1,229 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-<svg
- xmlns:dc="http://purl.org/dc/elements/1.1/"
- xmlns:cc="http://web.resource.org/cc/"
- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
- xmlns:svg="http://www.w3.org/2000/svg"
- xmlns="http://www.w3.org/2000/svg"
- xmlns:xlink="http://www.w3.org/1999/xlink"
- xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd"
- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
- inkscape:export-ydpi="90.000000"
- inkscape:export-xdpi="90.000000"
- inkscape:export-filename="/home/alver/Desktop/bilder/jabref/splash6.png"
- sodipodi:docname="splash.svg"
- sodipodi:docbase="/home/alver/jabref_beta/jabref/src/images"
- inkscape:version="0.42+0.43pre1"
- sodipodi:version="0.32"
- id="svg2138"
- height="1052.3622047"
- width="744.09448819">
- <defs
- id="defs2140">
- <pattern
- patternTransform="translate(316.0000,1046.362)"
- id="pattern9054"
- xlink:href="#pattern9048"
- inkscape:collect="always" />
- <linearGradient
- id="linearGradient5361"
- inkscape:collect="always">
- <stop
- id="stop5363"
- offset="0"
- style="stop-color:#000000;stop-opacity:1;" />
- <stop
- id="stop5365"
- offset="1"
- style="stop-color:#000000;stop-opacity:0;" />
- </linearGradient>
- <marker
- style="overflow:visible;"
- id="Arrow2Send"
- refX="0.0"
- refY="0.0"
- orient="auto"
- inkscape:stockid="Arrow2Send">
- <path
- transform="scale(0.3) rotate(180) translate(-5,0)"
- d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
- style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
- id="path3046"
- sodipodi:nodetypes="cccc" />
- </marker>
- <linearGradient
- gradientUnits="userSpaceOnUse"
- y2="300.91277"
- x2="491.20592"
- y1="300.91277"
- x1="445.01770"
- id="linearGradient5367"
- xlink:href="#linearGradient5361"
- inkscape:collect="always" />
- <pattern
- id="pattern9048"
- patternTransform="translate(231.0000,284.3622)"
- height="428.00000"
- width="572.00000"
- patternUnits="userSpaceOnUse">
- <image
- transform="translate(-231.0000,-284.3622)"
- style="opacity:1.0000000;stroke:#000000;stroke-width:5.0000000;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-opacity:1.0000000"
- inkscape:export-ydpi="90.000000"
- inkscape:export-xdpi="90.000000"
- inkscape:export-filename="/home/alver/Desktop/bilder/jabref/splash4.png"
- y="284.36218"
- x="231.00000"
- xlink:href="behandlet.png"
- sodipodi:absref="/home/alver/Desktop/bilder/jabref/behandlet.png"
- width="572.00000"
- height="428.00000"
- id="image9050" />
- </pattern>
- </defs>
- <sodipodi:namedview
- inkscape:window-y="80"
- inkscape:window-x="8"
- inkscape:window-height="856"
- inkscape:window-width="750"
- inkscape:current-layer="layer1"
- inkscape:document-units="px"
- inkscape:cy="698.1925"
- inkscape:cx="364.52617"
- inkscape:zoom="1"
- inkscape:pageshadow="2"
- inkscape:pageopacity="0.0"
- borderopacity="1.0"
- bordercolor="#666666"
- pagecolor="#ffffff"
- id="base" />
- <metadata
- id="metadata2143">
- <rdf:RDF>
- <cc:Work
- rdf:about="">
- <dc:format>image/svg+xml</dc:format>
- <dc:type
- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- </cc:Work>
- </rdf:RDF>
- </metadata>
- <g
- id="layer1"
- inkscape:groupmode="layer"
- inkscape:label="Layer 1">
- <rect
- inkscape:export-ydpi="75.000000"
- inkscape:export-xdpi="75.000000"
- inkscape:export-filename="/home/alver/jabref_beta/jabref/jabref-2.0-splash.png"
- y="170.36218"
- x="77.500000"
- height="432.00000"
- width="576.00000"
- id="rect6833"
- style="opacity:1.0000000;fill:#6b6b75;fill-opacity:1.0000000;stroke:none;stroke-width:5.0000000;stroke-linecap:round;stroke-linejoin:bevel;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000" />
- <image
- inkscape:export-ydpi="75.000000"
- inkscape:export-xdpi="75.000000"
- inkscape:export-filename="/home/alver/jabref_beta/jabref/jabref-2.0-splash.png"
- y="172.36218"
- x="79.000000"
- id="image1390"
- height="428.00000"
- width="572.00000"
- sodipodi:absref="/home/alver/oldhome/bilder/bilder/jabref/behandlet.png"
- xlink:href="/home/alver/oldhome/bilder/bilder/jabref/behandlet.png" />
- <flowRoot
- inkscape:export-ydpi="75.000000"
- inkscape:export-xdpi="75.000000"
- inkscape:export-filename="/home/alver/jabref_beta/jabref/jabref-2.0-splash.png"
- style="opacity:1.0000000;fill:#635578;fill-opacity:1.0000000;stroke:#b5b5c7;stroke-width:0.48137558;stroke-linejoin:bevel;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000"
- transform="matrix(1.875133,0.000000,0.000000,2.542210,-129.6969,-372.8897)"
- id="flowRoot2189"
- xml:space="preserve">
- <flowRegion
- id="flowRegion2191">
- <rect
- style="fill:#635578;fill-opacity:1.0000000;stroke:#b5b5c7;stroke-opacity:1.0000000;stroke-width:0.48137557;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-linejoin:bevel"
- y="199.10532"
- x="128.49385"
- height="127.49445"
- width="283.51782"
- id="rect2193" />
- </flowRegion>
- <flowPara
- style="font-size:90.000000px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125.00000%;writing-mode:lr-tb;text-anchor:start;fill:#635578;fill-opacity:1.0000000;stroke:#b5b5c7;stroke-width:0.48137558;stroke-linejoin:bevel;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;font-family:AR PL KaitiM GB"
- id="flowPara2201">JabRef</flowPara>
- </flowRoot> <flowRoot
- inkscape:export-ydpi="75.000000"
- inkscape:export-xdpi="75.000000"
- inkscape:export-filename="/home/alver/jabref_beta/jabref/jabref-2.0-splash.png"
- style="font-size:34.96500015px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:104.16220427%;writing-mode:lr-tb;text-anchor:start;opacity:1;fill:#ffffff;fill-opacity:1;stroke:#5cc757;stroke-width:0.64448702;stroke-linecap:round;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:0.64448701 0.64448701 ;stroke-dashoffset:0.45114091;stroke-opacity:1;font-family:FreeSans"
- transform="matrix(2.869197,-1.415830e-2,2.234317e-2,3.356271,-832.1435,-652.0185)"
- id="flowRoot2203"
- xml:space="preserve">
- <flowRegion
- style="stroke:url(#linearGradient5367);stroke-width:0.64448702;stroke-miterlimit:4;stroke-dasharray:0.64448701 0.64448701 ;stroke-dashoffset:0.45114091"
- id="flowRegion2205">
- <rect
- style="font-size:34.96500015px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:104.16220427%;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:#322b5b;stroke-width:0.64448702;stroke-linecap:round;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:0.64448701 0.64448701 ;stroke-dashoffset:0.45114091;stroke-opacity:1;font-family:FreeSans"
- y="286.45224"
- x="443.95346"
- height="119.83134"
- width="173.972"
- id="rect2207" />
- </flowRegion>
- <flowPara
- style="font-size:34.96500015px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:104.16220427%;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:#322b5b;stroke-width:0.64448702;stroke-linecap:round;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:0.64448701 0.64448701 ;stroke-dashoffset:0.45114091;stroke-opacity:1;font-family:FreeSans"
- id="flowPara2211">2.0</flowPara>
- </flowRoot> <flowRoot
- inkscape:export-ydpi="75.000000"
- inkscape:export-xdpi="75.000000"
- inkscape:export-filename="/home/alver/jabref_beta/jabref/jabref-2.0-splash.png"
- transform="matrix(0.972246,0.000000,0.000000,1.325301,6.054966,-126.1181)"
- style="font-size:11.9999996;font-style:oblique;font-variant:normal;font-weight:bold;font-stretch:normal;fill:#797580;fill-opacity:1.0000000;font-family:Bitstream Vera Sans;text-anchor:middle;writing-mode:lr;text-align:center;line-height:100%"
- id="flowRoot3076"
- xml:space="preserve"><flowRegion
- id="flowRegion3078">
- <rect
- style="fill:#797580;fill-opacity:1.0000000;font-family:Bitstream Vera Sans;font-weight:bold;font-style:oblique;font-stretch:normal;font-variant:normal;font-size:11.9999996;text-anchor:middle;text-align:center;writing-mode:lr;line-height:100%"
- y="514.56494"
- x="115.50008"
- height="78.684433"
- width="506.03476"
- id="rect3080" />
- </flowRegion><flowPara
- id="flowPara1339">This program is distributed under the terms of the General Public License.</flowPara><flowPara
- id="flowPara1341">Copyright (2003-2006) Morten O. Alver, Nizar Batada and all contributors.</flowPara></flowRoot> <text
- inkscape:export-ydpi="75.000000"
- inkscape:export-xdpi="75.000000"
- inkscape:export-filename="/home/alver/jabref_beta/jabref/jabref-2.0-splash.png"
- transform="scale(0.853277,1.171952)"
- sodipodi:linespacing="100%"
- id="text1393"
- y="315.20035"
- x="163.38908"
- style="font-size:183.29680;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;fill:#413b62;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Nimbus Roman No9 L;text-anchor:start;writing-mode:lr-tb"
- xml:space="preserve"><tspan
- y="315.20035"
- x="163.38908"
- id="tspan1395"
- sodipodi:role="line">JabRef</tspan></text>
- <text
- inkscape:export-ydpi="75.000000"
- inkscape:export-xdpi="75.000000"
- inkscape:export-filename="/home/alver/jabref_beta/jabref/jabref-2.0-splash.png"
- transform="scale(0.853347,1.171856)"
- sodipodi:linespacing="100%"
- id="text2179"
- y="397.84811"
- x="149.99753"
- style="font-size:45.702374;font-style:italic;font-variant:normal;font-weight:bold;font-stretch:normal;fill:#805b41;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Times New Roman;text-anchor:start;writing-mode:lr-tb"
- xml:space="preserve"><tspan
- y="397.84811"
- x="149.99753"
- id="tspan2181"
- sodipodi:role="line">reference manager</tspan></text>
- </g>
-</svg>
diff --git a/src/java/net/sf/jabref/AuthorList.java b/src/java/net/sf/jabref/AuthorList.java
index 571de46..fa5fd05 100644
--- a/src/java/net/sf/jabref/AuthorList.java
+++ b/src/java/net/sf/jabref/AuthorList.java
@@ -4,819 +4,1064 @@ import java.util.Vector;
import java.util.WeakHashMap;
/**
- * This is an immutable class representing information of either
- * <CODE>author</CODE> or <CODE>editor</CODE> field in bibtex record.
+ * This is an immutable class representing information of either <CODE>author</CODE>
+ * or <CODE>editor</CODE> field in bibtex record.
* <p>
* Constructor performs parsing of raw field text and stores preformatted data.
* Various accessor methods return author/editor field in different formats.
* <p>
- * Parsing algorithm is designed to satisfy two requirements:
- * (a) when author's name is typed correctly, the result should
- * coincide with the one of BiBTeX;
- * (b) for erroneous names, output should be reasonable (but may differ
- * from BiBTeX output).
- * The following rules are used:
+ * Parsing algorithm is designed to satisfy two requirements: (a) when author's
+ * name is typed correctly, the result should coincide with the one of BiBTeX;
+ * (b) for erroneous names, output should be reasonable (but may differ from
+ * BiBTeX output). The following rules are used:
* <ol>
* <li> 'author field' is a sequence of tokens;
- * <ul>
- * <li> tokens are separated by sequences of whitespaces
- * (<CODE>Character.isWhitespace(c)==true</CODE>), commas (,),
- * dashes (-), and tildas (~);
- * <li> every comma separates tokens, while sequences of other separators
- * are equivalent to a single separator; for example:
- * "a - b" consists of 2 tokens ("a" and "b"), while
- * "a,-,b" consists of 3 tokens ("a", "", and "b")
- * <li> anything enclosed in braces belonges to a single token; for example:
- * "abc x{a,b,-~ c}x" consists of 2 tokens, while
- * "abc xa,b,-~ cx" consists of 4 tokens ("abc", "xa","b", and "cx");
- * <li> a token followed immediately by a dash is "dash-terminated" token,
- * and all other tokens are "space-terminated" tokens; for example:
- * in "a-b- c - d" tokens "a" and "b" are dash-terminated and
- * "c" and "d" are space-terminated;
- * <li> for the purposes of splitting of 'author name' into parts and
- * construction of abbreviation of first name,
- * one needs definitions of first latter of a token, case of a token,
- * and abbreviation of a token:
- * <ul>
- * <li> 'first letter' of a token is the first letter character
- * (<CODE>Character.isLetter(c)==true</CODE>) that does not
- * belong to a sequence of letters that immediately follows
- * "\" character, with one exception:
- * if "\" is followed by "aa", "AA", "ae", "AE", "l", "L", "o", "O",
- * "oe", "OE", "i", or "j" followed by non-letter, the 'first letter'
- * of a token is a letter that follows "\"; for example:
- * in "a{x}b" 'first letter' is "a",
- * in "{\"{U}}bel" 'first letter' is "U",
- * in "{\noopsort{\"o}}xyz" 'first letter' is "o",
- * in "{\AE}x" 'first letter' is "A",
- * in "\aex\ijk\Oe\j" 'first letter' is "j";
- * if there is no letter satisfying the above rule, 'first letter'
- * is undefined;
- * <li> token is "lower-case" token, if its first letter id defined and
- * is lower-case (<CODE>Character.isLowerCase(c)==true</CODE>),
- * and token is "upper-case" token otherwise;
- * <li> 'abbreviation' of a token is the shortest prefix of the token
- * that (a) contains 'first letter' and (b) is braces-balanced;
- * if 'first letter' is undefined, 'abbreviation' is the token
- * itself; in the above examples, 'abbreviation's are
- * "a", "{\"{U}}", "{\noopsort{\"o}}", "{\AE}", "\aex\ijk\Oe\j";
- * </ul>
- * <li> the behavior based on the above definitions will be erroneous only
- * in one case: if the first-name-token is "{\noopsort{A}}john",
- * we abbreviate it as "{\noopsort{A}}.", while BiBTeX produces "j.";
- * fixing this problem, however, requires processing of the preabmle;
- * </ul>
- * <li> 'author name's in 'author field' are subsequences of tokens separated
- * by token "and" ("and" is case-insensitive); if 'author name' is an
- * empty sequence of tokens, it is ignored; for examle, both
- * "John Smith and Peter Black" and "and and John Smith and and Peter Black"
- * consists of 2 'author name's "Johm Smith" and "Peter Black"
- * (in erroneous situations, this is a bit different from BiBTeX behavior);
+ * <ul>
+ * <li> tokens are separated by sequences of whitespaces (<CODE>Character.isWhitespace(c)==true</CODE>),
+ * commas (,), dashes (-), and tildas (~);
+ * <li> every comma separates tokens, while sequences of other separators are
+ * equivalent to a single separator; for example: "a - b" consists of 2 tokens
+ * ("a" and "b"), while "a,-,b" consists of 3 tokens ("a", "", and "b")
+ * <li> anything enclosed in braces belonges to a single token; for example:
+ * "abc x{a,b,-~ c}x" consists of 2 tokens, while "abc xa,b,-~ cx" consists of 4
+ * tokens ("abc", "xa","b", and "cx");
+ * <li> a token followed immediately by a dash is "dash-terminated" token, and
+ * all other tokens are "space-terminated" tokens; for example: in "a-b- c - d"
+ * tokens "a" and "b" are dash-terminated and "c" and "d" are space-terminated;
+ * <li> for the purposes of splitting of 'author name' into parts and
+ * construction of abbreviation of first name, one needs definitions of first
+ * latter of a token, case of a token, and abbreviation of a token:
+ * <ul>
+ * <li> 'first letter' of a token is the first letter character (<CODE>Character.isLetter(c)==true</CODE>)
+ * that does not belong to a sequence of letters that immediately follows "\"
+ * character, with one exception: if "\" is followed by "aa", "AA", "ae", "AE",
+ * "l", "L", "o", "O", "oe", "OE", "i", or "j" followed by non-letter, the
+ * 'first letter' of a token is a letter that follows "\"; for example: in
+ * "a{x}b" 'first letter' is "a", in "{\"{U}}bel" 'first letter' is "U", in
+ * "{\noopsort{\"o}}xyz" 'first letter' is "o", in "{\AE}x" 'first letter' is
+ * "A", in "\aex\ijk\Oe\j" 'first letter' is "j"; if there is no letter
+ * satisfying the above rule, 'first letter' is undefined;
+ * <li> token is "lower-case" token, if its first letter id defined and is
+ * lower-case (<CODE>Character.isLowerCase(c)==true</CODE>), and token is
+ * "upper-case" token otherwise;
+ * <li> 'abbreviation' of a token is the shortest prefix of the token that (a)
+ * contains 'first letter' and (b) is braces-balanced; if 'first letter' is
+ * undefined, 'abbreviation' is the token itself; in the above examples,
+ * 'abbreviation's are "a", "{\"{U}}", "{\noopsort{\"o}}", "{\AE}",
+ * "\aex\ijk\Oe\j";
+ * </ul>
+ * <li> the behavior based on the above definitions will be erroneous only in
+ * one case: if the first-name-token is "{\noopsort{A}}john", we abbreviate it
+ * as "{\noopsort{A}}.", while BiBTeX produces "j."; fixing this problem,
+ * however, requires processing of the preabmle;
+ * </ul>
+ * <li> 'author name's in 'author field' are subsequences of tokens separated by
+ * token "and" ("and" is case-insensitive); if 'author name' is an empty
+ * sequence of tokens, it is ignored; for examle, both "John Smith and Peter
+ * Black" and "and and John Smith and and Peter Black" consists of 2 'author
+ * name's "Johm Smith" and "Peter Black" (in erroneous situations, this is a bit
+ * different from BiBTeX behavior);
* <li> 'author name' consists of 'first-part', 'von-part', 'last-part', and
- * 'junior-part', each of which is a sequence of tokens;
- * how a sequence of tokens has to be splitted into these parts, depends
- * the number of commas:
- * <ul>
- * <li> no commas, all tokens are upper-case:
- * 'junior-part' and 'von-part' are empty, 'last-part' consist
- * of the last token, 'first-part' consists of all other tokens
- * ('first-part' is empty, if 'author name' consists of a single token);
- * for example, in "John James Smith", 'last-part'="Smith" and
- * 'first-part'="John James";
- * <li> no commas, there exists lower-case token:
- * 'junior-part' is empty, 'first-part' consists of all upper-case
- * tokens before the first lower-case token, 'von-part' consists of
- * lower-case tokens starting the first lower-case token and ending
- * the lower-case token that is followed by upper-case token,
- * 'last-part' consists of the rest of tokens;
- * note that both 'first-part' and 'latst-part' may be empty and
- * 'last-part' may contain lower-case tokens; for example:
- * in "von der", 'first-part'='last-part'="", 'von-part'="von der";
- * in "Charles Louis Xavier Joseph de la Vall{\'e}e la Poussin",
- * 'first-part'="Charles Louis Xavier Joseph", 'von-part'="de la",
- * 'last-part'="Vall{\'e}e la Poussin";
- * <li> one comma:
- * 'junior-part' is empty, 'first-part' consists of all tokens after comma,
- * 'von-part' consists of the longest sequence of lower-case tokens
- * in the very beginning, 'last-part' consists of all tokens after
- * 'von-part' and before comma; note that any part can be empty;
- * for example: in "de la Vall{\'e}e la Poussin, Charles Louis Xavier Joseph",
- * 'first-part'="Charles Louis Xavier Joseph", 'von-part'="de la",
- * 'last-part'="Vall{\'e}e la Poussin";
- * in "Joseph de la Vall{\'e}e la Poussin, Charles Louis Xavier",
- * 'first-part'="Charles Louis Xavier", 'von-part'="",
- * 'last-part'="Joseph de la Vall{\'e}e la Poussin";
- * <li> two or more commas (any comma after the second one is ignored;
- * it merely separates tokens):
- * 'junior-part' consists of all tokens between first and second commas,
- * 'first-part' consists of all tokens after the second comma,
- * tokens before the first comma are splitted into 'von-part' and
- * 'last-part' similarly to the case of one comma; for example:
- * in "de la Vall{\'e}e Poussin, Jr., Charles Louis Xavier Joseph",
- * 'first-part'="Charles Louis Xavier Joseph", 'von-part'="de la",
- * 'last-part'="Vall{\'e}e la Poussin", and 'junior-part'="Jr.";
- * </ul>
- * <li> when 'first-part', 'last-part', 'von-part', or 'junior-part' is reconstructed
- * from tokens, tokens in a part are separated either by space or by dash,
- * depending on whether the token before the separator was space-terminated
- * or dash-terminated; for the last token in a part it does not matter
- * whether it was dash- or space-terminated;
- * <li> when 'first-part' is abbreviated, each token is replaced by its abbreviation
- * followed by a period; separators are the same as in the case of non-abbreviated
- * name; for example: in "Heinrich-{\"{U}}bel Kurt von Minich",
- * 'first-part'="Heinrich-{\"{U}}bel Kurt", and its abbreviation is
- * "H.-{\"{U}}. K."
+ * 'junior-part', each of which is a sequence of tokens; how a sequence of
+ * tokens has to be splitted into these parts, depends the number of commas:
+ * <ul>
+ * <li> no commas, all tokens are upper-case: 'junior-part' and 'von-part' are
+ * empty, 'last-part' consist of the last token, 'first-part' consists of all
+ * other tokens ('first-part' is empty, if 'author name' consists of a single
+ * token); for example, in "John James Smith", 'last-part'="Smith" and
+ * 'first-part'="John James";
+ * <li> no commas, there exists lower-case token: 'junior-part' is empty,
+ * 'first-part' consists of all upper-case tokens before the first lower-case
+ * token, 'von-part' consists of lower-case tokens starting the first lower-case
+ * token and ending the lower-case token that is followed by upper-case token,
+ * 'last-part' consists of the rest of tokens; note that both 'first-part' and
+ * 'latst-part' may be empty and 'last-part' may contain lower-case tokens; for
+ * example: in "von der", 'first-part'='last-part'="", 'von-part'="von der"; in
+ * "Charles Louis Xavier Joseph de la Vall{\'e}e la Poussin",
+ * 'first-part'="Charles Louis Xavier Joseph", 'von-part'="de la",
+ * 'last-part'="Vall{\'e}e la Poussin";
+ * <li> one comma: 'junior-part' is empty, 'first-part' consists of all tokens
+ * after comma, 'von-part' consists of the longest sequence of lower-case tokens
+ * in the very beginning, 'last-part' consists of all tokens after 'von-part'
+ * and before comma; note that any part can be empty; for example: in "de la
+ * Vall{\'e}e la Poussin, Charles Louis Xavier Joseph", 'first-part'="Charles
+ * Louis Xavier Joseph", 'von-part'="de la", 'last-part'="Vall{\'e}e la
+ * Poussin"; in "Joseph de la Vall{\'e}e la Poussin, Charles Louis Xavier",
+ * 'first-part'="Charles Louis Xavier", 'von-part'="", 'last-part'="Joseph de la
+ * Vall{\'e}e la Poussin";
+ * <li> two or more commas (any comma after the second one is ignored; it merely
+ * separates tokens): 'junior-part' consists of all tokens between first and
+ * second commas, 'first-part' consists of all tokens after the second comma,
+ * tokens before the first comma are splitted into 'von-part' and 'last-part'
+ * similarly to the case of one comma; for example: in "de la Vall{\'e}e
+ * Poussin, Jr., Charles Louis Xavier Joseph", 'first-part'="Charles Louis
+ * Xavier Joseph", 'von-part'="de la", 'last-part'="Vall{\'e}e la Poussin", and
+ * 'junior-part'="Jr.";
+ * </ul>
+ * <li> when 'first-part', 'last-part', 'von-part', or 'junior-part' is
+ * reconstructed from tokens, tokens in a part are separated either by space or
+ * by dash, depending on whether the token before the separator was
+ * space-terminated or dash-terminated; for the last token in a part it does not
+ * matter whether it was dash- or space-terminated;
+ * <li> when 'first-part' is abbreviated, each token is replaced by its
+ * abbreviation followed by a period; separators are the same as in the case of
+ * non-abbreviated name; for example: in "Heinrich-{\"{U}}bel Kurt von Minich",
+ * 'first-part'="Heinrich-{\"{U}}bel Kurt", and its abbreviation is "H.-{\"{U}}.
+ * K."
* </ol>
+ *
+ * @see tests.net.sf.jabref.AuthorListTest Testcases for this class.
*/
public class AuthorList {
- private Vector authors; // of Author
-
- // Variables for storing computed strings, so they only need be created once:
- private String authorsNatbib=null, authorsLastOnly=null, authorsLastFirst=null, authorLastFirstAnds=null,
- authorsFirstFirst=null, authorsFirstFirstAnds=null, authorsAlph=null;
-
-
- // The following variables are used only during parsing
-
- private String orig; // the raw bibtex author/editor field
- // the following variables are updated by getToken procedure
- private int token_start; // index in orig
- private int token_end; // to point 'abc' in ' abc xyz', start=2 and end=5
- // the following variables are valid only if getToken returns TOKEN_WORD
- private int token_abbr; // end of token abbreviation (always: token_start < token_abbr <= token_end)
- private char token_term; // either space or dash
- private boolean token_case; // true if upper-case token, false if lower-case token
-
- // Tokens of one author name.
- // Each token occupies TGL consecutive entries in this vector (as described below)
- private Vector tokens;
- private static final int TOKEN_GROUP_LENGTH = 4; // number of entries for a token
- // the following are offsets of an entry in a group of entries for one token
- private static final int OFFSET_TOKEN = 0; // String -- token itself;
- private static final int OFFSET_TOKEN_ABBR = 1; // String -- token abbreviation;
- private static final int OFFSET_TOKEN_TERM = 2; // Character -- token terminator (either " " or "-")
- //private static final int OFFSET_TOKEN_CASE = 3; // Boolean -- true=uppercase, false=lowercase
- // the following are indices in 'tokens' vector created during parsing of author name
- // and later used to properly split author name into parts
- int von_start, // first lower-case token (-1 if all tokens upper-case)
- last_start, // first upper-case token after first lower-case token (-1 if does not exist)
- comma_first, // token after first comma (-1 if no commas)
- comma_second; // token after second comma (-1 if no commas or only one comma)
-
- // Token types (returned by getToken procedure)
- private static final int TOKEN_EOF = 0;
- private static final int TOKEN_AND = 1;
- private static final int TOKEN_COMMA = 2;
- private static final int TOKEN_WORD = 3;
-
- // Constant Hashtable containing names of TeX special characters
- private static final java.util.Hashtable tex_names = new java.util.Hashtable();
- // and static constructor to initialize it
- static {
- tex_names.put("aa","aa"); // only keys are important in this table
- tex_names.put("ae","ae");
- tex_names.put("l","l");
- tex_names.put("o","o");
- tex_names.put("oe","oe");
- tex_names.put("i","i");
- tex_names.put("AA","AA");
- tex_names.put("AE","AE");
- tex_names.put("L","L");
- tex_names.put("O","O");
- tex_names.put("OE","OE");
- tex_names.put("j","j");
- }
-
- static WeakHashMap authorCache = new WeakHashMap();
-
- /**
- * Parses the parameter strings and stores preformatted author information.
- * @param bibtex_authors contents of either <CODE>author</CODE> or
- * <CODE>editor</CODE> bibtex field.
- */
- public AuthorList (String bibtex_authors) {
- authors = new Vector(5); // 5 seems to be reasonable initial size
- orig = bibtex_authors; // initialization
- token_start = 0; token_end = 0; // of parser
- while (token_start < orig.length()) {
- Author author = getAuthor();
- if (author != null) authors.add(author);
- }
- // clean-up
- orig = null; tokens = null;
- }
-
- public static String fixAuthor_Natbib(final String inOrig) {
- AuthorList authors = new AuthorList(inOrig);
- return authors.getAuthorsNatbib();
- }
-
- public static AuthorList getAuthorList(String inOrig) {
- Object o = authorCache.get(inOrig);
- if (o == null) {
- AuthorList authors = new AuthorList(inOrig);
- authorCache.put(inOrig, authors);
- return authors;
- } else
- return (AuthorList)o;
- }
-
- public static String fixAuthor_firstNameFirstCommas(final String inOrig, final boolean abbr) {
- AuthorList authors = getAuthorList(inOrig);
- return authors.getAuthorsFirstFirst(abbr);
- }
-
- public static String fixAuthor_firstNameFirst(final String inOrig) {
- AuthorList authors = getAuthorList(inOrig);
- return authors.getAuthorsFirstFirstAnds();
- }
-
- public static String fixAuthor_lastNameFirstCommas(final String inOrig, final boolean abbr) {
- AuthorList authors = getAuthorList(inOrig);
- return authors.getAuthorsLastFirst(abbr);
- }
-
- public static String fixAuthor_lastNameFirst(final String inOrig) {
- AuthorList authors = getAuthorList(inOrig);
- return authors.getAuthorsLastFirstAnds();
- }
-
- public static String fixAuthor_lastNameOnlyCommas(final String inOrig) {
- AuthorList authors = getAuthorList(inOrig);
- return authors.getAuthorsLastOnly();
- }
-
- public static String fixAuthorForAlphabetization(final String inOrig) {
- AuthorList authors = getAuthorList(inOrig);
- return authors.getAuthorsForAlphabetization();
-
- }
-
-
- /**
- * Parses one author name and returns preformatted information.
- * @return Preformatted author name; <CODE>null</CODE> if author name is empty.
- */
- private Author getAuthor() {
-
- tokens = new Vector(); // initialization
- von_start = -1; last_start = -1; comma_first = -1; comma_second = -1;
-
- // First step: collect tokens in 'tokens' Vector and calculate indices
- token_loop:
- while (true) {
- int token = getToken();
- cases: switch (token) {
- case TOKEN_EOF : case TOKEN_AND : break token_loop;
- case TOKEN_COMMA :
- if (comma_first < 0) comma_first = tokens.size();
- else if (comma_second < 0) comma_second = tokens.size();
- break cases;
- case TOKEN_WORD :
- tokens.add(orig.substring(token_start, token_end));
- tokens.add(orig.substring(token_start, token_abbr));
- tokens.add(new Character(token_term));
- tokens.add(Boolean.valueOf(token_case));
- if (comma_first >= 0) break cases;
- if (last_start >= 0) break cases;
- if (von_start < 0) {
- if (!token_case) {
- von_start = tokens.size()-TOKEN_GROUP_LENGTH; break cases;
- }
- } else if (last_start < 0 && token_case) {
- last_start = tokens.size()-TOKEN_GROUP_LENGTH; break cases;
- }
- }
- }// end token_loop
-
- // Second step: split name into parts (here: calculate indices
- // of parts in 'tokens' Vector)
- if (tokens.size()==0) return null; // no author information
-
- // the following negatives indicate absence of the corresponding part
- int first_part_start=-1, von_part_start=-1, last_part_start=-1, jr_part_start=-1;
- int first_part_end=0, von_part_end=0, last_part_end=0, jr_part_end=0;
- if (comma_first<0) { // no commas
- if (von_start<0) { // no 'von part'
- last_part_end = tokens.size();
- last_part_start = tokens.size() - TOKEN_GROUP_LENGTH;
- first_part_end = last_part_start;
- if (first_part_end>0) first_part_start = 0;
- } else { // 'von part' is present
- if (last_start>=0) {
- last_part_end = tokens.size();
- last_part_start = last_start;
- von_part_end = last_part_start;
- } else {
- von_part_end = tokens.size();
- }
- von_part_start = von_start;
- first_part_end = von_part_start;
- if (first_part_end>0) first_part_start = 0;
- }
- } else { // commas are present: it affects only 'first part' and 'junior part'
- first_part_end = tokens.size();
- if (comma_second<0) { // one comma
- if (comma_first < first_part_end) first_part_start = comma_first;
- } else { // two or more commas
- if (comma_second < first_part_end) first_part_start = comma_second;
- jr_part_end = comma_second;
- if (comma_first < jr_part_end) jr_part_start = comma_first;
- }
- if (von_start!=0) { // no 'von part'
- last_part_end = comma_first;
- if (last_part_end>0) last_part_start = 0;
- } else { // 'von part' is present
- if (last_start<0) {
- von_part_end = comma_first;
- } else {
- last_part_end = comma_first;
- last_part_start = last_start;
- von_part_end = last_part_start;
- }
- von_part_start = 0;
- }
- }
-
- // Third step: do actual splitting, construct Author object
- return new Author(
- (first_part_start<0 ? null : concatTokens(first_part_start,first_part_end,OFFSET_TOKEN,false)),
- (first_part_start<0 ? null : concatTokens(first_part_start,first_part_end,OFFSET_TOKEN_ABBR,true)),
- ( von_part_start<0 ? null : concatTokens( von_part_start, von_part_end,OFFSET_TOKEN,false)),
- ( last_part_start<0 ? null : concatTokens( last_part_start, last_part_end,OFFSET_TOKEN,false)),
- ( jr_part_start<0 ? null : concatTokens( jr_part_start, jr_part_end,OFFSET_TOKEN,false))
- );
- }
-
- /**
- * Concatenates list of tokens from 'tokens' Vector.
- * Tokens are separated by spaces or dashes, dependeing on stored in 'tokens'.
- * Callers always ensure that start < end; thus, there exists at least
- * one token to be concatenated.
- * @param start index of the first token to be concatenated in 'tokens' Vector
- * (always divisible by TOKEN_GROUP_LENGTH).
- * @param end index of the first token not to be concatenated in 'tokens' Vector
- * (always divisible by TOKEN_GROUP_LENGTH).
- * @param offset offset within token group (used to request concatenation of
- * either full tokens or abbreviation).
- * @param dot_after <CODE>true</CODE> -- add period after each token,
- * <CODE>false</CODE> -- do not add.
- * @return the result of concatenation.
- */
- private String concatTokens(int start, int end, int offset, boolean dot_after) {
- StringBuffer res = new StringBuffer();
- // Here we always have start < end
- res.append((String) tokens.get(start+offset));
- if (dot_after) res.append('.');
- start += TOKEN_GROUP_LENGTH;
- while (start < end) {
- res.append(tokens.get(start-TOKEN_GROUP_LENGTH+OFFSET_TOKEN_TERM));
- res.append((String) tokens.get(start+offset));
- if (dot_after) res.append('.');
- start += TOKEN_GROUP_LENGTH;
- }
- return res.toString();
- }
-
- /**
- * Parses the next token.
- * <p>
- * The string being parsed is stored in global variable <CODE>orig</CODE>,
- * and position which parsing has to start from is stored in global
- * variable <CODE>token_end</CODE>; thus, <CODE>token_end</CODE> has to be
- * set to 0 before the first invocation. Procedure updates <CODE>token_end</CODE>;
- * thus, subsequent invocations do not require any additional variable settings.
- * <p>
- * The type of the token is returned; if it is <CODE>TOKEN_WORD</CODE>, additional
- * information is given in global variables <CODE>token_start</CODE>, <CODE>token_end</CODE>,
- * <CODE>token_abbr</CODE>, <CODE>token_term</CODE>, and <CODE>token_case</CODE>;
- * namely: <CODE>orig.substring(token_start,token_end)</CODE> is the thext of the token,
- * <CODE>orig.substring(token_start,token_abbr)</CODE> is the token abbreviation,
- * <CODE>token_term</CODE> contains token terminator (space or dash),
- * and <CODE>token_case</CODE> is <CODE>true</CODE>, if token is upper-case
- * and <CODE>false</CODE> if token is lower-case.
- * @return <CODE>TOKEN_EOF</CODE> -- no more tokens,
- * <CODE>TOKEN_COMMA</CODE> -- token is comma,
- * <CODE>TOKEN_AND</CODE> -- token is the word "and" (or "And", or "aND", etc.),
- * <CODE>TOKEN_WORD</CODE> -- token is a word; additional information is given
- * in global variables <CODE>token_start</CODE>, <CODE>token_end</CODE>,
- * <CODE>token_abbr</CODE>, <CODE>token_term</CODE>, and <CODE>token_case</CODE>.
- */
- private int getToken() {
- token_start = token_end;
- while (token_start < orig.length()) {
- char c = orig.charAt(token_start);
- if ( !(c=='~' || c=='-' || Character.isWhitespace(c)) ) break;
- token_start++;
- }
- token_end = token_start;
- if (token_start >= orig.length()) return TOKEN_EOF;
- if (orig.charAt(token_start)==',') { token_end++; return TOKEN_COMMA; }
- token_abbr = -1;
- token_term = ' ';
- token_case = true;
- int braces_level = 0;
- int current_backslash = -1;
- boolean first_letter_is_found = false;
- while (token_end < orig.length()) {
- char c = orig.charAt(token_end);
- if (c=='{') { braces_level++; }
- if (braces_level > 0) if (c=='}') braces_level--;
- if (first_letter_is_found && token_abbr<0 && braces_level==0) token_abbr = token_end;
- if (!first_letter_is_found && current_backslash<0 && Character.isLetter(c)) {
- token_case = Character.isUpperCase(c); first_letter_is_found = true;
- }
- if (current_backslash>=0 && !Character.isLetter(c)) {
- if (!first_letter_is_found) {
- String tex_cmd_name = orig.substring(current_backslash+1, token_end);
- if (tex_names.get(tex_cmd_name)!=null) {
- token_case = Character.isUpperCase(tex_cmd_name.charAt(0));
- first_letter_is_found = true;
- }
- }
- current_backslash = -1;
- }
- if (c=='\\') current_backslash = token_end;
- if (braces_level==0)
- if (c==',' || c=='~' || /*c=='-' ||*/ Character.isWhitespace(c)) break;
- // Morten Alver 18 Apr 2006: Removed check for hyphen '-' above to prevent
- // problems with names like Bailey-Jones getting broken up and sorted wrong.
- token_end++;
- }
- if (token_abbr<0) token_abbr = token_end;
- if (token_end<orig.length() && orig.charAt(token_end)=='-') token_term='-';
- if (orig.substring(token_start,token_end).equalsIgnoreCase("and"))
- return TOKEN_AND; else return TOKEN_WORD;
- }
-
- /**
- * Returns the number of author names in this object.
- * @return the number of author names in this object.
- */
- public int size() { return authors.size(); }
- /**
- * Returns the <CODE>Author</CODE> object for ith author.
- * @param i index of the author (from 0 to <CODE>size()-1</CODE>).
- * @return the <CODE>Author</CODE> object.
- */
- public Author getAuthor(int i) { return (Author) authors.get(i); }
- /**
- * Returns the list of authors in "natbib" format.
- * <p>
- * "John Smith" ==> "Smith";
- * "John Smith and Black Brown, Peter" ==> "Smith and Black Brown";
- * "John von Neumann and John Smith and Black Brown, Peter" ==> "von Neumann et al.".
- * @return formatted list of authors.
- */
- public String getAuthorsNatbib() {
- // Check if we've computed this before:
- if (authorsNatbib != null)
- return authorsNatbib;
-
- StringBuffer res = new StringBuffer();
- if (size()>0) {
- res.append(getAuthor(0).getLastOnly());
- if (size()==2) {
- res.append(" and ");
- res.append(getAuthor(1).getLastOnly());
- } else if (size()>2) {
- res.append(" et al.");
- }
- }
- authorsNatbib = res.toString();
- return authorsNatbib;
- }
- /**
- * Returns the list of authors separated by commas with last name only;
- * If the list consists of three or more authors, "and" is inserted before
- * the last author's name.
- * <p>
- * "John Smith" ==> "Smith";
- * "John Smith and Black Brown, Peter" ==> "Smith and Black Brown" ;
- * "John von Neumann and John Smith and Black Brown, Peter" ==>
- * "von Neumann, Smith and Black Brown".
- * @return formatted list of authors.
- */
- public String getAuthorsLastOnly() {
- // Check if we've computed this before:
- if (authorsLastOnly != null)
- return authorsLastOnly;
- StringBuffer res = new StringBuffer();
- if (size() > 0) {
- res.append(getAuthor(0).getLastOnly());
- int i = 1;
- while (i < size() - 1) {
- res.append(", ");
- res.append(getAuthor(i).getLastOnly());
- i++;
- }
- if (size() > 2) res.append(",");
- if (size() > 1) {
- res.append(" and ");
- res.append(getAuthor(i).getLastOnly());
- }
- }
- authorsLastOnly = res.toString();
- return authorsLastOnly;
- }
- /**
- * Returns the list of authors separated by commas with first names after last name;
- * first names are abbreviated or not depending on parameter.
- * If the list consists of three or more authors, "and" is inserted before
- * the last author's name.
- * <p>
- * "John Smith" ==> "Smith, John" or "Smith, J.";
- * "John Smith and Black Brown, Peter" ==>
- * "Smith, John and Black Brown, Peter" or "Smith, J. and Black Brown, P.";
- * "John von Neumann and John Smith and Black Brown, Peter" ==>
- * "von Neumann, John, Smith, John and Black Brown, Peter" or
- * "von Neumann, J., Smith, J. and Black Brown, P.".
- * @param abbr <CODE>true</CODE> -- abbreviate first names,
- * <CODE>false</CODE> -- do not abbreviate.
- * @return formatted list of authors.
- */
- public String getAuthorsLastFirst(boolean abbr) {
- // Check if we've computed this before:
- if (authorsLastFirst != null)
- return authorsLastFirst;
-
- StringBuffer res = new StringBuffer();
- if (size()>0) {
- res.append(getAuthor(0).getLastFirst(abbr));
- int i = 1;
- while (i < size()-1) {
- res.append(", ");
- res.append(getAuthor(i).getLastFirst(abbr));
- i++;
- }
- if (size() > 2) res.append(",");
- if (size() > 1) {
- res.append(" and ");
- res.append(getAuthor(i).getLastFirst(abbr));
- }
- }
- authorsLastFirst = res.toString();
- return authorsLastFirst;
- }
- /**
- * Returns the list of authors separated by "and"s with first names after last name;
- * first names are not abbreviated.
- * <p>
- * "John Smith" ==> "Smith, John";
- * "John Smith and Black Brown, Peter" ==> "Smith, John and Black Brown, Peter";
- * "John von Neumann and John Smith and Black Brown, Peter" ==>
- * "von Neumann, John and Smith, John and Black Brown, Peter".
- * @return formatted list of authors.
- */
- public String getAuthorsLastFirstAnds() {
- // Check if we've computed this before:
- if (authorLastFirstAnds != null)
- return authorLastFirstAnds;
-
- StringBuffer res = new StringBuffer();
- if (size()>0) {
- res.append(getAuthor(0).getLastFirst(false));
- for (int i=1; i<size(); i++) {
- res.append(" and ");
- res.append(getAuthor(i).getLastFirst(false));
- }
- }
-
- authorLastFirstAnds = res.toString();
- return authorLastFirstAnds;
- }
- /**
- * Returns the list of authors separated by commas with first names before last name;
- * first names are abbreviated or not depending on parameter.
- * If the list consists of three or more authors, "and" is inserted before
- * the last author's name.
- * <p>
- * "John Smith" ==> "John Smith" or "J. Smith";
- * "John Smith and Black Brown, Peter" ==>
- * "John Smith and Peter Black Brown" or "J. Smith and P. Black Brown";
- * "John von Neumann and John Smith and Black Brown, Peter" ==>
- * "John von Neumann, John Smith and Peter Black Brown" or
- * "J. von Neumann, J. Smith and P. Black Brown".
- * @param abbr <CODE>true</CODE> -- abbreviate first names,
- * <CODE>false</CODE> -- do not abbreviate.
- * @return formatted list of authors.
- */
- public String getAuthorsFirstFirst(boolean abbr) {
- // Check if we've computed this before:
- if (authorsFirstFirst != null)
- return authorsFirstFirst;
-
- StringBuffer res = new StringBuffer();
- if (size()>0) {
- res.append(getAuthor(0).getFirstLast(abbr));
- int i = 1;
- while (i < size()-1) {
- res.append(", ");
- res.append(getAuthor(i).getFirstLast(abbr));
- i++;
- }
- if (size() > 2) res.append(",");
- if (size() > 1) {
- res.append(" and ");
- res.append(getAuthor(i).getFirstLast(abbr));
- }
- }
- authorsFirstFirst = res.toString();
- return authorsFirstFirst;
- }
- /**
- * Returns the list of authors separated by "and"s with first names before last name;
- * first names are not abbreviated.
- * <p>
- * "John Smith" ==> "John Smith";
- * "John Smith and Black Brown, Peter" ==> "John Smith and Peter Black Brown";
- * "John von Neumann and John Smith and Black Brown, Peter" ==>
- * "John von Neumann and John Smith and Peter Black Brown".
- * @return formatted list of authors.
- */
- public String getAuthorsFirstFirstAnds() {
- // Check if we've computed this before:
- if (authorsFirstFirstAnds != null)
- return authorsFirstFirstAnds;
-
- StringBuffer res = new StringBuffer();
- if (size()>0) {
- res.append(getAuthor(0).getFirstLast(false));
- for (int i=1; i<size(); i++) {
- res.append(" and ");
- res.append(getAuthor(i).getFirstLast(false));
- }
- }
- authorsFirstFirstAnds = res.toString();
- return authorsFirstFirstAnds;
- }
-
- /**
- * Returns the list of authors in a form suitable for alphabetization. This means that
- * last names come first, never preceded by "von" particles, and that any braces are
- * removed. First names are abbreviated so the same name is treated similarly if abbreviated
- * in one case and not in another.
- * This form is not intended to be suitable for presentation, only for sorting.
- *
- * <p>
- * "John Smith" ==> "Smith, J.";
- * "John von Neumann
- * @return formatted list of authors
- */
- public String getAuthorsForAlphabetization() {
- if (authorsAlph != null)
- return authorsAlph;
-
- StringBuffer res = new StringBuffer();
- if (size()>0) {
- res.append(getAuthor(0).getNameForAlphabetization());
- for (int i=1; i<size(); i++) {
- res.append(" and ");
- res.append(getAuthor(i).getNameForAlphabetization());
- }
- }
- authorsAlph = res.toString();
- return authorsAlph;
- }
-
-
-
- /**
- * This is an immutable class that keeps information regarding single author.
- * It is just a container for the information, with very simple methods
- * to access it.
- * <p>
- * Current usage: only methods <code>getLastOnly</code>,
- * <code>getFirstLast</code>, and <code>getLastFirst</code> are used;
- * all other methods are provided for completeness.
- */
- private static class Author {
- private final String first_part;
- private final String first_abbr;
- private final String von_part;
- private final String last_part;
- private final String jr_part;
- /**
- * Creates the Author object.
- * If any part of the name is absent, <CODE>null</CODE> must be passes;
- * otherwise other methods may return erroneous results.
- * @param first the first name of the author (may consist of several tokens,
- * like "Charles Louis Xavier Joseph" in
- * "Charles Louis Xavier Joseph de la Vall{\'e}e Poussin")
- * @param firstabbr the abbreviated first name of the author (may consist
- * of several tokens, like "C. L. X. J." in
- * "Charles Louis Xavier Joseph de la Vall{\'e}e Poussin").
- * It is a responsibility of the caller to create a reasonable
- * abbreviation of the first name.
- * @param von the von part of the author's name (may consist of
- * several tokens, like "de la" in
- * "Charles Louis Xavier Joseph de la Vall{\'e}e Poussin")
- * @param last the lats name of the author (may consist of several tokens,
- * like "Vall{\'e}e Poussin" in
- * "Charles Louis Xavier Joseph de la Vall{\'e}e Poussin")
- * @param jr the junior part of the author's name (may consist of
- * several tokens, like "Jr. III" in
- * "Smith, Jr. III, John")
- */
- public Author(String first, String firstabbr, String von, String last, String jr) {
- first_part = first;
- first_abbr = firstabbr;
- von_part = von;
- last_part = last;
- jr_part = jr;
- }
- /**
- * Retunrns the first name of the author stored in this object.
- * @return first name of the author (may consist of several tokens)
- */
- public String getFirst() { return first_part; }
- /**
- * Retunrns the abbreviated first name of the author stored in this object.
- * @return abbreviated first name of the author (may consist of several tokens)
- */
- public String getFirstAbbr() { return first_abbr; }
- /**
- * Retunrns the von part of the author's name stored in this object.
- * @return von part of the author's name (may consist of several tokens)
- */
- public String getVon() { return von_part; }
- /**
- * Retunrns the last name of the author stored in this object.
- * @return last name of the author (may consist of several tokens)
- */
- public String getLast() { return last_part; }
- /**
- * Retunrns the junior part of the author's name stored in this object.
- * @return junior part of the author's name (may consist of several tokens)
- */
- public String getJr() { return jr_part; }
- /**
- * Returns von part followed by last name.
- * If both fields were specified as <CODE>null</CODE>,
- * the empty string <CODE>""</CODE> is returned.
- * @return 'von Last'
- */
- public String getLastOnly() {
- if (von_part==null) {
- return (last_part==null ? "" : last_part);
- } else {
- return (last_part==null ? von_part : von_part + " " + last_part);
- }
- }
- /**
- * Returns the author's name in form 'von Last, Jr., First' with the first name
- * full or abbreviated depending on parameter.
- * @param abbr <CODE>true</CODE> - abbreviate first name,
- * <CODE>false</CODE> - do not abbreviate
- * @return 'von Last, Jr., First' (if <CODE>abbr==false</CODE>) or
- * 'von Last, Jr., F.' (if <CODE>abbr==true</CODE>)
- */
- public String getLastFirst(boolean abbr) {
- String res = getLastOnly();
- if (jr_part != null) res += ", " + jr_part;
- if (abbr) {
- if (first_abbr != null) res += ", " + first_abbr;
- } else {
- if (first_part != null) res += ", " + first_part;
- }
- return res;
- }
- /**
- * Returns the author's name in form 'First von Last, Jr.' with the first name
- * full or abbreviated depending on parameter.
- * @param abbr <CODE>true</CODE> - abbreviate first name,
- * <CODE>false</CODE> - do not abbreviate
- * @return 'First von Last, Jr.' (if <CODE>abbr==false</CODE>) or
- * 'F. von Last, Jr.' (if <CODE>abbr==true</CODE>)
- */
- public String getFirstLast(boolean abbr) {
- String res = getLastOnly();
- if (abbr) {
- res = (first_abbr==null ? "" : first_abbr + " ") + res;
- } else {
- res = (first_part==null ? "" : first_part + " ") + res;
- }
- if (jr_part != null) res += ", " + jr_part;
- return res;
- }
-
- public String getNameForAlphabetization() {
- StringBuffer res = new StringBuffer();
- if (last_part != null)
- res.append(last_part);
- if (jr_part != null) {
- res.append(", ");
- res.append(jr_part);
- }
- if (first_abbr != null) {
- res.append(", ");
- res.append(first_abbr);
- }
- while ((res.length() > 0) && (res.charAt(0) == '{'))
- res.deleteCharAt(0);
- return res.toString();
-
- }
- }//end Author
-}//end AuthorList
+ private Vector authors; // of Author
+
+ // Variables for storing computed strings, so they only need be created
+ // once:
+ private String authorsNatbib = null, authorsFirstFirstAnds = null,
+ authorsAlph = null;
+
+ private String[] authorsFirstFirst = new String[4], authorsLastOnly = new String[2],
+ authorLastFirstAnds = new String[2],
+ authorsLastFirst = new String[4];
+
+ // The following variables are used only during parsing
+
+ private String orig; // the raw bibtex author/editor field
+
+ // the following variables are updated by getToken procedure
+ private int token_start; // index in orig
+
+ private int token_end; // to point 'abc' in ' abc xyz', start=2 and end=5
+
+ // the following variables are valid only if getToken returns TOKEN_WORD
+ private int token_abbr; // end of token abbreviation (always: token_start <
+
+ // token_abbr <= token_end)
+
+ private char token_term; // either space or dash
+
+ private boolean token_case; // true if upper-case token, false if lower-case
+
+ // token
+
+ // Tokens of one author name.
+ // Each token occupies TGL consecutive entries in this vector (as described
+ // below)
+ private Vector tokens;
+
+ private static final int TOKEN_GROUP_LENGTH = 4; // number of entries for
+
+ // a token
+
+ // the following are offsets of an entry in a group of entries for one token
+ private static final int OFFSET_TOKEN = 0; // String -- token itself;
+
+ private static final int OFFSET_TOKEN_ABBR = 1; // String -- token
+
+ // abbreviation;
+
+ private static final int OFFSET_TOKEN_TERM = 2; // Character -- token
+
+ // terminator (either " " or
+ // "-")
+
+ // private static final int OFFSET_TOKEN_CASE = 3; // Boolean --
+ // true=uppercase, false=lowercase
+ // the following are indices in 'tokens' vector created during parsing of
+ // author name
+ // and later used to properly split author name into parts
+ int von_start, // first lower-case token (-1 if all tokens upper-case)
+ last_start, // first upper-case token after first lower-case token (-1
+ // if does not exist)
+ comma_first, // token after first comma (-1 if no commas)
+ comma_second; // token after second comma (-1 if no commas or only one
+
+ // comma)
+
+ // Token types (returned by getToken procedure)
+ private static final int TOKEN_EOF = 0;
+
+ private static final int TOKEN_AND = 1;
+
+ private static final int TOKEN_COMMA = 2;
+
+ private static final int TOKEN_WORD = 3;
+
+ // Constant Hashtable containing names of TeX special characters
+ private static final java.util.Hashtable tex_names = new java.util.Hashtable();
+ // and static constructor to initialize it
+ static {
+ tex_names.put("aa", "aa"); // only keys are important in this table
+ tex_names.put("ae", "ae");
+ tex_names.put("l", "l");
+ tex_names.put("o", "o");
+ tex_names.put("oe", "oe");
+ tex_names.put("i", "i");
+ tex_names.put("AA", "AA");
+ tex_names.put("AE", "AE");
+ tex_names.put("L", "L");
+ tex_names.put("O", "O");
+ tex_names.put("OE", "OE");
+ tex_names.put("j", "j");
+ }
+
+ static WeakHashMap authorCache = new WeakHashMap();
+
+ /**
+ * Parses the parameter strings and stores preformatted author information.
+ *
+ * Don't call this constructor directly but rather use the getAuthorList()
+ * method which caches its results.
+ *
+ * @param bibtex_authors
+ * contents of either <CODE>author</CODE> or <CODE>editor</CODE>
+ * bibtex field.
+ */
+ protected AuthorList(String bibtex_authors) {
+ authors = new Vector(5); // 5 seems to be reasonable initial size
+ orig = bibtex_authors; // initialization
+ token_start = 0;
+ token_end = 0; // of parser
+ while (token_start < orig.length()) {
+ Author author = getAuthor();
+ if (author != null)
+ authors.add(author);
+ }
+ // clean-up
+ orig = null;
+ tokens = null;
+ }
+
+ /**
+ * Retrieve an AuthorList for the given string of authors or editors.
+ *
+ * This function tries to cache AuthorLists by string passed in.
+ *
+ * @param authors
+ * The string of authors or editors in bibtex format to parse.
+ * @return An AuthorList object representing the given authors.
+ */
+ public static AuthorList getAuthorList(String authors) {
+ AuthorList authorList = (AuthorList) authorCache.get(authors);
+ if (authorList == null) {
+ authorList = new AuthorList(authors);
+ authorCache.put(authors, authorList);
+ }
+ return authorList;
+ }
+
+ /**
+ * This is a convenience method for getAuthorsFirstFirst()
+ *
+ * @see net.sf.jabref.AuthorList#getAuthorsFirstFirst
+ */
+ public static String fixAuthor_firstNameFirstCommas(String authors, boolean abbr,
+ boolean oxfordComma) {
+ return getAuthorList(authors).getAuthorsFirstFirst(abbr, oxfordComma);
+ }
+
+ /**
+ * This is a convenience method for getAuthorsFirstFirstAnds()
+ *
+ * @see net.sf.jabref.AuthorList#getAuthorsFirstFirstAnds
+ */
+ public static String fixAuthor_firstNameFirst(String authors) {
+ return getAuthorList(authors).getAuthorsFirstFirstAnds();
+ }
+
+ /**
+ * This is a convenience method for getAuthorsLastFirst()
+ *
+ * @see net.sf.jabref.AuthorList#getAuthorsLastFirst
+ */
+ public static String fixAuthor_lastNameFirstCommas(String authors, boolean abbr,
+ boolean oxfordComma) {
+ return getAuthorList(authors).getAuthorsLastFirst(abbr, oxfordComma);
+ }
+
+ /**
+ * This is a convenience method for getAuthorsLastFirstAnds(true)
+ *
+ * @see net.sf.jabref.AuthorList#getAuthorsLastFirstAnds
+ */
+ public static String fixAuthor_lastNameFirst(String authors) {
+ return getAuthorList(authors).getAuthorsLastFirstAnds(false);
+ }
+
+ /**
+ * This is a convenience method for getAuthorsLastFirstAnds()
+ *
+ * @see net.sf.jabref.AuthorList#getAuthorsLastFirstAnds
+ */
+ public static String fixAuthor_lastNameFirst(String authors, boolean abbreviate) {
+ return getAuthorList(authors).getAuthorsLastFirstAnds(abbreviate);
+ }
+
+ /**
+ * This is a convenience method for getAuthorsLastOnly()
+ *
+ * @see net.sf.jabref.AuthorList#getAuthorsLastOnly
+ */
+ public static String fixAuthor_lastNameOnlyCommas(String authors, boolean oxfordComma) {
+ return getAuthorList(authors).getAuthorsLastOnly(oxfordComma);
+ }
+
+ /**
+ * This is a convenience method for getAuthorsForAlphabetization()
+ *
+ * @see net.sf.jabref.AuthorList#getAuthorsForAlphabetization
+ */
+ public static String fixAuthorForAlphabetization(String authors) {
+ return getAuthorList(authors).getAuthorsForAlphabetization();
+ }
+
+ /**
+ * This is a convenience method for getAuthorsNatbib()
+ *
+ * @see net.sf.jabref.AuthorList#getAuthorsNatbib
+ */
+ public static String fixAuthor_Natbib(String authors) {
+ return AuthorList.getAuthorList(authors).getAuthorsNatbib();
+ }
+
+ /**
+ * Parses one author name and returns preformatted information.
+ *
+ * @return Preformatted author name; <CODE>null</CODE> if author name is
+ * empty.
+ */
+ private Author getAuthor() {
+
+ tokens = new Vector(); // initialization
+ von_start = -1;
+ last_start = -1;
+ comma_first = -1;
+ comma_second = -1;
+
+ // First step: collect tokens in 'tokens' Vector and calculate indices
+ token_loop: while (true) {
+ int token = getToken();
+ cases: switch (token) {
+ case TOKEN_EOF:
+ case TOKEN_AND:
+ break token_loop;
+ case TOKEN_COMMA:
+ if (comma_first < 0)
+ comma_first = tokens.size();
+ else if (comma_second < 0)
+ comma_second = tokens.size();
+ break cases;
+ case TOKEN_WORD:
+ tokens.add(orig.substring(token_start, token_end));
+ tokens.add(orig.substring(token_start, token_abbr));
+ tokens.add(new Character(token_term));
+ tokens.add(Boolean.valueOf(token_case));
+ if (comma_first >= 0)
+ break cases;
+ if (last_start >= 0)
+ break cases;
+ if (von_start < 0) {
+ if (!token_case) {
+ von_start = tokens.size() - TOKEN_GROUP_LENGTH;
+ break cases;
+ }
+ } else if (last_start < 0 && token_case) {
+ last_start = tokens.size() - TOKEN_GROUP_LENGTH;
+ break cases;
+ }
+ }
+ }// end token_loop
+
+ // Second step: split name into parts (here: calculate indices
+ // of parts in 'tokens' Vector)
+ if (tokens.size() == 0)
+ return null; // no author information
+
+ // the following negatives indicate absence of the corresponding part
+ int first_part_start = -1, von_part_start = -1, last_part_start = -1, jr_part_start = -1;
+ int first_part_end = 0, von_part_end = 0, last_part_end = 0, jr_part_end = 0;
+ if (comma_first < 0) { // no commas
+ if (von_start < 0) { // no 'von part'
+ last_part_end = tokens.size();
+ last_part_start = tokens.size() - TOKEN_GROUP_LENGTH;
+ first_part_end = last_part_start;
+ if (first_part_end > 0)
+ first_part_start = 0;
+ } else { // 'von part' is present
+ if (last_start >= 0) {
+ last_part_end = tokens.size();
+ last_part_start = last_start;
+ von_part_end = last_part_start;
+ } else {
+ von_part_end = tokens.size();
+ }
+ von_part_start = von_start;
+ first_part_end = von_part_start;
+ if (first_part_end > 0)
+ first_part_start = 0;
+ }
+ } else { // commas are present: it affects only 'first part' and
+ // 'junior part'
+ first_part_end = tokens.size();
+ if (comma_second < 0) { // one comma
+ if (comma_first < first_part_end)
+ first_part_start = comma_first;
+ } else { // two or more commas
+ if (comma_second < first_part_end)
+ first_part_start = comma_second;
+ jr_part_end = comma_second;
+ if (comma_first < jr_part_end)
+ jr_part_start = comma_first;
+ }
+ if (von_start != 0) { // no 'von part'
+ last_part_end = comma_first;
+ if (last_part_end > 0)
+ last_part_start = 0;
+ } else { // 'von part' is present
+ if (last_start < 0) {
+ von_part_end = comma_first;
+ } else {
+ last_part_end = comma_first;
+ last_part_start = last_start;
+ von_part_end = last_part_start;
+ }
+ von_part_start = 0;
+ }
+ }
+
+ // Third step: do actual splitting, construct Author object
+ return new Author((first_part_start < 0 ? null : concatTokens(first_part_start,
+ first_part_end, OFFSET_TOKEN, false)), (first_part_start < 0 ? null : concatTokens(
+ first_part_start, first_part_end, OFFSET_TOKEN_ABBR, true)), (von_part_start < 0 ? null
+ : concatTokens(von_part_start, von_part_end, OFFSET_TOKEN, false)),
+ (last_part_start < 0 ? null : concatTokens(last_part_start, last_part_end,
+ OFFSET_TOKEN, false)), (jr_part_start < 0 ? null : concatTokens(jr_part_start,
+ jr_part_end, OFFSET_TOKEN, false)));
+ }
+
+ /**
+ * Concatenates list of tokens from 'tokens' Vector. Tokens are separated by
+ * spaces or dashes, dependeing on stored in 'tokens'. Callers always ensure
+ * that start < end; thus, there exists at least one token to be
+ * concatenated.
+ *
+ * @param start
+ * index of the first token to be concatenated in 'tokens' Vector
+ * (always divisible by TOKEN_GROUP_LENGTH).
+ * @param end
+ * index of the first token not to be concatenated in 'tokens'
+ * Vector (always divisible by TOKEN_GROUP_LENGTH).
+ * @param offset
+ * offset within token group (used to request concatenation of
+ * either full tokens or abbreviation).
+ * @param dot_after
+ * <CODE>true</CODE> -- add period after each token, <CODE>false</CODE> --
+ * do not add.
+ * @return the result of concatenation.
+ */
+ private String concatTokens(int start, int end, int offset, boolean dot_after) {
+ StringBuffer res = new StringBuffer();
+ // Here we always have start < end
+ res.append((String) tokens.get(start + offset));
+ if (dot_after)
+ res.append('.');
+ start += TOKEN_GROUP_LENGTH;
+ while (start < end) {
+ res.append(tokens.get(start - TOKEN_GROUP_LENGTH + OFFSET_TOKEN_TERM));
+ res.append((String) tokens.get(start + offset));
+ if (dot_after)
+ res.append('.');
+ start += TOKEN_GROUP_LENGTH;
+ }
+ return res.toString();
+ }
+
+ /**
+ * Parses the next token.
+ * <p>
+ * The string being parsed is stored in global variable <CODE>orig</CODE>,
+ * and position which parsing has to start from is stored in global variable
+ * <CODE>token_end</CODE>; thus, <CODE>token_end</CODE> has to be set
+ * to 0 before the first invocation. Procedure updates <CODE>token_end</CODE>;
+ * thus, subsequent invocations do not require any additional variable
+ * settings.
+ * <p>
+ * The type of the token is returned; if it is <CODE>TOKEN_WORD</CODE>,
+ * additional information is given in global variables <CODE>token_start</CODE>,
+ * <CODE>token_end</CODE>, <CODE>token_abbr</CODE>, <CODE>token_term</CODE>,
+ * and <CODE>token_case</CODE>; namely: <CODE>orig.substring(token_start,token_end)</CODE>
+ * is the thext of the token, <CODE>orig.substring(token_start,token_abbr)</CODE>
+ * is the token abbreviation, <CODE>token_term</CODE> contains token
+ * terminator (space or dash), and <CODE>token_case</CODE> is <CODE>true</CODE>,
+ * if token is upper-case and <CODE>false</CODE> if token is lower-case.
+ *
+ * @return <CODE>TOKEN_EOF</CODE> -- no more tokens, <CODE>TOKEN_COMMA</CODE> --
+ * token is comma, <CODE>TOKEN_AND</CODE> -- token is the word
+ * "and" (or "And", or "aND", etc.), <CODE>TOKEN_WORD</CODE> --
+ * token is a word; additional information is given in global
+ * variables <CODE>token_start</CODE>, <CODE>token_end</CODE>,
+ * <CODE>token_abbr</CODE>, <CODE>token_term</CODE>, and
+ * <CODE>token_case</CODE>.
+ */
+ private int getToken() {
+ token_start = token_end;
+ while (token_start < orig.length()) {
+ char c = orig.charAt(token_start);
+ if (!(c == '~' || c == '-' || Character.isWhitespace(c)))
+ break;
+ token_start++;
+ }
+ token_end = token_start;
+ if (token_start >= orig.length())
+ return TOKEN_EOF;
+ if (orig.charAt(token_start) == ',') {
+ token_end++;
+ return TOKEN_COMMA;
+ }
+ token_abbr = -1;
+ token_term = ' ';
+ token_case = true;
+ int braces_level = 0;
+ int current_backslash = -1;
+ boolean first_letter_is_found = false;
+ while (token_end < orig.length()) {
+ char c = orig.charAt(token_end);
+ if (c == '{') {
+ braces_level++;
+ }
+ if (braces_level > 0)
+ if (c == '}')
+ braces_level--;
+ if (first_letter_is_found && token_abbr < 0 && braces_level == 0)
+ token_abbr = token_end;
+ if (!first_letter_is_found && current_backslash < 0 && Character.isLetter(c)) {
+ token_case = Character.isUpperCase(c);
+ first_letter_is_found = true;
+ }
+ if (current_backslash >= 0 && !Character.isLetter(c)) {
+ if (!first_letter_is_found) {
+ String tex_cmd_name = orig.substring(current_backslash + 1, token_end);
+ if (tex_names.get(tex_cmd_name) != null) {
+ token_case = Character.isUpperCase(tex_cmd_name.charAt(0));
+ first_letter_is_found = true;
+ }
+ }
+ current_backslash = -1;
+ }
+ if (c == '\\')
+ current_backslash = token_end;
+ if (braces_level == 0)
+ if (c == ',' || c == '~' || /* c=='-' || */Character.isWhitespace(c))
+ break;
+ // Morten Alver 18 Apr 2006: Removed check for hyphen '-' above to
+ // prevent
+ // problems with names like Bailey-Jones getting broken up and
+ // sorted wrong.
+ token_end++;
+ }
+ if (token_abbr < 0)
+ token_abbr = token_end;
+ if (token_end < orig.length() && orig.charAt(token_end) == '-')
+ token_term = '-';
+ if (orig.substring(token_start, token_end).equalsIgnoreCase("and"))
+ return TOKEN_AND;
+ else
+ return TOKEN_WORD;
+ }
+
+ /**
+ * Returns the number of author names in this object.
+ *
+ * @return the number of author names in this object.
+ */
+ public int size() {
+ return authors.size();
+ }
+
+ /**
+ * Returns the <CODE>Author</CODE> object for the i-th author.
+ *
+ * @param i
+ * Index of the author (from 0 to <CODE>size()-1</CODE>).
+ * @return the <CODE>Author</CODE> object.
+ */
+ public Author getAuthor(int i) {
+ return (Author) authors.get(i);
+ }
+
+ /**
+ * Returns the list of authors in "natbib" format.
+ * <p>
+ * <ul>
+ * <li>"John Smith" -> "Smith"</li>
+ * <li>"John Smith and Black Brown, Peter" ==> "Smith and Black Brown"</li>
+ * <li>"John von Neumann and John Smith and Black Brown, Peter" ==> "von
+ * Neumann et al." </li>
+ * </ul>
+ *
+ * @return formatted list of authors.
+ */
+ public String getAuthorsNatbib() {
+ // Check if we've computed this before:
+ if (authorsNatbib != null)
+ return authorsNatbib;
+
+ StringBuffer res = new StringBuffer();
+ if (size() > 0) {
+ res.append(getAuthor(0).getLastOnly());
+ if (size() == 2) {
+ res.append(" and ");
+ res.append(getAuthor(1).getLastOnly());
+ } else if (size() > 2) {
+ res.append(" et al.");
+ }
+ }
+ authorsNatbib = res.toString();
+ return authorsNatbib;
+ }
+
+ /**
+ * Returns the list of authors separated by commas with last name only; If
+ * the list consists of three or more authors, "and" is inserted before the
+ * last author's name.
+ * <p>
+ *
+ * <ul>
+ * <li> "John Smith" ==> "Smith"</li>
+ * <li> "John Smith and Black Brown, Peter" ==> "Smith and Black Brown"</li>
+ * <li> "John von Neumann and John Smith and Black Brown, Peter" ==> "von
+ * Neumann, Smith and Black Brown".</li>
+ * </ul>
+ *
+ * @param oxfordComma
+ * Whether to put a comma before the and at the end.
+ *
+ * @see http://en.wikipedia.org/wiki/Serial_comma For an detailed
+ * explaination about the Oxford comma.
+ *
+ * @return formatted list of authors.
+ */
+ public String getAuthorsLastOnly(boolean oxfordComma) {
+
+ int abbrInt = (oxfordComma ? 0 : 1);
+
+ // Check if we've computed this before:
+ if (authorsLastOnly[abbrInt] != null)
+ return authorsLastOnly[abbrInt];
+
+ StringBuffer res = new StringBuffer();
+ if (size() > 0) {
+ res.append(getAuthor(0).getLastOnly());
+ int i = 1;
+ while (i < size() - 1) {
+ res.append(", ");
+ res.append(getAuthor(i).getLastOnly());
+ i++;
+ }
+ if (size() > 2 && oxfordComma)
+ res.append(",");
+ if (size() > 1) {
+ res.append(" and ");
+ res.append(getAuthor(i).getLastOnly());
+ }
+ }
+ authorsLastOnly[abbrInt] = res.toString();
+ return authorsLastOnly[abbrInt];
+ }
+
+ /**
+ * Returns the list of authors separated by commas with first names after
+ * last name; first names are abbreviated or not depending on parameter. If
+ * the list consists of three or more authors, "and" is inserted before the
+ * last author's name.
+ * <p>
+ *
+ * <ul>
+ * <li> "John Smith" ==> "Smith, John" or "Smith, J."</li>
+ * <li> "John Smith and Black Brown, Peter" ==> "Smith, John and Black
+ * Brown, Peter" or "Smith, J. and Black Brown, P."</li>
+ * <li> "John von Neumann and John Smith and Black Brown, Peter" ==> "von
+ * Neumann, John, Smith, John and Black Brown, Peter" or "von Neumann, J.,
+ * Smith, J. and Black Brown, P.".</li>
+ * </ul>
+ *
+ * @param abbreviate
+ * whether to abbreivate first names.
+ *
+ * @param oxfordComma
+ * Whether to put a comma before the and at the end.
+ *
+ * @see http://en.wikipedia.org/wiki/Serial_comma For an detailed
+ * explaination about the Oxford comma.
+ *
+ * @return formatted list of authors.
+ */
+ public String getAuthorsLastFirst(boolean abbreviate, boolean oxfordComma) {
+ int abbrInt = (abbreviate ? 0 : 1);
+ abbrInt += (oxfordComma ? 0 : 2);
+
+ // Check if we've computed this before:
+ if (authorsLastFirst[abbrInt] != null)
+ return authorsLastFirst[abbrInt];
+
+ StringBuffer res = new StringBuffer();
+ if (size() > 0) {
+ res.append(getAuthor(0).getLastFirst(abbreviate));
+ int i = 1;
+ while (i < size() - 1) {
+ res.append(", ");
+ res.append(getAuthor(i).getLastFirst(abbreviate));
+ i++;
+ }
+ if (size() > 2 && oxfordComma)
+ res.append(",");
+ if (size() > 1) {
+ res.append(" and ");
+ res.append(getAuthor(i).getLastFirst(abbreviate));
+ }
+ }
+ authorsLastFirst[abbrInt] = res.toString();
+ return authorsLastFirst[abbrInt];
+ }
+
+ /**
+ * Returns the list of authors separated by "and"s with first names after
+ * last name; first names are not abbreviated.
+ * <p>
+ * <ul>
+ * <li>"John Smith" ==> "Smith, John"</li>
+ * <li>"John Smith and Black Brown, Peter" ==> "Smith, John and Black
+ * Brown, Peter"</li>
+ * <li>"John von Neumann and John Smith and Black Brown, Peter" ==> "von
+ * Neumann, John and Smith, John and Black Brown, Peter".</li>
+ * </ul>
+ *
+ * @return formatted list of authors.
+ */
+ public String getAuthorsLastFirstAnds(boolean abbreviate) {
+
+ int abbrInt = (abbreviate ? 0 : 1);
+ // Check if we've computed this before:
+ if (authorLastFirstAnds[abbrInt] != null)
+ return authorLastFirstAnds[abbrInt];
+
+ StringBuffer res = new StringBuffer();
+ if (size() > 0) {
+ res.append(getAuthor(0).getLastFirst(abbreviate));
+ for (int i = 1; i < size(); i++) {
+ res.append(" and ");
+ res.append(getAuthor(i).getLastFirst(abbreviate));
+ }
+ }
+
+ authorLastFirstAnds[abbrInt] = res.toString();
+ return authorLastFirstAnds[abbrInt];
+ }
+
+ /**
+ * Returns the list of authors separated by commas with first names before
+ * last name; first names are abbreviated or not depending on parameter. If
+ * the list consists of three or more authors, "and" is inserted before the
+ * last author's name.
+ * <p>
+ * <ul>
+ * <li>"John Smith" ==> "John Smith" or "J. Smith"</li>
+ * <li>"John Smith and Black Brown, Peter" ==> "John Smith and Peter Black
+ * Brown" or "J. Smith and P. Black Brown"</li>
+ * <li> "John von Neumann and John Smith and Black Brown, Peter" ==> "John
+ * von Neumann, John Smith and Peter Black Brown" or "J. von Neumann, J.
+ * Smith and P. Black Brown" </li>
+ * </ul>
+ *
+ * @param abbr
+ * whether to abbreivate first names.
+ *
+ * @param oxfordComma
+ * Whether to put a comma before the and at the end.
+ *
+ * @see http://en.wikipedia.org/wiki/Serial_comma For an detailed
+ * explaination about the Oxford comma.
+ *
+ * @return formatted list of authors.
+ */
+ public String getAuthorsFirstFirst(boolean abbr, boolean oxfordComma) {
+
+ int abbrInt = (abbr ? 0 : 1);
+ abbrInt += (oxfordComma ? 0 : 2);
+
+ // Check if we've computed this before:
+ if (authorsFirstFirst[abbrInt] != null)
+ return authorsFirstFirst[abbrInt];
+
+ StringBuffer res = new StringBuffer();
+ if (size() > 0) {
+ res.append(getAuthor(0).getFirstLast(abbr));
+ int i = 1;
+ while (i < size() - 1) {
+ res.append(", ");
+ res.append(getAuthor(i).getFirstLast(abbr));
+ i++;
+ }
+ if (size() > 2 && oxfordComma)
+ res.append(",");
+ if (size() > 1) {
+ res.append(" and ");
+ res.append(getAuthor(i).getFirstLast(abbr));
+ }
+ }
+ authorsFirstFirst[abbrInt] = res.toString();
+ return authorsFirstFirst[abbrInt];
+ }
+
+ /**
+ * Returns the list of authors separated by "and"s with first names before
+ * last name; first names are not abbreviated.
+ * <p>
+ * <ul>
+ * <li>"John Smith" ==> "John Smith"</li>
+ * <li>"John Smith and Black Brown, Peter" ==> "John Smith and Peter Black
+ * Brown"</li>
+ * <li>"John von Neumann and John Smith and Black Brown, Peter" ==> "John
+ * von Neumann and John Smith and Peter Black Brown" </li>
+ * </li>
+ *
+ * @return formatted list of authors.
+ */
+ public String getAuthorsFirstFirstAnds() {
+ // Check if we've computed this before:
+ if (authorsFirstFirstAnds != null)
+ return authorsFirstFirstAnds;
+
+ StringBuffer res = new StringBuffer();
+ if (size() > 0) {
+ res.append(getAuthor(0).getFirstLast(false));
+ for (int i = 1; i < size(); i++) {
+ res.append(" and ");
+ res.append(getAuthor(i).getFirstLast(false));
+ }
+ }
+ authorsFirstFirstAnds = res.toString();
+ return authorsFirstFirstAnds;
+ }
+
+ /**
+ * Returns the list of authors in a form suitable for alphabetization. This
+ * means that last names come first, never preceded by "von" particles, and
+ * that any braces are removed. First names are abbreviated so the same name
+ * is treated similarly if abbreviated in one case and not in another. This
+ * form is not intended to be suitable for presentation, only for sorting.
+ *
+ * <p>
+ * <ul>
+ * <li>"John Smith" ==> "Smith, J.";</li>
+ *
+ *
+ * @return formatted list of authors
+ */
+ public String getAuthorsForAlphabetization() {
+ if (authorsAlph != null)
+ return authorsAlph;
+
+ StringBuffer res = new StringBuffer();
+ if (size() > 0) {
+ res.append(getAuthor(0).getNameForAlphabetization());
+ for (int i = 1; i < size(); i++) {
+ res.append(" and ");
+ res.append(getAuthor(i).getNameForAlphabetization());
+ }
+ }
+ authorsAlph = res.toString();
+ return authorsAlph;
+ }
+
+ /**
+ * This is an immutable class that keeps information regarding single
+ * author. It is just a container for the information, with very simple
+ * methods to access it.
+ * <p>
+ * Current usage: only methods <code>getLastOnly</code>,
+ * <code>getFirstLast</code>, and <code>getLastFirst</code> are used;
+ * all other methods are provided for completeness.
+ */
+ public static class Author {
+ private final String first_part;
+
+ private final String first_abbr;
+
+ private final String von_part;
+
+ private final String last_part;
+
+ private final String jr_part;
+
+ /**
+ * Creates the Author object. If any part of the name is absent, <CODE>null</CODE>
+ * must be passes; otherwise other methods may return erroneous results.
+ *
+ * @param first
+ * the first name of the author (may consist of several
+ * tokens, like "Charles Louis Xavier Joseph" in "Charles
+ * Louis Xavier Joseph de la Vall{\'e}e Poussin")
+ * @param firstabbr
+ * the abbreviated first name of the author (may consist of
+ * several tokens, like "C. L. X. J." in "Charles Louis
+ * Xavier Joseph de la Vall{\'e}e Poussin"). It is a
+ * responsibility of the caller to create a reasonable
+ * abbreviation of the first name.
+ * @param von
+ * the von part of the author's name (may consist of several
+ * tokens, like "de la" in "Charles Louis Xavier Joseph de la
+ * Vall{\'e}e Poussin")
+ * @param last
+ * the lats name of the author (may consist of several
+ * tokens, like "Vall{\'e}e Poussin" in "Charles Louis Xavier
+ * Joseph de la Vall{\'e}e Poussin")
+ * @param jr
+ * the junior part of the author's name (may consist of
+ * several tokens, like "Jr. III" in "Smith, Jr. III, John")
+ */
+ public Author(String first, String firstabbr, String von, String last, String jr) {
+ first_part = first;
+ first_abbr = firstabbr;
+ von_part = von;
+ last_part = last;
+ jr_part = jr;
+ }
+
+ /**
+ * Returns the first name of the author stored in this object ("First").
+ *
+ * @return first name of the author (may consist of several tokens)
+ */
+ public String getFirst() {
+ return first_part;
+ }
+
+ /**
+ * Returns the abbreviated first name of the author stored in this
+ * object ("F.").
+ *
+ * @return abbreviated first name of the author (may consist of several
+ * tokens)
+ */
+ public String getFirstAbbr() {
+ return first_abbr;
+ }
+
+ /**
+ * Returns the von part of the author's name stored in this object
+ * ("von").
+ *
+ * @return von part of the author's name (may consist of several tokens)
+ */
+ public String getVon() {
+ return von_part;
+ }
+
+ /**
+ * Returns the last name of the author stored in this object ("Last").
+ *
+ * @return last name of the author (may consist of several tokens)
+ */
+ public String getLast() {
+ return last_part;
+ }
+
+ /**
+ * Returns the junior part of the author's name stored in this object
+ * ("Jr").
+ *
+ * @return junior part of the author's name (may consist of several
+ * tokens) or null if the author does not have a Jr. Part
+ */
+ public String getJr() {
+ return jr_part;
+ }
+
+ /**
+ * Returns von-part followed by last name ("von Last"). If both fields
+ * were specified as <CODE>null</CODE>, the empty string <CODE>""</CODE>
+ * is returned.
+ *
+ * @return 'von Last'
+ */
+ public String getLastOnly() {
+ if (von_part == null) {
+ return (last_part == null ? "" : last_part);
+ } else {
+ return (last_part == null ? von_part : von_part + " " + last_part);
+ }
+ }
+
+ /**
+ * Returns the author's name in form 'von Last, Jr., First' with the
+ * first name full or abbreviated depending on parameter.
+ *
+ * @param abbr
+ * <CODE>true</CODE> - abbreviate first name, <CODE>false</CODE> -
+ * do not abbreviate
+ * @return 'von Last, Jr., First' (if <CODE>abbr==false</CODE>) or
+ * 'von Last, Jr., F.' (if <CODE>abbr==true</CODE>)
+ */
+ public String getLastFirst(boolean abbr) {
+ String res = getLastOnly();
+ if (jr_part != null)
+ res += ", " + jr_part;
+ if (abbr) {
+ if (first_abbr != null)
+ res += ", " + first_abbr;
+ } else {
+ if (first_part != null)
+ res += ", " + first_part;
+ }
+ return res;
+ }
+
+ /**
+ * Returns the author's name in form 'First von Last, Jr.' with the
+ * first name full or abbreviated depending on parameter.
+ *
+ * @param abbr
+ * <CODE>true</CODE> - abbreviate first name, <CODE>false</CODE> -
+ * do not abbreviate
+ * @return 'First von Last, Jr.' (if <CODE>abbr==false</CODE>) or 'F.
+ * von Last, Jr.' (if <CODE>abbr==true</CODE>)
+ */
+ public String getFirstLast(boolean abbr) {
+ String res = getLastOnly();
+ if (abbr) {
+ res = (first_abbr == null ? "" : first_abbr + " ") + res;
+ } else {
+ res = (first_part == null ? "" : first_part + " ") + res;
+ }
+ if (jr_part != null)
+ res += ", " + jr_part;
+ return res;
+ }
+
+ /**
+ * Returns the name as "Last, Jr, F." omitting the von-part and removing
+ * starting braces.
+ *
+ * @return "Last, Jr, F." as described above or "" if all these parts
+ * are empty.
+ */
+ public String getNameForAlphabetization() {
+ StringBuffer res = new StringBuffer();
+ if (last_part != null)
+ res.append(last_part);
+ if (jr_part != null) {
+ res.append(", ");
+ res.append(jr_part);
+ }
+ if (first_abbr != null) {
+ res.append(", ");
+ res.append(first_abbr);
+ }
+ while ((res.length() > 0) && (res.charAt(0) == '{'))
+ res.deleteCharAt(0);
+ return res.toString();
+ }
+ }// end Author
+}// end AuthorList
diff --git a/src/java/net/sf/jabref/BasePanel.java b/src/java/net/sf/jabref/BasePanel.java
index e6b1ff7..3acf1c6 100644
--- a/src/java/net/sf/jabref/BasePanel.java
+++ b/src/java/net/sf/jabref/BasePanel.java
@@ -28,36 +28,82 @@ http://www.gnu.org/copyleft/gpl.ja.html
package net.sf.jabref;
-import java.awt.*;
-import java.awt.datatransfer.*;
-import java.awt.event.*;
-import java.io.*;
-import java.util.*;
-import java.util.List;
+import java.awt.BorderLayout;
+import java.awt.Component;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Toolkit;
+import java.awt.datatransfer.Clipboard;
+import java.awt.datatransfer.ClipboardOwner;
+import java.awt.datatransfer.DataFlavor;
+import java.awt.datatransfer.StringSelection;
+import java.awt.datatransfer.Transferable;
+import java.awt.datatransfer.UnsupportedFlavorException;
+import java.awt.event.ActionEvent;
+import java.awt.event.KeyAdapter;
+import java.awt.event.KeyEvent;
+import java.io.File;
+import java.io.IOException;
+import java.io.StringWriter;
import java.nio.charset.UnsupportedCharsetException;
-import javax.swing.*;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.Vector;
+
+import javax.swing.AbstractAction;
+import javax.swing.BorderFactory;
+import javax.swing.JFileChooser;
+import javax.swing.JList;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JSplitPane;
+import javax.swing.JTextArea;
+import javax.swing.ListSelectionModel;
+import javax.swing.SwingUtilities;
+import javax.swing.filechooser.FileFilter;
import javax.swing.tree.TreePath;
-import javax.swing.undo.*;
-import net.sf.jabref.collab.*;
+import javax.swing.undo.CannotRedoException;
+import javax.swing.undo.CannotUndoException;
+
+import net.sf.jabref.collab.ChangeScanner;
+import net.sf.jabref.collab.FileUpdateListener;
+import net.sf.jabref.collab.FileUpdatePanel;
import net.sf.jabref.export.*;
import net.sf.jabref.external.AutoSetExternalFileForEntries;
-import net.sf.jabref.groups.*;
-import net.sf.jabref.imports.*;
-import net.sf.jabref.labelPattern.LabelPatternUtil;
-import net.sf.jabref.undo.*;
-import net.sf.jabref.wizard.text.gui.TextInputDialog;
+import net.sf.jabref.external.WriteXMPAction;
+import net.sf.jabref.groups.GroupSelector;
+import net.sf.jabref.groups.GroupTreeNode;
+import net.sf.jabref.gui.GlazedEntrySorter;
+import net.sf.jabref.gui.MainTable;
+import net.sf.jabref.gui.MainTableFormat;
+import net.sf.jabref.gui.MainTableSelectionListener;
+import net.sf.jabref.imports.AppendDatabaseAction;
+import net.sf.jabref.imports.BibtexParser;
import net.sf.jabref.journals.AbbreviateAction;
import net.sf.jabref.journals.UnabbreviateAction;
-import net.sf.jabref.gui.*;
+import net.sf.jabref.labelPattern.LabelPatternUtil;
import net.sf.jabref.search.NoSearchMatcher;
import net.sf.jabref.search.SearchMatcher;
-import com.jgoodies.uif_lite.component.UIFSplitPane;
-import com.jgoodies.forms.builder.DefaultFormBuilder;
-import com.jgoodies.forms.layout.FormLayout;
+import net.sf.jabref.undo.CountingUndoManager;
+import net.sf.jabref.undo.NamedCompound;
+import net.sf.jabref.undo.UndoableChangeType;
+import net.sf.jabref.undo.UndoableInsertEntry;
+import net.sf.jabref.undo.UndoableKeyChange;
+import net.sf.jabref.undo.UndoableRemoveEntry;
+import net.sf.jabref.wizard.text.gui.TextInputDialog;
import ca.odell.glazedlists.FilterList;
-import ca.odell.glazedlists.matchers.Matcher;
-import ca.odell.glazedlists.event.ListEventListener;
import ca.odell.glazedlists.event.ListEvent;
+import ca.odell.glazedlists.event.ListEventListener;
+import ca.odell.glazedlists.matchers.Matcher;
+
+import com.jgoodies.forms.builder.DefaultFormBuilder;
+import com.jgoodies.forms.layout.FormLayout;
+import com.jgoodies.uif_lite.component.UIFSplitPane;
public class BasePanel extends JPanel implements ClipboardOwner, FileUpdateListener {
@@ -66,7 +112,7 @@ public class BasePanel extends JPanel implements ClipboardOwner, FileUpdateListe
private EntryEditor currentEditor = null;
private PreviewPanel currentPreview = null;
- boolean tmp = true;
+ boolean tmp = true;
private MainTableSelectionListener selectionListener = null;
private ListEventListener groupsHighlightListener;
@@ -79,8 +125,10 @@ public class BasePanel extends JPanel implements ClipboardOwner, FileUpdateListe
JabRefFrame frame;
BibtexDatabase database;
// The database shown in this panel.
- File file = null,
- fileToOpen = null; // The filename of the database.
+
+ // Moving file to MetaData (Morten, 2006.08.29)
+ // private File fileToOpen = null;
+
String fileMonitorHandle = null;
boolean saving = false, updatedExternally = false;
private String encoding;
@@ -191,7 +239,7 @@ public class BasePanel extends JPanel implements ClipboardOwner, FileUpdateListe
db.setCompleters(autoCompleters);
}*/
- this.file = file;
+ metaData.setFile(file);
// Register so we get notifications about outside changes to the file.
if (file != null)
@@ -202,20 +250,37 @@ public class BasePanel extends JPanel implements ClipboardOwner, FileUpdateListe
}
}
+ public boolean isBaseChanged(){
+ return baseChanged;
+ }
+
public int getMode() {
return mode;
}
- public BibtexDatabase database() { return database; }
- public MetaData metaData() { return metaData; }
- public File file() { return file; }
- public JabRefFrame frame() { return frame; }
- public JabRefPreferences prefs() { return Globals.prefs; }
+ public BibtexDatabase database() {
+ return database;
+ }
- public String getEncoding() { return encoding; }
- public void setEncoding(String encoding) {
- this.encoding = encoding;
- }
+ public MetaData metaData() {
+ return metaData;
+ }
+
+ public JabRefFrame frame() {
+ return frame;
+ }
+
+ public JabRefPreferences prefs() {
+ return Globals.prefs;
+ }
+
+ public String getEncoding() {
+ return encoding;
+ }
+
+ public void setEncoding(String encoding) {
+ this.encoding = encoding;
+ }
public void output(String s) {
//Util.pr("\""+s+"\""+(SwingUtilities.isEventDispatchThread()));
@@ -266,8 +331,21 @@ public class BasePanel extends JPanel implements ClipboardOwner, FileUpdateListe
actions.put("test", new BaseAction () {
public void action() throws Throwable {
+ ExportFormats.initAllExports();
+ JFileChooser fc = ExportFormats.createExportFileChooser("/home/alver/Documents");
+ fc.showSaveDialog(frame);
+ File file = fc.getSelectedFile();
+ if (file == null)
+ return;
+ FileFilter ff = fc.getFileFilter();
+ if (ff instanceof ExportFileFilter) {
+ ExportFormat format = ((ExportFileFilter)ff).getExportFormat();
+ format.performExport(database, file.getPath(), "UTF8", null);
+ // Make sure we remember which filter was used, to set the default
+ // for next time:
+ Globals.prefs.put("lastUsedExport", format.getConsoleName());
-
+ }
}
});
@@ -279,7 +357,7 @@ public class BasePanel extends JPanel implements ClipboardOwner, FileUpdateListe
public void init() throws Throwable {
success = false;
cancelled = false;
- if (file == null)
+ if (getFile() == null)
runCommand("saveAs");
else {
@@ -299,11 +377,11 @@ public class BasePanel extends JPanel implements ClipboardOwner, FileUpdateListe
else if (answer == JOptionPane.YES_OPTION) {
ChangeScanner scanner = new ChangeScanner(frame, BasePanel.this); //, panel.database(), panel.metaData());
//try {
- scanner.changeScan(file());
+ scanner.changeScan(getFile());
setUpdatedExternally(false);
SwingUtilities.invokeLater(new Runnable() {
public void run() {
- sidePaneManager.hideAway("fileUpdate");
+ sidePaneManager.hide("fileUpdate");
}
});
@@ -322,16 +400,18 @@ public class BasePanel extends JPanel implements ClipboardOwner, FileUpdateListe
public void update() {
if (success) {
- frame.setTabTitle(BasePanel.this, file.getName());
+ // Reset title of tab
+ frame.setTabTitle(BasePanel.this, getFile().getName(),
+ getFile().getAbsolutePath());
frame.output(Globals.lang("Saved database")+" '"
- +file.getPath()+"'.");
+ +getFile().getPath()+"'.");
} else if (!cancelled) {
frame.output(Globals.lang("Save failed"));
}
}
public void run() {
- if (file == null) {
+ if (getFile() == null) {
cancelled = true;
return;
}
@@ -361,7 +441,7 @@ public class BasePanel extends JPanel implements ClipboardOwner, FileUpdateListe
}
// Done with autosetting keys. Now save the database:
- success = saveDatabase(file, false, encoding);
+ success = saveDatabase(getFile(), false, encoding);
//Util.pr("Testing resolve string... BasePanel line 237");
//Util.pr("Resolve aq: "+database.resolveString("aq"));
@@ -397,10 +477,10 @@ public class BasePanel extends JPanel implements ClipboardOwner, FileUpdateListe
JFileChooser.SAVE_DIALOG, false);
if (chosenFile != null) {
- file = new File(chosenFile);
- if (!file.exists() ||
+ metaData.setFile(new File(chosenFile));
+ if (!metaData.getFile().exists() ||
(JOptionPane.showConfirmDialog
- (frame, "'"+file.getName()+"' "+Globals.lang("exists. Overwrite file?"),
+ (frame, "'"+metaData.getFile().getName()+"' "+Globals.lang("exists. Overwrite file?"),
Globals.lang("Save database"), JOptionPane.OK_CANCEL_OPTION)
== JOptionPane.OK_OPTION)) {
@@ -408,17 +488,18 @@ public class BasePanel extends JPanel implements ClipboardOwner, FileUpdateListe
// Register so we get notifications about outside changes to the file.
try {
- fileMonitorHandle = Globals.fileUpdateMonitor.addUpdateListener(BasePanel.this,file);
+ fileMonitorHandle = Globals.fileUpdateMonitor.addUpdateListener(BasePanel.this,getFile());
} catch (IOException ex) {
ex.printStackTrace();
}
- Globals.prefs.put("workingDirectory", file.getParent());
- frame.getFileHistory().newFile(file.getPath());
+ Globals.prefs.put("workingDirectory", metaData.getFile().getParent());
+ frame.getFileHistory().newFile(metaData.getFile().getPath());
}
- else
- file = null;
+ else {
+ metaData.setFile(null);
}
+ }
}
});
@@ -723,8 +804,8 @@ public class BasePanel extends JPanel implements ClipboardOwner, FileUpdateListe
// The action for toggling the groups interface
actions.put("toggleGroups", new BaseAction() {
public void action() {
- sidePaneManager.togglePanel("groups");
- frame.groupToggle.setSelected(sidePaneManager.isPanelVisible("groups"));
+ sidePaneManager.toggle("groups");
+ frame.groupToggle.setSelected(sidePaneManager.isComponentVisible("groups"));
}
});
@@ -829,7 +910,7 @@ public class BasePanel extends JPanel implements ClipboardOwner, FileUpdateListe
actions.put("search", new BaseAction() {
public void action() {
//sidePaneManager.togglePanel("search");
- sidePaneManager.ensureVisible("search");
+ sidePaneManager.show("search");
//boolean on = sidePaneManager.isPanelVisible("search");
frame.searchToggle.setSelected(true);
if (true)
@@ -840,8 +921,8 @@ public class BasePanel extends JPanel implements ClipboardOwner, FileUpdateListe
actions.put("toggleSearch", new BaseAction() {
public void action() {
//sidePaneManager.togglePanel("search");
- sidePaneManager.togglePanel("search");
- boolean on = sidePaneManager.isPanelVisible("search");
+ sidePaneManager.toggle("search");
+ boolean on = sidePaneManager.isComponentVisible("search");
frame.searchToggle.setSelected(on);
if (on)
frame.searchManager.startSearch();
@@ -850,7 +931,7 @@ public class BasePanel extends JPanel implements ClipboardOwner, FileUpdateListe
actions.put("incSearch", new BaseAction() {
public void action() {
- sidePaneManager.ensureVisible("search");
+ sidePaneManager.show("search");
frame.searchToggle.setSelected(true);
frame.searchManager.startIncrementalSearch();
}
@@ -935,6 +1016,10 @@ public class BasePanel extends JPanel implements ClipboardOwner, FileUpdateListe
actions.put("mergeDatabase", new AppendDatabaseAction(frame, this));
+
+
+
+
actions.put("openFile", new BaseAction() {
public void action() {
(new Thread() {
@@ -1297,7 +1382,8 @@ public class BasePanel extends JPanel implements ClipboardOwner, FileUpdateListe
try {
BibtexEntry[] bes = mainTable.getSelectedEntries();
StringWriter sw = new StringWriter();
- FileActions.exportEntries(database, bes, format, custom, directory, sw);
+ System.out.println("actual export to clipboard not implemented...");
+ //FileActions.exportEntries(database, bes, format, custom, directory, sw);
ClipboardOwner owner = new ClipboardOwner() {
public void lostOwnership(Clipboard clipboard, Transferable content) {}
};
@@ -1317,8 +1403,8 @@ public class BasePanel extends JPanel implements ClipboardOwner, FileUpdateListe
});
-
-
+ actions.put("writeXMP", new WriteXMPAction(this));
+
actions.put("abbreviateIso", new AbbreviateAction(this, true));
actions.put("abbreviateMedline", new AbbreviateAction(this, false));
actions.put("unabbreviate", new UnabbreviateAction(this));
@@ -1466,8 +1552,9 @@ public class BasePanel extends JPanel implements ClipboardOwner, FileUpdateListe
* prompted for an entry type.
*
* @param type The type of the entry to create.
+ * @return The newly created BibtexEntry or null the operation was canceled by the user.
*/
- public void newEntry(BibtexEntryType type) {
+ public BibtexEntry newEntry(BibtexEntryType type) {
if (type == null) {
// Find out what type is wanted.
EntryTypeDialog etd = new EntryTypeDialog(frame);
@@ -1505,10 +1592,12 @@ public class BasePanel extends JPanel implements ClipboardOwner, FileUpdateListe
markBaseChanged(); // The database just changed.
new FocusRequester(getEntryEditor(be));
+ return be;
} catch (KeyCollisionException ex) {
Util.pr(ex.getMessage());
}
}
+ return null;
}
@@ -1559,13 +1648,15 @@ public class BasePanel extends JPanel implements ClipboardOwner, FileUpdateListe
MainTableFormat tableFormat = new MainTableFormat(this);
tableFormat.updateTableFormat();
//EventTableModel tableModel = new EventTableModel(sortedList, tableFormat);
- mainTable = new MainTable(/*tableModel, */tableFormat, searchFilterList, frame);
+ mainTable = new MainTable(/*tableModel, */tableFormat, searchFilterList, frame, this);
selectionListener = new MainTableSelectionListener(this, mainTable);
mainTable.updateFont();
mainTable.addSelectionListener(selectionListener);
mainTable.addMouseListener(selectionListener);
-
+ mainTable.addKeyListener(selectionListener);
+ mainTable.addFocusListener(selectionListener);
+
// Add the listener that will take care of highlighting groups as the selection changes:
groupsHighlightListener = new ListEventListener() {
public void listChanged(ListEvent listEvent) {
@@ -2086,7 +2177,7 @@ public class BasePanel extends JPanel implements ClipboardOwner, FileUpdateListe
// database has changed.
String oldTitle = frame.getTabTitle(this);
if (!oldTitle.endsWith("*"))
- frame.setTabTitle(this, oldTitle+"*");
+ frame.setTabTitle(this, oldTitle+"*", frame.getTabTooltip(this));
// If the status line states that the base has been saved, we
// remove this message, since it is no longer relevant. If a
@@ -2107,10 +2198,11 @@ public class BasePanel extends JPanel implements ClipboardOwner, FileUpdateListe
}
else if (baseChanged && !nonUndoableChange) {
baseChanged = false;
- if (file != null)
- frame.setTabTitle(BasePanel.this, file.getName());
+ if (getFile() != null)
+ frame.setTabTitle(BasePanel.this, getFile().getName(),
+ getFile().getAbsolutePath());
else
- frame.setTabTitle(BasePanel.this, Globals.lang("untitled"));
+ frame.setTabTitle(BasePanel.this, Globals.lang("untitled"), null);
}
}
@@ -2329,7 +2421,7 @@ public class BasePanel extends JPanel implements ClipboardOwner, FileUpdateListe
public void run() {
// Test: running scan automatically in background
ChangeScanner scanner = new ChangeScanner(frame, BasePanel.this);
- scanner.changeScan(BasePanel.this.file());
+ scanner.changeScan(BasePanel.this.getFile());
try {
scanner.join();
} catch (InterruptedException e) {
@@ -2337,8 +2429,10 @@ public class BasePanel extends JPanel implements ClipboardOwner, FileUpdateListe
}
if (scanner.changesFound()) {
- FileUpdatePanel pan = new FileUpdatePanel(frame, BasePanel.this, sidePaneManager, file, scanner);
- sidePaneManager.add("fileUpdate", pan);
+ FileUpdatePanel pan = new FileUpdatePanel(frame, BasePanel.this,
+ sidePaneManager, getFile(), scanner);
+ sidePaneManager.register("fileUpdate", pan);
+ sidePaneManager.show("fileUpdate");
setUpdatedExternally(false);
//scanner.displayResult();
} else {
@@ -2353,7 +2447,7 @@ public class BasePanel extends JPanel implements ClipboardOwner, FileUpdateListe
}
public void fileRemoved() {
- Util.pr("File '"+file.getPath()+"' has been deleted.");
+ Util.pr("File '"+getFile().getPath()+"' has been deleted.");
}
@@ -2376,6 +2470,15 @@ public class BasePanel extends JPanel implements ClipboardOwner, FileUpdateListe
}
/**
+ * Get the file where this database was last saved to or loaded from, if any.
+ *
+ * @return The relevant File, or null if none is defined.
+ */
+ public File getFile() {
+ return metaData.getFile();
+ }
+
+ /**
* Get a String containing a comma-separated list of the bibtex keys
* of the selected entries.
*
@@ -2406,4 +2509,4 @@ public class BasePanel extends JPanel implements ClipboardOwner, FileUpdateListe
return frame.groupSelector;
}
-}
+}
\ No newline at end of file
diff --git a/src/java/net/sf/jabref/BibtexEntry.java b/src/java/net/sf/jabref/BibtexEntry.java
index 002635a..950fad4 100644
--- a/src/java/net/sf/jabref/BibtexEntry.java
+++ b/src/java/net/sf/jabref/BibtexEntry.java
@@ -207,10 +207,16 @@ public class BibtexEntry
* be used for entries that are being displayed in the GUI. Furthermore, it
* does not check values for content, so e.g. empty strings will be set as such.
*/
- public void setField(HashMap fields){
+ public void setField(Map fields){
_fields.putAll(fields);
}
+ /**
+ * Set a field, and notify listeners about the change.
+ *
+ * @param name The field to set.
+ * @param value The value to set.
+ */
public void setField(String name, Object value) {
if (ID_FIELD.equals(name)) {
@@ -225,34 +231,25 @@ public class BibtexEntry
Object oldValue = _fields.get(name);
try {
- /* The first event is no longer needed, so the following comment doesn't apply
- as of 2005.08.11.
-
- // First throw an empty event that just signals that this entry
- // is about to change. This is needed, so the EntrySorter can
- // remove the entry from its TreeSet. After a sort-sensitive
- // field changes, the entry will not be found by the TreeMap,
- // so without this event it would be impossible to reinsert this
- // entry to keep everything sorted properly.
- firePropertyChangedEvent(null, null, null);
- */
-
// We set the field before throwing the changeEvent, to enable
- // the change listener to access the new value if the change
- // sets off a change in database sorting etc.
- _fields.put(name, value);
+ // the change listener to access the new value if the change
+ // sets off a change in database sorting etc.
+ _fields.put(name, value);
firePropertyChangedEvent(name, oldValue, value);
} catch (PropertyVetoException pve) {
- // Since we have already made the change, we must undo it since
- // the change was rejected:
- _fields.put(name, oldValue);
+ // Since we have already made the change, we must undo it since
+ // the change was rejected:
+ _fields.put(name, oldValue);
throw new IllegalArgumentException("Change rejected: " + pve);
}
}
/**
- * Removes the mapping for the field name.
+ * Remove the mapping for the field name, and notify listeners about
+ * the change.
+ *
+ * @param name The field to clear.
*/
public void clearField(String name) {
@@ -263,7 +260,7 @@ public class BibtexEntry
Object oldValue = _fields.get(name);
_fields.remove(name);
try {
- firePropertyChangedEvent(name, oldValue, "");
+ firePropertyChangedEvent(name, oldValue, null);
} catch (PropertyVetoException pve) {
throw new IllegalArgumentException("Change rejected: " + pve);
}
@@ -435,4 +432,5 @@ public class BibtexEntry
return text;
return text.substring(0, maxCharacters + 1) + "...";
}
+
}
diff --git a/src/java/net/sf/jabref/EntryComparator.java b/src/java/net/sf/jabref/EntryComparator.java
index 62e379f..f33c2fd 100644
--- a/src/java/net/sf/jabref/EntryComparator.java
+++ b/src/java/net/sf/jabref/EntryComparator.java
@@ -126,7 +126,6 @@ public class EntryComparator implements Comparator {
} else {
String ours = ((String) f1).toLowerCase(),
theirs = ((String) f2).toLowerCase();
- System.out.println(ours);
int comp = ours.compareTo(theirs);
result = -comp;
}
diff --git a/src/java/net/sf/jabref/EntryEditor.java b/src/java/net/sf/jabref/EntryEditor.java
index 6aacd67..ce1d53d 100644
--- a/src/java/net/sf/jabref/EntryEditor.java
+++ b/src/java/net/sf/jabref/EntryEditor.java
@@ -46,1353 +46,1349 @@ import net.sf.jabref.undo.*;
import net.sf.jabref.external.ExternalFilePanel;
import net.sf.jabref.journals.JournalAbbreviations;
import net.sf.jabref.gui.date.*;
-
+import com.jgoodies.forms.builder.DefaultFormBuilder;
+import com.jgoodies.forms.layout.FormLayout;
+
+/**
+ * GUI component that allows editing of the fields of a BibtexEntry. EntryEditor
+ * also registers itself as a VetoableChangeListener, receiving events whenever
+ * a field of the entry changes, enabling the text fields to update themselves
+ * if the change is made from somewhere else.
+ */
public class EntryEditor extends JPanel implements VetoableChangeListener {
- /*
- * GUI component that allows editing of the fields of a BibtexEntry.
- * EntryTypeForm also registers itself as a VetoableChangeListener, receiving
- * events whenever a field of the entry changes, enabling the text fields to
- * update themselves if the change is made from somewhere else.
- */
-
- // A reference to the entry this object works on.
- private BibtexEntry entry;
- BibtexEntryType type;
- CloseAction closeAction;
-
- // The action concerned with closing the window.
- DeleteAction deleteAction = new DeleteAction();
-
- // The action that deletes the current entry, and closes the editor.
- CopyKeyAction copyKeyAction;
-
- // The action concerned with copying the BibTeX key to the clipboard.
- AbstractAction nextEntryAction = new NextEntryAction();
-
- // The action concerned with copying the BibTeX key to the clipboard.
- AbstractAction prevEntryAction = new PrevEntryAction();
-
- // Actions for switching to next/previous entry.
- public StoreFieldAction storeFieldAction;
-
- // The action concerned with storing a field value.
- SwitchLeftAction switchLeftAction = new SwitchLeftAction();
- SwitchRightAction switchRightAction = new SwitchRightAction();
-
- // The actions concerned with switching the panels.
- GenerateKeyAction generateKeyAction;
-
- // The action which generates a bibtexkey for this entry.
- SaveDatabaseAction saveDatabaseAction = new SaveDatabaseAction();
- JPanel mainPanel = new JPanel();
- JPanel srcPanel = new JPanel();
- EntryEditorTab genPan, optPan, reqPan, absPan;
-
- JTextField bibtexKey;
- FieldTextField tf;
- JTextArea source;
- JToolBar tlb;
- JTabbedPane tabbed = new JTabbedPane(); //JTabbedPane.RIGHT);
- GridBagLayout gbl = new GridBagLayout();
- GridBagConstraints con;
- JLabel lab;
- TypeLabel typeLabel;
- JabRefFrame frame;
- BasePanel panel;
- EntryEditor ths = this;
- HashSet contentSelectors = new HashSet();
- Logger logger = Logger.getLogger(EntryEditor.class.getName());
- boolean updateSource = true; // This can be set to false to stop the source
-
- List tabs = new ArrayList();
-
- // text area from gettin updated. This is used in cases where the source
- // couldn't be parsed, and the user is given the option to edit it.
- boolean lastSourceAccepted = true; // This indicates whether the last
-
- // attempt
- // at parsing the source was successful. It is used to determine whether the
- // dialog should close; it should stay open if the user received an error
- // message about the source, whatever he or she chose to do about it.
- String lastSourceStringAccepted = null; // This is used to prevent double
-
-
- // fields.
- // These values can be used to calculate the preferred height for the form.
- // reqW starts at 1 because it needs room for the bibtex key field.
- private int sourceIndex = -1; // The index the source panel has in tabbed.
-
- //private final int REQ=0, OPT=1, GEN=2, FIELD_WIDTH=40, FIELD_HEIGHT=2;
- private final String KEY_PROPERTY = "bibtexkey";
- JabRefPreferences prefs;
- HelpAction helpAction;
- UndoAction undoAction = new UndoAction();
- RedoAction redoAction = new RedoAction();
- TabListener tabListener = new TabListener();
-
- public EntryEditor(JabRefFrame frame_, BasePanel panel_, BibtexEntry entry_) {
-
- frame = frame_;
- panel = panel_;
- entry = entry_;
- prefs = Globals.prefs;
- type = entry.getType();
-
-
- entry.addPropertyChangeListener(this);
-
- helpAction = new HelpAction(frame.helpDiag, GUIGlobals.entryEditorHelp, "Help");
- closeAction = new CloseAction();
- copyKeyAction = new CopyKeyAction();
- generateKeyAction = new GenerateKeyAction(frame);
- storeFieldAction = new StoreFieldAction();
-
- BorderLayout bl = new BorderLayout();
- setLayout(bl);
- setupToolBar();
- setupFieldPanels();
- setupSourcePanel();
- add(tabbed, BorderLayout.CENTER);
- tabbed.addChangeListener(tabListener);
- if (prefs.getBoolean("showSource") && prefs.getBoolean("defaultShowSource"))
- tabbed.setSelectedIndex(sourceIndex);
-
- updateAllFields();
- }
-
- private void setupFieldPanels() {
- tabbed.removeAll();
- tabs.clear();
- String[] fields = entry.getRequiredFields();
-
-
- List fieldList = null;
- if (fields != null)
- fieldList = java.util.Arrays.asList(fields);
- reqPan = new EntryEditorTab(fieldList, this, true, Globals.lang("Required fields"));
- tabbed.addTab(Globals.lang("Required fields"),
- GUIGlobals.getImage("required"), reqPan.getPane(),
- Globals.lang("Show required fields"));
- tabs.add(reqPan);
- //}
-
- if ((entry.getOptionalFields() != null) && (entry.getOptionalFields().length >= 1)) {
- optPan = new EntryEditorTab(java.util.Arrays.asList(entry.getOptionalFields()),
- this, false, Globals.lang("Optional fields"));
- tabbed.addTab(Globals.lang("Optional fields"),
- GUIGlobals.getImage("optional"), optPan.getPane(),
- Globals.lang("Show optional fields"));
- tabs.add(optPan);
- }
-
- EntryEditorTabList tabList = Globals.prefs.getEntryEditorTabList();
- for (int i=0; i<tabList.getTabCount(); i++) {
- EntryEditorTab newTab = new EntryEditorTab(tabList.getTabFields(i),
- this, false, tabList.getTabName(i));
- tabbed.addTab(tabList.getTabName(i), GUIGlobals.getImage("general"), newTab.getPane());
- tabs.add(newTab);
- }
-
- srcPanel.setName(Globals.lang("BibTeX source"));
- if (Globals.prefs.getBoolean("showSource")) {
- tabbed.addTab(Globals.lang("BibTeX source"),
- GUIGlobals.getImage("source"), srcPanel,
- Globals.lang("Show/edit BibTeX source"));
- tabs.add(srcPanel);
- }
- sourceIndex = tabs.size() - 1; // Set the sourceIndex variable.
- srcPanel.setFocusCycleRoot(true);
- }
-
- public BibtexEntryType getType() {
- return type;
- }
-
-
- public BibtexEntry getEntry() {
- return entry;
- }
-
- private void setupToolBar() {
- tlb = new JToolBar(JToolBar.VERTICAL);
-
- //tlb.setMargin(new Insets(2,2,2,2));
- tlb.setMargin(new Insets(0, 0, 0, 2));
-
- // The toolbar carries all the key bindings that are valid for the whole
- // window.
- //tlb.setBackground(GUIGlobals.lightGray);//Color.white);
- ActionMap am = tlb.getActionMap();
- InputMap im = tlb.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
-
- im.put(prefs.getKey("Close entry editor"), "close");
- am.put("close", closeAction);
- im.put(prefs.getKey("Entry editor, store field"), "store");
- am.put("store", storeFieldAction);
- im.put(prefs.getKey("Autogenerate BibTeX keys"), "generateKey");
- am.put("generateKey", generateKeyAction);
- /*im.put(prefs.getKey("Entry editor, previous panel"), "left");
- im.put(prefs.getKey("Entry editor, previous panel 2"), "left");
- am.put("left", switchLeftAction);
- im.put(prefs.getKey("Entry editor, next panel"), "right");
- im.put(prefs.getKey("Entry editor, next panel 2"), "right");
- am.put("right", switchRightAction);*/
- im.put(prefs.getKey("Entry editor, previous entry"), "prev");
- am.put("prev", prevEntryAction);
- im.put(prefs.getKey("Entry editor, next entry"), "next");
- am.put("next", nextEntryAction);
- im.put(prefs.getKey("Undo"), "undo");
- am.put("undo", undoAction);
- im.put(prefs.getKey("Redo"), "redo");
- am.put("redo", redoAction);
- im.put(prefs.getKey("Help"), "help");
- am.put("help", helpAction);
-
- tlb.setFloatable(false);
- tlb.add(closeAction);
-
- setLabel();
- tlb.add(typeLabel);
-
- //tlb.addSeparator();
- //tlb.add(copyKeyAction);
- tlb.addSeparator();
- tlb.add(generateKeyAction);
- tlb.addSeparator();
-
- //tlb.add(undoAction);
- //tlb.add(redoAction);
- tlb.add(deleteAction);
- tlb.add(prevEntryAction);
-
- tlb.add(nextEntryAction);
- tlb.addSeparator();
- tlb.add(helpAction);
-
- Component[] comps = tlb.getComponents();
-
- for (int i = 0; i < comps.length; i++)
- ((JComponent) comps[i]).setOpaque(false);
-
- add(tlb, BorderLayout.WEST);
- }
-
- private void setLabel() {
- typeLabel = new TypeLabel(entry.getType().getName());
- }
-
- /**
- * Rebuild the field tabs. This is called e.g. when a new content selector has been added.
- */
- public void rebuildPanels() {
- // Remove change listener, because the rebuilding causes meaningless events and trouble:
- tabbed.removeChangeListener(tabListener);
- setupFieldPanels();//reqPanel, optPanel, genPanel, absPanel);
- // Add the change listener again:
- tabbed.addChangeListener(tabListener);
- revalidate();
- repaint();
- }
-
-
- /**
- * getExtra checks the field name against BibtexFields.getFieldExtras(name).
- * If the name has an entry, the proper component to be shown is created and
- * returned. Otherwise, null is returned. In addition, e.g. listeners can be
- * added to the field editor, even if no component is returned.
- *
- * @param string
- * Field name
- * @return Component to show, or null if none.
- */
- public JComponent getExtra(String string, FieldEditor editor) {
- final FieldEditor ed = editor;
-
- // fieldName and parameter string identically ????
- final String fieldName = editor.getFieldName();
-
- String s = BibtexFields.getFieldExtras( string ) ;
-
- // timestamp or a other field with datepicker command
- if ( (fieldName.equals( Globals.prefs.get("timeStampField"))) ||
- ((s != null) && s.equals("datepicker")) )
- {
- // double click AND datefield => insert the current date (today)
- ((JTextArea) ed).addMouseListener(new MouseAdapter(){
- public void mouseClicked(MouseEvent e){
- if(e.getClickCount()==2) // double click
- {
- String date = Util.easyDateFormat();
- ed.setText(date);
- }
- }
- });
-
- // insert a datepicker, if the extras field contains this command
- if ((s != null) && s.equals("datepicker"))
- {
- DatePickerButton datePicker = new DatePickerButton( ed ) ;
- return datePicker.getDatePicker() ;
- }
- }
-
- if ((s != null) && s.equals("external")) {
-
- // Add external viewer listener for "pdf" and "url" fields.
- ((JComponent) editor).addMouseListener(new ExternalViewerListener());
-
- return null;
- }
- else if ((s != null) && s.equals("journalNames")) {
- // Add controls for switching between abbreviated and full journal names.
- // If this field also has a FieldContentSelector, we need to combine these.
- JPanel controls = new JPanel();
- controls.setLayout(new BorderLayout());
- if (panel.metaData.getData(Globals.SELECTOR_META_PREFIX
- + editor.getFieldName()) != null) {
- FieldContentSelector ws = new FieldContentSelector(frame, panel, frame, editor,
- panel.metaData, storeFieldAction, false);
- contentSelectors.add(ws);
- controls.add(ws, BorderLayout.NORTH);
- }
- controls.add(JournalAbbreviations.getNameSwitcher(this, editor, panel.undoManager),
- BorderLayout.SOUTH);
- return controls;
- }
- else if (panel.metaData.getData(Globals.SELECTOR_META_PREFIX
- + editor.getFieldName()) != null)
- {
- FieldContentSelector ws = new FieldContentSelector(frame, panel, frame, editor,
- panel.metaData, storeFieldAction, false);
- contentSelectors.add(ws);
-
- return ws;
- } else if ((s != null) && s.equals("browse")) {
- JButton but = new JButton(Globals.lang("Browse"));
- ((JComponent) editor).addMouseListener(new ExternalViewerListener());
-
- //but.setBackground(GUIGlobals.lightGray);
- but.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- String dir = ed.getText();
-
- if (dir.equals(""))
- dir = prefs.get(fieldName + Globals.FILETYPE_PREFS_EXT, "");
-
- String chosenFile =
- Globals.getNewFile(frame, new File(dir), "." + fieldName,
- JFileChooser.OPEN_DIALOG, false);
-
- if (chosenFile != null) {
- File newFile = new File(chosenFile); //chooser.getSelectedFile();
- ed.setText(newFile.getPath());
- prefs.put(fieldName + Globals.FILETYPE_PREFS_EXT, newFile.getPath());
- updateField(ed);
- }
- }
- });
-
- return but;
- //} else if ((s != null) && s.equals("browsePdf")) {
- } else if ((s != null) && (s.equals("browseDoc") || s.equals("browseDocZip"))) {
-
- final String ext = "."+fieldName.toLowerCase();
- final OpenFileFilter off;
- if (s.equals("browseDocZip"))
- off = new OpenFileFilter(new String[] { ext, ext+".gz", ext+".bz2" });
- else
- off = new OpenFileFilter(new String[] { ext });
-
- ExternalFilePanel pan = new ExternalFilePanel(frame, panel.metaData(), this, fieldName, off, ed);
- return pan;
- }
- /*else if ((s != null) && s.equals("browsePs")) {
- ExternalFilePanel pan = new ExternalFilePanel(frame, this, "ps", off, ed);
- return pan;
- }*/
- else if ((s != null) && s.equals("url")) {
- ((JComponent) editor).setDropTarget(new DropTarget((Component) editor,
- DnDConstants.ACTION_NONE, new SimpleUrlDragDrop(editor, storeFieldAction)));
-
- return null;
- }
-
- else
- return null;
- }
-
- private void setupSourcePanel() {
- source =
- new JTextArea() {
- private boolean antialias = Globals.prefs.getBoolean("antialias");
- public void paint(Graphics g) {
- Graphics2D g2 = (Graphics2D)g;
- if (antialias)
- g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
- super.paint(g2);
- }
- };
- con = new GridBagConstraints();
- con.insets = new Insets(10, 10, 10, 10);
- con.fill = GridBagConstraints.BOTH;
- con.gridwidth = GridBagConstraints.REMAINDER;
- con.gridheight = GridBagConstraints.REMAINDER;
- con.weightx = 1;
- con.weighty = 1;
- srcPanel.setLayout(gbl);
- source.setEditable(true); //prefs.getBoolean("enableSourceEditing"));
- source.setLineWrap(true);
- source.setTabSize(GUIGlobals.INDENT);
- source.addFocusListener(new FieldEditorFocusListener());
- // Add the global focus listener, so a menu item can see if this field
- // was focused when
- // an action was called.
- source.addFocusListener(Globals.focusListener);
- source.setFont(new Font("Monospaced", Font.PLAIN, Globals.prefs.getInt("fontSize")));
- setupJTextComponent(source);
- updateSource();
-
- JScrollPane sp =
- new JScrollPane(source, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
- JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
- gbl.setConstraints(sp, con);
- srcPanel.add(sp);
- }
-
- public void updateSource() {
- if (updateSource) {
- StringWriter sw = new StringWriter(200);
-
- try {
- entry.write(sw, new net.sf.jabref.export.LatexFieldFormatter(), false);
-
- String srcString = sw.getBuffer().toString();
- source.setText(srcString);
- lastSourceStringAccepted = srcString;
- } catch (IOException ex) {
- source.setText("Error: " + ex.getMessage() + "\n\n" + "Correct the entry, and "
- + "reopen editor to display/edit source.");
- source.setEditable(false);
- }
- }
- }
-
- public void setupJTextComponent(JTextComponent ta) {
-
- /*
- * NOTE: This method is only used for the source panel, not for the other tabs. Look at
- * EntryEditorTab for the setup of text components in the other tabs.
- */
-
- /*
- * if ((ta instanceof FieldTextArea) && (prefs.getBoolean("autoComplete"))) {
- * FieldTextArea fta = (FieldTextArea)ta; Completer comp =
- * baseFrame.getAutoCompleter(fta.getFieldName()); if (comp != null)
- * fta.setAutoComplete(comp); }
- */
-
- // Set up key bindings and focus listener for the FieldEditor.
- InputMap im = ta.getInputMap(JComponent.WHEN_FOCUSED);
- ActionMap am = ta.getActionMap();
-
- //im.put(KeyStroke.getKeyStroke(GUIGlobals.closeKey), "close");
- //am.put("close", closeAction);
- im.put(prefs.getKey("Entry editor, store field"), "store");
- am.put("store", storeFieldAction);
-
- im.put(prefs.getKey("Entry editor, next panel"), "right");
- im.put(prefs.getKey("Entry editor, next panel 2"), "right");
- am.put("right", switchRightAction);
-
- im.put(prefs.getKey("Entry editor, previous panel"), "left");
- im.put(prefs.getKey("Entry editor, previous panel 2"), "left");
- am.put("left", switchLeftAction);
-
- im.put(prefs.getKey("Help"), "help");
- am.put("help", helpAction);
- im.put(prefs.getKey("Save database"), "save");
- am.put("save", saveDatabaseAction);
-
- im.put(Globals.prefs.getKey("Next tab"), "nexttab");
- am.put("nexttab", frame.nextTab);
- im.put(Globals.prefs.getKey("Previous tab"), "prevtab");
- am.put("prevtab", frame.prevTab);
- try {
- HashSet keys =
- new HashSet(ta.getFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS));
- keys.clear();
- keys.add(AWTKeyStroke.getAWTKeyStroke("pressed TAB"));
- ta.setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, keys);
- keys =
- new HashSet(ta.getFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS));
- keys.clear();
- keys.add(KeyStroke.getKeyStroke("shift pressed TAB"));
- ta.setFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, keys);
- } catch (Throwable t) {
- System.err.println(t);
- }
-
- ta.addFocusListener(new FieldListener());
- }
-
- public void requestFocus() {
- activateVisible();
- }
-
- private void activateVisible() {
- Object activeTab = tabs.get(tabbed.getSelectedIndex());
-
- if (activeTab instanceof EntryEditorTab)
- ((EntryEditorTab)activeTab).activate();
- else
- new FocusRequester(source);
- //((JComponent)activeTab).requestFocus();
- }
-
- /**
- * Reports the enabled status of the editor, as set by setEnabled()
- */
- public boolean isEnabled() {
- return source.isEnabled();
- }
-
- /**
- * Sets the enabled status of all text fields of the entry editor.
- */
- public void setEnabled(boolean enabled) {
- for (Iterator i=tabs.iterator(); i.hasNext();) {
- Object o = i.next();
- if (o instanceof EntryEditorTab) {
- ((EntryEditorTab)o).setEnabled(enabled);
- }
- }
- source.setEnabled(enabled);
-
- }
-
- /**
- * Centers the given row, and highlights it.
- *
- * @param row
- * an <code>int</code> value
- */
- private void scrollTo(int row) {
- panel.mainTable.setRowSelectionInterval(row, row);
- panel.mainTable.ensureVisible(row);
- }
-
- /**
- * Makes sure the current edit is stored.
- */
- public void storeCurrentEdit() {
- Component comp = Globals.focusListener.getFocused();
- if ((comp instanceof FieldEditor) && this.isAncestorOf(comp)) {
- storeFieldAction.actionPerformed(new ActionEvent(comp, 0, ""));
- }
- }
-
-
- /**
- * Returns the index of the active (visible) panel.
- *
- * @return an <code>int</code> value
- */
- public int getVisiblePanel() {
- return tabbed.getSelectedIndex();
- }
-
- /** Returns the name of the currently selected component. */
- public String getVisiblePanelName() {
- return tabbed.getSelectedComponent().getName();
- }
-
- /**
- * Sets the panel with the given index visible.
- *
- * @param i
- * an <code>int</code> value
- */
- public void setVisiblePanel(int i) {
- tabbed.setSelectedIndex(Math.min(i, tabbed.getTabCount() - 1));
- }
-
- public void setVisiblePanel(String name) {
- for (int i = 0; i < tabbed.getTabCount(); ++i) {
- if (name.equals(tabbed.getComponent(i).getName())) {
- tabbed.setSelectedIndex(i);
- return;
- }
- }
- if (tabbed.getTabCount() > 0)
- tabbed.setSelectedIndex(0);
- }
-
- /**
- * Updates this editor to show the given entry, regardless of type
- * correspondence.
- *
- * @param be
- * a <code>BibtexEntry</code> value
- */
- public synchronized void switchTo(BibtexEntry be) {
- if (entry == be)
- return;
-
- //Util.pr("EntryEditor.switchTo(BibtexEntry): "+entry.getCiteKey());
- //Util.pr("::EntryEditor.switchTo(BibtexEntry): "+this.type.getName());
- storeCurrentEdit();
-
- // Remove this instance as property listener for the entry:
- entry.removePropertyChangeListener(this);
- // Register as property listener for the new entry:
- be.addPropertyChangeListener(this);
-
- entry = be;
-
- updateAllFields();
- validateAllFields();
- updateSource();
- panel.showing = be;
-
- }
-
- /**
- * Returns false if the contents of the source panel has not been validated,
- * true othervise.
- */
- public boolean lastSourceAccepted() {
- //Util.pr("Sourceaccepted ....");
- if (tabbed.getSelectedComponent() == srcPanel)
- storeSource(false);
-
- return lastSourceAccepted;
- }
-
- /*
- * public boolean storeSourceIfNeeded() { if (tabbed.getSelectedIndex() ==
- * sourceIndex) return storeSource(); else return true; }
- */
- public boolean storeSource(boolean showError) {
- // Store edited bibtex code.
- BibtexParser bp = new BibtexParser(new java.io.StringReader(source.getText()));
-
- try {
- BibtexDatabase db = bp.parse().getDatabase();
-
- if (db.getEntryCount() > 1)
- throw new Exception("More than one entry found.");
-
- if (db.getEntryCount() < 1)
- throw new Exception("No entries found.");
-
- NamedCompound compound = new NamedCompound(Globals.lang("source edit"));
- BibtexEntry nu = db.getEntryById((String) db.getKeySet().iterator().next());
- String id = entry.getId();
- String
- //oldKey = entry.getCiteKey(),
- newKey = nu.getCiteKey();
- boolean anyChanged = false;
- boolean duplicateWarning = false;
- boolean emptyWarning = newKey == null || newKey.equals("");
-
- if (panel.database.setCiteKeyForEntry(id, newKey)) {
- duplicateWarning = true;
-
- // First, remove fields that the user have removed.
- }
-
- Object[] fields = entry.getAllFields();
-
- for (int i = 0; i < fields.length; i++) {
- if (BibtexFields.isDisplayableField(fields[i].toString())) {
- if (nu.getField(fields[i].toString()) == null) {
- compound.addEdit(new UndoableFieldChange(entry, fields[i].toString(),
- entry.getField(fields[i].toString()), (Object) null));
- entry.clearField(fields[i].toString());
- anyChanged = true;
- }
- }
- }
-
- // Then set all fields that have been set by the user.
- fields = nu.getAllFields();
-
- for (int i = 0; i < fields.length; i++) {
- if (entry.getField(fields[i].toString()) != nu.getField(fields[i].toString())) {
- String toSet = (String) nu.getField(fields[i].toString());
-
- // Test if the field is legally set.
- (new LatexFieldFormatter()).format(toSet, fields[i].toString());
-
- compound.addEdit(new UndoableFieldChange(entry, fields[i].toString(),
- entry.getField(fields[i].toString()), toSet));
- entry.setField(fields[i].toString(), toSet);
- anyChanged = true;
- }
- }
-
- compound.end();
-
- if (!anyChanged)
- return true;
-
- panel.undoManager.addEdit(compound);
-
- /*
- * if (((oldKey == null) && (newKey != null)) || ((oldKey != null) &&
- * (newKey == null)) || ((oldKey != null) && (newKey != null) &&
- * !oldKey.equals(newKey))) { }
- */
- if (duplicateWarning) {
- warnDuplicateBibtexkey();
- } else if (emptyWarning && showError) {
- warnEmptyBibtexkey();
- } else {
- panel.output(Globals.lang("Stored entry") + ".");
- }
-
- lastSourceStringAccepted = source.getText();
- updateAllFields();
- lastSourceAccepted = true;
- updateSource = true;
-
- // TODO: does updating work properly after source stored?
- // panel.tableModel.remap();
- // panel.entryTable.repaint();
- //panel.refreshTable();
- panel.markBaseChanged();
-
- return true;
- } catch (Throwable ex) {
- //ex.printStackTrace();
- // The source couldn't be parsed, so the user is given an
- // error message, and the choice to keep or revert the contents
- // of the source text field.
- updateSource = false;
- lastSourceAccepted = false;
- tabbed.setSelectedComponent(srcPanel);
-
- if (showError) {
- Object[] options =
- { Globals.lang("Edit"), Globals.lang("Revert to original source") };
-
- int answer =
- JOptionPane.showOptionDialog(frame, "Error: " + ex.getMessage(),
- Globals.lang("Problem with parsing entry"), JOptionPane.YES_NO_OPTION,
- JOptionPane.ERROR_MESSAGE, null, options, options[0]);
-
- if (answer != 0) {
- updateSource = true;
- updateSource();
- }
- }
-
- return false;
- }
- }
-
-
- public void setField(String fieldName, String newFieldData) {
-
- for (Iterator i=tabs.iterator(); i.hasNext();) {
- Object o = i.next();
- if (o instanceof EntryEditorTab) {
- ((EntryEditorTab)o).updateField(fieldName, newFieldData);
- }
- }
-
- }
-
-
- /**
- * Sets all the text areas according to the shown entry.
- */
- public void updateAllFields() {
- //System.out.println("EntryEditor.updateAllFields()");
- for (Iterator i=tabs.iterator(); i.hasNext();) {
- Object o = i.next();
- if (o instanceof EntryEditorTab) {
- ((EntryEditorTab)o).setEntry(entry);
- }
- }
- }
-
- /**
- * Removes the "invalid field" color from all text areas.
- */
- public void validateAllFields() {
- for (Iterator i=tabs.iterator(); i.hasNext();) {
- Object o = i.next();
- if (o instanceof EntryEditorTab) {
- ((EntryEditorTab)o).validateAllFields();
- }
- }
- }
-
- public void updateAllContentSelectors() {
- if (contentSelectors.size() > 0) {
- for (Iterator i = contentSelectors.iterator(); i.hasNext();)
- ((FieldContentSelector) i.next()).updateList();
- }
- }
-
- // Update the JTextArea when a field has changed.
- public void vetoableChange(PropertyChangeEvent e) {
- String newValue = ((e.getNewValue() != null) ? e.getNewValue().toString() : "");
- setField(e.getPropertyName(), newValue);
-
- //Util.pr(e.getPropertyName());
- }
-
-
- public void updateField(final Object source) {
- storeFieldAction.actionPerformed(new ActionEvent(source, 0, ""));
- }
-
- private class TypeLabel extends JPanel {
- private String label;
-
- public TypeLabel(String type) {
- label = type;
- addMouseListener(new MouseAdapter() {
- public void mouseClicked(MouseEvent e) {
- boolean ctrlClick = prefs.getBoolean("ctrlClick");
-
- if ((e.getButton() == MouseEvent.BUTTON3)
- || (ctrlClick && (e.getButton() == MouseEvent.BUTTON1)
- && e.isControlDown())) {
- JPopupMenu typeMenu = new JPopupMenu();
-
- //typeMenu.addSeparator();
- for (Iterator i = BibtexEntryType.ALL_TYPES.keySet().iterator();
- i.hasNext();)
- typeMenu.add(new ChangeTypeAction(BibtexEntryType.getType(
- (String) i.next()), panel));
-
- typeMenu.show(ths, e.getX(), e.getY());
- }
- }
- });
- }
-
- public void paint(Graphics g) {
- Graphics2D g2 = (Graphics2D) g;
- g2.setColor(GUIGlobals.validFieldColor);
- g2.setFont(GUIGlobals.typeNameFont);
-
- FontMetrics fm = g2.getFontMetrics();
- int width = fm.stringWidth(label);
- g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
- RenderingHints.VALUE_ANTIALIAS_ON);
- g2.rotate(-Math.PI / 2, 0, 0);
- g2.drawString(label, -width - 7, 28);
- }
- }
-
- class FieldListener extends FocusAdapter {
- /*
- * Focus listener that fires the storeFieldAction when a FieldTextArea loses
- * focus.
- */
- public void focusGained(FocusEvent e) {
- }
-
- public void focusLost(FocusEvent e) {
- //Util.pr("Lost focus "+e.getSource().toString().substring(0,30));
- if (!e.isTemporary())
- updateField(e.getSource());
- }
- }
+ // A reference to the entry this object works on.
+ private BibtexEntry entry;
+ BibtexEntryType type;
- class TabListener implements ChangeListener {
- public void stateChanged(ChangeEvent e) {
+ // The action concerned with closing the window.
+ CloseAction closeAction;
- SwingUtilities.invokeLater(new Runnable() {
- public void run() {
- activateVisible();
- }
- });
+ // The action that deletes the current entry, and closes the editor.
+ DeleteAction deleteAction = new DeleteAction();
+ // The action concerned with copying the BibTeX key to the clipboard.
+ CopyKeyAction copyKeyAction;
- // After the initial event train has finished, we tell the editor tab to update all
- // its fields. This makes sure they are updated even if the tab we just left contained one
- // or more of the same fields as this one:
- SwingUtilities.invokeLater(new Runnable() {
- public void run() {
- Object activeTab = tabs.get(tabbed.getSelectedIndex());
- if (activeTab instanceof EntryEditorTab)
- ((EntryEditorTab)activeTab).updateAll();
- }
- });
+ // The action concerned with copying the BibTeX key to the clipboard.
+ AbstractAction nextEntryAction = new NextEntryAction();
- }
- }
-
- class DeleteAction extends AbstractAction {
- public DeleteAction() {
- super(Globals.lang("Delete"), GUIGlobals.getImage("delete"));
- putValue(SHORT_DESCRIPTION, Globals.lang("Delete entry"));
- }
-
- public void actionPerformed(ActionEvent e) {
- // Show confirmation dialog if not disabled:
- boolean goOn = panel.showDeleteConfirmationDialog(1);
+ // Actions for switching to next/previous entry.
+ AbstractAction prevEntryAction = new PrevEntryAction();
- if (!goOn)
- return;
+ // The action concerned with storing a field value.
+ public StoreFieldAction storeFieldAction;
- panel.entryEditorClosing(EntryEditor.this);
- panel.database.removeEntry(entry.getId());
- panel.markBaseChanged();
- panel.undoManager.addEdit(new UndoableRemoveEntry(panel.database, entry, panel));
- panel.output(Globals.lang("Deleted") + " " + Globals.lang("entry"));
- }
- }
-
- class CloseAction extends AbstractAction {
- public CloseAction() {
- super(Globals.lang("Close window"), GUIGlobals.getImage("close"));
- putValue(SHORT_DESCRIPTION, Globals.lang("Close window"));
- }
+ // The actions concerned with switching the panels.
+ SwitchLeftAction switchLeftAction = new SwitchLeftAction();
- public void actionPerformed(ActionEvent e) {
- if (tabbed.getSelectedComponent() == srcPanel) {
- updateField(source);
- if (lastSourceAccepted)
- panel.entryEditorClosing(EntryEditor.this);
- } else
- panel.entryEditorClosing(EntryEditor.this);
- }
- }
-
- class CopyKeyAction extends AbstractAction {
- public CopyKeyAction() {
- super("Copy BibTeX key to clipboard");
- putValue(SHORT_DESCRIPTION, "Copy BibTeX key to clipboard (Ctrl-K)");
-
- //putValue(MNEMONIC_KEY, GUIGlobals.copyKeyCode);
- }
-
- public void actionPerformed(ActionEvent e) {
- String s = (String) (entry.getField(KEY_PROPERTY));
- StringSelection ss = new StringSelection(s);
-
- if (s != null)
- Toolkit.getDefaultToolkit().getSystemClipboard().setContents(ss, ss);
- }
- }
-
- public class StoreFieldAction extends AbstractAction {
- public StoreFieldAction() {
- super("Store field value");
- putValue(SHORT_DESCRIPTION, "Store field value");
- }
-
- public void actionPerformed(ActionEvent e) {
-
- if (e.getSource() instanceof FieldTextArea) {
- String toSet = null;
- FieldEditor fe = (FieldEditor) e.getSource();
- boolean set;
- // Trim the whitespace off this value
- fe.setText(fe.getText().trim());
-
- if (fe.getText().length() > 0) {
- toSet = fe.getText();
- }
+ SwitchRightAction switchRightAction = new SwitchRightAction();
+ // The action which generates a bibtexkey for this entry.
+ GenerateKeyAction generateKeyAction;
- // We check if the field has changed, since we don't want to
- // mark the
- // base as changed unless we have a real change.
- if (toSet == null) {
- if (entry.getField(fe.getFieldName()) == null)
- set = false;
- else
- set = true;
- } else {
- if ((entry.getField(fe.getFieldName()) != null)
- && toSet.equals(entry.getField(fe.getFieldName()).toString()))
- set = false;
- else
- set = true;
- }
+ SaveDatabaseAction saveDatabaseAction = new SaveDatabaseAction();
- if (set) {
- try {
- // The following statement attempts to write the
- // new contents into a StringWriter, and this will
- // cause an IOException if the field is not
- // properly formatted. If that happens, the field
- // is not stored and the textarea turns red.
- if (toSet != null)
- (new LatexFieldFormatter()).format(toSet, fe.getFieldName());
-
- Object oldValue = entry.getField(fe.getFieldName());
-
- if (toSet != null)
- entry.setField(fe.getFieldName(), toSet);
- else
- entry.clearField(fe.getFieldName());
-
- if ((toSet != null) && (toSet.length() > 0))
- //fe.setLabelColor(GUIGlobals.validFieldColor);
- fe.setBackground(GUIGlobals.validFieldBackground);
- else
- //fe.setLabelColor(GUIGlobals.nullFieldColor);
- fe.setBackground(GUIGlobals.validFieldBackground);
-
- // Add an UndoableFieldChange to the baseframe's
- // undoManager.
- panel.undoManager.addEdit(new UndoableFieldChange(entry, fe.getFieldName(),
- oldValue, toSet));
- updateSource();
- panel.markBaseChanged();
-
- // TODO: is this a safe solution to keep selection on entry?
- SwingUtilities.invokeLater(new Runnable() {
- public void run() {
- panel.highlightEntry(entry);
- }
- });
-
-
- } catch (IllegalArgumentException ex) {
- JOptionPane.showMessageDialog(frame, "Error: " + ex.getMessage(),
- Globals.lang("Error setting field"), JOptionPane.ERROR_MESSAGE);
- fe.setBackground(GUIGlobals.invalidFieldBackground);
- }
- }
- else {
- // set == false
- // We set the field and label color.
- fe.setBackground(GUIGlobals.validFieldBackground);
-
- /*
- * fe.setLabelColor((toSet == null) ? GUIGlobals.nullFieldColor :
- * GUIGlobals.validFieldColor);
- */
- }
- } else if (e.getSource() instanceof FieldTextField) {
- // Storage from bibtex key field.
- FieldTextField fe = (FieldTextField) e.getSource();
- String oldValue = entry.getCiteKey();
- String newValue = fe.getText();
-
- if (newValue.equals(""))
- newValue = null;
-
- if (((oldValue == null) && (newValue == null))
- || ((oldValue != null) && (newValue != null) && oldValue.equals(newValue)))
- return; // No change.
-
- // Make sure the key is legal:
- String cleaned = Util.checkLegalKey(newValue);
- if ((cleaned != null) && !cleaned.equals(newValue)) {
- JOptionPane.showMessageDialog(frame, Globals.lang("Invalid BibTeX key"),
- Globals.lang("Error setting field"), JOptionPane.ERROR_MESSAGE);
- fe.setBackground(GUIGlobals.invalidFieldBackground);
- return;
- } else {
- fe.setBackground(/*fe.getTextComponent().hasFocus() ?
- GUIGlobals.activeEditor :*/
- GUIGlobals.validFieldBackground);
- }
+ JPanel mainPanel = new JPanel();
- boolean isDuplicate = panel.database.setCiteKeyForEntry(entry.getId(), newValue);
+ JPanel srcPanel = new JPanel();
- if (newValue != null) {
- if (isDuplicate)
- warnDuplicateBibtexkey();
- else
- panel.output(Globals.lang("BibTeX key is unique."));
- } else { // key is null/empty
- warnEmptyBibtexkey();
- }
+ EntryEditorTab genPan, optPan, reqPan, absPan;
- // Add an UndoableKeyChange to the baseframe's undoManager.
- panel.undoManager.addEdit(new UndoableKeyChange(panel.database, entry.getId(),
- oldValue, newValue));
+ JTextField bibtexKey;
- if ((newValue != null) && (newValue.length() > 0))
- //fe.setLabelColor(GUIGlobals.validFieldColor);
- fe.setBackground(GUIGlobals.validFieldBackground);
- else
- //fe.setLabelColor(GUIGlobals.nullFieldColor);
- fe.setBackground(GUIGlobals.validFieldBackground);
+ FieldTextField tf;
- updateSource();
- panel.markBaseChanged();
- } else if ((source.isEditable())
- && (!source.getText().equals(lastSourceStringAccepted))) {
- boolean accepted = storeSource(true);
+ JTextArea source;
- if (accepted) {
- }
- }
- }
- }
+ JToolBar tlb;
- class SwitchLeftAction extends AbstractAction {
- public SwitchLeftAction() {
- super("Switch to the panel to the left");
- }
+ JTabbedPane tabbed = new JTabbedPane(); // JTabbedPane.RIGHT);
- public void actionPerformed(ActionEvent e) {
- //System.out.println("switch left");
- int i = tabbed.getSelectedIndex();
- tabbed.setSelectedIndex(((i > 0) ? (i - 1) : (tabbed.getTabCount() - 1)));
+ JLabel lab;
- activateVisible();
- }
- }
+ TypeLabel typeLabel;
- class SwitchRightAction extends AbstractAction {
- public SwitchRightAction() {
- super("Switch to the panel to the right");
- }
+ JabRefFrame frame;
- public void actionPerformed(ActionEvent e) {
- //System.out.println("switch right");
- int i = tabbed.getSelectedIndex();
- tabbed.setSelectedIndex((i < (tabbed.getTabCount() - 1)) ? (i + 1) : 0);
- activateVisible();
+ BasePanel panel;
- }
- }
+ EntryEditor ths = this;
- class NextEntryAction extends AbstractAction {
- public NextEntryAction() {
- super(Globals.lang("Next entry"), GUIGlobals.getImage("down"));
+ HashSet contentSelectors = new HashSet();
- putValue(SHORT_DESCRIPTION, Globals.lang("Next entry"));
- }
+ Logger logger = Logger.getLogger(EntryEditor.class.getName());
- public void actionPerformed(ActionEvent e) {
+ boolean updateSource = true; // This can be set to false to stop the
+ // source
- int thisRow = panel.mainTable.findEntry(entry);
- String id = null;
- int newRow = -1;
+ List tabs = new ArrayList();
- if ((thisRow + 1) < panel.database.getEntryCount())
- newRow = thisRow + 1;
- else if (thisRow > 0)
- newRow = 0;
- else
- return; // newRow is still -1, so we can assume the database has only one entry.
+ // text area from gettin updated. This is used in cases where the source
+ // couldn't be parsed, and the user is given the option to edit it.
+ boolean lastSourceAccepted = true; // This indicates whether the last
- scrollTo(newRow);
- panel.mainTable.setRowSelectionInterval(newRow, newRow);
+ // attempt
+ // at parsing the source was successful. It is used to determine whether the
+ // dialog should close; it should stay open if the user received an error
+ // message about the source, whatever he or she chose to do about it.
+ String lastSourceStringAccepted = null; // This is used to prevent double
- }
- }
+ // fields.
+ // These values can be used to calculate the preferred height for the form.
+ // reqW starts at 1 because it needs room for the bibtex key field.
+ private int sourceIndex = -1; // The index the source panel has in tabbed.
- class PrevEntryAction extends AbstractAction {
- public PrevEntryAction() {
- super(Globals.lang("Previous entry"), GUIGlobals.getImage("up"));
+ JabRefPreferences prefs;
- putValue(SHORT_DESCRIPTION, Globals.lang("Previous entry"));
- }
+ HelpAction helpAction;
- public void actionPerformed(ActionEvent e) {
- int thisRow = panel.mainTable.findEntry(entry);
- String id = null;
- int newRow = -1;
+ UndoAction undoAction = new UndoAction();
- if ((thisRow - 1) >= 0)
- newRow = thisRow - 1;
- else if (thisRow != (panel.database.getEntryCount() - 1))
- newRow = panel.database.getEntryCount() - 1;
- else
- return; // newRow is still -1, so we can assume the database has only one entry.
- //id = panel.tableModel.getIdForRow(newRow);
- //switchTo(id);
+ RedoAction redoAction = new RedoAction();
- scrollTo(newRow);
- panel.mainTable.setRowSelectionInterval(newRow, newRow);
+ TabListener tabListener = new TabListener();
- }
- }
+ public EntryEditor(JabRefFrame frame_, BasePanel panel_, BibtexEntry entry_) {
- class GenerateKeyAction extends AbstractAction {
- JabRefFrame parent;
- BibtexEntry selectedEntry;
+ frame = frame_;
+ panel = panel_;
+ entry = entry_;
+ prefs = Globals.prefs;
+ type = entry.getType();
- public GenerateKeyAction(JabRefFrame parentFrame) {
- super(Globals.lang("Generate BibTeX key"), GUIGlobals.getImage("makeKey"));
- parent = parentFrame;
+ entry.addPropertyChangeListener(this);
- // selectedEntry = newEntry ;
- putValue(SHORT_DESCRIPTION, Globals.lang("Generate BibTeX key"));
+ helpAction = new HelpAction(frame.helpDiag, GUIGlobals.entryEditorHelp, "Help");
+ closeAction = new CloseAction();
+ copyKeyAction = new CopyKeyAction();
+ generateKeyAction = new GenerateKeyAction(frame);
+ storeFieldAction = new StoreFieldAction();
- // putValue(MNEMONIC_KEY, GUIGlobals.showGenKeyCode);
- }
+ BorderLayout bl = new BorderLayout();
+ setLayout(bl);
+ setupToolBar();
+ setupFieldPanels();
+ setupSourcePanel();
+ add(tabbed, BorderLayout.CENTER);
+ tabbed.addChangeListener(tabListener);
+ if (prefs.getBoolean("showSource") && prefs.getBoolean("defaultShowSource"))
+ tabbed.setSelectedIndex(sourceIndex);
- public void actionPerformed(ActionEvent e) {
- // 1. get Bitexentry for selected index (already have)
- // 2. run the LabelMaker by it
- try {
- // this updates the table automatically, on close, but not
- // within the tab
- Object oldValue = entry.getField(BibtexFields.KEY_FIELD);
-
- //entry = frame.labelMaker.applyRule(entry, panel.database) ;
- LabelPatternUtil.makeLabel(prefs.getKeyPattern(), panel.database, entry);
-
- // Store undo information:
- panel.undoManager.addEdit(new UndoableKeyChange(panel.database, entry.getId(),
- (String) oldValue, (String) entry.getField(BibtexFields.KEY_FIELD)));
-
- // here we update the field
- String bibtexKeyData = (String) entry.getField(BibtexFields.KEY_FIELD);
-
- // set the field named for "bibtexkey"
- setField(BibtexFields.KEY_FIELD, bibtexKeyData);
- updateSource();
- panel.markBaseChanged();
- } catch (Throwable t) {
- System.err.println("error setting key: " + t);
- }
- }
- }
+ updateAllFields();
+ }
- class UndoAction extends AbstractAction {
- public UndoAction() {
- super("Undo", GUIGlobals.getImage("undo"));
- putValue(SHORT_DESCRIPTION, "Undo");
- }
+ private void setupFieldPanels() {
+ tabbed.removeAll();
+ tabs.clear();
+ String[] fields = entry.getRequiredFields();
- public void actionPerformed(ActionEvent e) {
- try {
- panel.runCommand("undo");
- } catch (Throwable ex) {
- }
- }
- }
+ List fieldList = null;
+ if (fields != null)
+ fieldList = java.util.Arrays.asList(fields);
+ reqPan = new EntryEditorTab(fieldList, this, true, Globals.lang("Required fields"));
+ tabbed.addTab(Globals.lang("Required fields"), GUIGlobals.getImage("required"), reqPan
+ .getPane(), Globals.lang("Show required fields"));
+ tabs.add(reqPan);
- class RedoAction extends AbstractAction {
- public RedoAction() {
- super("Undo", GUIGlobals.getImage("redo"));
- putValue(SHORT_DESCRIPTION, "Redo");
- }
+ if ((entry.getOptionalFields() != null) && (entry.getOptionalFields().length >= 1)) {
+ optPan = new EntryEditorTab(java.util.Arrays.asList(entry.getOptionalFields()), this,
+ false, Globals.lang("Optional fields"));
+ tabbed.addTab(Globals.lang("Optional fields"), GUIGlobals.getImage("optional"), optPan
+ .getPane(), Globals.lang("Show optional fields"));
+ tabs.add(optPan);
+ }
+
+ EntryEditorTabList tabList = Globals.prefs.getEntryEditorTabList();
+ for (int i = 0; i < tabList.getTabCount(); i++) {
+ EntryEditorTab newTab = new EntryEditorTab(tabList.getTabFields(i), this, false,
+ tabList.getTabName(i));
+ tabbed.addTab(tabList.getTabName(i), GUIGlobals.getImage("general"), newTab.getPane());
+ tabs.add(newTab);
+ }
+
+ srcPanel.setName(Globals.lang("BibTeX source"));
+ if (Globals.prefs.getBoolean("showSource")) {
+ tabbed.addTab(Globals.lang("BibTeX source"), GUIGlobals.getImage("source"), srcPanel,
+ Globals.lang("Show/edit BibTeX source"));
+ tabs.add(srcPanel);
+ }
+ sourceIndex = tabs.size() - 1; // Set the sourceIndex variable.
+ srcPanel.setFocusCycleRoot(true);
+ }
+
+ public BibtexEntryType getType() {
+ return type;
+ }
+
+ public BibtexEntry getEntry() {
+ return entry;
+ }
+
+ private void setupToolBar() {
+ tlb = new JToolBar(JToolBar.VERTICAL);
+
+ // tlb.setMargin(new Insets(2,2,2,2));
+ tlb.setMargin(new Insets(0, 0, 0, 2));
+
+ // The toolbar carries all the key bindings that are valid for the whole
+ // window.
+ // tlb.setBackground(GUIGlobals.lightGray);//Color.white);
+ ActionMap am = tlb.getActionMap();
+ InputMap im = tlb.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
+
+ im.put(prefs.getKey("Close entry editor"), "close");
+ am.put("close", closeAction);
+ im.put(prefs.getKey("Entry editor, store field"), "store");
+ am.put("store", storeFieldAction);
+ im.put(prefs.getKey("Autogenerate BibTeX keys"), "generateKey");
+ am.put("generateKey", generateKeyAction);
+ /*
+ * im.put(prefs.getKey("Entry editor, previous panel"), "left");
+ * im.put(prefs.getKey("Entry editor, previous panel 2"), "left");
+ * am.put("left", switchLeftAction); im.put(prefs.getKey("Entry editor,
+ * next panel"), "right"); im.put(prefs.getKey("Entry editor, next panel
+ * 2"), "right"); am.put("right", switchRightAction);
+ */
+ im.put(prefs.getKey("Entry editor, previous entry"), "prev");
+ am.put("prev", prevEntryAction);
+ im.put(prefs.getKey("Entry editor, next entry"), "next");
+ am.put("next", nextEntryAction);
+ im.put(prefs.getKey("Undo"), "undo");
+ am.put("undo", undoAction);
+ im.put(prefs.getKey("Redo"), "redo");
+ am.put("redo", redoAction);
+ im.put(prefs.getKey("Help"), "help");
+ am.put("help", helpAction);
+
+ tlb.setFloatable(false);
+ tlb.add(closeAction);
+
+ setLabel();
+ tlb.add(typeLabel);
+
+ // tlb.addSeparator();
+ // tlb.add(copyKeyAction);
+ tlb.addSeparator();
+ tlb.add(generateKeyAction);
+ tlb.addSeparator();
+
+ // tlb.add(undoAction);
+ // tlb.add(redoAction);
+ tlb.add(deleteAction);
+ tlb.add(prevEntryAction);
+
+ tlb.add(nextEntryAction);
+ tlb.addSeparator();
+ tlb.add(helpAction);
+
+ Component[] comps = tlb.getComponents();
+
+ for (int i = 0; i < comps.length; i++)
+ ((JComponent) comps[i]).setOpaque(false);
+
+ add(tlb, BorderLayout.WEST);
+ }
+
+ private void setLabel() {
+ typeLabel = new TypeLabel(entry.getType().getName());
+ }
+
+ /**
+ * Rebuild the field tabs. This is called e.g. when a new content selector
+ * has been added.
+ */
+ public void rebuildPanels() {
+ // Remove change listener, because the rebuilding causes meaningless
+ // events and trouble:
+ tabbed.removeChangeListener(tabListener);
+
+ setupFieldPanels();
+ // Add the change listener again:
+ tabbed.addChangeListener(tabListener);
+ revalidate();
+ repaint();
+ }
+
+ /**
+ * getExtra checks the field name against BibtexFields.getFieldExtras(name).
+ * If the name has an entry, the proper component to be shown is created and
+ * returned. Otherwise, null is returned. In addition, e.g. listeners can be
+ * added to the field editor, even if no component is returned.
+ *
+ * @param string
+ * Field name
+ * @return Component to show, or null if none.
+ */
+ public JComponent getExtra(String string, FieldEditor editor) {
+ final FieldEditor ed = editor;
+
+ // fieldName and parameter string identically ????
+ final String fieldName = editor.getFieldName();
+
+ String s = BibtexFields.getFieldExtras(string);
+
+ // timestamp or a other field with datepicker command
+ if ((fieldName.equals(Globals.prefs.get("timeStampField")))
+ || ((s != null) && s.equals("datepicker"))) {
+ // double click AND datefield => insert the current date (today)
+ ((JTextArea) ed).addMouseListener(new MouseAdapter() {
+ public void mouseClicked(MouseEvent e) {
+ if (e.getClickCount() == 2) // double click
+ {
+ String date = Util.easyDateFormat();
+ ed.setText(date);
+ }
+ }
+ });
+
+ // insert a datepicker, if the extras field contains this command
+ if ((s != null) && s.equals("datepicker")) {
+ DatePickerButton datePicker = new DatePickerButton(ed);
+ return datePicker.getDatePicker();
+ }
+ }
+
+ if ((s != null) && s.equals("external")) {
+
+ // Add external viewer listener for "pdf" and "url" fields.
+ ((JComponent) editor).addMouseListener(new ExternalViewerListener());
+
+ return null;
+ } else if ((s != null) && s.equals("journalNames")) {
+ // Add controls for switching between abbreviated and full journal
+ // names.
+ // If this field also has a FieldContentSelector, we need to combine
+ // these.
+ JPanel controls = new JPanel();
+ controls.setLayout(new BorderLayout());
+ if (panel.metaData.getData(Globals.SELECTOR_META_PREFIX + editor.getFieldName()) != null) {
+ FieldContentSelector ws = new FieldContentSelector(frame, panel, frame, editor,
+ panel.metaData, storeFieldAction, false, ", ");
+ contentSelectors.add(ws);
+ controls.add(ws, BorderLayout.NORTH);
+ }
+ controls.add(JournalAbbreviations.getNameSwitcher(this, editor, panel.undoManager),
+ BorderLayout.SOUTH);
+ return controls;
+ } else if (panel.metaData.getData(Globals.SELECTOR_META_PREFIX + editor.getFieldName()) != null) {
+ FieldContentSelector ws = new FieldContentSelector(frame, panel, frame, editor,
+ panel.metaData, storeFieldAction, false,
+ (editor.getFieldName().equals("author") ? " and " : ", "));
+ contentSelectors.add(ws);
+
+ return ws;
+ } else if ((s != null) && s.equals("browse")) {
+ JButton but = new JButton(Globals.lang("Browse"));
+ ((JComponent) editor).addMouseListener(new ExternalViewerListener());
+
+ // but.setBackground(GUIGlobals.lightGray);
+ but.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ String dir = ed.getText();
+
+ if (dir.equals(""))
+ dir = prefs.get(fieldName + Globals.FILETYPE_PREFS_EXT, "");
+
+ String chosenFile = Globals.getNewFile(frame, new File(dir), "." + fieldName,
+ JFileChooser.OPEN_DIALOG, false);
+
+ if (chosenFile != null) {
+ File newFile = new File(chosenFile); // chooser.getSelectedFile();
+ ed.setText(newFile.getPath());
+ prefs.put(fieldName + Globals.FILETYPE_PREFS_EXT, newFile.getPath());
+ updateField(ed);
+ }
+ }
+ });
+
+ return but;
+ // } else if ((s != null) && s.equals("browsePdf")) {
+ } else if ((s != null) && (s.equals("browseDoc") || s.equals("browseDocZip"))) {
+
+ final String ext = "." + fieldName.toLowerCase();
+ final OpenFileFilter off;
+ if (s.equals("browseDocZip"))
+ off = new OpenFileFilter(new String[] { ext, ext + ".gz", ext + ".bz2" });
+ else
+ off = new OpenFileFilter(new String[] { ext });
+
+ ExternalFilePanel pan = new ExternalFilePanel(frame, panel.metaData(), this, fieldName,
+ off, ed);
+ return pan;
+ }
+ /*
+ * else if ((s != null) && s.equals("browsePs")) { ExternalFilePanel pan =
+ * new ExternalFilePanel(frame, this, "ps", off, ed); return pan; }
+ */
+ else if ((s != null) && s.equals("url")) {
+ ((JComponent) editor).setDropTarget(new DropTarget((Component) editor,
+ DnDConstants.ACTION_NONE, new SimpleUrlDragDrop(editor, storeFieldAction)));
+
+ return null;
+ }
+
+ else
+ return null;
+ }
+
+ private void setupSourcePanel() {
+ source = new JTextArea() {
+ private boolean antialias = Globals.prefs.getBoolean("antialias");
+
+ public void paint(Graphics g) {
+ Graphics2D g2 = (Graphics2D) g;
+ if (antialias)
+ g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
+ RenderingHints.VALUE_ANTIALIAS_ON);
+ super.paint(g2);
+ }
+ };
+
+ //DefaultFormBuilder builder = new DefaultFormBuilder
+ // (srcPanel, new FormLayout( "fill:pref:grow", "fill:pref:grow"));
+ source.setEditable(true); // prefs.getBoolean("enableSourceEditing"));
+ source.setLineWrap(true);
+ source.setTabSize(GUIGlobals.INDENT);
+ source.addFocusListener(new FieldEditorFocusListener());
+ // Add the global focus listener, so a menu item can see if this field
+ // was focused when
+ // an action was called.
+ source.addFocusListener(Globals.focusListener);
+ source.setFont(new Font("Monospaced", Font.PLAIN, Globals.prefs.getInt("fontSize")));
+ setupJTextComponent(source);
+ updateSource();
+
+ JScrollPane sp = new JScrollPane(source, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
+ JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
+ //builder.append(sp);
+
+ srcPanel.setLayout(new BorderLayout());
+ srcPanel.add(sp, BorderLayout.CENTER);
- public void actionPerformed(ActionEvent e) {
- try {
- panel.runCommand("redo");
- } catch (Throwable ex) {
- }
}
- }
- class SaveDatabaseAction extends AbstractAction {
- public SaveDatabaseAction() {
- super("Save database");
- }
+ public void updateSource() {
+ if (updateSource) {
+ StringWriter sw = new StringWriter(200);
- public void actionPerformed(ActionEvent e) {
- Object activeTab = tabs.get(tabbed.getSelectedIndex());
- if (activeTab instanceof EntryEditorTab) {
- // Normal panel.
- EntryEditorTab fp = (EntryEditorTab)activeTab;
- updateField(fp.getActive());
- } else
- // Source panel.
- updateField(activeTab);
-
- try {
- panel.runCommand("save");
- } catch (Throwable ex) {
- }
- }
- }
-
- class ExternalViewerListener extends MouseAdapter {
- public void mouseClicked(MouseEvent evt) {
- if (evt.getClickCount() == 2) {
- FieldTextArea tf = (FieldTextArea) evt.getSource();
-
- if (tf.getText().equals(""))
- return;
-
- tf.selectAll();
-
- String link = tf.getText(); // get selected ? String
-
- // getSelectedText()
- try {
- Util.openExternalViewer(panel.metaData(), link, tf.getFieldName());
- } catch (IOException ex) {
- System.err.println("Error opening file.");
- }
- }
- }
- }
+ try {
+ entry.write(sw, new net.sf.jabref.export.LatexFieldFormatter(), false);
- class ChangeTypeAction extends AbstractAction {
- BibtexEntryType type;
- BasePanel panel;
+ String srcString = sw.getBuffer().toString();
+ source.setText(srcString);
+ lastSourceStringAccepted = srcString;
+ } catch (IOException ex) {
+ source.setText("Error: " + ex.getMessage() + "\n\n" + "Correct the entry, and "
+ + "reopen editor to display/edit source.");
+ source.setEditable(false);
+ }
- public ChangeTypeAction(BibtexEntryType type, BasePanel bp) {
- super(type.getName());
- this.type = type;
- panel = bp;
- }
- public void actionPerformed(ActionEvent evt) {
- panel.changeType(entry, type);
- }
- }
-
- /**
- * Scans all groups.
- * @return true if the specified entry is contained in any ExplicitGroup,
- * false otherwise.
- */
- private boolean containedInExplicitGroup(BibtexEntry entry) {
- AbstractGroup[] matchingGroups = panel.getGroupSelector().getGroupTreeRoot().
- getMatchingGroups(entry);
- for (int i = 0; i < matchingGroups.length; ++i) {
- if (matchingGroups[i] instanceof ExplicitGroup)
- return true;
- }
- return false;
- }
-
- private void warnDuplicateBibtexkey() {
- panel.output(Globals.lang("Warning") + ": "
- + Globals.lang("Duplicate BibTeX key."));
-
- if (prefs.getBoolean("dialogWarningForDuplicateKey")) {
- // JZTODO lyrics
- CheckBoxMessage jcb = new CheckBoxMessage(Globals.lang("Warning")
- + ": " + Globals.lang("Duplicate BibTeX key. Grouping may not work for this entry."),
- Globals.lang("Disable this warning dialog"), false);
- JOptionPane.showMessageDialog(frame, jcb, Globals.lang("Warning"),
- JOptionPane.WARNING_MESSAGE);
-
- if (jcb.isSelected())
- prefs.putBoolean("dialogWarningForDuplicateKey", false);
}
- }
-
- private void warnEmptyBibtexkey() {
- // JZTODO lyrics
- panel.output(Globals.lang("Warning") + ": "
- + Globals.lang("Empty BibTeX key."));
-
- if (prefs.getBoolean("dialogWarningForEmptyKey")) {
- // JZTODO lyrics
- CheckBoxMessage jcb = new CheckBoxMessage(Globals.lang("Warning")
- + ": " + Globals.lang("Empty BibTeX key. Grouping may not work for this entry."),
- Globals.lang("Disable this warning dialog"), false);
- JOptionPane.showMessageDialog(frame, jcb, Globals.lang("Warning"),
- JOptionPane.WARNING_MESSAGE);
-
- if (jcb.isSelected())
- prefs.putBoolean("dialogWarningForEmptyKey", false);
- }
- }
+ }
+
+ /**
+ * NOTE: This method is only used for the source panel, not for the
+ * other tabs. Look at EntryEditorTab for the setup of text components
+ * in the other tabs.
+ */
+ public void setupJTextComponent(JTextComponent ta) {
+
+
+ // Set up key bindings and focus listener for the FieldEditor.
+ InputMap im = ta.getInputMap(JComponent.WHEN_FOCUSED);
+ ActionMap am = ta.getActionMap();
+
+ // im.put(KeyStroke.getKeyStroke(GUIGlobals.closeKey), "close");
+ // am.put("close", closeAction);
+ im.put(prefs.getKey("Entry editor, store field"), "store");
+ am.put("store", storeFieldAction);
+
+ im.put(prefs.getKey("Entry editor, next panel"), "right");
+ im.put(prefs.getKey("Entry editor, next panel 2"), "right");
+ am.put("right", switchRightAction);
+
+ im.put(prefs.getKey("Entry editor, previous panel"), "left");
+ im.put(prefs.getKey("Entry editor, previous panel 2"), "left");
+ am.put("left", switchLeftAction);
+
+ im.put(prefs.getKey("Help"), "help");
+ am.put("help", helpAction);
+ im.put(prefs.getKey("Save database"), "save");
+ am.put("save", saveDatabaseAction);
+
+ im.put(Globals.prefs.getKey("Next tab"), "nexttab");
+ am.put("nexttab", frame.nextTab);
+ im.put(Globals.prefs.getKey("Previous tab"), "prevtab");
+ am.put("prevtab", frame.prevTab);
+ try {
+ HashSet keys = new HashSet(ta
+ .getFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS));
+ keys.clear();
+ keys.add(AWTKeyStroke.getAWTKeyStroke("pressed TAB"));
+ ta.setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, keys);
+ keys = new HashSet(ta
+ .getFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS));
+ keys.clear();
+ keys.add(KeyStroke.getKeyStroke("shift pressed TAB"));
+ ta.setFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, keys);
+ } catch (Throwable t) {
+ System.err.println(t);
+ }
+
+ ta.addFocusListener(new FieldListener());
+ }
+
+ public void requestFocus() {
+ activateVisible();
+ }
+
+ private void activateVisible() {
+ Object activeTab = tabs.get(tabbed.getSelectedIndex());
+
+ if (activeTab instanceof EntryEditorTab)
+ ((EntryEditorTab) activeTab).activate();
+ else
+ new FocusRequester(source);
+ // ((JComponent)activeTab).requestFocus();
+ }
+
+ /**
+ * Reports the enabled status of the editor, as set by setEnabled()
+ */
+ public boolean isEnabled() {
+ return source.isEnabled();
+ }
+
+ /**
+ * Sets the enabled status of all text fields of the entry editor.
+ */
+ public void setEnabled(boolean enabled) {
+ for (Iterator i = tabs.iterator(); i.hasNext();) {
+ Object o = i.next();
+ if (o instanceof EntryEditorTab) {
+ ((EntryEditorTab) o).setEnabled(enabled);
+ }
+ }
+ source.setEnabled(enabled);
+
+ }
+
+ /**
+ * Centers the given row, and highlights it.
+ *
+ * @param row
+ * an <code>int</code> value
+ */
+ private void scrollTo(int row) {
+ panel.mainTable.setRowSelectionInterval(row, row);
+ panel.mainTable.ensureVisible(row);
+ }
+
+ /**
+ * Makes sure the current edit is stored.
+ */
+ public void storeCurrentEdit() {
+ Component comp = Globals.focusListener.getFocused();
+ if ((comp instanceof FieldEditor) && this.isAncestorOf(comp)) {
+ storeFieldAction.actionPerformed(new ActionEvent(comp, 0, ""));
+ }
+ }
+
+ /**
+ * Returns the index of the active (visible) panel.
+ *
+ * @return an <code>int</code> value
+ */
+ public int getVisiblePanel() {
+ return tabbed.getSelectedIndex();
+ }
+
+ /** Returns the name of the currently selected component. */
+ public String getVisiblePanelName() {
+ return tabbed.getSelectedComponent().getName();
+ }
+
+ /**
+ * Sets the panel with the given index visible.
+ *
+ * @param i
+ * an <code>int</code> value
+ */
+ public void setVisiblePanel(int i) {
+ tabbed.setSelectedIndex(Math.min(i, tabbed.getTabCount() - 1));
+ }
+
+ public void setVisiblePanel(String name) {
+ for (int i = 0; i < tabbed.getTabCount(); ++i) {
+ if (name.equals(tabbed.getComponent(i).getName())) {
+ tabbed.setSelectedIndex(i);
+ return;
+ }
+ }
+ if (tabbed.getTabCount() > 0)
+ tabbed.setSelectedIndex(0);
+ }
+
+ /**
+ * Updates this editor to show the given entry, regardless of type
+ * correspondence.
+ *
+ * @param be
+ * a <code>BibtexEntry</code> value
+ */
+ public synchronized void switchTo(BibtexEntry be) {
+ if (entry == be)
+ return;
+
+ // Util.pr("EntryEditor.switchTo(BibtexEntry): "+entry.getCiteKey());
+ // Util.pr("::EntryEditor.switchTo(BibtexEntry): "+this.type.getName());
+ storeCurrentEdit();
+
+ // Remove this instance as property listener for the entry:
+ entry.removePropertyChangeListener(this);
+
+ // Register as property listener for the new entry:
+ be.addPropertyChangeListener(this);
+
+ entry = be;
+
+ updateAllFields();
+ validateAllFields();
+ updateSource();
+ panel.showing = be;
+
+ }
+
+ /**
+ * Returns false if the contents of the source panel has not been validated,
+ * true othervise.
+ */
+ public boolean lastSourceAccepted() {
+ if (tabbed.getSelectedComponent() == srcPanel)
+ storeSource(false);
+
+ return lastSourceAccepted;
+ }
+
+ /*
+ * public boolean storeSourceIfNeeded() { if (tabbed.getSelectedIndex() ==
+ * sourceIndex) return storeSource(); else return true; }
+ */
+ public boolean storeSource(boolean showError) {
+ // Store edited bibtex code.
+ BibtexParser bp = new BibtexParser(new java.io.StringReader(source.getText()));
+
+ try {
+ BibtexDatabase db = bp.parse().getDatabase();
+
+ if (db.getEntryCount() > 1)
+ throw new Exception("More than one entry found.");
+
+ if (db.getEntryCount() < 1)
+ throw new Exception("No entries found.");
+
+ NamedCompound compound = new NamedCompound(Globals.lang("source edit"));
+ BibtexEntry nu = db.getEntryById((String) db.getKeySet().iterator().next());
+ String id = entry.getId();
+ String
+ // oldKey = entry.getCiteKey(),
+ newKey = nu.getCiteKey();
+ boolean anyChanged = false;
+ boolean duplicateWarning = false;
+ boolean emptyWarning = newKey == null || newKey.equals("");
+
+ if (panel.database.setCiteKeyForEntry(id, newKey)) {
+ duplicateWarning = true;
+
+ // First, remove fields that the user have removed.
+ }
+
+ Object[] fields = entry.getAllFields();
+
+ for (int i = 0; i < fields.length; i++) {
+ if (BibtexFields.isDisplayableField(fields[i].toString())) {
+ if (nu.getField(fields[i].toString()) == null) {
+ compound.addEdit(new UndoableFieldChange(entry, fields[i].toString(), entry
+ .getField(fields[i].toString()), (Object) null));
+ entry.clearField(fields[i].toString());
+ anyChanged = true;
+ }
+ }
+ }
+
+ // Then set all fields that have been set by the user.
+ fields = nu.getAllFields();
+
+ for (int i = 0; i < fields.length; i++) {
+ if (entry.getField(fields[i].toString()) != nu.getField(fields[i].toString())) {
+ String toSet = (String) nu.getField(fields[i].toString());
+
+ // Test if the field is legally set.
+ (new LatexFieldFormatter()).format(toSet, fields[i].toString());
+
+ compound.addEdit(new UndoableFieldChange(entry, fields[i].toString(), entry
+ .getField(fields[i].toString()), toSet));
+ entry.setField(fields[i].toString(), toSet);
+ anyChanged = true;
+ }
+ }
+
+ compound.end();
+
+ if (!anyChanged)
+ return true;
+
+ panel.undoManager.addEdit(compound);
+
+ /*
+ * if (((oldKey == null) && (newKey != null)) || ((oldKey != null) &&
+ * (newKey == null)) || ((oldKey != null) && (newKey != null) &&
+ * !oldKey.equals(newKey))) { }
+ */
+ if (duplicateWarning) {
+ warnDuplicateBibtexkey();
+ } else if (emptyWarning && showError) {
+ warnEmptyBibtexkey();
+ } else {
+ panel.output(Globals.lang("Stored entry") + ".");
+ }
+
+ lastSourceStringAccepted = source.getText();
+ updateAllFields();
+ lastSourceAccepted = true;
+ updateSource = true;
+
+ // TODO: does updating work properly after source stored?
+ // panel.tableModel.remap();
+ // panel.entryTable.repaint();
+ // panel.refreshTable();
+ panel.markBaseChanged();
+
+ return true;
+ } catch (Throwable ex) {
+ // ex.printStackTrace();
+ // The source couldn't be parsed, so the user is given an
+ // error message, and the choice to keep or revert the contents
+ // of the source text field.
+ updateSource = false;
+ lastSourceAccepted = false;
+ tabbed.setSelectedComponent(srcPanel);
+
+ if (showError) {
+ Object[] options = { Globals.lang("Edit"),
+ Globals.lang("Revert to original source") };
+
+ int answer = JOptionPane.showOptionDialog(frame, "Error: " + ex.getMessage(),
+ Globals.lang("Problem with parsing entry"), JOptionPane.YES_NO_OPTION,
+ JOptionPane.ERROR_MESSAGE, null, options, options[0]);
+
+ if (answer != 0) {
+ updateSource = true;
+ updateSource();
+ }
+ }
+
+ return false;
+ }
+ }
+
+ public void setField(String fieldName, String newFieldData) {
+
+ for (Iterator i = tabs.iterator(); i.hasNext();) {
+ Object o = i.next();
+ if (o instanceof EntryEditorTab) {
+ ((EntryEditorTab) o).updateField(fieldName, newFieldData);
+ }
+ }
+
+ }
+
+ /**
+ * Sets all the text areas according to the shown entry.
+ */
+ public void updateAllFields() {
+ for (Iterator i = tabs.iterator(); i.hasNext();) {
+ Object o = i.next();
+ if (o instanceof EntryEditorTab) {
+ ((EntryEditorTab) o).setEntry(entry);
+ }
+ }
+ }
+
+ /**
+ * Removes the "invalid field" color from all text areas.
+ */
+ public void validateAllFields() {
+ for (Iterator i = tabs.iterator(); i.hasNext();) {
+ Object o = i.next();
+ if (o instanceof EntryEditorTab) {
+ ((EntryEditorTab) o).validateAllFields();
+ }
+ }
+ }
+
+ public void updateAllContentSelectors() {
+ if (contentSelectors.size() > 0) {
+ for (Iterator i = contentSelectors.iterator(); i.hasNext();)
+ ((FieldContentSelector) i.next()).rebuildComboBox();
+ }
+ }
+
+ /*
+ * Update the JTextArea when a field has changed.
+ *
+ * (non-Javadoc)
+ *
+ * @see java.beans.VetoableChangeListener#vetoableChange(java.beans.PropertyChangeEvent)
+ */
+ public void vetoableChange(PropertyChangeEvent e) {
+ String newValue = ((e.getNewValue() != null) ? e.getNewValue().toString() : "");
+ setField(e.getPropertyName(), newValue);
+ }
+
+ public void updateField(final Object source) {
+ storeFieldAction.actionPerformed(new ActionEvent(source, 0, ""));
+ }
+
+ private class TypeLabel extends JPanel {
+ private String label;
+
+ public TypeLabel(String type) {
+ label = type;
+ addMouseListener(new MouseAdapter() {
+ public void mouseClicked(MouseEvent e) {
+ boolean ctrlClick = prefs.getBoolean("ctrlClick");
+
+ if ((e.getButton() == MouseEvent.BUTTON3)
+ || (ctrlClick && (e.getButton() == MouseEvent.BUTTON1) && e.isControlDown())) {
+ JPopupMenu typeMenu = new JPopupMenu();
+
+ // typeMenu.addSeparator();
+ for (Iterator i = BibtexEntryType.ALL_TYPES.keySet().iterator(); i
+ .hasNext();)
+ typeMenu.add(new ChangeTypeAction(BibtexEntryType.getType((String) i
+ .next()), panel));
+
+ typeMenu.show(ths, e.getX(), e.getY());
+ }
+ }
+ });
+ }
+
+ public void paint(Graphics g) {
+ Graphics2D g2 = (Graphics2D) g;
+ g2.setColor(GUIGlobals.validFieldColor);
+ g2.setFont(GUIGlobals.typeNameFont);
+
+ FontMetrics fm = g2.getFontMetrics();
+ int width = fm.stringWidth(label);
+ g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+ g2.rotate(-Math.PI / 2, 0, 0);
+ g2.drawString(label, -width - 7, 28);
+ }
+ }
+
+ class FieldListener extends FocusAdapter {
+ /*
+ * Focus listener that fires the storeFieldAction when a FieldTextArea
+ * loses focus.
+ */
+ public void focusGained(FocusEvent e) {
+ }
+
+ public void focusLost(FocusEvent e) {
+ // Util.pr("Lost focus "+e.getSource().toString().substring(0,30));
+ if (!e.isTemporary())
+ updateField(e.getSource());
+ }
+ }
+
+ class TabListener implements ChangeListener {
+ public void stateChanged(ChangeEvent e) {
+
+ SwingUtilities.invokeLater(new Runnable() {
+ public void run() {
+ activateVisible();
+ }
+ });
+
+ // After the initial event train has finished, we tell the editor
+ // tab to update all
+ // its fields. This makes sure they are updated even if the tab we
+ // just left contained one
+ // or more of the same fields as this one:
+ SwingUtilities.invokeLater(new Runnable() {
+ public void run() {
+ Object activeTab = tabs.get(tabbed.getSelectedIndex());
+ if (activeTab instanceof EntryEditorTab)
+ ((EntryEditorTab) activeTab).updateAll();
+ }
+ });
+
+ }
+ }
+
+ class DeleteAction extends AbstractAction {
+ public DeleteAction() {
+ super(Globals.lang("Delete"), GUIGlobals.getImage("delete"));
+ putValue(SHORT_DESCRIPTION, Globals.lang("Delete entry"));
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ // Show confirmation dialog if not disabled:
+ boolean goOn = panel.showDeleteConfirmationDialog(1);
+
+ if (!goOn)
+ return;
+
+ panel.entryEditorClosing(EntryEditor.this);
+ panel.database.removeEntry(entry.getId());
+ panel.markBaseChanged();
+ panel.undoManager.addEdit(new UndoableRemoveEntry(panel.database, entry, panel));
+ panel.output(Globals.lang("Deleted") + " " + Globals.lang("entry"));
+ }
+ }
+
+ class CloseAction extends AbstractAction {
+ public CloseAction() {
+ super(Globals.lang("Close window"), GUIGlobals.getImage("close"));
+ putValue(SHORT_DESCRIPTION, Globals.lang("Close window"));
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ if (tabbed.getSelectedComponent() == srcPanel) {
+ updateField(source);
+ if (lastSourceAccepted)
+ panel.entryEditorClosing(EntryEditor.this);
+ } else
+ panel.entryEditorClosing(EntryEditor.this);
+ }
+ }
+
+ class CopyKeyAction extends AbstractAction {
+ public CopyKeyAction() {
+ super("Copy BibTeX key to clipboard");
+ putValue(SHORT_DESCRIPTION, "Copy BibTeX key to clipboard (Ctrl-K)");
+ // putValue(MNEMONIC_KEY, GUIGlobals.copyKeyCode);
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ String s = (String) (entry.getField(BibtexFields.KEY_FIELD));
+ StringSelection ss = new StringSelection(s);
+
+ if (s != null)
+ Toolkit.getDefaultToolkit().getSystemClipboard().setContents(ss, ss);
+ }
+ }
+
+ public class StoreFieldAction extends AbstractAction {
+ public StoreFieldAction() {
+ super("Store field value");
+ putValue(SHORT_DESCRIPTION, "Store field value");
+ }
+
+ public void actionPerformed(ActionEvent e) {
+
+ if (e.getSource() instanceof FieldTextArea) {
+ String toSet = null;
+ FieldEditor fe = (FieldEditor) e.getSource();
+ boolean set;
+ // Trim the whitespace off this value
+ String currentText = fe.getText();
+ String trim = currentText.trim();
+
+ if (trim.length() > 0) {
+ toSet = trim;
+ }
+
+ // We check if the field has changed, since we don't want to
+ // mark the base as changed unless we have a real change.
+ if (toSet == null) {
+ if (entry.getField(fe.getFieldName()) == null)
+ set = false;
+ else
+ set = true;
+ } else {
+ if ((entry.getField(fe.getFieldName()) != null)
+ && toSet.equals(entry.getField(fe.getFieldName()).toString()))
+ set = false;
+ else
+ set = true;
+ }
+
+ if (set) {
+ try {
+ // The following statement attempts to write the
+ // new contents into a StringWriter, and this will
+ // cause an IOException if the field is not
+ // properly formatted. If that happens, the field
+ // is not stored and the textarea turns red.
+ if (toSet != null)
+ (new LatexFieldFormatter()).format(toSet, fe.getFieldName());
+
+ Object oldValue = entry.getField(fe.getFieldName());
+
+ if (toSet != null)
+ entry.setField(fe.getFieldName(), toSet);
+ else
+ entry.clearField(fe.getFieldName());
+
+ if ((toSet != null) && (toSet.length() > 0))
+ // fe.setLabelColor(GUIGlobals.validFieldColor);
+ fe.setBackground(GUIGlobals.validFieldBackground);
+ else
+ // fe.setLabelColor(GUIGlobals.nullFieldColor);
+ fe.setBackground(GUIGlobals.validFieldBackground);
+
+ // Add an UndoableFieldChange to the baseframe's
+ // undoManager.
+ panel.undoManager.addEdit(new UndoableFieldChange(entry, fe.getFieldName(),
+ oldValue, toSet));
+ updateSource();
+ panel.markBaseChanged();
+
+ // TODO: is this a safe solution to keep selection on
+ // entry?
+ SwingUtilities.invokeLater(new Runnable() {
+ public void run() {
+ panel.highlightEntry(entry);
+ }
+ });
+
+ } catch (IllegalArgumentException ex) {
+ JOptionPane.showMessageDialog(frame, "Error: " + ex.getMessage(), Globals
+ .lang("Error setting field"), JOptionPane.ERROR_MESSAGE);
+ fe.setBackground(GUIGlobals.invalidFieldBackground);
+ }
+ } else {
+ // set == false
+ // We set the field and label color.
+ fe.setBackground(GUIGlobals.validFieldBackground);
+ }
+ } else if (e.getSource() instanceof FieldTextField) {
+ // Storage from bibtex key field.
+ FieldTextField fe = (FieldTextField) e.getSource();
+ String oldValue = entry.getCiteKey();
+ String newValue = fe.getText();
+
+ if (newValue.equals(""))
+ newValue = null;
+
+ if (((oldValue == null) && (newValue == null))
+ || ((oldValue != null) && (newValue != null) && oldValue.equals(newValue)))
+ return; // No change.
+
+ // Make sure the key is legal:
+ String cleaned = Util.checkLegalKey(newValue);
+ if ((cleaned != null) && !cleaned.equals(newValue)) {
+ JOptionPane.showMessageDialog(frame, Globals.lang("Invalid BibTeX key"),
+ Globals.lang("Error setting field"), JOptionPane.ERROR_MESSAGE);
+ fe.setBackground(GUIGlobals.invalidFieldBackground);
+ return;
+ } else {
+ fe.setBackground(/*
+ * fe.getTextComponent().hasFocus() ?
+ * GUIGlobals.activeEditor :
+ */
+ GUIGlobals.validFieldBackground);
+ }
+
+ boolean isDuplicate = panel.database.setCiteKeyForEntry(entry.getId(), newValue);
+
+ if (newValue != null) {
+ if (isDuplicate)
+ warnDuplicateBibtexkey();
+ else
+ panel.output(Globals.lang("BibTeX key is unique."));
+ } else { // key is null/empty
+ warnEmptyBibtexkey();
+ }
+
+ // Add an UndoableKeyChange to the baseframe's undoManager.
+ panel.undoManager.addEdit(new UndoableKeyChange(panel.database, entry.getId(),
+ oldValue, newValue));
+
+ if ((newValue != null) && (newValue.length() > 0))
+ // fe.setLabelColor(GUIGlobals.validFieldColor);
+ fe.setBackground(GUIGlobals.validFieldBackground);
+ else
+ // fe.setLabelColor(GUIGlobals.nullFieldColor);
+ fe.setBackground(GUIGlobals.validFieldBackground);
+
+ updateSource();
+ panel.markBaseChanged();
+ } else if ((source.isEditable())
+ && (!source.getText().equals(lastSourceStringAccepted))) {
+ boolean accepted = storeSource(true);
+
+ if (accepted) {
+ }
+ }
+ }
+ }
+
+ class SwitchLeftAction extends AbstractAction {
+ public SwitchLeftAction() {
+ super("Switch to the panel to the left");
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ // System.out.println("switch left");
+ int i = tabbed.getSelectedIndex();
+ tabbed.setSelectedIndex(((i > 0) ? (i - 1) : (tabbed.getTabCount() - 1)));
+
+ activateVisible();
+ }
+ }
+
+ class SwitchRightAction extends AbstractAction {
+ public SwitchRightAction() {
+ super("Switch to the panel to the right");
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ // System.out.println("switch right");
+ int i = tabbed.getSelectedIndex();
+ tabbed.setSelectedIndex((i < (tabbed.getTabCount() - 1)) ? (i + 1) : 0);
+ activateVisible();
+
+ }
+ }
+
+ class NextEntryAction extends AbstractAction {
+ public NextEntryAction() {
+ super(Globals.lang("Next entry"), GUIGlobals.getImage("down"));
+
+ putValue(SHORT_DESCRIPTION, Globals.lang("Next entry"));
+ }
+
+ public void actionPerformed(ActionEvent e) {
+
+ int thisRow = panel.mainTable.findEntry(entry);
+ int newRow = -1;
+
+ if ((thisRow + 1) < panel.database.getEntryCount())
+ newRow = thisRow + 1;
+ else if (thisRow > 0)
+ newRow = 0;
+ else
+ return; // newRow is still -1, so we can assume the database has
+ // only one entry.
+
+ scrollTo(newRow);
+ panel.mainTable.setRowSelectionInterval(newRow, newRow);
+
+ }
+ }
+
+ class PrevEntryAction extends AbstractAction {
+ public PrevEntryAction() {
+ super(Globals.lang("Previous entry"), GUIGlobals.getImage("up"));
+
+ putValue(SHORT_DESCRIPTION, Globals.lang("Previous entry"));
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ int thisRow = panel.mainTable.findEntry(entry);
+ int newRow = -1;
+
+ if ((thisRow - 1) >= 0)
+ newRow = thisRow - 1;
+ else if (thisRow != (panel.database.getEntryCount() - 1))
+ newRow = panel.database.getEntryCount() - 1;
+ else
+ return; // newRow is still -1, so we can assume the database has
+ // only one entry.
+ // id = panel.tableModel.getIdForRow(newRow);
+ // switchTo(id);
+
+ scrollTo(newRow);
+ panel.mainTable.setRowSelectionInterval(newRow, newRow);
+
+ }
+ }
+
+ class GenerateKeyAction extends AbstractAction {
+ JabRefFrame parent;
+
+ BibtexEntry selectedEntry;
+
+ public GenerateKeyAction(JabRefFrame parentFrame) {
+ super(Globals.lang("Generate BibTeX key"), GUIGlobals.getImage("makeKey"));
+ parent = parentFrame;
+
+ // selectedEntry = newEntry ;
+ putValue(SHORT_DESCRIPTION, Globals.lang("Generate BibTeX key"));
+
+ // putValue(MNEMONIC_KEY, GUIGlobals.showGenKeyCode);
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ // 1. get Bitexentry for selected index (already have)
+ // 2. run the LabelMaker by it
+ try {
+ // this updates the table automatically, on close, but not
+ // within the tab
+ Object oldValue = entry.getField(BibtexFields.KEY_FIELD);
+
+ // entry = frame.labelMaker.applyRule(entry, panel.database) ;
+ LabelPatternUtil.makeLabel(prefs.getKeyPattern(), panel.database, entry);
+
+ // Store undo information:
+ panel.undoManager.addEdit(new UndoableKeyChange(panel.database, entry.getId(),
+ (String) oldValue, (String) entry.getField(BibtexFields.KEY_FIELD)));
+
+ // here we update the field
+ String bibtexKeyData = (String) entry.getField(BibtexFields.KEY_FIELD);
+
+ // set the field named for "bibtexkey"
+ setField(BibtexFields.KEY_FIELD, bibtexKeyData);
+ updateSource();
+ panel.markBaseChanged();
+ } catch (Throwable t) {
+ System.err.println("error setting key: " + t);
+ }
+ }
+ }
+
+ class UndoAction extends AbstractAction {
+ public UndoAction() {
+ super("Undo", GUIGlobals.getImage("undo"));
+ putValue(SHORT_DESCRIPTION, "Undo");
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ try {
+ panel.runCommand("undo");
+ } catch (Throwable ex) {
+ }
+ }
+ }
+
+ class RedoAction extends AbstractAction {
+ public RedoAction() {
+ super("Undo", GUIGlobals.getImage("redo"));
+ putValue(SHORT_DESCRIPTION, "Redo");
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ try {
+ panel.runCommand("redo");
+ } catch (Throwable ex) {
+ }
+ }
+ }
+
+ class SaveDatabaseAction extends AbstractAction {
+ public SaveDatabaseAction() {
+ super("Save database");
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ Object activeTab = tabs.get(tabbed.getSelectedIndex());
+ if (activeTab instanceof EntryEditorTab) {
+ // Normal panel.
+ EntryEditorTab fp = (EntryEditorTab) activeTab;
+ updateField(fp.getActive());
+ } else
+ // Source panel.
+ updateField(activeTab);
+
+ try {
+ panel.runCommand("save");
+ } catch (Throwable ex) {
+ }
+ }
+ }
+
+ class ExternalViewerListener extends MouseAdapter {
+ public void mouseClicked(MouseEvent evt) {
+ if (evt.getClickCount() == 2) {
+ FieldTextArea tf = (FieldTextArea) evt.getSource();
+
+ if (tf.getText().equals(""))
+ return;
+
+ tf.selectAll();
+
+ String link = tf.getText(); // get selected ? String
+
+ // getSelectedText()
+ try {
+ Util.openExternalViewer(panel.metaData(), link, tf.getFieldName());
+ } catch (IOException ex) {
+ System.err.println("Error opening file.");
+ }
+ }
+ }
+ }
+
+ class ChangeTypeAction extends AbstractAction {
+ BibtexEntryType type;
+
+ BasePanel panel;
+
+ public ChangeTypeAction(BibtexEntryType type, BasePanel bp) {
+ super(type.getName());
+ this.type = type;
+ panel = bp;
+ }
+
+ public void actionPerformed(ActionEvent evt) {
+ panel.changeType(entry, type);
+ }
+ }
+
+ /**
+ * Scans all groups.
+ *
+ * @return true if the specified entry is contained in any ExplicitGroup,
+ * false otherwise.
+ */
+ private boolean containedInExplicitGroup(BibtexEntry entry) {
+ AbstractGroup[] matchingGroups = panel.getGroupSelector().getGroupTreeRoot()
+ .getMatchingGroups(entry);
+ for (int i = 0; i < matchingGroups.length; ++i) {
+ if (matchingGroups[i] instanceof ExplicitGroup)
+ return true;
+ }
+ return false;
+ }
+
+ private void warnDuplicateBibtexkey() {
+ panel.output(Globals.lang("Warning") + ": " + Globals.lang("Duplicate BibTeX key."));
+
+ if (prefs.getBoolean("dialogWarningForDuplicateKey")) {
+ // JZTODO lyrics
+ CheckBoxMessage jcb = new CheckBoxMessage(Globals.lang("Warning") + ": "
+ + Globals.lang("Duplicate BibTeX key. Grouping may not work for this entry."),
+ Globals.lang("Disable this warning dialog"), false);
+ JOptionPane.showMessageDialog(frame, jcb, Globals.lang("Warning"),
+ JOptionPane.WARNING_MESSAGE);
+
+ if (jcb.isSelected())
+ prefs.putBoolean("dialogWarningForDuplicateKey", false);
+ }
+ }
+
+ private void warnEmptyBibtexkey() {
+ // JZTODO lyrics
+ panel.output(Globals.lang("Warning") + ": " + Globals.lang("Empty BibTeX key."));
+
+ if (prefs.getBoolean("dialogWarningForEmptyKey")) {
+ // JZTODO lyrics
+ CheckBoxMessage jcb = new CheckBoxMessage(Globals.lang("Warning") + ": "
+ + Globals.lang("Empty BibTeX key. Grouping may not work for this entry."), Globals
+ .lang("Disable this warning dialog"), false);
+ JOptionPane.showMessageDialog(frame, jcb, Globals.lang("Warning"),
+ JOptionPane.WARNING_MESSAGE);
+
+ if (jcb.isSelected())
+ prefs.putBoolean("dialogWarningForEmptyKey", false);
+ }
+ }
}
diff --git a/src/java/net/sf/jabref/EntryEditorTab.java b/src/java/net/sf/jabref/EntryEditorTab.java
index 4cb6ac9..a401507 100644
--- a/src/java/net/sf/jabref/EntryEditorTab.java
+++ b/src/java/net/sf/jabref/EntryEditorTab.java
@@ -24,272 +24,483 @@
*/
package net.sf.jabref;
-import javax.swing.*;
-import javax.swing.text.JTextComponent;
-import java.util.*;
+import java.awt.AWTKeyStroke;
+import java.awt.BorderLayout;
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+import java.awt.KeyboardFocusManager;
+import java.awt.event.FocusEvent;
+import java.awt.event.FocusListener;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
import java.util.List;
-import java.awt.*;
-import java.awt.event.*;
-public class EntryEditorTab {
+import javax.swing.ActionMap;
+import javax.swing.InputMap;
+import javax.swing.JComponent;
+import javax.swing.JPanel;
+import javax.swing.KeyStroke;
+import javax.swing.event.DocumentEvent;
+import javax.swing.event.DocumentListener;
+import javax.swing.text.JTextComponent;
- private JPanel panel = new JPanel();
- private String[] fields;
- private final static Object[] ARRAY = new String[0];
- private EntryEditor parent;
- private HashMap editors = new HashMap();
- private FieldEditor activeField = null;
- private JScrollPane sp = new JScrollPane(panel, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
- // private BibtexEntry entry;
-
- public EntryEditorTab(List fields, EntryEditor parent, boolean addKeyField, String name) {
- if (fields != null)
- this.fields = (String[])fields.toArray(ARRAY);
- else
- this.fields = new String[] {};
- this.parent = parent;
- setupPanel(addKeyField, name);
+import com.jgoodies.forms.builder.DefaultFormBuilder;
+import com.jgoodies.forms.layout.FormLayout;
- // The following line makes sure focus cycles inside tab instead of being lost
- // to other parts of the frame:
- panel.setFocusCycleRoot(true);
+/**
+ * A single tab displayed in the EntryEditor holding several FieldEditors.
+ *
+ * @author $Author: coezbek $
+ * @version $Revision: 1.19 $ ($Date: 2006/11/12 01:41:55 $)
+ *
+ */
+public class EntryEditorTab {
- }
+ private JPanel panel = new JPanel();
+ private String[] fields;
- private final void setupPanel(boolean addKeyField, String title) {
- GridBagLayout gbl = new GridBagLayout();
- GridBagConstraints con = new GridBagConstraints();
- panel.setLayout(gbl);
- double totalWeight = 0;
+ private EntryEditor parent;
- //panel.setOpaque(true);
- //panel.setBackground(java.awt.Color.white);
+ private HashMap editors = new HashMap();
- for (int i=0; i<fields.length; i++) {
+ private FieldEditor activeField = null;
- // Create the text area:
- FieldTextArea ta = new FieldTextArea(fields[i], null);//stringContent);
- JComponent ex = parent.getExtra(fields[i], ta);
- // Attach listeners and key bindings:
- setupJTextComponent(ta);
- ta.addFocusListener(new FieldListener(ta));
+ private Component firstComponent;
- // Store the editor for later reference:
- editors.put(fields[i], ta);
- if (i == 0)
- activeField = ta;
+ public EntryEditorTab(List fields, EntryEditor parent, boolean addKeyField, String name) {
+ if (fields != null)
+ this.fields = (String[]) fields.toArray(new String[0]);
+ else
+ this.fields = new String[] {};
- // The label for this field:
- con.insets = new Insets(5, 5, 0, 0);
- con.anchor = GridBagConstraints.WEST;
- con.fill = GridBagConstraints.BOTH;
- con.gridwidth = 1;
- con.weightx = 0;
- con.weighty = 0;
- con.anchor = GridBagConstraints.NORTH;
- con.fill = GridBagConstraints.BOTH;
- gbl.setConstraints(ta.getLabel(), con);
- panel.add(ta.getLabel());
-
- // The field itself:
- con.fill = GridBagConstraints.BOTH;
- con.weightx = 1;
- con.weighty = BibtexFields.getFieldWeight(fields[i]);
- totalWeight += con.weighty;
- // The gridwidth depends on whether we will add an extra component to the right:
- if (ex != null)
- con.gridwidth = 1;
- else
- con.gridwidth = GridBagConstraints.REMAINDER;
- gbl.setConstraints(ta.getPane(), con);
- panel.add(ta.getPane());
-
- // Possibly an extra component:
- if (ex != null) {
- con.gridwidth = GridBagConstraints.REMAINDER;
- con.anchor = GridBagConstraints.NORTH;
- con.fill = GridBagConstraints.HORIZONTAL;
- con.weightx = 0;
- gbl.setConstraints(ex, con);
- panel.add(ex);
- }
- panel.setName(title);
- }
+ this.parent = parent;
- // Add the edit field for Bibtex-key.
- if (addKeyField) {
- con.insets.top += 25;
- con.insets.bottom = 10;
- con.gridwidth = 1;
- con.weighty = 0;
- con.weightx = 0;
- con.fill = GridBagConstraints.HORIZONTAL;
- con.anchor = GridBagConstraints.SOUTHWEST;
- FieldTextField tf = new FieldTextField(BibtexFields.KEY_FIELD,
- (String) parent.getEntry().getField(BibtexFields.KEY_FIELD), true);
- editors.put("bibtexkey", tf);
-
- // If the key field is the only field, we should have only one editor, and this one should be set
- // as active initially:
- if (editors.size() == 1)
- activeField = tf;
-
- gbl.setConstraints(tf.getLabel(), con);
- panel.add(tf.getLabel());
- con.gridwidth = GridBagConstraints.REMAINDER;
- con.weightx = 1;
- setupJTextComponent(tf);
- tf.addFocusListener(new FieldListener(tf));
- gbl.setConstraints(tf, con);
- panel.add(tf);
- }
-
-
- }
+ newSetupPanel(addKeyField, name);
+ /*
+ * The following line makes sure focus cycles inside tab instead of
+ * being lost to other parts of the frame:
+ */
+ panel.setFocusCycleRoot(true);
+ }
- public void setActive(FieldEditor c) {
- activeField = c;
- //System.out.println(c.toString());
- }
- public FieldEditor getActive() {
- return activeField;
- }
+ void newSetupPanel(boolean addKeyField, String title) {
+
+ InputMap im = panel.getInputMap(JComponent.WHEN_FOCUSED);
+ ActionMap am = panel.getActionMap();
- public List getFields() {
- return java.util.Arrays.asList(fields);
- }
+ im.put(Globals.prefs.getKey("Entry editor, previous entry"), "prev");
+ am.put("prev", parent.prevEntryAction);
+ im.put(Globals.prefs.getKey("Entry editor, next entry"), "next");
+ am.put("next", parent.nextEntryAction);
- public void activate() {
- if (activeField != null)
- activeField.requestFocus();
-
-
- //System.out.println("Activate, hurra");
- }
-
- public void updateAll() {
- // Test: make sure all fields are correct:
- setEntry(parent.getEntry());
- /*for (int i=0; i<fields.length; i++) {
- FieldEditor fe = (FieldEditor)editors.get(fields[i]);
- fe.setText(e);
- } */
- }
-
- public void setEntry(BibtexEntry entry) {
- for (Iterator i=editors.keySet().iterator(); i.hasNext();) {
- String field = (String)i.next();
- FieldEditor ed = (FieldEditor)editors.get(field);
- Object content = entry.getField(ed.getFieldName());
- ed.setText((content == null) ? "" : content.toString());
- }
- }
-
- public boolean updateField(String field, String content) {
- if (!editors.containsKey(field))
- return false;
- FieldEditor ed = (FieldEditor)editors.get(field);
- ed.setText(content);
- return true;
- }
-
- public void validateAllFields() {
- for (Iterator i = editors.keySet().iterator(); i.hasNext();) {
- String field = (String) i.next();
- FieldEditor ed = (FieldEditor) editors.get(field);
- ed.setEnabled(true);
- if (((Component) ed).hasFocus())
- ed.setBackground(GUIGlobals.activeEditor);
- else
- ed.setBackground(GUIGlobals.validFieldBackground);
- }
- }
-
- public void setEnabled(boolean enabled) {
- for (Iterator i=editors.keySet().iterator(); i.hasNext();) {
- String field = (String)i.next();
- FieldEditor ed = (FieldEditor)editors.get(field);
- ed.setEnabled(enabled);
- }
- }
-
- public Component getPane() {
-
- return panel;
- }
-
- public void setupJTextComponent(JTextComponent ta) {
- // Activate autocompletion if it should be used for this field.
-
- // Set up key bindings and focus listener for the FieldEditor.
- InputMap im = ta.getInputMap(JComponent.WHEN_FOCUSED);
- ActionMap am = ta.getActionMap();
-
- im.put(Globals.prefs.getKey("Entry editor, previous entry"), "prev");
- am.put("prev", parent.prevEntryAction);
- im.put(Globals.prefs.getKey("Entry editor, next entry"), "next");
- am.put("next", parent.nextEntryAction);
-
- im.put(Globals.prefs.getKey("Entry editor, store field"), "store");
- am.put("store", parent.storeFieldAction);
- im.put(Globals.prefs.getKey("Entry editor, next panel"), "right");
- im.put(Globals.prefs.getKey("Entry editor, next panel 2"), "right");
- am.put("left", parent.switchLeftAction);
- im.put(Globals.prefs.getKey("Entry editor, previous panel"), "left");
- im.put(Globals.prefs.getKey("Entry editor, previous panel 2"), "left");
- am.put("right", parent.switchRightAction);
- im.put(Globals.prefs.getKey("Help"), "help");
- am.put("help", parent.helpAction);
- im.put(Globals.prefs.getKey("Save database"), "save");
- am.put("save", parent.saveDatabaseAction);
- im.put(Globals.prefs.getKey("Next tab"), "nexttab");
- am.put("nexttab", parent.frame.nextTab);
- im.put(Globals.prefs.getKey("Previous tab"), "prevtab");
- am.put("prevtab", parent.frame.prevTab);
-
-
- try {
- HashSet keys =
- new HashSet(ta.getFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS));
- keys.clear();
- keys.add(AWTKeyStroke.getAWTKeyStroke("pressed TAB"));
- ta.setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, keys);
- keys =
- new HashSet(ta.getFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS));
- keys.clear();
- keys.add(KeyStroke.getKeyStroke("shift pressed TAB"));
- ta.setFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, keys);
- } catch (Throwable t) {
- System.err.println(t);
+ im.put(Globals.prefs.getKey("Entry editor, store field"), "store");
+ am.put("store", parent.storeFieldAction);
+ im.put(Globals.prefs.getKey("Entry editor, next panel"), "right");
+ im.put(Globals.prefs.getKey("Entry editor, next panel 2"), "right");
+ am.put("left", parent.switchLeftAction);
+ im.put(Globals.prefs.getKey("Entry editor, previous panel"), "left");
+ im.put(Globals.prefs.getKey("Entry editor, previous panel 2"), "left");
+ am.put("right", parent.switchRightAction);
+ im.put(Globals.prefs.getKey("Help"), "help");
+ am.put("help", parent.helpAction);
+ im.put(Globals.prefs.getKey("Save database"), "save");
+ am.put("save", parent.saveDatabaseAction);
+ im.put(Globals.prefs.getKey("Next tab"), "nexttab");
+ am.put("nexttab", parent.frame.nextTab);
+ im.put(Globals.prefs.getKey("Previous tab"), "prevtab");
+ am.put("prevtab", parent.frame.prevTab);
+
+
+ panel.setName(title);
+ //String rowSpec = "left:pref, 4dlu, fill:pref:grow, 4dlu, fill:pref";
+ String colSpec = "fill:pref, 1dlu, fill:pref:grow, 1dlu, fill:pref";
+ StringBuffer sb = new StringBuffer();
+ for (int i = 0; i < fields.length; i++) {
+ sb.append("fill:pref:grow, ");
}
+ if (addKeyField)
+ sb.append("4dlu, fill:pref");
+ else
+ sb.delete(sb.length()-2, sb.length());
+ String rowSpec = sb.toString();
- }
-
-
- /*
- * Focus listener that fires the storeFieldAction when a FieldTextArea loses
- * focus.
- */
- class FieldListener extends FocusAdapter {
-
- FieldEditor fe;
+ DefaultFormBuilder builder = new DefaultFormBuilder
+ (panel, new FormLayout(colSpec, rowSpec));
- public FieldListener(FieldEditor fe) {
- this.fe = fe;
- }
+ for (int i = 0; i < fields.length; i++) {
+ // Create the text area:
+ final FieldTextArea ta = new FieldTextArea(fields[i], null);
+ JComponent ex = parent.getExtra(fields[i], ta);
+ setupJTextComponent(ta);
- public void focusGained(FocusEvent e) {
- setActive(fe);
+ // Store the editor for later reference:
+ editors.put(fields[i], ta);
+ if (i == 0)
+ activeField = ta;
+ //System.out.println(fields[i]+": "+BibtexFields.getFieldWeight(fields[i]));
+ ta.getPane().setPreferredSize(new Dimension(100,
+ (int)(50.0*BibtexFields.getFieldWeight(fields[i]))));
+ builder.append(ta.getLabel());
+ if (ex == null)
+ builder.append(ta.getPane(), 3);
+ else {
+ builder.append(ta.getPane());
+ JPanel pan = new JPanel();
+ pan.setLayout(new BorderLayout());
+ pan.add(ex, BorderLayout.NORTH);
+ builder.append(pan);
+ }
+ builder.nextLine();
}
- public void focusLost(FocusEvent e) {
- if (!e.isTemporary())
- parent.updateField(fe);
- }
+ // Add the edit field for Bibtex-key.
+ if (addKeyField) {
+ final FieldTextField tf = new FieldTextField(BibtexFields.KEY_FIELD, (String) parent
+ .getEntry().getField(BibtexFields.KEY_FIELD), true);
+ setupJTextComponent(tf);
+
+ editors.put("bibtexkey", tf);
+ /*
+ * If the key field is the only field, we should have only one
+ * editor, and this one should be set as active initially:
+ */
+ if (editors.size() == 1)
+ activeField = tf;
+ builder.nextLine();
+ builder.append(tf.getLabel());
+ builder.append(tf, 3);
+ }
}
+ void setupPanel(boolean addKeyField, String title) {
+ GridBagLayout gbl = new GridBagLayout();
+ GridBagConstraints con = new GridBagConstraints();
+ panel.setLayout(gbl);
+ double totalWeight = 0;
+
+ for (int i = 0; i < fields.length; i++) {
+ // Create the text area:
+ final FieldTextArea ta = new FieldTextArea(fields[i], null);
+ JComponent ex = parent.getExtra(fields[i], ta);
+
+ if (firstComponent == null){
+ firstComponent = ex;
+ }
+
+ setupJTextComponent(ta);
+
+ // Store the editor for later reference:
+ editors.put(fields[i], ta);
+ if (i == 0)
+ activeField = ta;
+
+ // The label for this field:
+ con.insets = new Insets(5, 5, 0, 0);
+ con.anchor = GridBagConstraints.WEST;
+ con.fill = GridBagConstraints.BOTH;
+ con.gridwidth = 1;
+ con.weightx = 0;
+ con.weighty = 0;
+ con.anchor = GridBagConstraints.NORTH;
+ con.fill = GridBagConstraints.BOTH;
+ gbl.setConstraints(ta.getLabel(), con);
+ panel.add(ta.getLabel());
+
+ // The field itself:
+ con.fill = GridBagConstraints.BOTH;
+ con.weightx = 1;
+ con.weighty = BibtexFields.getFieldWeight(fields[i]);
+ totalWeight += con.weighty;
+ // The gridwidth depends on whether we will add an extra component
+ // to the right:
+ if (ex != null)
+ con.gridwidth = 1;
+ else
+ con.gridwidth = GridBagConstraints.REMAINDER;
+ gbl.setConstraints(ta.getPane(), con);
+ panel.add(ta.getPane());
+
+ // Possibly an extra component:
+ if (ex != null) {
+ con.gridwidth = GridBagConstraints.REMAINDER;
+ con.anchor = GridBagConstraints.NORTH;
+ con.fill = GridBagConstraints.HORIZONTAL;
+ con.weightx = 0;
+ gbl.setConstraints(ex, con);
+ panel.add(ex);
+ }
+ panel.setName(title);
+ }
+
+ // Add the edit field for Bibtex-key.
+ if (addKeyField) {
+ con.insets.top += 25;
+ con.insets.bottom = 10;
+ con.gridwidth = 1;
+ con.weighty = 0;
+ con.weightx = 0;
+ con.fill = GridBagConstraints.HORIZONTAL;
+ con.anchor = GridBagConstraints.SOUTHWEST;
+
+ final FieldTextField tf = new FieldTextField(BibtexFields.KEY_FIELD, (String) parent
+ .getEntry().getField(BibtexFields.KEY_FIELD), true);
+ setupJTextComponent(tf);
+
+ editors.put("bibtexkey", tf);
+ /*
+ * If the key field is the only field, we should have only one
+ * editor, and this one should be set as active initially:
+ */
+ if (editors.size() == 1)
+ activeField = tf;
+
+ gbl.setConstraints(tf.getLabel(), con);
+ panel.add(tf.getLabel());
+ con.gridwidth = GridBagConstraints.REMAINDER;
+ con.weightx = 1;
+
+ gbl.setConstraints(tf, con);
+ panel.add(tf);
+ }
+ }
+
+ BibtexEntry entry;
+
+ public BibtexEntry getEntry() {
+ return entry;
+ }
+
+ boolean isFieldModified(FieldEditor f) {
+ String text = f.getText().trim();
+
+ if (text.length() == 0) {
+ return getEntry().getField(f.getFieldName()) != null;
+ } else {
+ Object entryValue = getEntry().getField(f.getFieldName());
+ return entryValue == null || !entryValue.toString().equals(text);
+ }
+ }
+
+ public void markIfModified(FieldEditor f) {
+ // Only mark as changed if not already is and the field was indeed
+ // modified
+ if (!updating && !parent.panel.isBaseChanged() && isFieldModified(f)) {
+ markBaseChanged();
+ }
+ }
+
+ void markBaseChanged() {
+ parent.panel.markBaseChanged();
+ }
+
+ /**
+ * Only sets the activeField variable but does not focus it.
+ *
+ * Call activate afterwards.
+ *
+ * @param c
+ */
+ public void setActive(FieldEditor c) {
+ activeField = c;
+ }
+
+ public FieldEditor getActive() {
+ return activeField;
+ }
+
+ public List getFields() {
+ return java.util.Arrays.asList(fields);
+ }
+
+ public void activate() {
+ if (activeField != null){
+ /**
+ * Corrected to fix [ 1594169 ] Entry editor: navigation between panels
+ */
+ new FocusRequester(activeField.getTextComponent());
+ }
+ }
+
+ /**
+ * Reset all fields from the data in the BibtexEntry.
+ *
+ */
+ public void updateAll() {
+ setEntry(getEntry());
+ }
+
+ protected boolean updating = false;
+
+ public void setEntry(BibtexEntry entry) {
+ try {
+ updating = true;
+ Iterator i = editors.values().iterator();
+ while (i.hasNext()) {
+ FieldEditor editor = (FieldEditor) i.next();
+ Object content = entry.getField(editor.getFieldName());
+ editor.setText((content == null) ? "" : content.toString());
+ }
+ this.entry = entry;
+ } finally {
+ updating = false;
+ }
+ }
+
+ public boolean updateField(String field, String content) {
+ if (!editors.containsKey(field))
+ return false;
+ FieldEditor ed = (FieldEditor) editors.get(field);
+ ed.setText(content);
+ return true;
+ }
+
+ public void validateAllFields() {
+ for (Iterator i = editors.keySet().iterator(); i.hasNext();) {
+ String field = (String) i.next();
+ FieldEditor ed = (FieldEditor) editors.get(field);
+ ed.setEnabled(true);
+ if (((Component) ed).hasFocus())
+ ed.setBackground(GUIGlobals.activeEditor);
+ else
+ ed.setBackground(GUIGlobals.validFieldBackground);
+ }
+ }
+
+ public void setEnabled(boolean enabled) {
+ Iterator i = editors.values().iterator();
+ while (i.hasNext()) {
+ FieldEditor editor = (FieldEditor) i.next();
+ editor.setEnabled(enabled);
+ }
+ }
+
+ public Component getPane() {
+ return panel;
+ }
+
+ /**
+ * Set up key bindings and focus listener for the FieldEditor.
+ *
+ * @param component
+ */
+ public void setupJTextComponent(final JTextComponent component) {
+
+ component.addFocusListener(fieldListener);
+
+ InputMap im = component.getInputMap(JComponent.WHEN_FOCUSED);
+ ActionMap am = component.getActionMap();
+
+ im.put(Globals.prefs.getKey("Entry editor, previous entry"), "prev");
+ am.put("prev", parent.prevEntryAction);
+ im.put(Globals.prefs.getKey("Entry editor, next entry"), "next");
+ am.put("next", parent.nextEntryAction);
+
+ im.put(Globals.prefs.getKey("Entry editor, store field"), "store");
+ am.put("store", parent.storeFieldAction);
+ im.put(Globals.prefs.getKey("Entry editor, next panel"), "right");
+ im.put(Globals.prefs.getKey("Entry editor, next panel 2"), "right");
+ am.put("left", parent.switchLeftAction);
+ im.put(Globals.prefs.getKey("Entry editor, previous panel"), "left");
+ im.put(Globals.prefs.getKey("Entry editor, previous panel 2"), "left");
+ am.put("right", parent.switchRightAction);
+ im.put(Globals.prefs.getKey("Help"), "help");
+ am.put("help", parent.helpAction);
+ im.put(Globals.prefs.getKey("Save database"), "save");
+ am.put("save", parent.saveDatabaseAction);
+ im.put(Globals.prefs.getKey("Next tab"), "nexttab");
+ am.put("nexttab", parent.frame.nextTab);
+ im.put(Globals.prefs.getKey("Previous tab"), "prevtab");
+ am.put("prevtab", parent.frame.prevTab);
+
+ try {
+ HashSet keys = new HashSet(component
+ .getFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS));
+ keys.clear();
+ keys.add(AWTKeyStroke.getAWTKeyStroke("pressed TAB"));
+ component.setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, keys);
+ keys = new HashSet(component
+ .getFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS));
+ keys.clear();
+ keys.add(KeyStroke.getKeyStroke("shift pressed TAB"));
+ component.setFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, keys);
+ } catch (Throwable t) {
+ System.err.println(t);
+ }
+ }
+
+ /*
+ * Focus listener that fires the storeFieldAction when a FieldTextArea loses
+ * focus.
+ *
+ * TODO: It would be nice to test this thoroughly.
+ */
+ FocusListener fieldListener = new FocusListener() {
+
+ JTextComponent c;
+
+ DocumentListener d;
+
+ public void focusGained(FocusEvent e) {
+
+ synchronized (this){
+ if (c != null) {
+ c.getDocument().removeDocumentListener(d);
+ c = null;
+ d = null;
+ }
+
+ if (e.getSource() instanceof JTextComponent) {
+
+ c = (JTextComponent) e.getSource();
+ /**
+ * [ 1553552 ] Not properly detecting changes to flag as
+ * changed
+ */
+ d = new DocumentListener() {
+
+ void fire(DocumentEvent e) {
+ if (c.isFocusOwner()) {
+ markIfModified((FieldEditor) c);
+ }
+ }
+
+ public void changedUpdate(DocumentEvent e) {
+ fire(e);
+ }
+
+ public void insertUpdate(DocumentEvent e) {
+ fire(e);
+ }
+
+ public void removeUpdate(DocumentEvent e) {
+ fire(e);
+ }
+ };
+ c.getDocument().addDocumentListener(d);
+ }
+ }
+
+ setActive((FieldEditor) e.getSource());
+
+ }
+
+ public void focusLost(FocusEvent e) {
+ synchronized (this) {
+ if (c != null) {
+ c.getDocument().removeDocumentListener(d);
+ c = null;
+ d = null;
+ }
+ }
+ if (!e.isTemporary())
+ parent.updateField((FieldEditor) e.getSource());
+ }
+ };
}
-
diff --git a/src/java/net/sf/jabref/ExternalTab.java b/src/java/net/sf/jabref/ExternalTab.java
index 77bd0bc..04f35de 100644
--- a/src/java/net/sf/jabref/ExternalTab.java
+++ b/src/java/net/sf/jabref/ExternalTab.java
@@ -1,154 +1,203 @@
package net.sf.jabref;
-import javax.swing.*;
-import java.awt.*;
+import java.awt.BorderLayout;
+import java.awt.event.ItemEvent;
+import java.awt.event.ItemListener;
-import com.jgoodies.forms.layout.*;
-import com.jgoodies.forms.builder.*;
+import javax.swing.Action;
+import javax.swing.BorderFactory;
+import javax.swing.JButton;
+import javax.swing.JCheckBox;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JTextField;
+
+import com.jgoodies.forms.builder.DefaultFormBuilder;
+import com.jgoodies.forms.layout.FormLayout;
public class ExternalTab extends JPanel implements PrefsTab {
- JabRefPreferences _prefs;
- JabRefFrame _frame;
- //private JComboBox language = new JComboBox(GUIGlobals.LANGUAGES.keySet().toArray());
- JTextField pdfDir, psDir, pdf, ps, html, lyx, winEdt, citeCommand;
-
- //private HelpAction ownerHelp, pdfHelp;
-
-
- public ExternalTab(JabRefFrame frame, JabRefPreferences prefs) {
- _prefs = prefs;
- _frame = frame;
- setLayout(new BorderLayout());
-
- //pdfHelp = new HelpAction(frame.helpDiag, GUIGlobals.pdfHelp,
- // "Help", GUIGlobals.helpSmallIconFile);
-
- psDir = new JTextField(30);
- pdfDir = new JTextField(30);
- pdf = new JTextField(30);
- ps = new JTextField(30);
- html = new JTextField(30);
- lyx = new JTextField(30);
- winEdt = new JTextField(30);
- citeCommand = new JTextField(30);
- BrowseAction browse;
-
- FormLayout layout = new FormLayout
- ("1dlu, 8dlu, left:pref, 4dlu, fill:200dlu, 4dlu, fill:pref",// 4dlu, left:pref, 4dlu",
- "");
-
- DefaultFormBuilder builder = new DefaultFormBuilder(layout);
-
- builder.appendSeparator(Globals.lang("PDF links"));
- JPanel pan = new JPanel();
- builder.append(pan);
- JLabel lab = new JLabel(Globals.lang("Main PDF directory") + ":");
- builder.append(lab);
- builder.append(pdfDir);
- browse = new BrowseAction(_frame, pdfDir, true);
- builder.append(new JButton(browse));
- builder.nextLine();
- builder.appendSeparator(Globals.lang("PS links"));
- pan = new JPanel();
- builder.append(pan);
- lab = new JLabel(Globals.lang("Main PS directory") + ":");
- builder.append(lab);
- builder.append(psDir);
- browse = new BrowseAction(_frame, psDir, true);
- builder.append(new JButton(browse));
- builder.nextLine();
- builder.appendSeparator(Globals.lang("External programs"));
-
-
- builder.nextLine();
- lab = new JLabel(Globals.lang("Path to PDF viewer") + ":");
- builder.append(pan);
- builder.append(lab);
- builder.append(pdf);
- browse = new BrowseAction(_frame, pdf, false);
- if (Globals.ON_WIN)
- browse.setEnabled(false);
- builder.append(new JButton(browse));
- builder.nextLine();
- lab = new JLabel(Globals.lang("Path to PS viewer") + ":");
- builder.append(pan);
- builder.append(lab);
- builder.append(ps);
- browse = new BrowseAction(_frame, ps, false);
- if (Globals.ON_WIN)
- browse.setEnabled(false);
- builder.append(new JButton(browse));
- builder.nextLine();
- lab = new JLabel(Globals.lang("Path to HTML viewer") + ":");
- builder.append(pan);
- builder.append(lab);
- builder.append(html);
- browse = new BrowseAction(_frame, html, false);
- if (Globals.ON_WIN)
- browse.setEnabled(false);
- builder.append(new JButton(browse));
- builder.nextLine();
- lab = new JLabel(Globals.lang("Path to LyX pipe") + ":");
- builder.append(pan);
- builder.append(lab);
- builder.append(lyx);
- browse = new BrowseAction(_frame, lyx, false);
- builder.append(new JButton(browse));
- builder.nextLine();
- lab = new JLabel(Globals.lang("Path to WinEdt.exe") + ":");
- builder.append(pan);
- builder.append(lab);
- builder.append(winEdt);
- browse = new BrowseAction(_frame, winEdt, false);
- builder.append(new JButton(browse));
- builder.nextLine();
- builder.append(pan);
- builder.append(Globals.lang("Cite command (for Emacs/WinEdt)")+":");
- builder.append(citeCommand);
- //builder.appendSeparator();
-
- pan = builder.getPanel();
- pan.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
- add(pan, BorderLayout.CENTER);
- }
-
- public void setValues() {
- pdfDir.setText(_prefs.get("pdfDirectory"));
- psDir.setText(_prefs.get("psDirectory"));
- if (!Globals.ON_WIN) {
- pdf.setText(_prefs.get("pdfviewer"));
- ps.setText(_prefs.get("psviewer"));
- html.setText(_prefs.get("htmlviewer"));
- } else {
- pdf.setText(Globals.lang("Uses default application"));
- ps.setText(Globals.lang("Uses default application"));
- html.setText(Globals.lang("Uses default application"));
- pdf.setEnabled(false);
- ps.setEnabled(false);
- html.setEnabled(false);
- }
-
- lyx.setText(_prefs.get("lyxpipe"));
- winEdt.setText(_prefs.get("winEdtPath"));
- citeCommand.setText(_prefs.get("citeCommand"));
- }
-
- public void storeSettings() {
-
- // We should maybe do some checking on the validity of the contents?
- _prefs.put("pdfDirectory", pdfDir.getText());
- _prefs.put("psDirectory", psDir.getText());
- _prefs.put("pdfviewer", pdf.getText());
- _prefs.put("psviewer", ps.getText());
- _prefs.put("htmlviewer", html.getText());
- _prefs.put("lyxpipe", lyx.getText());
- _prefs.put("winEdtPath", winEdt.getText());
- _prefs.put("citeCommand", citeCommand.getText());
- }
-
- public boolean readyToClose() {
- return true;
- }
+ JabRefPreferences _prefs;
+
+ JabRefFrame _frame;
+
+ // private JComboBox language = new
+ // JComboBox(GUIGlobals.LANGUAGES.keySet().toArray());
+ JTextField pdfDir, regExpTextField, psDir, pdf, ps, html, lyx, winEdt, citeCommand;
+
+ ItemListener regExpListener;
+
+ JCheckBox useRegExpComboBox;
+
+ public ExternalTab(JabRefFrame frame, JabRefPreferences prefs, HelpDialog helpDialog) {
+ _prefs = prefs;
+ _frame = frame;
+ setLayout(new BorderLayout());
+
+ psDir = new JTextField(30);
+ pdfDir = new JTextField(30);
+ pdf = new JTextField(30);
+ ps = new JTextField(30);
+ html = new JTextField(30);
+ lyx = new JTextField(30);
+ winEdt = new JTextField(30);
+ citeCommand = new JTextField(30);
+
+ regExpTextField = new JTextField(30);
+
+ useRegExpComboBox = new JCheckBox(Globals.lang("Use Regular Expression Search"));
+ regExpListener = new ItemListener() {
+ public void itemStateChanged(ItemEvent e) {
+ regExpTextField.setEditable(useRegExpComboBox.isSelected());
+ if (useRegExpComboBox.isSelected()) {
+ regExpTextField.setText(Globals.prefs
+ .get(JabRefPreferences.REG_EXP_SEARCH_EXPRESSION_KEY));
+ } else {
+ Globals.prefs.put(JabRefPreferences.REG_EXP_SEARCH_EXPRESSION_KEY,
+ regExpTextField.getText());
+ regExpTextField.setText(Globals.prefs
+ .get(JabRefPreferences.DEFAULT_REG_EXP_SEARCH_EXPRESSION_KEY));
+ }
+ }
+ };
+ useRegExpComboBox.addItemListener(regExpListener);
+
+ BrowseAction browse;
+
+ FormLayout layout = new FormLayout(
+ "1dlu, 8dlu, left:pref, 4dlu, fill:200dlu, 4dlu, fill:pref",// 4dlu,
+ // left:pref,
+ // 4dlu",
+ "");
+
+ DefaultFormBuilder builder = new DefaultFormBuilder(layout);
+
+ builder.appendSeparator(Globals.lang("PDF and PS links"));
+ JPanel pan = new JPanel();
+ builder.append(pan);
+ JLabel lab = new JLabel(Globals.lang("Main PDF directory") + ":");
+ builder.append(lab);
+ builder.append(pdfDir);
+ browse = new BrowseAction(_frame, pdfDir, true);
+ builder.append(new JButton(browse));
+ builder.nextLine();
+
+ pan = new JPanel();
+ builder.append(pan);
+ lab = new JLabel(Globals.lang("Main PS directory") + ":");
+ builder.append(lab);
+ builder.append(psDir);
+ browse = new BrowseAction(_frame, psDir, true);
+ builder.append(new JButton(browse));
+ builder.nextLine();
+
+ builder.append(new JPanel());
+ builder.append(useRegExpComboBox);
+ builder.append(regExpTextField);
+ HelpAction helpAction = new HelpAction(helpDialog, GUIGlobals.regularExpressionSearchHelp,
+ Globals.lang("Help on Regular Expression Search"), GUIGlobals.getIconUrl("helpSmall"));
+ builder.append(helpAction.getIconButton());
+ builder.nextLine();
+
+ builder.appendSeparator(Globals.lang("External programs"));
+
+ builder.nextLine();
+ lab = new JLabel(Globals.lang("Path to PDF viewer") + ":");
+ builder.append(pan);
+ builder.append(lab);
+ builder.append(pdf);
+ browse = new BrowseAction(_frame, pdf, false);
+ if (Globals.ON_WIN)
+ browse.setEnabled(false);
+ builder.append(new JButton(browse));
+ builder.nextLine();
+ lab = new JLabel(Globals.lang("Path to PS viewer") + ":");
+ builder.append(pan);
+ builder.append(lab);
+ builder.append(ps);
+ browse = new BrowseAction(_frame, ps, false);
+ if (Globals.ON_WIN)
+ browse.setEnabled(false);
+ builder.append(new JButton(browse));
+ builder.nextLine();
+ lab = new JLabel(Globals.lang("Path to HTML viewer") + ":");
+ builder.append(pan);
+ builder.append(lab);
+ builder.append(html);
+ browse = new BrowseAction(_frame, html, false);
+ if (Globals.ON_WIN)
+ browse.setEnabled(false);
+ builder.append(new JButton(browse));
+ builder.nextLine();
+ lab = new JLabel(Globals.lang("Path to LyX pipe") + ":");
+ builder.append(pan);
+ builder.append(lab);
+ builder.append(lyx);
+ browse = new BrowseAction(_frame, lyx, false);
+ builder.append(new JButton(browse));
+ builder.nextLine();
+ lab = new JLabel(Globals.lang("Path to WinEdt.exe") + ":");
+ builder.append(pan);
+ builder.append(lab);
+ builder.append(winEdt);
+ browse = new BrowseAction(_frame, winEdt, false);
+ builder.append(new JButton(browse));
+ builder.nextLine();
+ builder.append(pan);
+ builder.append(Globals.lang("Cite command (for Emacs/WinEdt)") + ":");
+ builder.append(citeCommand);
+ // builder.appendSeparator();
+
+ pan = builder.getPanel();
+ pan.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
+ add(pan, BorderLayout.CENTER);
+ }
+
+ public void setValues() {
+ pdfDir.setText(_prefs.get("pdfDirectory"));
+ psDir.setText(_prefs.get("psDirectory"));
+ if (!Globals.ON_WIN) {
+ pdf.setText(_prefs.get("pdfviewer"));
+ ps.setText(_prefs.get("psviewer"));
+ html.setText(_prefs.get("htmlviewer"));
+ } else {
+ pdf.setText(Globals.lang("Uses default application"));
+ ps.setText(Globals.lang("Uses default application"));
+ html.setText(Globals.lang("Uses default application"));
+ pdf.setEnabled(false);
+ ps.setEnabled(false);
+ html.setEnabled(false);
+ }
+
+ lyx.setText(_prefs.get("lyxpipe"));
+ winEdt.setText(_prefs.get("winEdtPath"));
+ citeCommand.setText(_prefs.get("citeCommand"));
+
+ regExpTextField.setText(_prefs.get(JabRefPreferences.REG_EXP_SEARCH_EXPRESSION_KEY));
+ useRegExpComboBox.setSelected(_prefs.getBoolean(JabRefPreferences.USE_REG_EXP_SEARCH_KEY));
+ regExpListener.itemStateChanged(null);
+ }
+
+ public void storeSettings() {
+
+ _prefs.putBoolean(JabRefPreferences.USE_REG_EXP_SEARCH_KEY, useRegExpComboBox.isSelected());
+ if (useRegExpComboBox.isSelected()) {
+ _prefs.put(JabRefPreferences.REG_EXP_SEARCH_EXPRESSION_KEY, regExpTextField.getText());
+ }
+
+ // We should maybe do some checking on the validity of the contents?
+ _prefs.put("pdfDirectory", pdfDir.getText());
+ _prefs.put("psDirectory", psDir.getText());
+ _prefs.put("pdfviewer", pdf.getText());
+ _prefs.put("psviewer", ps.getText());
+ _prefs.put("htmlviewer", html.getText());
+ _prefs.put("lyxpipe", lyx.getText());
+ _prefs.put("winEdtPath", winEdt.getText());
+ _prefs.put("citeCommand", citeCommand.getText());
+ }
+
+ public boolean readyToClose() {
+ return true;
+ }
}
diff --git a/src/java/net/sf/jabref/FieldComparator.java b/src/java/net/sf/jabref/FieldComparator.java
index ddded3b..77e58ea 100644
--- a/src/java/net/sf/jabref/FieldComparator.java
+++ b/src/java/net/sf/jabref/FieldComparator.java
@@ -1,81 +1,119 @@
package net.sf.jabref;
-import net.sf.jabref.BibtexEntry;
-import net.sf.jabref.GUIGlobals;
-import net.sf.jabref.AuthorList;
-import net.sf.jabref.imports.ImportFormatReader;
-
import java.util.Comparator;
/**
- * Created by IntelliJ IDEA.
- * User: alver
- * Date: Oct 13, 2005
- * Time: 10:10:04 PM
- * To change this template use File | Settings | File Templates.
+ *
+ * A comparator for BibtexEntry fields
+ *
+ * Initial Version:
+ *
+ * @author alver
+ * @version Date: Oct 13, 2005 Time: 10:10:04 PM To
+ *
+ * Current Version:
+ *
+ * @author $Author: coezbek $
+ * @version $Revision: 1.5 $ ($Date: 2006/09/02 00:03:48 $)
+ *
+ * TODO: Testcases
+ *
*/
public class FieldComparator implements Comparator {
- private String field;
- private boolean isNameField, isTypeHeader;
- private int multiplier;
-
- public FieldComparator(String field) {
- this(field, false);
- }
-
- public FieldComparator(String field, boolean reversed) {
- this.field = field;
- multiplier = reversed ? -1 : 1;
- isNameField = (field.equals("author") || field.equals("editor"));
- isTypeHeader = field.equals(GUIGlobals.TYPE_HEADER);
- }
-
- public int compare(Object o1, Object o2) {
- BibtexEntry e1 = (BibtexEntry)o1,
- e2 = (BibtexEntry)o2;
-
- Object f1 = e1.getField(field),
- f2 = e2.getField(field);
-
-
- // If the field is author or editor, we rearrange names so they are
- // sorted according to last name.
- if (isNameField) {
- if (f1 != null)
- f1 = AuthorList.fixAuthorForAlphabetization((String)f1);
- if (f2 != null)
- f2 = AuthorList.fixAuthorForAlphabetization((String)f2);
- //System.out.println(".. "+f1);
- }
- else if (isTypeHeader) {
- // Sort by type.
- f1 = e1.getType().getName();
- f2 = e2.getType().getName();
- }
-
- if ((f1 == null) && (f2 == null)) return 0;
- if ((f1 != null) && (f2 == null)) return -1*multiplier;
- if (f1 == null) return multiplier;
-
- int result = 0;
- //System.out.println(f1);
- if ((f1 instanceof Integer) && (f2 instanceof Integer)) {
- result = -(((Integer) f1).compareTo((Integer) f2));
- } else if (f2 instanceof Integer) {
- Integer f1AsInteger = new Integer(f1.toString());
- result = -((f1AsInteger).compareTo((Integer) f2));
- } else if (f1 instanceof Integer) {
- Integer f2AsInteger = new Integer(f2.toString());
- result = -(((Integer) f1).compareTo(f2AsInteger));
- } else {
- String ours = ((String) f1).toLowerCase(),
- theirs = ((String) f2).toLowerCase();
- //System.out.println(ours);
- result = ours.compareTo(theirs);
- }
-
- return result*multiplier;
- }
+ String field;
+
+ boolean isNameField, isTypeHeader, isYearField, isMonthField;
+
+ int multiplier;
+
+ public FieldComparator(String field) {
+ this(field, false);
+ }
+
+ public FieldComparator(String field, boolean reversed) {
+ this.field = field;
+ multiplier = reversed ? -1 : 1;
+ isTypeHeader = field.equals(GUIGlobals.TYPE_HEADER);
+
+ isNameField = (field.equals("author") || field.equals("editor"));
+ isYearField = field.equals("year");
+ isMonthField = field.equals("month");
+ }
+
+ public int compare(Object o1, Object o2) {
+ BibtexEntry e1 = (BibtexEntry) o1, e2 = (BibtexEntry) o2;
+
+ Object f1, f2;
+
+ if (isTypeHeader) {
+ // Sort by type.
+ f1 = e1.getType().getName();
+ f2 = e2.getType().getName();
+ } else {
+
+ // If the field is author or editor, we rearrange names so they are
+ // sorted according to last name.
+ f1 = e1.getField(field);
+ f2 = e2.getField(field);
+ }
+
+ // Catch all cases involving null:
+ if (f1 == null)
+ return f2 == null ? 0 : multiplier;
+
+ if (f2 == null)
+ return -multiplier;
+
+ // Now we now that both f1 and f2 are != null
+ if (isNameField) {
+ if (f1 != null)
+ f1 = AuthorList.fixAuthorForAlphabetization((String) f1);
+ if (f2 != null)
+ f2 = AuthorList.fixAuthorForAlphabetization((String) f2);
+ } else if (isYearField) {
+ /*
+ * [ 1285977 ] Impossible to properly sort a numeric field
+ *
+ * http://sourceforge.net/tracker/index.php?func=detail&aid=1285977&group_id=92314&atid=600307
+ */
+ f1 = Util.toFourDigitYear((String) f1);
+ f2 = Util.toFourDigitYear((String) f2);
+ } else if (isMonthField) {
+ /*
+ * [ 1535044 ] Month sorting
+ *
+ * http://sourceforge.net/tracker/index.php?func=detail&aid=1535044&group_id=92314&atid=600306
+ */
+ f1 = new Integer(Util.getMonthNumber((String)f1));
+ f2 = new Integer(Util.getMonthNumber((String)f2));
+ // Somehow this is twisted
+ multiplier = -multiplier;
+ }
+
+ int result = 0;
+ if ((f1 instanceof Integer) && (f2 instanceof Integer)) {
+ result = -(((Integer) f1).compareTo((Integer) f2));
+ } else if (f2 instanceof Integer) {
+ Integer f1AsInteger = new Integer(f1.toString());
+ result = -((f1AsInteger).compareTo((Integer) f2));
+ } else if (f1 instanceof Integer) {
+ Integer f2AsInteger = new Integer(f2.toString());
+ result = -(((Integer) f1).compareTo(f2AsInteger));
+ } else {
+ String ours = ((String) f1).toLowerCase(), theirs = ((String) f2).toLowerCase();
+ result = ours.compareTo(theirs);
+ }
+
+ return result * multiplier;
+ }
+ /**
+ * Returns the field this Comparator compares by.
+ *
+ * @return The field name.
+ */
+ public String getFieldName() {
+ return field;
+ }
}
diff --git a/src/java/net/sf/jabref/FieldContentSelector.java b/src/java/net/sf/jabref/FieldContentSelector.java
index babd23b..f3e768a 100644
--- a/src/java/net/sf/jabref/FieldContentSelector.java
+++ b/src/java/net/sf/jabref/FieldContentSelector.java
@@ -26,220 +26,229 @@
*/
package net.sf.jabref;
-import java.awt.*;
-import java.awt.event.*;
+import java.awt.Dialog;
+import java.awt.Dimension;
+import java.awt.Frame;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Window;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.Iterator;
import java.util.Vector;
-import javax.swing.*;
+import javax.swing.AbstractAction;
+import javax.swing.Box;
+import javax.swing.JButton;
+import javax.swing.JComboBox;
+import javax.swing.JComponent;
import com.jgoodies.forms.layout.Sizes;
import com.jgoodies.looks.Options;
-public class FieldContentSelector extends JComponent implements ActionListener {
-
- protected final String DELIMITER = " ", DELIMITER_2 = "";
- protected final FieldEditor m_editor;
- JComboBox list = new JComboBox() {
- public Dimension getPreferredSize() {
- Dimension parents = super.getPreferredSize();
- if (parents.width > GUIGlobals.MAX_CONTENT_SELECTOR_WIDTH)
- parents.width = GUIGlobals.MAX_CONTENT_SELECTOR_WIDTH;
- return parents;
- }
- };
- JButton manage;
- GridBagLayout gbl = new GridBagLayout();
- GridBagConstraints con = new GridBagConstraints();
- protected final MetaData m_metaData;
- protected final JabRefFrame m_frame;
- protected final Window m_owner;
- protected final BasePanel m_panel;
- protected final AbstractAction m_action;
- protected final boolean m_horizontalLayout;
-
- /**
- * @param action
- * The action that will be performed to conclude content
- * insertion.
- */
- public FieldContentSelector(JabRefFrame frame, BasePanel panel,
- Dialog owner, FieldEditor editor, MetaData data,
- AbstractAction action, boolean horizontalLayout) {
- m_editor = editor;
- m_metaData = data;
- m_action = action;
- m_frame = frame;
- m_panel = panel;
- m_owner = owner;
- m_horizontalLayout = horizontalLayout;
- doInit();
- }
-
- /**
- * @param action
- * The action that will be performed to conclude content
- * insertion.
- */
- public FieldContentSelector(JabRefFrame frame, BasePanel panel,
- Frame owner, FieldEditor editor, MetaData data,
- AbstractAction action, boolean horizontalLayout) {
- m_editor = editor;
- m_metaData = data;
- m_action = action;
- m_frame = frame;
- m_panel = panel;
- m_owner = owner;
- m_horizontalLayout = horizontalLayout;
- doInit();
- }
-
- private void doInit() {
- setLayout(gbl);
- //list.setEditable(true);
-
- list.setMaximumRowCount(35);
- // Set the width of the popup independent of the size of th box itself:
- list.putClientProperty(
- Options.COMBO_POPUP_PROTOTYPE_DISPLAY_VALUE_KEY,
- "The longest text in the combo popup menu. And even longer.");
- /*
- * list.getInputMap().put(Globals.prefs.getKey("Select value"),
- * "enter"); list.getActionMap().put("enter", new EnterAction());
- * System.out.println(Globals.prefs.getKey("Select value"));
- */
- updateList();
- // else
- // list = new JComboBox(items.toArray());
- con.gridwidth = m_horizontalLayout ? 3 : GridBagConstraints.REMAINDER;
- con.fill = GridBagConstraints.HORIZONTAL;
- con.weightx = 1;
- // list.setPreferredSize(new Dimension(140,
- // list.getPreferredSize().height));
- gbl.setConstraints(list, con);
- list.addActionListener(this);
-
- add(list);
-
- if (m_horizontalLayout)
- add(Box.createHorizontalStrut(Sizes.dialogUnitXAsPixel(2,this)));
-
- manage = new JButton(Globals.lang("Manage"));
- gbl.setConstraints(manage, con);
- add(manage);
-
- manage.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- // m_owner is either a Frame or a Dialog
- ContentSelectorDialog2 csd = m_owner instanceof Frame ?
- new ContentSelectorDialog2(
- (Frame) m_owner, m_frame, m_panel, true, m_metaData,
- m_editor.getFieldName())
- : new ContentSelectorDialog2((Dialog) m_owner, m_frame,
- m_panel, true, m_metaData, m_editor
- .getFieldName());
- Util.placeDialog(csd, m_frame);
- csd.setVisible(true); // csd.show(); -> deprecated since 1.5
- updateList();
- }
- });
- }
-
- public void updateList() {
- list.removeAllItems();
- list.addItem(""); // (Globals.lang(""));
- Vector items = m_metaData.getData(Globals.SELECTOR_META_PREFIX
- + m_editor.getFieldName());
- if ((items != null) && (items.size() > 0)) {
- for (int i = 0; i < items.size(); i++)
- list.addItem(items.elementAt(i));
- }
- }
-
- public void actionPerformed(ActionEvent e) {
- if (e.getActionCommand().equals("comboBoxChanged")
- && (e.getModifiers() == 0))
- // These conditions signify arrow key navigation in the dropdown
- // list, so we should
- // not react to it. I'm not sure if this is well defined enough to
- // be guaranteed to work
- // everywhere.
- return;
-
- if (list.getSelectedIndex() == 0)
- return; // The first element is only for show.
-
- String chosen = (String) list.getSelectedItem();
- // System.out.println(list.getSelectedIndex()+"\t"+chosen);
- if (chosen == null)
- return;
- if (list.getSelectedIndex() == -1) { // User edited in a new word.
- // Add this.
- addWord(chosen);
- /*
- * Vector items = metaData.getData(Globals.SELECTOR_META_PREFIX+
- * editor.getFieldName()); boolean exists = false; int pos = -1; for
- * (int i=0; i<items.size(); i++) { String s =
- * (String)items.elementAt(i); if (s.equals(chosen)) { exists =
- * true; break; } if
- * (s.toLowerCase().compareTo(chosen.toLowerCase()) < 0) pos = i+1; }
- * if (!exists) { items.add(Math.max(0, pos), chosen);
- * parent.panel.markNonUndoableBaseChanged(); updateList(); }
- */
- }
- if (!m_editor.getText().equals(""))
- m_editor.append(DELIMITER);
- m_editor.append(chosen + DELIMITER_2);
- list.setSelectedIndex(0);
- if (m_action != null)
- m_action.actionPerformed(new ActionEvent(m_editor, 0, ""));
-
- // Transfer focus to the editor.
- m_editor.requestFocus();
- // new FocusRequester(editor.getTextComponent());
- }
-
- /**
- * Adds a word to the selector (to the JList and to the MetaData), unless it
- * is already there
- *
- * @param newWord
- * String Word to add
- */
- public void addWord(String newWord) {
-
- Vector items = m_metaData.getData(Globals.SELECTOR_META_PREFIX
- + m_editor.getFieldName());
- boolean exists = false;
- int pos = -1;
- for (int i = 0; i < items.size(); i++) {
- String s = (String) items.elementAt(i);
- if (s.equals(newWord)) {
- exists = true;
- break;
- }
- if (s.toLowerCase().compareTo(newWord.toLowerCase()) < 0)
- pos = i + 1;
- }
- if (!exists) {
- items.add(Math.max(0, pos), newWord);
- m_panel.markNonUndoableBaseChanged();
- m_panel.updateAllContentSelectors();
- // updateList();
- }
-
- }
-
- /*
- * class EnterAction extends AbstractAction { public void
- * actionPerformed(ActionEvent e) { System.out.println("enter");
- * ths.actionPerformed(e); } }
- */
-
- /*
- * public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
- * System.out.println("visible"); } public void
- * popupMenuWillBecomeInvisible(PopupMenuEvent e) {
- * System.out.println("invisible"); } public void
- * popupMenuCanceled(PopupMenuEvent e) { System.out.println("canceled"); }
- */
+/**
+ * A combo-box and a manage button that will add selected strings to an
+ * associated entry editor.
+ *
+ * Used to manage keywords and authors for instance.
+ *
+ * @author $Author: coezbek $
+ * @version $Revision: 1.22 $ ($Date: 2006/08/31 23:13:30 $)
+ *
+ */
+public class FieldContentSelector extends JComponent {
+
+ JComboBox comboBox;
+
+ FieldEditor editor;
+
+ MetaData metaData;
+
+ JabRefFrame frame;
+
+ Window owner;
+
+ BasePanel panel;
+
+ String delimiter;
+
+ /**
+ *
+ * Create a new FieldContentSelector.
+ *
+ * @param frame
+ * The one JabRef-Frame.
+ * @param panel
+ * The basepanel the entry-editor is on.
+ * @param owner
+ * The window/frame/dialog which should be the owner of the
+ * content selector dialog.
+ * @param editor
+ * The entry editor which will be appended by the text selected
+ * by the user from the combobox.
+ * @param metaData
+ * The metadata that contains the list of items to display in the
+ * combobox under the key Globals.SELECTOR_META_PREFIX +
+ * editor.getFieldName().
+ * @param action
+ * The action that will be performed to after an item from the
+ * combobox has been appended to the text in the entryeditor.
+ * @param horizontalLayout
+ * Whether to put a 2 pixel horizontal strut between combobox and
+ * button.
+ */
+ public FieldContentSelector(JabRefFrame jabRefFrame, final BasePanel panel,
+ Window ownerFrameOrDialog, final FieldEditor editor, final MetaData metaData,
+ final AbstractAction action, boolean horizontalLayout, String delimiter) {
+
+ this.frame = jabRefFrame;
+ this.editor = editor;
+ this.metaData = metaData;
+ this.panel = panel;
+ this.owner = ownerFrameOrDialog;
+ this.delimiter = delimiter;
+
+ comboBox = new JComboBox() {
+ public Dimension getPreferredSize() {
+ Dimension parents = super.getPreferredSize();
+ if (parents.width > GUIGlobals.MAX_CONTENT_SELECTOR_WIDTH)
+ parents.width = GUIGlobals.MAX_CONTENT_SELECTOR_WIDTH;
+ return parents;
+ }
+ };
+
+ GridBagLayout gbl = new GridBagLayout();
+ GridBagConstraints con = new GridBagConstraints();
+
+ setLayout(gbl);
+
+ // comboBox.setEditable(true);
+
+ comboBox.setMaximumRowCount(35);
+
+ // Set the width of the popup independent of the size of th box itself:
+ comboBox.putClientProperty(Options.COMBO_POPUP_PROTOTYPE_DISPLAY_VALUE_KEY,
+ "The longest text in the combo popup menu. And even longer.");
+
+ rebuildComboBox();
+
+ con.gridwidth = horizontalLayout ? 3 : GridBagConstraints.REMAINDER;
+ con.fill = GridBagConstraints.HORIZONTAL;
+ con.weightx = 1;
+ gbl.setConstraints(comboBox, con);
+
+ comboBox.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ /*
+ * These conditions signify arrow key navigation in the dropdown
+ * list, so we should not react to it. I'm not sure if this is
+ * well defined enough to be guaranteed to work everywhere.
+ */
+ if (e.getActionCommand().equals("comboBoxChanged") && (e.getModifiers() == 0))
+ return;
+
+ // The first element is only for show.
+ // CO: Why?
+ if (comboBox.getSelectedIndex() == 0)
+ return;
+
+ String chosen = (String) comboBox.getSelectedItem();
+ if (chosen == null || chosen.equals(""))
+ return;
+
+ // The following is not possible at the moment since the
+ // combobox cannot be edited!
+
+ // User edited in a new word. Add it.
+ // if (comboBox.getSelectedIndex() == -1)
+ // addWord(chosen);
+
+ // TODO: could improve checking as not do add the same item twice
+ if (!editor.getText().equals(""))
+ editor.append(FieldContentSelector.this.delimiter);
+
+ editor.append(chosen);
+
+ comboBox.setSelectedIndex(0);
+
+ // Fire event that we changed the editor
+ if (action != null)
+ action.actionPerformed(new ActionEvent(editor, 0, ""));
+
+ // Transfer focus to the editor.
+ editor.requestFocus();
+ }
+ });
+
+ add(comboBox);
+
+ if (horizontalLayout)
+ add(Box.createHorizontalStrut(Sizes.dialogUnitXAsPixel(2, this)));
+
+ JButton manage = new JButton(Globals.lang("Manage"));
+ gbl.setConstraints(manage, con);
+ add(manage);
+
+ manage.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ // I don't get the difference here:
+ ContentSelectorDialog2 csd = owner instanceof Frame ? new ContentSelectorDialog2(
+ (Frame) owner, frame, panel, true, metaData, editor.getFieldName())
+ : new ContentSelectorDialog2((Dialog) owner, frame, panel, true, metaData,
+ editor.getFieldName());
+ Util.placeDialog(csd, frame);
+
+ // Calling setVisible(true) will open the modal dialog and block
+ // for the dialog to close.
+ csd.setVisible(true);
+
+ // So we need to rebuild the ComboBox afterwards
+ rebuildComboBox();
+ }
+ });
+ }
+
+ void rebuildComboBox() {
+ comboBox.removeAllItems();
+
+ // TODO: CO - What for?
+ comboBox.addItem("");
+ Vector items = metaData.getData(Globals.SELECTOR_META_PREFIX + editor.getFieldName());
+ if (items != null) {
+ Iterator i = items.iterator();
+ while (i.hasNext())
+ comboBox.addItem(i.next());
+ }
+ }
+
+ // Not used since the comboBox is not editable
+
+ // /**
+ // * Adds a word to the selector (to the JList and to the MetaData), unless it
+ // * is already there
+ // *
+ // * @param newWord
+ // * String Word to add
+ // */
+ // public void addWord(String newWord) {
+ //
+ // Vector items = metaData.getData(Globals.SELECTOR_META_PREFIX + editor.getFieldName());
+ // boolean exists = false;
+ // int pos = -1;
+ // for (int i = 0; i < items.size(); i++) {
+ // String s = (String) items.elementAt(i);
+ // if (s.equals(newWord)) {
+ // exists = true;
+ // break;
+ // }
+ // if (s.toLowerCase().compareTo(newWord.toLowerCase()) < 0)
+ // pos = i + 1;
+ // }
+ // if (!exists) {
+ // items.add(Math.max(0, pos), newWord);
+ // // TODO CO: Why is this non-undoable?
+ // panel.markNonUndoableBaseChanged();
+ // panel.updateAllContentSelectors();
+ // }
+ // }
}
diff --git a/src/java/net/sf/jabref/FieldEditor.java b/src/java/net/sf/jabref/FieldEditor.java
index 9194670..3fef613 100644
--- a/src/java/net/sf/jabref/FieldEditor.java
+++ b/src/java/net/sf/jabref/FieldEditor.java
@@ -1,52 +1,95 @@
/*
-Copyright (C) 2003 Nizar N. Batada, Morten O. Alver
+ Copyright (C) 2003 Nizar N. Batada, Morten O. Alver
-All programs in this directory and
-subdirectories are published under the GNU General Public License as
-described below.
+ All programs in this directory and
+ subdirectories are published under the GNU General Public License as
+ described below.
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or (at
-your option) any later version.
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or (at
+ your option) any later version.
-This program is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
-USA
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA
-Further information about the GNU GPL is available at:
-http://www.gnu.org/copyleft/gpl.ja.html
+ Further information about the GNU GPL is available at:
+ http://www.gnu.org/copyleft/gpl.ja.html
-*/
+ */
package net.sf.jabref;
+import java.awt.Color;
+import java.awt.Container;
+
+import javax.swing.JComponent;
+import javax.swing.JLabel;
+
+
+/**
+ * FieldEditors is a common interface between the FieldTextField and FieldTextArea.
+ *
+ * @author $Author: coezbek $
+ * @version $Revision: 1.6 $ ($Date: 2006/09/11 18:47:34 $)
+ *
+ */
public interface FieldEditor {
- public String getFieldName();
- public javax.swing.JComponent getPane();
- // Returns the component to be added to a container. Might
- // be a JScrollPane or the component itself.
- public javax.swing.JComponent getTextComponent();
- // Returns the text component itself.
- public javax.swing.JLabel getLabel();
- public void setLabelColor(java.awt.Color c);
- public void setBackground(java.awt.Color c);
- public String getText();
- public void setText(String newText);
- public void append(String text);
- public java.awt.Container getParent();
- public void requestFocus();
- public void setEnabled(boolean enabled);
- // paste text into component, it should also take some selected text into account
- public void paste(String textToInsert) ;
-
- // normally implemented in JTextArea and JTextField
- public String getSelectedText() ;
+ public String getFieldName();
+
+ /*
+ * Returns the component to be added to a container. Might be a JScrollPane
+ * or the component itself.
+ */
+ public JComponent getPane();
+
+ /*
+ * Returns the text component itself.
+ */
+ public JComponent getTextComponent();
+
+ public JLabel getLabel();
+
+ public void setLabelColor(Color c);
+
+ public void setBackground(Color c);
+
+ public String getText();
+
+ /**
+ * Sets the given text on the current field editor and marks this text
+ * editor as modified.
+ *
+ * @param newText
+ */
+ public void setText(String newText);
+
+ public void append(String text);
+
+ public Container getParent();
+
+ public void requestFocus();
+
+ public void setEnabled(boolean enabled);
+
+ /**
+ * paste text into component, it should also take some selected text into
+ * account
+ */
+ public void paste(String textToInsert);
+
+ /**
+ * normally implemented in JTextArea and JTextField
+ *
+ * @return
+ */
+ public String getSelectedText();
}
diff --git a/src/java/net/sf/jabref/FieldNameLabel.java b/src/java/net/sf/jabref/FieldNameLabel.java
index 13ec080..7d46b43 100644
--- a/src/java/net/sf/jabref/FieldNameLabel.java
+++ b/src/java/net/sf/jabref/FieldNameLabel.java
@@ -2,18 +2,18 @@ package net.sf.jabref;
import javax.swing.JLabel;
import javax.swing.Icon;
-import java.awt.Graphics2D;
-import java.awt.RenderingHints;
-import java.awt.Graphics;
+import java.awt.*;
import javax.swing.BorderFactory;
public class FieldNameLabel extends JLabel {
public FieldNameLabel(String name) {
- super(name, JLabel.CENTER);
+ super(name, JLabel.LEFT);
+ setVerticalAlignment(NORTH);
//setFont(GUIGlobals.fieldNameFont);
setForeground(GUIGlobals.validFieldColor);
- setBorder(BorderFactory.createEtchedBorder());
+ setBorder(BorderFactory.createMatteBorder(1,0,0,0, Color.GRAY));
+ //setBorder(BorderFactory.createEtchedBorder());
}
public void paintComponent(Graphics g) {
diff --git a/src/java/net/sf/jabref/FieldTextArea.java b/src/java/net/sf/jabref/FieldTextArea.java
index 6df5279..d733e7a 100644
--- a/src/java/net/sf/jabref/FieldTextArea.java
+++ b/src/java/net/sf/jabref/FieldTextArea.java
@@ -1,198 +1,194 @@
/*
-Copyright (C) 2003 Nizar N. Batada, Morten O. Alver
+ Copyright (C) 2003 Nizar N. Batada, Morten O. Alver
-All programs in this directory and
-subdirectories are published under the GNU General Public License as
-described below.
+ All programs in this directory and
+ subdirectories are published under the GNU General Public License as
+ described below.
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or (at
-your option) any later version.
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or (at
+ your option) any later version.
-This program is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
-USA
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA
-Further information about the GNU GPL is available at:
-http://www.gnu.org/copyleft/gpl.ja.html
+ Further information about the GNU GPL is available at:
+ http://www.gnu.org/copyleft/gpl.ja.html
-*/
+ */
package net.sf.jabref;
-import javax.swing.*;
-import javax.swing.border.EtchedBorder;
-import java.awt.*;
-//import java.awt.Color;
-import java.awt.event.*;
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.RenderingHints;
import java.util.regex.Pattern;
-import java.util.regex.Matcher;
-
-public class FieldTextArea extends JTextArea implements FieldEditor, KeyListener {
-
- Dimension PREFERRED_SIZE;
- protected JScrollPane sp;
- protected FieldNameLabel label;
- protected String fieldName;
- //protected Completer completer;
- static Pattern bull = Pattern.compile("\\s*[-\\*]+.*");
- static Pattern indent = Pattern.compile("\\s+.*");
- private boolean antialias = Globals.prefs.getBoolean("antialias");
-
- public FieldTextArea(String fieldName_, String content) {
- super(content);
-
- // Add the global focus listener, so a menu item can see if this field was focused when
- // an action was called.
- addFocusListener(Globals.focusListener);
- addFocusListener(new FieldEditorFocusListener());
- sp = new JScrollPane(this, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
- JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
- sp.setMinimumSize(new Dimension(200, 1));
-
-
-
- setLineWrap(true);
- setWrapStyleWord(true);
- fieldName = fieldName_;
-
- label = new FieldNameLabel(" "+Util.nCase(fieldName)+" ");
- //label.setBorder(BorderFactory.createEtchedBorder
- // (GUIGlobals.lightGray, Color.gray));
- //label.setBorder(BorderFactory.createEtchedBorder());
- //label.setOpaque(true);
- //label.setBackground(GUIGlobals.lightGray);
- //label.setForeground(Color.gray);
- setBackground(GUIGlobals.validFieldBackground);
- //if ((content != null) && (content.length() > 0))
- //label.setForeground(GUIGlobals.validFieldColor);
- // At construction time, the field can never have an invalid value.
- //else
- // label.setForeground(GUIGlobals.nullFieldColor);
-
- FieldTextMenu popMenu = new FieldTextMenu(this) ;
- this.addMouseListener( popMenu );
- label.addMouseListener( popMenu);
- //this.addKeyListener(this);
- }
-
- /*
- public void setAutoComplete(Completer completer) {
- addKeyListener(new AutoCompListener(completer));
- }
- */
-
- /*public Dimension getPreferredSize() {
- return PREFERRED_SIZE;
- }*/
-
- public Dimension getPreferredScrollableViewportSize() {
- return PREFERRED_SIZE;
- }
-
-
-
-
- public void paint(Graphics g) {
- Graphics2D g2 = (Graphics2D)g;
- if (antialias)
- g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
- super.paint(g2);
- }
-
- public String getFieldName() { return fieldName; }
- public void setFieldName(String newName) { fieldName = newName ; }
- public JLabel getLabel() { return label; }
- public void setLabelColor(Color c) { label.setForeground(c); }
- public JComponent getPane() { return sp; }
- public JComponent getTextComponent() { return this; }
-
- public void paste(String textToInsert)
- {
- int sel = getSelectionEnd() - getSelectionStart() ;
- if (sel > 0) // selected text available
- replaceSelection(textToInsert);
- else
- {
- int cPos = this.getCaretPosition() ;
- this.insert(textToInsert, cPos);
- }
- }
-
-
- public void keyPressed(KeyEvent event) {
- int keyCode = event.getKeyCode();
- if (keyCode == KeyEvent.VK_ENTER) {
- // Consume; we will handle this ourselves:
- event.consume();
- autoWrap();
-
- }
-
- }
-
- private void autoWrap() {
- int pos = getCaretPosition();
- int posAfter = pos+1;
- StringBuffer sb = new StringBuffer(getText());
- // First insert the line break:
- sb.insert(pos, '\n');
-
- // We want to investigate the beginning of the last line:
- //int end = sb.length();
-
- //System.out.println("."+sb.substring(0, pos)+".");
-
- // Find 0 or the last line break before our current position:
- int idx = sb.substring(0, pos).lastIndexOf("\n") +1;
- String prevLine = sb.substring(idx, pos);
- if (bull.matcher(prevLine).matches()) {
- int id = findFirstNonWhitespace(prevLine);
- if (id >= 0) {
- sb.insert(posAfter, prevLine.substring(0, id));
- posAfter += id;
- }
- }
- else if (indent.matcher(prevLine).matches()) {
- int id = findFirstNonWhitespace(prevLine);
- if (id >= 0) {
- sb.insert(posAfter, prevLine.substring(0, id));
- posAfter += id;
- }
- }
- /*if (prevLine.startsWith(" ")) {
- sb.insert(posAfter, " ");
- posAfter++;
- } */
-
-
- setText(sb.toString());
- setCaretPosition(posAfter);
- }
-
- private int findFirstNonWhitespace(String s) {
- for (int i=0; i<s.length(); i++) {
- if (!Character.isWhitespace(s.charAt(i)))
- return i;
- }
- return -1;
- }
-
- public void keyReleased(KeyEvent event) {
-
- }
-
- public void keyTyped(KeyEvent event) {
- }
-
-/* public void setText(String t) {
- super.setText(t); //To change body of overridden methods use File | Settings | File Templates.
- Thread.dumpStack();
- }*/
+
+import javax.swing.JComponent;
+import javax.swing.JLabel;
+import javax.swing.JScrollPane;
+import javax.swing.JTextArea;
+
+/**
+ * An implementation of the FieldEditor backed by a JTextArea. Used for
+ * multi-line input.
+ *
+ * @author $Author: mortenalver $
+ * @version $Revision: 1.21 $ ($Date: 2006/09/29 17:31:43 $)
+ *
+ */
+public class FieldTextArea extends JTextArea implements FieldEditor {
+
+ Dimension PREFERRED_SIZE;
+
+ JScrollPane sp;
+
+ FieldNameLabel label;
+
+ String fieldName;
+
+ final static Pattern bull = Pattern.compile("\\s*[-\\*]+.*");
+
+ final static Pattern indent = Pattern.compile("\\s+.*");
+
+ final boolean antialias = Globals.prefs.getBoolean("antialias");
+
+ public FieldTextArea(String fieldName_, String content) {
+ super(content);
+
+ // Add the global focus listener, so a menu item can see if this field
+ // was focused when an action was called.
+ addFocusListener(Globals.focusListener);
+ addFocusListener(new FieldEditorFocusListener());
+ sp = new JScrollPane(this, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
+ JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
+ sp.setMinimumSize(new Dimension(200, 1));
+
+ setLineWrap(true);
+ setWrapStyleWord(true);
+ fieldName = fieldName_;
+
+ label = new FieldNameLabel(" " + Util.nCase(fieldName) + " ");
+ setBackground(GUIGlobals.validFieldBackground);
+
+ FieldTextMenu popMenu = new FieldTextMenu(this);
+ this.addMouseListener(popMenu);
+ label.addMouseListener(popMenu);
+ }
+
+ public Dimension getPreferredScrollableViewportSize() {
+ return getPreferredSize();
+ }
+
+ public void paint(Graphics g) {
+ Graphics2D g2 = (Graphics2D) g;
+ if (antialias)
+ g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+ super.paint(g2);
+ }
+
+ public String getFieldName() {
+ return fieldName;
+ }
+
+ public void setFieldName(String newName) {
+ fieldName = newName;
+ }
+
+ public JLabel getLabel() {
+ return label;
+ }
+
+ public void setLabelColor(Color c) {
+ label.setForeground(c);
+ }
+
+ public JComponent getPane() {
+ return sp;
+ }
+
+ public JComponent getTextComponent() {
+ return this;
+ }
+
+ public void paste(String textToInsert) {
+ int sel = getSelectionEnd() - getSelectionStart();
+ if (sel > 0) // selected text available
+ replaceSelection(textToInsert);
+ else {
+ int cPos = this.getCaretPosition();
+ this.insert(textToInsert, cPos);
+ }
+ }
+
+ // public void keyPressed(KeyEvent event) {
+ // int keyCode = event.getKeyCode();
+ // if (keyCode == KeyEvent.VK_ENTER) {
+ // // Consume; we will handle this ourselves:
+ // event.consume();
+ // autoWrap();
+ //
+ // }
+ //
+ // }
+ //
+ // private void autoWrap() {
+ // int pos = getCaretPosition();
+ // int posAfter = pos + 1;
+ // StringBuffer sb = new StringBuffer(getText());
+ // // First insert the line break:
+ // sb.insert(pos, '\n');
+ //
+ // // We want to investigate the beginning of the last line:
+ // // int end = sb.length();
+ //
+ // // System.out.println("."+sb.substring(0, pos)+".");
+ //
+ // // Find 0 or the last line break before our current position:
+ // int idx = sb.substring(0, pos).lastIndexOf("\n") + 1;
+ // String prevLine = sb.substring(idx, pos);
+ // if (bull.matcher(prevLine).matches()) {
+ // int id = findFirstNonWhitespace(prevLine);
+ // if (id >= 0) {
+ // sb.insert(posAfter, prevLine.substring(0, id));
+ // posAfter += id;
+ // }
+ // } else if (indent.matcher(prevLine).matches()) {
+ // int id = findFirstNonWhitespace(prevLine);
+ // if (id >= 0) {
+ // sb.insert(posAfter, prevLine.substring(0, id));
+ // posAfter += id;
+ // }
+ // }
+ // /*
+ // * if (prevLine.startsWith(" ")) { sb.insert(posAfter, " "); posAfter++; }
+ // */
+ //
+ // setText(sb.toString());
+ // setCaretPosition(posAfter);
+ // }
+ //
+ // private int findFirstNonWhitespace(String s) {
+ // for (int i = 0; i < s.length(); i++) {
+ // if (!Character.isWhitespace(s.charAt(i)))
+ // return i;
+ // }
+ // return -1;
+ // }
+ //
+ // public void keyReleased(KeyEvent event) {
+ //
+ // }
+ //
+ // public void keyTyped(KeyEvent event) {
+ // }
}
diff --git a/src/java/net/sf/jabref/FieldTextField.java b/src/java/net/sf/jabref/FieldTextField.java
index 2b778db..82182d3 100644
--- a/src/java/net/sf/jabref/FieldTextField.java
+++ b/src/java/net/sf/jabref/FieldTextField.java
@@ -1,29 +1,29 @@
/*
-Copyright (C) 2003 Morten O. Alver, Nizar N. Batada
+ Copyright (C) 2003 Morten O. Alver, Nizar N. Batada
-All programs in this directory and
-subdirectories are published under the GNU General Public License as
-described below.
+ All programs in this directory and
+ subdirectories are published under the GNU General Public License as
+ described below.
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or (at
-your option) any later version.
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or (at
+ your option) any later version.
-This program is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
-USA
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA
-Further information about the GNU GPL is available at:
-http://www.gnu.org/copyleft/gpl.ja.html
+ Further information about the GNU GPL is available at:
+ http://www.gnu.org/copyleft/gpl.ja.html
-*/
+ */
package net.sf.jabref;
import javax.swing.*;
@@ -33,65 +33,76 @@ import java.awt.event.FocusEvent;
public class FieldTextField extends JTextField implements FieldEditor {
- protected String fieldName;
- protected JLabel label;
- private boolean antialias = Globals.prefs.getBoolean("antialias");
-
- public FieldTextField(String fieldName_, String content, boolean changeColorOnFocus) {
- super(content);
-
- // Add the global focus listener, so a menu item can see if this field was focused when
- // an action was called.
- addFocusListener(Globals.focusListener);
- if (changeColorOnFocus)
- addFocusListener(new FieldEditorFocusListener());
- fieldName = fieldName_;
- label = new FieldNameLabel(" "+Util.nCase(fieldName)+" ");
- //label = new JLabel(" "+Util.nCase(fieldName)+" ", JLabel.CENTER);
- label.setBorder(BorderFactory.createEtchedBorder());
- setBackground(GUIGlobals.validFieldBackground);
- //label.setOpaque(true);
- //if ((content != null) && (content.length() > 0))
- //label.setForeground(GUIGlobals.validFieldColor);
- // At construction time, the field can never have an invalid value.
- //else label.setForeground(GUIGlobals.nullFieldColor);
-
- FieldTextMenu popMenu = new FieldTextMenu(this) ;
- this.addMouseListener( popMenu );
- label.addMouseListener( popMenu);
- }
-
- public void append(String text) {
- setText(getText()+text);
- }
-
- public String getFieldName() { return fieldName; }
- public JLabel getLabel() { return label; }
- public void setLabelColor(Color c) {
- label.setForeground(c);
- throw new NullPointerException("ok");
- }
-
- public JComponent getPane() { return this; }
-
- public JComponent getTextComponent() { return this; }
-
- public void paint(Graphics g) {
- Graphics2D g2 = (Graphics2D)g;
- if (antialias)
- g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
- super.paint(g2);
- }
-
- public void paste(String textToInsert)
- {
- int sel = getSelectionEnd() - getSelectionStart() ;
- if (sel < 1)
- {
- int cPos = getCaretPosition() ;
- select(cPos, cPos);
- }
- replaceSelection(textToInsert);
- }
+ protected String fieldName;
+
+ protected JLabel label;
+
+ private boolean antialias = Globals.prefs.getBoolean("antialias");
+
+ public FieldTextField(String fieldName_, String content, boolean changeColorOnFocus) {
+ super(content);
+
+ // Add the global focus listener, so a menu item can see if this field
+ // was focused when
+ // an action was called.
+ addFocusListener(Globals.focusListener);
+ if (changeColorOnFocus)
+ addFocusListener(new FieldEditorFocusListener());
+ fieldName = fieldName_;
+ label = new FieldNameLabel(" " + Util.nCase(fieldName) + " ");
+ // label = new JLabel(" "+Util.nCase(fieldName)+" ", JLabel.CENTER);
+ // label.setBorder(BorderFactory.createEtchedBorder());
+ setBackground(GUIGlobals.validFieldBackground);
+ // label.setOpaque(true);
+ // if ((content != null) && (content.length() > 0))
+ // label.setForeground(GUIGlobals.validFieldColor);
+ // At construction time, the field can never have an invalid value.
+ // else label.setForeground(GUIGlobals.nullFieldColor);
+
+ FieldTextMenu popMenu = new FieldTextMenu(this);
+ this.addMouseListener(popMenu);
+ label.addMouseListener(popMenu);
+ }
+
+ public void append(String text) {
+ setText(getText() + text);
+ }
+
+ public String getFieldName() {
+ return fieldName;
+ }
+
+ public JLabel getLabel() {
+ return label;
+ }
+
+ public void setLabelColor(Color c) {
+ label.setForeground(c);
+ throw new NullPointerException("ok");
+ }
+
+ public JComponent getPane() {
+ return this;
+ }
+
+ public JComponent getTextComponent() {
+ return this;
+ }
+
+ public void paint(Graphics g) {
+ Graphics2D g2 = (Graphics2D) g;
+ if (antialias)
+ g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+ super.paint(g2);
+ }
+
+ public void paste(String textToInsert) {
+ int sel = getSelectionEnd() - getSelectionStart();
+ if (sel < 1) {
+ int cPos = getCaretPosition();
+ select(cPos, cPos);
+ }
+ replaceSelection(textToInsert);
+ }
}
diff --git a/src/java/net/sf/jabref/GUIGlobals.java b/src/java/net/sf/jabref/GUIGlobals.java
index 9697025..d6f81be 100644
--- a/src/java/net/sf/jabref/GUIGlobals.java
+++ b/src/java/net/sf/jabref/GUIGlobals.java
@@ -40,356 +40,350 @@ import java.io.InputStream;
import java.io.IOException;
import java.io.File;
+/**
+ * Static variables for graphics files and keyboard shortcuts.
+ */
public class GUIGlobals {
- /*
- * Static variables for graphics files and keyboard shortcuts.
- */
-
- // for debugging
- static int teller = 0;
-
- // HashMap containing refs to all open BibtexDatabases.
- //static HashMap frames = new HashMap();
-
- // Frame titles.
- public static String
- frameTitle = "JabRef",
-// version = "1.8b",
- version = Globals.VERSION,
- stringsTitle = "Strings for database",
- //untitledStringsTitle = stringsTitle + Globals.lang("untitled"),
- untitledTitle = "untitled",
- helpTitle = "JabRef help",
- TYPE_HEADER = "entrytype",
- NUMBER_COL = "#",
- encPrefix = "Encoding: ", // Part of the signature in written bib files.
- linuxDefaultLookAndFeel = "com.jgoodies.looks.plastic.Plastic3DLookAndFeel",
- //"com.shfarr.ui.plaf.fh.FhLookAndFeel",
-//"net.sourceforge.mlf.metouia.MetouiaLookAndFeel",
-//"org.compiere.plaf.CompiereLookAndFeel",
- windowsDefaultLookAndFeel = "com.jgoodies.looks.windows.WindowsLookAndFeel";
-
- public static Font CURRENTFONT,
- typeNameFont,
- jabRefFont,
- fieldNameFont;
-
- // Signature written at the top of the .bib file.
- public static final String SIGNATURE =
- "This file was created with JabRef";
-
- // Size of help window.
- static Dimension
- helpSize = new Dimension(700, 600),
- aboutSize = new Dimension(600, 265),
- searchPaneSize = new Dimension(430, 70),
- searchFieldSize = new Dimension(215, 25);
-
- // Divider size for BaseFrame split pane. 0 means non-resizable.
- public static final int
- SPLIT_PANE_DIVIDER_SIZE = 4,
- SPLIT_PANE_DIVIDER_LOCATION = 145,
- TABLE_ROW_PADDING = 4,
- KEYBIND_COL_0 = 200,
- KEYBIND_COL_1 = 80, // Added to the font size when determining table
- PREVIEW_PANEL_PADDING = 15, // Extra room given to the preview editor, in addition to its own
- PREVIEW_PANEL_HEIGHT = 200,
- MAX_CONTENT_SELECTOR_WIDTH = 240; // The max width of the combobox for content selectors.
- // calculated preferred size
- //public static final int[] PREVIEW_HEIGHT = {115, 300};
- // row height
- public static final double
- VERTICAL_DIVIDER_LOCATION = 0.4;
-
- // File names.
- public static String //configFile = "preferences.dat",
- backupExt = ".bak",
- tempExt = ".tmp",
- defaultDir = ".";
-
- // Image paths.
- public static String
- imageSize = "24",
- extension = ".gif",
- ex = imageSize + extension,
- pre = "/images/",
- helpPre = "/help/",
- fontPath = "/images/font/";
-
- static HashMap tableIcons = new HashMap(); // Contains table icon mappings. Set up
- // further below.
- public static Color activeEditor = new Color(230, 230, 255);
-
- static HashMap iconMap;
-
- public static JLabel getTableIcon(String fieldType) {
- Object o = tableIcons.get(fieldType);
- if (o == null) {
- Globals.logger("Error: no table icon defined for type '"+fieldType+"'.");
- return null;
- } else return (JLabel)o;
- }
-
-
-// Help files (in HTML format):
- public static String
- baseFrameHelp = "BaseFrameHelp.html",
- entryEditorHelp = "EntryEditorHelp.html",
- stringEditorHelp = "StringEditorHelp.html",
- helpContents = "Contents.html",
- searchHelp = "SearchHelp.html",
- groupsHelp = "GroupsHelp.html",
- customEntriesHelp = "CustomEntriesHelp.html",
- contentSelectorHelp = "ContentSelectorHelp.html",
- labelPatternHelp = "LabelPatterns.html",
- ownerHelp = "OwnerHelp.html",
- timeStampHelp = "TimeStampHelp.html",
- pdfHelp = "ExternalFiles.html",
- exportCustomizationHelp = "CustomExports.html",
- importCustomizationHelp = "CustomImports.html",
- medlineHelp = "MedlineHelp.html",
- citeSeerHelp = "CiteSeerHelp.html",
- generalFieldsHelp = "GeneralFields.html",
-// searchHelp = "SearchHelp.html",
- aboutPage = "About.html",
- shortPlainImport="ShortPlainImport.html",
- importInspectionHelp = "ImportInspectionDialog.html",
- shortIntegrityCheck="ShortIntegrityCheck.html",
- shortAuxImport="ShortAuxImport.html",
- remoteHelp = "RemoteHelp.html",
- journalAbbrHelp = "JournalAbbreviations.html";
-
-
-// Colors.
- public static Color
- lightGray = new Color(230, 30, 30), // Light gray background
- validFieldColor = new Color(100, 100, 150), // Empty field, blue.
- nullFieldColor = new Color(75, 130, 95), // Valid field, green.
- invalidFieldColor = new Color(141, 0, 61), // Invalid field, red.
+ // Frame titles.
+ public static String
+ frameTitle = "JabRef",
+// version = "1.8b",
+ version = Globals.VERSION,
+ stringsTitle = "Strings for database",
+ //untitledStringsTitle = stringsTitle + Globals.lang("untitled"),
+ untitledTitle = "untitled",
+ helpTitle = "JabRef help",
+ TYPE_HEADER = "entrytype",
+ NUMBER_COL = "#",
+ encPrefix = "Encoding: ", // Part of the signature in written bib files.
+ linuxDefaultLookAndFeel = "com.jgoodies.looks.plastic.Plastic3DLookAndFeel",
+ //"com.shfarr.ui.plaf.fh.FhLookAndFeel",
+// "net.sourceforge.mlf.metouia.MetouiaLookAndFeel",
+// "org.compiere.plaf.CompiereLookAndFeel",
+ windowsDefaultLookAndFeel = "com.jgoodies.looks.windows.WindowsLookAndFeel";
+
+ public static Font CURRENTFONT,
+ typeNameFont,
+ jabRefFont,
+ fieldNameFont;
+
+ // Signature written at the top of the .bib file.
+ public static final String SIGNATURE =
+ "This file was created with JabRef";
+
+ // Size of help window.
+ static Dimension
+ helpSize = new Dimension(700, 600),
+ aboutSize = new Dimension(600, 265),
+ searchPaneSize = new Dimension(430, 70),
+ searchFieldSize = new Dimension(215, 25);
+
+ // Divider size for BaseFrame split pane. 0 means non-resizable.
+ public static final int
+ SPLIT_PANE_DIVIDER_SIZE = 4,
+ SPLIT_PANE_DIVIDER_LOCATION = 145 + 15, // + 15 for possible scrollbar.
+ TABLE_ROW_PADDING = 4,
+ KEYBIND_COL_0 = 200,
+ KEYBIND_COL_1 = 80, // Added to the font size when determining table
+ PREVIEW_PANEL_PADDING = 15, // Extra room given to the preview editor, in addition to its own
+ PREVIEW_PANEL_HEIGHT = 200,
+ MAX_CONTENT_SELECTOR_WIDTH = 240; // The max width of the combobox for content selectors.
+ // calculated preferred size
+ //public static final int[] PREVIEW_HEIGHT = {115, 300};
+ // row height
+ public static final double
+ VERTICAL_DIVIDER_LOCATION = 0.4;
+
+ // File names.
+ public static String //configFile = "preferences.dat",
+ backupExt = ".bak",
+ tempExt = ".tmp",
+ defaultDir = ".";
+
+ // Image paths.
+ public static String
+ imageSize = "24",
+ extension = ".gif",
+ ex = imageSize + extension,
+ pre = "/images/",
+ helpPre = "/help/",
+ fontPath = "/images/font/";
+
+ static HashMap tableIcons = new HashMap(); // Contains table icon mappings. Set up
+ // further below.
+ public static Color activeEditor = new Color(230, 230, 255);
+
+ static HashMap iconMap;
+
+ public static JLabel getTableIcon(String fieldType) {
+ Object o = tableIcons.get(fieldType);
+ if (o == null) {
+ Globals.logger("Error: no table icon defined for type '"+fieldType+"'.");
+ return null;
+ } else return (JLabel)o;
+ }
+
+
+ //Help files (in HTML format):
+ public static String
+ baseFrameHelp = "BaseFrameHelp.html",
+ entryEditorHelp = "EntryEditorHelp.html",
+ stringEditorHelp = "StringEditorHelp.html",
+ helpContents = "Contents.html",
+ searchHelp = "SearchHelp.html",
+ groupsHelp = "GroupsHelp.html",
+ customEntriesHelp = "CustomEntriesHelp.html",
+ contentSelectorHelp = "ContentSelectorHelp.html",
+ labelPatternHelp = "LabelPatterns.html",
+ ownerHelp = "OwnerHelp.html",
+ timeStampHelp = "TimeStampHelp.html",
+ pdfHelp = "ExternalFiles.html",
+ exportCustomizationHelp = "CustomExports.html",
+ importCustomizationHelp = "CustomImports.html",
+ medlineHelp = "MedlineHelp.html",
+ citeSeerHelp = "CiteSeerHelp.html",
+ generalFieldsHelp = "GeneralFields.html",
+// searchHelp = "SearchHelp.html",
+ aboutPage = "About.html",
+ shortPlainImport="ShortPlainImport.html",
+ importInspectionHelp = "ImportInspectionDialog.html",
+ shortIntegrityCheck="ShortIntegrityCheck.html",
+ shortAuxImport="ShortAuxImport.html",
+ remoteHelp = "RemoteHelp.html",
+ journalAbbrHelp = "JournalAbbreviations.html",
+ regularExpressionSearchHelp = "ExternalFiles.html#RegularExpressionSearch",
+ nameFormatterHelp = "CustomExports.html#NameFormatter",
+ previewHelp = "PreviewHelp.html";
+
+// Colors.
+ public static Color
+ lightGray = new Color(230, 30, 30), // Light gray background
+ validFieldColor = new Color(100, 100, 150), // Empty field, blue.
+ nullFieldColor = new Color(75, 130, 95), // Valid field, green.
+ invalidFieldColor = new Color(141, 0, 61), // Invalid field, red.
// invalidFieldColor = new Color(210, 70, 70), // Invalid field, red.
- validFieldBackground = Color.white, // Valid field backgnd.
-//invalidFieldBackground = new Color(210, 70, 70), // Invalid field backgnd.
- invalidFieldBackground = new Color(255, 100, 100), // Invalid field backgnd.
- gradientGray = new Color(112, 121, 165), // Title bar gradient color, sidepaneheader
- gradientBlue = new Color(0, 27, 102), // Title bar gradient color, sidepaneheader
- //activeTabbed = Color.black, // active Database (JTabbedPane)
- //inActiveTabbed = Color.gray.darker(), // inactive Database
- activeTabbed = validFieldColor.darker(), // active Database (JTabbedPane)
- inActiveTabbed = Color.black, // inactive Database
- infoField = new Color(254, 255, 225) // color for an info field
- ;
-
-
- public static String META_FLAG = "jabref-meta: ";
- public static String META_FLAG_OLD = "bibkeeper-meta: ";
- public static String ENTRYTYPE_FLAG = "jabref-entrytype: ";
-
- // some fieldname constants
- public static final double
- DEFAULT_FIELD_WEIGHT = 1,
- MAX_FIELD_WEIGHT = 2;
-
- public static final double
- SMALL_W = 0.30,
- MEDIUM_W = 0.5,
- LARGE_W = 1.5 ;
-
- public static final double PE_HEIGHT = 2;
-
-// Size constants for EntryTypeForm; small, medium and large.
- public static int[] FORM_WIDTH = new int[] { 500, 650, 820};
- public static int[] FORM_HEIGHT = new int[] { 90, 110, 130};
-
-// Constants controlling formatted bibtex output.
- public static final int
- INDENT = 4,
- LINE_LENGTH = 65; // Maximum
-
- public static int DEFAULT_FIELD_LENGTH = 100,
- NUMBER_COL_LENGTH = 32,
- WIDTH_ICON_COL = 19;
-
- // Column widths for export customization dialog table:
- public static final int
- EXPORT_DIALOG_COL_0_WIDTH = 50,
- EXPORT_DIALOG_COL_1_WIDTH = 200,
- EXPORT_DIALOG_COL_2_WIDTH = 30;
-
- // Column widths for import customization dialog table:
- public static final int
- IMPORT_DIALOG_COL_0_WIDTH = 200,
- IMPORT_DIALOG_COL_1_WIDTH = 80,
- IMPORT_DIALOG_COL_2_WIDTH = 200,
- IMPORT_DIALOG_COL_3_WIDTH = 200;
-
- public static final Map LANGUAGES;
-
- static {
- LANGUAGES = new HashMap();
- // LANGUAGES contains mappings for supported languages.
- LANGUAGES.put("English", "en");
- LANGUAGES.put("Deutsch", "de");
- LANGUAGES.put("Fran\u00E7ais", "fr");
- LANGUAGES.put("Italiano", "it");
- LANGUAGES.put("Norsk", "no");
-
- }
-
- /**
- * Read either the default icon theme, or a custom one. If loading of the custom theme
- * fails, try to fall back on the default theme.
- */
- public static void setUpIconTheme() {
- String defaultPrefix = "/images/crystal_16/", prefix = defaultPrefix;
-
- URL defaultResource = GUIGlobals.class.getResource(prefix+"Icons.properties");
- URL resource = defaultResource;
-
- if (Globals.prefs.getBoolean("useCustomIconTheme")) {
- String filename = Globals.prefs.get("customIconThemeFile");
- if (filename != null)
- try {
- File file = new File(filename);
- String parent = file.getParentFile().getAbsolutePath();
- prefix = "file://"+parent+System.getProperty("file.separator");
- resource = new URL("file://"+file.getAbsolutePath());
- } catch (MalformedURLException e) {
- e.printStackTrace();
- }
- }
- try {
- iconMap = readIconThemeFile(resource, prefix);
- } catch (IOException e) {
- System.err.println(Globals.lang("Unable to read icon theme file")+" '"+
- resource.toString()+"'");
- // If we were trying to load a custom theme, try the default one as a fallback:
- if (resource != defaultResource)
- try {
- iconMap = readIconThemeFile(defaultResource, defaultPrefix);
- } catch (IOException e2) {
- System.err.println(Globals.lang("Unable to read default icon theme."));
- }
-
- }
-
-
- }
-
- /**
- * Looks up the URL for the image representing the given function, in the resource
- * file listing images.
- * @param name The name of the icon, such as "open", "save", "saveAs" etc.
- * @return The URL to the actual image to use.
- */
- public static URL getIconUrl(String name) {
- if (iconMap.containsKey(name)) {
- String path = (String)iconMap.get(name);
- URL url = GUIGlobals.class.getResource(path);
- if (url == null)
- // This may be a resource outside of the jar file, so we try a general URL:
- try {
- url = new URL(path);
- } catch (MalformedURLException e) {
- url = null;
- }
- if (url == null)
- System.err.println(Globals.lang("Could not find image file")+" '"+path+"'");
- return url;
- }
- else return null;
- }
-
- /**
- * Constructs an ImageIcon for the given function, using the image specified in
- * the resource files resource/Icons_en.properties.
- * @param name The name of the icon, such as "open", "save", "saveAs" etc.
- * @return The ImageIcon for the function.
- */
- public static ImageIcon getImage(String name) {
- URL u = getIconUrl(name);
- return u != null ? new ImageIcon(getIconUrl(name)) : null;
- }
-
- /**
- * Read a typical java property file into a HashMap. Currently doesn't support escaping
- * of the '=' character - it simply looks for the first '=' to determine where the key ends.
- * Both the key and the value is trimmed for whitespace at the ends.
- * @param file The URL to read information from.
- * @param prefix A String to prefix to all values read. Can represent e.g. the directory
- * where icon files are to be found.
- * @return A HashMap containing all key-value pairs found.
- * @throws IOException
- */
- private static HashMap readIconThemeFile(URL file, String prefix) throws IOException {
- HashMap map = new HashMap();
- InputStream in = null;
- try {
- in = file.openStream();
- StringBuffer buffer = new StringBuffer();
- int c;
- while ((c = in.read()) != -1)
- buffer.append((char)c);
- String[] lines = buffer.toString().split("\n");
- String directory = null;
- for (int i=0; i<lines.length; i++) {
- String line = lines[i].trim();
- int index = line.indexOf("=");
- if (index >= 0) {
- String key = line.substring(0, index).trim();
- String value = prefix+line.substring(index+1).trim();
- map.put(key, value);
- }
- }
- } catch (IOException ex) {
- throw ex;
- } finally {
- try {
- if (in != null) in.close();
- } catch (IOException ex) {
- ex.printStackTrace();
- }
- }
- return map;
- }
-
- /** returns the path to language independent help files */
- public static String getLocaleHelpPath()
- {
- JabRefPreferences prefs = JabRefPreferences.getInstance() ;
- String middle = prefs.get("language")+"/";
- if (middle.equals("en/")) middle = ""; // english in base help dir.
-
- return (helpPre + middle );
- }
-
-
- /**
- * Perform initializations that are only used in graphical mode. This is to prevent
- * the "Xlib: connection to ":0.0" refused by server" error when access to the X server
- * on Un*x is unavailable.
- */
- public static void init() {
- typeNameFont = new Font("arial", Font.ITALIC+Font.BOLD, 24);
- fieldNameFont = new Font("arial", Font.ITALIC+Font.BOLD, 14);
- JLabel lab;
- lab = new JLabel(getImage("pdfSmall"));
- lab.setToolTipText(Globals.lang("Open")+" PDF");
- tableIcons.put("pdf", lab);
- lab = new JLabel(getImage("wwwSmall"));
- lab.setToolTipText(Globals.lang("Open")+" URL");
- tableIcons.put("url", lab);
- lab = new JLabel(getImage("citeseer"));
- lab.setToolTipText(Globals.lang("Open")+" CiteSeer URL");
- tableIcons.put("citeseerurl", lab);
- lab = new JLabel(getImage("doiSmall"));
- lab.setToolTipText(Globals.lang("Open")+" DOI "+Globals.lang("web link"));
- tableIcons.put("doi", lab);
- lab = new JLabel(getImage("psSmall"));
- lab.setToolTipText(Globals.lang("Open")+" PS");
- tableIcons.put("ps", lab);
-
- //jabRefFont = new Font("arial", Font.ITALIC/*+Font.BOLD*/, 20);
- }
+ validFieldBackground = Color.white, // Valid field backgnd.
+// invalidFieldBackground = new Color(210, 70, 70), // Invalid field backgnd.
+ invalidFieldBackground = new Color(255, 100, 100), // Invalid field backgnd.
+ gradientGray = new Color(112, 121, 165), // Title bar gradient color, sidepaneheader
+ gradientBlue = new Color(0, 27, 102), // Title bar gradient color, sidepaneheader
+ //activeTabbed = Color.black, // active Database (JTabbedPane)
+ //inActiveTabbed = Color.gray.darker(), // inactive Database
+ activeTabbed = validFieldColor.darker(), // active Database (JTabbedPane)
+ inActiveTabbed = Color.black, // inactive Database
+ infoField = new Color(254, 255, 225) // color for an info field
+ ;
+
+ public static String META_FLAG = "jabref-meta: ";
+ public static String META_FLAG_OLD = "bibkeeper-meta: ";
+ public static String ENTRYTYPE_FLAG = "jabref-entrytype: ";
+
+ // some fieldname constants
+ public static final double
+ DEFAULT_FIELD_WEIGHT = 1,
+ MAX_FIELD_WEIGHT = 2;
+
+ public static final double
+ SMALL_W = 0.30,
+ MEDIUM_W = 0.5,
+ LARGE_W = 1.5 ;
+
+ public static final double PE_HEIGHT = 2;
+
+// Size constants for EntryTypeForm; small, medium and large.
+ public static int[] FORM_WIDTH = new int[] { 500, 650, 820};
+ public static int[] FORM_HEIGHT = new int[] { 90, 110, 130};
+
+// Constants controlling formatted bibtex output.
+ public static final int
+ INDENT = 4,
+ LINE_LENGTH = 65; // Maximum
+
+ public static int DEFAULT_FIELD_LENGTH = 100,
+ NUMBER_COL_LENGTH = 32,
+ WIDTH_ICON_COL = 19;
+
+ // Column widths for export customization dialog table:
+ public static final int
+ EXPORT_DIALOG_COL_0_WIDTH = 50,
+ EXPORT_DIALOG_COL_1_WIDTH = 200,
+ EXPORT_DIALOG_COL_2_WIDTH = 30;
+
+ // Column widths for import customization dialog table:
+ public static final int
+ IMPORT_DIALOG_COL_0_WIDTH = 200,
+ IMPORT_DIALOG_COL_1_WIDTH = 80,
+ IMPORT_DIALOG_COL_2_WIDTH = 200,
+ IMPORT_DIALOG_COL_3_WIDTH = 200;
+
+ public static final Map LANGUAGES;
+
+ static {
+ LANGUAGES = new HashMap();
+ // LANGUAGES contains mappings for supported languages.
+ LANGUAGES.put("English", "en");
+ LANGUAGES.put("Deutsch", "de");
+ LANGUAGES.put("Fran\u00E7ais", "fr");
+ LANGUAGES.put("Italiano", "it");
+ LANGUAGES.put("Nederlands", "du");
+ LANGUAGES.put("Norsk", "no");
+
+ }
+
+ /**
+ * Read either the default icon theme, or a custom one. If loading of the custom theme
+ * fails, try to fall back on the default theme.
+ */
+ public static void setUpIconTheme() {
+ String defaultPrefix = "/images/crystal_16/", prefix = defaultPrefix;
+
+ URL defaultResource = GUIGlobals.class.getResource(prefix+"Icons.properties");
+ URL resource = defaultResource;
+
+ if (Globals.prefs.getBoolean("useCustomIconTheme")) {
+ String filename = Globals.prefs.get("customIconThemeFile");
+ if (filename != null)
+ try {
+ File file = new File(filename);
+ String parent = file.getParentFile().getAbsolutePath();
+ prefix = "file://"+parent+System.getProperty("file.separator");
+ resource = new URL("file://"+file.getAbsolutePath());
+ } catch (MalformedURLException e) {
+ e.printStackTrace();
+ }
+ }
+ try {
+ iconMap = readIconThemeFile(resource, prefix);
+ } catch (IOException e) {
+ System.err.println(Globals.lang("Unable to read icon theme file")+" '"+
+ resource.toString()+"'");
+ // If we were trying to load a custom theme, try the default one as a fallback:
+ if (resource != defaultResource)
+ try {
+ iconMap = readIconThemeFile(defaultResource, defaultPrefix);
+ } catch (IOException e2) {
+ System.err.println(Globals.lang("Unable to read default icon theme."));
+ }
+
+ }
+
+
+ }
+
+ /**
+ * Looks up the URL for the image representing the given function, in the resource
+ * file listing images.
+ * @param name The name of the icon, such as "open", "save", "saveAs" etc.
+ * @return The URL to the actual image to use.
+ */
+ public static URL getIconUrl(String name) {
+ if (iconMap.containsKey(name)) {
+ String path = (String)iconMap.get(name);
+ URL url = GUIGlobals.class.getResource(path);
+ if (url == null)
+ // This may be a resource outside of the jar file, so we try a general URL:
+ try {
+ url = new URL(path);
+ } catch (MalformedURLException e) {
+ url = null;
+ }
+ if (url == null)
+ System.err.println(Globals.lang("Could not find image file")+" '"+path+"'");
+ return url;
+ }
+ else return null;
+ }
+
+ /**
+ * Constructs an ImageIcon for the given function, using the image specified in
+ * the resource files resource/Icons_en.properties.
+ * @param name The name of the icon, such as "open", "save", "saveAs" etc.
+ * @return The ImageIcon for the function.
+ */
+ public static ImageIcon getImage(String name) {
+ URL u = getIconUrl(name);
+ return u != null ? new ImageIcon(getIconUrl(name)) : null;
+ }
+
+ /**
+ * Read a typical java property file into a HashMap. Currently doesn't support escaping
+ * of the '=' character - it simply looks for the first '=' to determine where the key ends.
+ * Both the key and the value is trimmed for whitespace at the ends.
+ * @param file The URL to read information from.
+ * @param prefix A String to prefix to all values read. Can represent e.g. the directory
+ * where icon files are to be found.
+ * @return A HashMap containing all key-value pairs found.
+ * @throws IOException
+ */
+ private static HashMap readIconThemeFile(URL file, String prefix) throws IOException {
+ HashMap map = new HashMap();
+ InputStream in = null;
+ try {
+ in = file.openStream();
+ StringBuffer buffer = new StringBuffer();
+ int c;
+ while ((c = in.read()) != -1)
+ buffer.append((char)c);
+ String[] lines = buffer.toString().split("\n");
+ for (int i=0; i<lines.length; i++) {
+ String line = lines[i].trim();
+ int index = line.indexOf("=");
+ if (index >= 0) {
+ String key = line.substring(0, index).trim();
+ String value = prefix+line.substring(index+1).trim();
+ map.put(key, value);
+ }
+ }
+ } catch (IOException ex) {
+ throw ex;
+ } finally {
+ try {
+ if (in != null) in.close();
+ } catch (IOException ex) {
+ ex.printStackTrace();
+ }
+ }
+ return map;
+ }
+
+ /** returns the path to language independent help files */
+ public static String getLocaleHelpPath()
+ {
+ JabRefPreferences prefs = JabRefPreferences.getInstance() ;
+ String middle = prefs.get("language")+"/";
+ if (middle.equals("en/")) middle = ""; // english in base help dir.
+
+ return (helpPre + middle );
+ }
+
+
+ /**
+ * Perform initializations that are only used in graphical mode. This is to prevent
+ * the "Xlib: connection to ":0.0" refused by server" error when access to the X server
+ * on Un*x is unavailable.
+ */
+ public static void init() {
+ typeNameFont = new Font("arial", Font.ITALIC+Font.BOLD, 24);
+ fieldNameFont = new Font("arial", Font.ITALIC+Font.BOLD, 14);
+ JLabel lab;
+ lab = new JLabel(getImage("pdfSmall"));
+ lab.setToolTipText(Globals.lang("Open")+" PDF");
+ tableIcons.put("pdf", lab);
+ lab = new JLabel(getImage("wwwSmall"));
+ lab.setToolTipText(Globals.lang("Open")+" URL");
+ tableIcons.put("url", lab);
+ lab = new JLabel(getImage("citeseer"));
+ lab.setToolTipText(Globals.lang("Open")+" CiteSeer URL");
+ tableIcons.put("citeseerurl", lab);
+ lab = new JLabel(getImage("doiSmall"));
+ lab.setToolTipText(Globals.lang("Open")+" DOI "+Globals.lang("web link"));
+ tableIcons.put("doi", lab);
+ lab = new JLabel(getImage("psSmall"));
+ lab.setToolTipText(Globals.lang("Open")+" PS");
+ tableIcons.put("ps", lab);
+
+ //jabRefFont = new Font("arial", Font.ITALIC/*+Font.BOLD*/, 20);
+ }
}
diff --git a/src/java/net/sf/jabref/Globals.java b/src/java/net/sf/jabref/Globals.java
index 9e036e7..d138361 100644
--- a/src/java/net/sf/jabref/Globals.java
+++ b/src/java/net/sf/jabref/Globals.java
@@ -25,1300 +25,1319 @@
*/
package net.sf.jabref;
-import java.io.* ;
+import java.io.*;
import java.nio.charset.Charset;
-import java.util.* ;
+import java.util.*;
import java.util.List;
-import java.util.logging.* ;
-import java.util.logging.Filter ;
+import java.util.logging.*;
+import java.util.logging.Filter;
-import java.awt.* ;
-import javax.swing.* ;
+import java.awt.*;
+import javax.swing.*;
-import net.sf.jabref.collab.* ;
-import net.sf.jabref.imports.* ;
-import net.sf.jabref.util.* ;
+import net.sf.jabref.collab.*;
+import net.sf.jabref.imports.*;
+import net.sf.jabref.util.*;
import net.sf.jabref.journals.JournalAbbreviations;
public class Globals {
- public static int SHORTCUT_MASK,// = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
- FUTURE_YEAR = 2050, // Needs to give a year definitely in the future. Used for guessing the
- // year field when parsing textual data. :-)
-
- STANDARD_EXPORT_COUNT = 5, // The number of standard export formats.
- METADATA_LINE_LENGTH = 70; // The line length used to wrap metadata.
-
- private static String resourcePrefix = "resource/JabRef",
- menuResourcePrefix = "resource/Menu",
- integrityResourcePrefix = "resource/IntegrityMessage";
- private static final String buildInfos = "/resource/build.properties" ;
- public static final String additionalFields = "/resource/fields/fields.xml" ; // some extra field definitions
- private static String logfile = "jabref.log";
- public static ResourceBundle messages, menuTitles, intMessages ;
- public static FileUpdateMonitor fileUpdateMonitor = new FileUpdateMonitor();
- public static ImportFormatReader importFormatReader = new ImportFormatReader();
-
- public static ErrorConsole errorConsole;
-
- public static String VERSION,
- BUILD,
- BUILD_DATE ;
-
- static
- {
- TBuildInfo bi = new TBuildInfo(buildInfos) ;
- VERSION = bi.getBUILD_VERSION() ;
- BUILD = bi.getBUILD_NUMBER() ;
- BUILD_DATE = bi.getBUILD_DATE() ;
-
- // TODO: Error console initialization here. When should it be used?
- errorConsole = ErrorConsole.getInstance();
- }
-
-
-
- //public static ResourceBundle preferences = ResourceBundle.getBundle("resource/defaultPrefs");
- public static Locale locale;
- public static final String FILETYPE_PREFS_EXT = "_dir",
- SELECTOR_META_PREFIX = "selector_",
- LAYOUT_PREFIX = "/resource/layout/",
- MAC = "Mac OS X",
- DOI_LOOKUP_PREFIX = "http://dx.doi.org/",
- NONE = "_non__",
- FORMATTER_PACKAGE = "net.sf.jabref.export.layout.format.";
- public static float duplicateThreshold = 0.75f;
- private static Handler consoleHandler = new java.util.logging.ConsoleHandler();
- public static String[] ENCODINGS,
- ALL_ENCODINGS = //(String[]) Charset.availableCharsets().keySet().toArray(new String[]{});
- new String[] {"ISO8859_1", "UTF8", "UTF-16", "ASCII",
- "Cp1250", "Cp1251", "Cp1252", "Cp1253", "Cp1254", "Cp1257",
- "JIS", "SJIS", "EUC-JP", // Added Japanese encodings.
- "Big5", "Big5_HKSCS", "GBK",
- "ISO8859_2", "ISO8859_3", "ISO8859_4", "ISO8859_5", "ISO8859_6",
- "ISO8859_7", "ISO8859_8", "ISO8859_9", "ISO8859_13", "ISO8859_15"};
-
- // String array that maps from month number to month string label:
- public static String[] MONTHS = new String[] {"jan", "feb", "mar", "apr", "may", "jun",
- "jul", "aug", "sep", "oct", "nov", "dec"};
-
- // Map that maps from month string labels to
- public static Map MONTH_STRINGS = new HashMap();
- static {
- MONTH_STRINGS.put("jan", "January");
- MONTH_STRINGS.put("feb", "February");
- MONTH_STRINGS.put("mar", "March");
- MONTH_STRINGS.put("apr", "April");
- MONTH_STRINGS.put("may", "May");
- MONTH_STRINGS.put("jun", "June");
- MONTH_STRINGS.put("jul", "July");
- MONTH_STRINGS.put("aug", "August");
- MONTH_STRINGS.put("sep", "September");
- MONTH_STRINGS.put("oct", "October");
- MONTH_STRINGS.put("nov", "November");
- MONTH_STRINGS.put("dec", "December");
-
- // Build list of encodings, by filtering out all that are not supported
- // on this system:
- List encodings = new ArrayList();
- for (int i=0; i<ALL_ENCODINGS.length; i++) {
- if (Charset.isSupported(ALL_ENCODINGS[i]))
- encodings.add(ALL_ENCODINGS[i]);
- }
- ENCODINGS = (String[])encodings.toArray(new String[0]);
-
- }
-
-
- public static GlobalFocusListener focusListener = new GlobalFocusListener();
- public static JabRefPreferences prefs = null;
- public static HelpDialog helpDiag = null;
- public static String osName = System.getProperty("os.name", "def");
- public static boolean ON_MAC = (osName.equals(MAC)),
- ON_WIN = osName.startsWith("Windows");
-
-
- public static String[] SKIP_WORDS = {"a", "an", "the", "for", "on"};
- public static SidePaneManager sidePaneManager;
- public static final String NEWLINE = System.getProperty("line.separator");
- public static final boolean UNIX_NEWLINE = NEWLINE.equals("\n"); // true if we have unix newlines.
-
- public static final String BIBTEX_STRING = "__string";
- // "Fieldname" to indicate that a field should be treated as a bibtex string. Used when writing database to file.
-
- public static void logger(String s) {
- Logger.global.info(s);
- }
-
- public static void turnOffLogging() { // only log exceptions
- Logger.global.setLevel(java.util.logging.Level.SEVERE);
- }
-
- // should be only called once
- public static void turnOnConsoleLogging() {
- Logger.global.addHandler(consoleHandler);
-
- }
-
-
-
- public static void turnOnFileLogging() {
- Logger.global.setLevel(java.util.logging.Level.ALL);
- java.util.logging.Handler handler;
- handler = new ConsoleHandler();
- /*try {
- handler = new FileHandler(logfile); // this will overwrite
- }
- catch (IOException e) { //can't open log file so use console
- e.printStackTrace();
-
- } */
- Logger.global.addHandler(handler);
-
- handler.setFilter(new Filter() { // select what gets logged
- public boolean isLoggable(LogRecord record) {
- return true;
- }
- });
- }
-
- public static void setLanguage(String language, String country) {
- locale = new Locale(language, country);
- messages = ResourceBundle.getBundle(resourcePrefix, locale);
- menuTitles = ResourceBundle.getBundle(menuResourcePrefix, locale);
- intMessages = ResourceBundle.getBundle(integrityResourcePrefix, locale);
- Locale.setDefault(locale);
- javax.swing.JComponent.setDefaultLocale(locale);
- }
-
-
- public static JournalAbbreviations journalAbbrev;
-
-
- public static String lang(String key, String[] params) {
- String translation = null;
- try {
- if (Globals.messages != null) {
- translation = Globals.messages.getString(key.replaceAll(" ", "_"));
- }
- }
- catch (MissingResourceException ex) {
- translation = key;
-
- //Thread.dumpStack(); // For debugging
- /*logger("Warning: could not get translation for \""
- + key + "\"");*/
- }
- if ((translation != null) && (translation.length() != 0)) {
- translation = translation.replaceAll("_", " ");
- StringBuffer sb = new StringBuffer();
- boolean b = false;
- char c;
- for (int i = 0; i < translation.length(); ++i) {
- c = translation.charAt(i);
- if (c == '%') {
- b = true;
- } else {
- if (!b) {
- sb.append(c);
- } else {
- b = false;
- try {
- int index = Integer.parseInt(String.valueOf(c));
- if (params != null && index >= 0 && index <= params.length)
- sb.append(params[index]);
- } catch (NumberFormatException e) {
- // append literally (for quoting) or insert special symbol
- switch (c) {
- case 'c': // colon
- sb.append(':');
- break;
- case 'e': // equal
- sb.append('=');
- break;
- default: // anything else, e.g. %
- sb.append(c);
- }
- }
- }
- }
- }
- return sb.toString();
- }
- return key;
- }
-
- public static String lang(String key) {
- return lang(key, (String[])null);
- }
-
- public static String lang(String key, String s1) {
- return lang(key, new String[]{s1});
- }
-
- public static String lang(String key, String s1, String s2) {
- return lang(key, new String[]{s1, s2});
- }
-
- public static String lang(String key, String s1, String s2, String s3) {
- return lang(key, new String[]{s1, s2, s3});
- }
-
- public static String menuTitle(String key) {
- String translation = null;
- try {
- if (Globals.messages != null) {
- translation = Globals.menuTitles.getString(key.replaceAll(" ", "_"));
- }
- }
- catch (MissingResourceException ex) {
- translation = key;
-
- //System.err.println("Warning: could not get menu item translation for \""
- // + key + "\"");
-
- }
- if ((translation != null) && (translation.length() != 0)) {
- return translation.replaceAll("_", " ");
- }
- else {
- return key;
- }
- }
-
- public static String getIntegrityMessage(String key)
- {
- String translation = null;
- try {
- if (Globals.intMessages != null) {
- translation = Globals.intMessages.getString(key);
- }
- }
- catch (MissingResourceException ex) {
- translation = key;
-
-// System.err.println("Warning: could not get menu item translation for \""
-// + key + "\"");
- }
- if ((translation != null) && (translation.length() != 0)) {
- return translation ;
- }
- else {
- return key;
- }
- }
-
-
- //============================================================
- // Using the hashmap of entry types found in BibtexEntryType
- //============================================================
- public static BibtexEntryType getEntryType(String type) {
- // decide which entryType object to return
- Object o = BibtexEntryType.ALL_TYPES.get(type);
- if (o != null) {
- return (BibtexEntryType) o;
- }
- else {
- return BibtexEntryType.OTHER;
- }
- /*
- if(type.equals("article"))
- return BibtexEntryType.ARTICLE;
- else if(type.equals("book"))
- return BibtexEntryType.BOOK;
- else if(type.equals("inproceedings"))
- return BibtexEntryType.INPROCEEDINGS;
- */
- }
-
- /**
- * This method provides the correct opening brace to use when writing a field
- * to BibTeX format.
- * @return A String containing the braces to use.
- */
- public static String getOpeningBrace() {
- return "{";
- /*
- As of version 2.0, storing all fields with double braces is no longer supported, because
- it causes problems with e.g. the author field.
-
- if (prefs.getBoolean("autoDoubleBraces"))
- return "{{";
- else
- return "{";
- */
- }
-
- /**
- * This method provides the correct closing brace to use when writing a field
- * to BibTeX format.
- * @return A String containing the braces to use.
- */
- public static String getClosingBrace() {
- return "}";
- /*
- As of version 2.0, storing all fields with double braces is no longer supported, because
- it causes problems with e.g. the author field.
-
- if (prefs.getBoolean("autoDoubleBraces"))
- return "}}";
- else
- */
-
- }
-
- /* public static void setupKeyBindings(JabRefPreferences prefs) {
- }*/
-
-
- public static String[] getMultipleFiles(JFrame owner,
- File directory, String extension,
- boolean updateWorkingdirectory) {
-
- OpenFileFilter off = null;
- if (extension == null)
- off = new OpenFileFilter();
- else if (!extension.equals(NONE))
- off = new OpenFileFilter(extension);
- Object o = getNewFileImpl(owner, directory, extension, null, off,
- JFileChooser.OPEN_DIALOG, updateWorkingdirectory, false, true);
- String[] toReturn;
- if (o instanceof String[])
- toReturn = (String[])o;
- else toReturn = new String[] {(String)o};
-
- return toReturn;
- }
-
- public static String getNewFile(JFrame owner,
- File directory, String extension,
- int dialogType,
- boolean updateWorkingDirectory) {
- return getNewFile(owner, directory, extension, null, dialogType,
- updateWorkingDirectory, false);
- }
-
-
- public static String getNewFile(JFrame owner,
- File directory, String extension,
- String description,
- int dialogType,
- boolean updateWorkingDirectory) {
- return getNewFile(owner, directory, extension, description, dialogType,
- updateWorkingDirectory, false);
- }
-
-
- public static String getNewDir(JFrame owner,
- File directory, String extension,
- int dialogType, boolean updateWorkingDirectory) {
- return getNewFile(owner, directory, extension, null, dialogType,
- updateWorkingDirectory, true);
- }
-
- public static String getNewDir(JFrame owner,
- File directory, String extension,
- String description,
- int dialogType, boolean updateWorkingDirectory) {
- return getNewFile(owner, directory, extension, description, dialogType,
- updateWorkingDirectory, true);
- }
-
- private static String getNewFile(JFrame owner,
- File directory, String extension,
- String description,
- int dialogType,
- boolean updateWorkingDirectory,
- boolean dirOnly) {
-
- OpenFileFilter off = null;
-
- if (extension == null)
- off = new OpenFileFilter();
- else if (!extension.equals(NONE))
- off = new OpenFileFilter(extension);
-
- return (String)getNewFileImpl(owner, directory, extension, description, off,
- dialogType, updateWorkingDirectory, dirOnly, false);
- }
-
- private static Object getNewFileImpl(JFrame owner,
- File directory, String extension,
- String description,
- OpenFileFilter off,
- int dialogType,
- boolean updateWorkingDirectory,
- boolean dirOnly,
- boolean multipleSelection) {
-
- if (ON_MAC && prefs.getBoolean("useNativeFileDialogOnMac")) {
-
- return getNewFileForMac(owner, directory, extension, dialogType,
- updateWorkingDirectory, dirOnly, off);
- }
-
- JFileChooser fc = null;
- try {
- fc = new JabRefFileChooser(directory);
- } catch (InternalError errl) {
- // This try/catch clause was added because a user reported an
- // InternalError getting thrown on WinNT, presumably because of a
- // bug in JGoodies Windows PLAF. This clause can be removed if the
- // bug is fixed, but for now we just resort to the native file
- // dialog, using the same method as is always used on Mac:
- return getNewFileForMac(owner, directory, extension, dialogType,
- updateWorkingDirectory, dirOnly, off);
- }
-
- if (dirOnly) {
- fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
-
- }
-
- fc.setMultiSelectionEnabled(multipleSelection);
-
- fc.addChoosableFileFilter(off);
- fc.setDialogType(dialogType);
- int dialogResult;
- if (dialogType == JFileChooser.OPEN_DIALOG) {
- dialogResult = fc.showOpenDialog(owner);
- } else if (dialogType == JFileChooser.SAVE_DIALOG) {
- dialogResult = fc.showSaveDialog(owner);
- } else {
- dialogResult = fc.showDialog(owner, description);
- }
-
- // the getSelectedFile method returns a valid fileselection
- // (if something is selected) indepentently from dialog return status
- if (dialogResult != JFileChooser.APPROVE_OPTION)
- return null;
-
- // okay button
- File selectedFile = fc.getSelectedFile();
- if (selectedFile == null) { // cancel
- return null;
- }
-
- // If this is a save dialog, and the user has not chosen "All files" as filter
- // we enforce the given extension. But only if extension is not null.
- if ((extension != null) && (dialogType == JFileChooser.SAVE_DIALOG) && (fc.getFileFilter() == off) &&
- !off.accept(selectedFile)) {
-
- // add the first extension if there are multiple extensions
- selectedFile = new File(selectedFile.getPath() + extension.split("[, ]+", 0)[0]);
- }
-
- if (updateWorkingDirectory) {
- prefs.put("workingDirectory", selectedFile.getPath());
- }
-
- if (!multipleSelection)
- return selectedFile.getAbsolutePath();
- else {
- File[] files = fc.getSelectedFiles();
- String[] filenames = new String[files.length];
- for (int i=0; i<files.length; i++)
- filenames[i] = files[i].getAbsolutePath();
- return filenames;
- }
- }
-
- private static String getNewFileForMac(JFrame owner,
- File directory, String extensions,
- int dialogType,
- boolean updateWorkingDirectory,
- boolean dirOnly,
- FilenameFilter filter) {
-
- FileDialog fc = new FileDialog(owner);
-
- //fc.setFilenameFilter(filter);
- if (directory != null) {
- fc.setDirectory(directory.getParent());
- }
- if (dialogType == JFileChooser.OPEN_DIALOG) {
- fc.setMode(FileDialog.LOAD);
- }
- else {
- fc.setMode(FileDialog.SAVE);
- }
-
- fc.setVisible(true); // fc.show(); -> deprecated since 1.5
-
- if (fc.getFile() != null) {
- Globals.prefs.put("workingDirectory", fc.getDirectory() + fc.getFile());
- return fc.getDirectory() + fc.getFile();
- }
- else {
- return null;
- }
- }
-
-
- public static String SPECIAL_COMMAND_CHARS = "\"`^~'c";
- public static HashMap HTML_CHARS = new HashMap(),
- HTMLCHARS = new HashMap(),
- XML_CHARS = new HashMap(),
- ASCII2XML_CHARS = new HashMap(),
- UNICODE_CHARS = new HashMap(),
- RTFCHARS = new HashMap(),
- URL_CHARS = new HashMap();
- static {
-
- //System.out.println(journalAbbrev.getAbbreviatedName("Journal of Fish Biology", true));
- //System.out.println(journalAbbrev.getAbbreviatedName("Journal of Fish Biology", false));
- //System.out.println(journalAbbrev.getFullName("Aquaculture Eng."));
- /*for (Iterator i=journalAbbrev.fullNameIterator(); i.hasNext();) {
- String s = (String)i.next();
- System.out.println(journalAbbrev.getFullName(s)+" : "+journalAbbrev.getAbbreviatedName(s, true));
- } */
-
- // Start the thread that monitors file time stamps.
- //Util.pr("Starting FileUpdateMonitor thread. Globals line 293.");
- fileUpdateMonitor.start();
-
- try {
- SHORTCUT_MASK = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
- } catch (Throwable t) {
-
- }
-
- // Special characters in URLs need to be replaced to ensure that the URL
- // opens properly on all platforms:
- URL_CHARS.put("<", "%3c");
- URL_CHARS.put(">", "%3e");
- URL_CHARS.put("(", "%28");
- URL_CHARS.put(")", "%29");
- URL_CHARS.put(" ", "%20");
- URL_CHARS.put("&", "%26");
- URL_CHARS.put("$", "%24");
-
-
-
-// HTMLCHARS.put("\"a", "ä");
-// HTMLCHARS.put("\"A", "Ä");
-// HTMLCHARS.put("\"e", "ë");
-// HTMLCHARS.put("\"E", "Ë");
-// HTMLCHARS.put("\"i", "ï");
-// HTMLCHARS.put("\"I", "Ï");
-// HTMLCHARS.put("\"o", "ö");
-// HTMLCHARS.put("\"O", "Ö");
-// HTMLCHARS.put("\"u", "ü");
-// HTMLCHARS.put("\"U", "Ü");
-// HTMLCHARS.put("`a", "à");
-// HTMLCHARS.put("`A", "À");
-// HTMLCHARS.put("`e", "è");
-// HTMLCHARS.put("`E", "È");
-// HTMLCHARS.put("`i", "ì");
-// HTMLCHARS.put("`I", "Ì");
-// HTMLCHARS.put("`o", "ò");
-// HTMLCHARS.put("`O", "Ò");
-// HTMLCHARS.put("`u", "ù");
-// HTMLCHARS.put("`U", "Ù");
-// HTMLCHARS.put("'e", "é");
-// HTMLCHARS.put("'E", "É");
-// HTMLCHARS.put("'i", "í");
-// HTMLCHARS.put("'I", "Í");
-// HTMLCHARS.put("'o", "ó");
-// HTMLCHARS.put("'O", "Ó");
-// HTMLCHARS.put("'u", "ú");
-// HTMLCHARS.put("'U", "Ú");
-// HTMLCHARS.put("'a", "á");
-// HTMLCHARS.put("'A", "Á");
-// HTMLCHARS.put("^a", "ô");
-// HTMLCHARS.put("^A", "Ô");
-// HTMLCHARS.put("^o", "ô");
-// HTMLCHARS.put("^O", "Ô");
-// HTMLCHARS.put("^u", "û");
-// HTMLCHARS.put("^U", "Û");
-// HTMLCHARS.put("^e", "ê");
-// HTMLCHARS.put("^E", "Ê");
-// HTMLCHARS.put("^i", "î");
-// HTMLCHARS.put("^I", "Î");
-// HTMLCHARS.put("~o", "õ");
-// HTMLCHARS.put("~O", "Õ");
-// HTMLCHARS.put("~n", "ñ");
-// HTMLCHARS.put("~N", "Ñ");
-// HTMLCHARS.put("~a", "ã");
-// HTMLCHARS.put("~A", "Ã");
-// HTMLCHARS.put("cc", "ç");
-// HTMLCHARS.put("cC", "Ç");
-
-
- // Following character definitions contributed by Ervin Kolenovic:
- // HTML named entities from #192 - #255 (UNICODE Latin-1)
- HTMLCHARS.put("`A", "À"); // #192
- HTMLCHARS.put("'A", "Á"); // #193
- HTMLCHARS.put("^A", "Â"); // #194
- HTMLCHARS.put("~A", "Ã"); // #195
- HTMLCHARS.put("\"A", "Ä"); // #196
- HTMLCHARS.put("AA", "Å"); // #197
- HTMLCHARS.put("AE", "Æ"); // #198
- HTMLCHARS.put("cC", "Ç"); // #199
- HTMLCHARS.put("`E", "È"); // #200
- HTMLCHARS.put("'E", "É"); // #201
- HTMLCHARS.put("^E", "Ê"); // #202
- HTMLCHARS.put("\"E", "Ë"); // #203
- HTMLCHARS.put("`I", "Ì"); // #204
- HTMLCHARS.put("'I", "Í"); // #205
- HTMLCHARS.put("^I", "Î"); // #206
- HTMLCHARS.put("\"I", "Ï"); // #207
- HTMLCHARS.put("DH", "Ð"); // #208
- HTMLCHARS.put("~N", "Ñ"); // #209
- HTMLCHARS.put("`O", "Ò"); // #210
- HTMLCHARS.put("'O", "Ó"); // #211
- HTMLCHARS.put("^O", "Ô"); // #212
- HTMLCHARS.put("~O", "Õ"); // #213
- HTMLCHARS.put("\"O", "Ö"); // #214
- // According to ISO 8859-1 the "\times" symbol should be placed here (#215).
- // Omitting this, because it is a mathematical symbol.
- HTMLCHARS.put("O", "&OSlash;"); // #216
- HTMLCHARS.put("`U", "Ù"); // #217
- HTMLCHARS.put("'U", "Ú"); // #218
- HTMLCHARS.put("^U", "Û"); // #219
- HTMLCHARS.put("\"U", "Ü"); // #220
- HTMLCHARS.put("'Y", "Ý"); // #221
- HTMLCHARS.put("TH", "Þ"); // #222
- HTMLCHARS.put("ss", "ß"); // #223
- HTMLCHARS.put("`a", "à"); // #224
- HTMLCHARS.put("'a", "á"); // #225
- HTMLCHARS.put("^a", "â"); // #226
- HTMLCHARS.put("~a", "ã"); // #227
- HTMLCHARS.put("\"a", "ä"); // #228
- HTMLCHARS.put("aa", "å"); // #229
- HTMLCHARS.put("ae", "æ"); // #230
- HTMLCHARS.put("cc", "ç"); // #231
- HTMLCHARS.put("`e", "è"); // #232
- HTMLCHARS.put("'e", "é"); // #233
- HTMLCHARS.put("^e", "ê"); // #234
- HTMLCHARS.put("\"e", "ë"); // #235
- HTMLCHARS.put("`i", "ì"); // #236
- HTMLCHARS.put("'i", "í"); // #237
- HTMLCHARS.put("^i", "î"); // #238
- HTMLCHARS.put("\"i", "ï"); // #239
- HTMLCHARS.put("dh", "ð"); // #240
- HTMLCHARS.put("~n", "ñ"); // #241
- HTMLCHARS.put("`o", "ò"); // #242
- HTMLCHARS.put("'o", "ó"); // #243
- HTMLCHARS.put("^o", "ô"); // #244
- HTMLCHARS.put("~o", "õ"); // #245
- HTMLCHARS.put("\"o", "ö"); // #246
- // According to ISO 8859-1 the "\div" symbol should be placed here (#247).
- // Omitting this, because it is a mathematical symbol.
- HTMLCHARS.put("o", "ø"); // #248
- HTMLCHARS.put("`u", "ù"); // #249
- HTMLCHARS.put("'u", "ú"); // #250
- HTMLCHARS.put("^u", "û"); // #251
- HTMLCHARS.put("\"u", "ü"); // #252
- HTMLCHARS.put("'y", "ý"); // #253
- HTMLCHARS.put("th", "þ"); // #254
- HTMLCHARS.put("\"y", "ÿ"); // #255
-
- // HTML special characters without names (UNICODE Latin Extended-A), indicated by UNICODE number
- HTMLCHARS.put("=A", "Ā"); // "Amacr"
- HTMLCHARS.put("=a", "ā"); // "amacr"
- HTMLCHARS.put("uA", "Ă"); // "Abreve"
- HTMLCHARS.put("ua", "ă"); // "abreve"
- HTMLCHARS.put("kA", "Ą"); // "Aogon"
- HTMLCHARS.put("ka", "ą"); // "aogon"
- HTMLCHARS.put("'C", "Ć"); // "Cacute"
- HTMLCHARS.put("'c", "ć"); // "cacute"
- HTMLCHARS.put("^C", "Ĉ"); // "Ccirc"
- HTMLCHARS.put("^c", "ĉ"); // "ccirc"
- HTMLCHARS.put(".C", "Ċ"); // "Cdot"
- HTMLCHARS.put(".c", "ċ"); // "cdot"
- HTMLCHARS.put("vC", "Č"); // "Ccaron"
- HTMLCHARS.put("vc", "č"); // "ccaron"
- HTMLCHARS.put("vD", "Ď"); // "Dcaron"
- // Symbol #271 (d�) has no special Latex command
- HTMLCHARS.put("DJ", "Đ"); // "Dstrok"
- HTMLCHARS.put("dj", "đ"); // "dstrok"
- HTMLCHARS.put("=E", "Ē"); // "Emacr"
- HTMLCHARS.put("=e", "ē"); // "emacr"
- HTMLCHARS.put("uE", "Ĕ"); // "Ebreve"
- HTMLCHARS.put("ue", "ĕ"); // "ebreve"
- HTMLCHARS.put(".E", "Ė"); // "Edot"
- HTMLCHARS.put(".e", "ė"); // "edot"
- HTMLCHARS.put("kE", "Ę"); // "Eogon"
- HTMLCHARS.put("ke", "ę"); // "eogon"
- HTMLCHARS.put("vE", "Ě"); // "Ecaron"
- HTMLCHARS.put("ve", "ě"); // "ecaron"
- HTMLCHARS.put("^G", "Ĝ"); // "Gcirc"
- HTMLCHARS.put("^g", "ĝ"); // "gcirc"
- HTMLCHARS.put("uG", "Ğ"); // "Gbreve"
- HTMLCHARS.put("ug", "ğ"); // "gbreve"
- HTMLCHARS.put(".G", "Ġ"); // "Gdot"
- HTMLCHARS.put(".g", "ġ"); // "gdot"
- HTMLCHARS.put("cG", "Ģ"); // "Gcedil"
- HTMLCHARS.put("'g", "ģ"); // "gacute"
- HTMLCHARS.put("^H", "Ĥ"); // "Hcirc"
- HTMLCHARS.put("^h", "ĥ"); // "hcirc"
- HTMLCHARS.put("Hstrok", "Ħ"); // "Hstrok"
- HTMLCHARS.put("hstrok", "ħ"); // "hstrok"
- HTMLCHARS.put("~I", "Ĩ"); // "Itilde"
- HTMLCHARS.put("~i", "ĩ"); // "itilde"
- HTMLCHARS.put("=I", "Ī"); // "Imacr"
- HTMLCHARS.put("=i", "ī"); // "imacr"
- HTMLCHARS.put("uI", "Ĭ"); // "Ibreve"
- HTMLCHARS.put("ui", "ĭ"); // "ibreve"
- HTMLCHARS.put("kI", "Į"); // "Iogon"
- HTMLCHARS.put("ki", "į"); // "iogon"
- HTMLCHARS.put(".I", "İ"); // "Idot"
- HTMLCHARS.put("i", "ı"); // "inodot"
- // Symbol #306 (IJ) has no special Latex command
- // Symbol #307 (ij) has no special Latex command
- HTMLCHARS.put("^J", "Ĵ"); // "Jcirc"
- HTMLCHARS.put("^j", "ĵ"); // "jcirc"
- HTMLCHARS.put("cK", "Ķ"); // "Kcedil"
- HTMLCHARS.put("ck", "ķ"); // "kcedil"
- // Symbol #312 (k) has no special Latex command
- HTMLCHARS.put("'L", "Ĺ"); // "Lacute"
- HTMLCHARS.put("'l", "ĺ"); // "lacute"
- HTMLCHARS.put("cL", "Ļ"); // "Lcedil"
- HTMLCHARS.put("cl", "ļ"); // "lcedil"
- // Symbol #317 (L�) has no special Latex command
- // Symbol #318 (l�) has no special Latex command
- HTMLCHARS.put("Lmidot", "Ŀ"); // "Lmidot"
- HTMLCHARS.put("lmidot", "ŀ"); // "lmidot"
- HTMLCHARS.put("L", "Ł"); // "Lstrok"
- HTMLCHARS.put("l", "ł"); // "lstrok"
- HTMLCHARS.put("'N", "Ń"); // "Nacute"
- HTMLCHARS.put("'n", "ń"); // "nacute"
- HTMLCHARS.put("cN", "Ņ"); // "Ncedil"
- HTMLCHARS.put("cn", "ņ"); // "ncedil"
- HTMLCHARS.put("vN", "Ň"); // "Ncaron"
- HTMLCHARS.put("vn", "ň"); // "ncaron"
- // Symbol #329 (�n) has no special Latex command
- HTMLCHARS.put("NG", "Ŋ"); // "ENG"
- HTMLCHARS.put("ng", "ŋ"); // "eng"
- HTMLCHARS.put("=O", "Ō"); // "Omacr"
- HTMLCHARS.put("=o", "ō"); // "omacr"
- HTMLCHARS.put("uO", "Ŏ"); // "Obreve"
- HTMLCHARS.put("uo", "ŏ"); // "obreve"
- HTMLCHARS.put("HO", "Ő"); // "Odblac"
- HTMLCHARS.put("Ho", "ő"); // "odblac"
- HTMLCHARS.put("OE", "Œ"); // "OElig"
- HTMLCHARS.put("oe", "œ"); // "oelig"
- HTMLCHARS.put("'R", "Ŕ"); // "Racute"
- HTMLCHARS.put("'r", "ŕ"); // "racute"
- HTMLCHARS.put("cR", "Ŗ"); // "Rcedil"
- HTMLCHARS.put("cr", "ŗ"); // "rcedil"
- HTMLCHARS.put("vR", "Ř"); // "Rcaron"
- HTMLCHARS.put("vr", "ř"); // "rcaron"
- HTMLCHARS.put("'S", "Ś"); // "Sacute"
- HTMLCHARS.put("'s", "ś"); // "sacute"
- HTMLCHARS.put("^S", "Ŝ"); // "Scirc"
- HTMLCHARS.put("^s", "ŝ"); // "scirc"
- HTMLCHARS.put("cS", "Ş"); // "Scedil"
- HTMLCHARS.put("cs", "ş"); // "scedil"
- HTMLCHARS.put("vS", "Š"); // "Scaron"
- HTMLCHARS.put("vs", "š"); // "scaron"
- HTMLCHARS.put("cT", "Ţ"); // "Tcedil"
- HTMLCHARS.put("ct", "ţ"); // "tcedil"
- HTMLCHARS.put("vT", "Ť"); // "Tcaron"
- // Symbol #357 (t�) has no special Latex command
- HTMLCHARS.put("Tstrok", "Ŧ"); // "Tstrok"
- HTMLCHARS.put("tstrok", "ŧ"); // "tstrok"
- HTMLCHARS.put("~U", "Ũ"); // "Utilde"
- HTMLCHARS.put("~u", "ũ"); // "utilde"
- HTMLCHARS.put("=U", "Ū"); // "Umacr"
- HTMLCHARS.put("=u", "ū"); // "umacr"
- HTMLCHARS.put("uU", "Ŭ"); // "Ubreve"
- HTMLCHARS.put("uu", "ŭ"); // "ubreve"
- HTMLCHARS.put("rU", "Ů"); // "Uring"
- HTMLCHARS.put("ru", "ů"); // "uring"
- HTMLCHARS.put("HU", "Ű"); // "Odblac"
- HTMLCHARS.put("Hu", "ű"); // "odblac"
- HTMLCHARS.put("kU", "Ų"); // "Uogon"
- HTMLCHARS.put("ku", "ų"); // "uogon"
- HTMLCHARS.put("^W", "Ŵ"); // "Wcirc"
- HTMLCHARS.put("^w", "ŵ"); // "wcirc"
- HTMLCHARS.put("^Y", "Ŷ"); // "Ycirc"
- HTMLCHARS.put("^y", "ŷ"); // "ycirc"
- HTMLCHARS.put("\"Y", "Ÿ"); // "Yuml"
- HTMLCHARS.put("'Z", "Ź"); // "Zacute"
- HTMLCHARS.put("'z", "ź"); // "zacute"
- HTMLCHARS.put(".Z", "Ż"); // "Zdot"
- HTMLCHARS.put(".z", "ż"); // "zdot"
- HTMLCHARS.put("vZ", "Ž"); // "Zcaron"
- HTMLCHARS.put("vz", "ž"); // "zcaron"
- // Symbol #383 (f) has no special Latex command
-
-
- XML_CHARS.put("\\{\\\\\\\"\\{a\\}\\}", "ä");
- XML_CHARS.put("\\{\\\\\\\"\\{A\\}\\}", "Ä");
- XML_CHARS.put("\\{\\\\\\\"\\{e\\}\\}", "ë");
- XML_CHARS.put("\\{\\\\\\\"\\{E\\}\\}", "Ë");
- XML_CHARS.put("\\{\\\\\\\"\\{i\\}\\}", "ï");
- XML_CHARS.put("\\{\\\\\\\"\\{I\\}\\}", "Ï");
- XML_CHARS.put("\\{\\\\\\\"\\{o\\}\\}", "ö");
- XML_CHARS.put("\\{\\\\\\\"\\{O\\}\\}", "Ö");
- XML_CHARS.put("\\{\\\\\\\"\\{u\\}\\}", "ü");
- XML_CHARS.put("\\{\\\\\\\"\\{U\\}\\}", "Ü");
-
- XML_CHARS.put("\\{\\\\\\`\\{e\\}\\}", "è");
- XML_CHARS.put("\\{\\\\\\`\\{E\\}\\}", "È");
- XML_CHARS.put("\\{\\\\\\`\\{i\\}\\}", "ì");
- XML_CHARS.put("\\{\\\\\\`\\{I\\}\\}", "Ì");
- XML_CHARS.put("\\{\\\\\\`\\{o\\}\\}", "ò");
- XML_CHARS.put("\\{\\\\\\`\\{O\\}\\}", "Ò");
- XML_CHARS.put("\\{\\\\\\`\\{u\\}\\}", "ù");
- XML_CHARS.put("\\{\\\\\\`\\{U\\}\\}", "Ù");
- XML_CHARS.put("\\{\\\\\\'\\{e\\}\\}", "é");
- XML_CHARS.put("\\{\\\\\\\uFFFD\\{E\\}\\}", "É");
- XML_CHARS.put("\\{\\\\\\\uFFFD\\{i\\}\\}", "í");
- XML_CHARS.put("\\{\\\\\\\uFFFD\\{I\\}\\}", "Í");
- XML_CHARS.put("\\{\\\\\\\uFFFD\\{o\\}\\}", "ó");
- XML_CHARS.put("\\{\\\\\\\uFFFD\\{O\\}\\}", "Ó");
- XML_CHARS.put("\\{\\\\\\\uFFFD\\{u\\}\\}", "ú");
- XML_CHARS.put("\\{\\\\\\\uFFFD\\{U\\}\\}", "Ú");
- XML_CHARS.put("\\{\\\\\\\uFFFD\\{a\\}\\}", "á");
- XML_CHARS.put("\\{\\\\\\\uFFFD\\{A\\}\\}", "Á");
-
- XML_CHARS.put("\\{\\\\\\^\\{o\\}\\}", "ô");
- XML_CHARS.put("\\{\\\\\\^\\{O\\}\\}", "Ô");
- XML_CHARS.put("\\{\\\\\\^\\{u\\}\\}", "ù");
- XML_CHARS.put("\\{\\\\\\^\\{U\\}\\}", "Ù");
- XML_CHARS.put("\\{\\\\\\^\\{e\\}\\}", "ê");
- XML_CHARS.put("\\{\\\\\\^\\{E\\}\\}", "Ê");
- XML_CHARS.put("\\{\\\\\\^\\{i\\}\\}", "î");
- XML_CHARS.put("\\{\\\\\\^\\{I\\}\\}", "Î");
- XML_CHARS.put("\\{\\\\\\~\\{o\\}\\}", "õ");
- XML_CHARS.put("\\{\\\\\\~\\{O\\}\\}", "Õ");
- XML_CHARS.put("\\{\\\\\\~\\{n\\}\\}", "ñ");
- XML_CHARS.put("\\{\\\\\\~\\{N\\}\\}", "Ñ");
- XML_CHARS.put("\\{\\\\\\~\\{a\\}\\}", "ã");
- XML_CHARS.put("\\{\\\\\\~\\{A\\}\\}", "Ã");
-
-
- XML_CHARS.put("\\{\\\\\\\"a\\}", "ä");
- XML_CHARS.put("\\{\\\\\\\"A\\}", "Ä");
- XML_CHARS.put("\\{\\\\\\\"e\\}", "ë");
- XML_CHARS.put("\\{\\\\\\\"E\\}", "Ë");
- XML_CHARS.put("\\{\\\\\\\"i\\}", "ï");
- XML_CHARS.put("\\{\\\\\\\"I\\}", "Ï");
- XML_CHARS.put("\\{\\\\\\\"o\\}", "ö");
- XML_CHARS.put("\\{\\\\\\\"O\\}", "Ö");
- XML_CHARS.put("\\{\\\\\\\"u\\}", "ü");
- XML_CHARS.put("\\{\\\\\\\"U\\}", "Ü");
-
- XML_CHARS.put("\\{\\\\\\`e\\}", "è");
- XML_CHARS.put("\\{\\\\\\`E\\}", "È");
- XML_CHARS.put("\\{\\\\\\`i\\}", "ì");
- XML_CHARS.put("\\{\\\\\\`I\\}", "Ì");
- XML_CHARS.put("\\{\\\\\\`o\\}", "ò");
- XML_CHARS.put("\\{\\\\\\`O\\}", "Ò");
- XML_CHARS.put("\\{\\\\\\`u\\}", "ù");
- XML_CHARS.put("\\{\\\\\\`U\\}", "Ù");
- XML_CHARS.put("\\{\\\\\\'e\\}", "é");
- XML_CHARS.put("\\{\\\\\\'E\\}", "É");
- XML_CHARS.put("\\{\\\\\\'i\\}", "í");
- XML_CHARS.put("\\{\\\\\\'I\\}", "Í");
- XML_CHARS.put("\\{\\\\\\'o\\}", "ó");
- XML_CHARS.put("\\{\\\\\\'O\\}", "Ó");
- XML_CHARS.put("\\{\\\\\\'u\\}", "ú");
- XML_CHARS.put("\\{\\\\\\'U\\}", "Ú");
- XML_CHARS.put("\\{\\\\\\'a\\}", "á");
- XML_CHARS.put("\\{\\\\\\'A\\}", "Á");
-
- XML_CHARS.put("\\{\\\\\\^a\\}", "ô");
- XML_CHARS.put("\\{\\\\\\^A\\}", "Ô");
- XML_CHARS.put("\\{\\\\\\^o\\}", "ô");
- XML_CHARS.put("\\{\\\\\\^O\\}", "Ô");
- XML_CHARS.put("\\{\\\\\\^u\\}", "ù");
- XML_CHARS.put("\\{\\\\\\^U\\}", "Ù");
- XML_CHARS.put("\\{\\\\\\^e\\}", "ê");
- XML_CHARS.put("\\{\\\\\\^E\\}", "Ê");
- XML_CHARS.put("\\{\\\\\\^i\\}", "î");
- XML_CHARS.put("\\{\\\\\\^I\\}", "Î");
- XML_CHARS.put("\\{\\\\\\~o\\}", "õ");
- XML_CHARS.put("\\{\\\\\\~O\\}", "Õ");
- XML_CHARS.put("\\{\\\\\\~n\\}", "ñ");
- XML_CHARS.put("\\{\\\\\\~N\\}", "Ñ");
- XML_CHARS.put("\\{\\\\\\~a\\}", "ã");
- XML_CHARS.put("\\{\\\\\\~A\\}", "Ã");
-
- ASCII2XML_CHARS.put("<", "<");
- ASCII2XML_CHARS.put("\"", """);
- ASCII2XML_CHARS.put(">", ">");
-
-
- UNICODE_CHARS.put("\u00C0", "A");
- UNICODE_CHARS.put("\u00C1", "A");
- UNICODE_CHARS.put("\u00C2", "A");
- UNICODE_CHARS.put("\u00C3", "A");
- UNICODE_CHARS.put("\u00C4", "A");
- UNICODE_CHARS.put("\u00C5", "Aa");
- UNICODE_CHARS.put("\u00C6", "Ae");
- UNICODE_CHARS.put("\u00C7", "C");
- UNICODE_CHARS.put("\u00C8", "E");
- UNICODE_CHARS.put("\u00C9", "E");
- UNICODE_CHARS.put("\u00CA", "E");
- UNICODE_CHARS.put("\u00CB", "E");
- UNICODE_CHARS.put("\u00CC", "I");
- UNICODE_CHARS.put("\u00CD", "I");
- UNICODE_CHARS.put("\u00CE", "I");
- UNICODE_CHARS.put("\u00CF", "I");
- UNICODE_CHARS.put("\u00D0", "D");
- UNICODE_CHARS.put("\u00D1", "N");
- UNICODE_CHARS.put("\u00D2", "O");
- UNICODE_CHARS.put("\u00D3", "O");
- UNICODE_CHARS.put("\u00D4", "O");
- UNICODE_CHARS.put("\u00D5", "O");
- UNICODE_CHARS.put("\u00D6", "Oe");
- UNICODE_CHARS.put("\u00D8", "Oe");
- UNICODE_CHARS.put("\u00D9", "U");
- UNICODE_CHARS.put("\u00DA", "U");
- UNICODE_CHARS.put("\u00DB", "U");
- UNICODE_CHARS.put("\u00DC", "Ue"); // U umlaut ..
- UNICODE_CHARS.put("\u00DD", "Y");
- UNICODE_CHARS.put("\u00DF", "ss");
- UNICODE_CHARS.put("\u00E0", "a");
- UNICODE_CHARS.put("\u00E1", "a");
- UNICODE_CHARS.put("\u00E2", "a");
- UNICODE_CHARS.put("\u00E3", "a");
- UNICODE_CHARS.put("\u00E4", "ae");
- UNICODE_CHARS.put("\u00E5", "aa");
- UNICODE_CHARS.put("\u00E6", "ae");
- UNICODE_CHARS.put("\u00E7", "c");
- UNICODE_CHARS.put("\u00E8", "e");
- UNICODE_CHARS.put("\u00E9", "e");
- UNICODE_CHARS.put("\u00EA", "e");
- UNICODE_CHARS.put("\u00EB", "e");
- UNICODE_CHARS.put("\u00EC", "i");
- UNICODE_CHARS.put("\u00ED", "i");
- UNICODE_CHARS.put("\u00EE", "i");
- UNICODE_CHARS.put("\u00EF", "i");
- UNICODE_CHARS.put("\u00F0", "o");
- UNICODE_CHARS.put("\u00F1", "n");
- UNICODE_CHARS.put("\u00F2", "o");
- UNICODE_CHARS.put("\u00F3", "o");
- UNICODE_CHARS.put("\u00F4", "o");
- UNICODE_CHARS.put("\u00F5", "o");
- UNICODE_CHARS.put("\u00F6", "oe");
- UNICODE_CHARS.put("\u00F8", "oe");
- UNICODE_CHARS.put("\u00F9", "u");
- UNICODE_CHARS.put("\u00FA", "u");
- UNICODE_CHARS.put("\u00FB", "u");
- UNICODE_CHARS.put("\u00FC", "ue"); // u umlaut...
- UNICODE_CHARS.put("\u00FD", "y");
- UNICODE_CHARS.put("\u00FF", "y");
- UNICODE_CHARS.put("\u0100", "A");
- UNICODE_CHARS.put("\u0101", "a");
- UNICODE_CHARS.put("\u0102", "A");
- UNICODE_CHARS.put("\u0103", "a");
- UNICODE_CHARS.put("\u0104", "A");
- UNICODE_CHARS.put("\u0105", "a");
- UNICODE_CHARS.put("\u0106", "C");
- UNICODE_CHARS.put("\u0107", "c");
- UNICODE_CHARS.put("\u0108", "C");
- UNICODE_CHARS.put("\u0109", "c");
- UNICODE_CHARS.put("\u010A", "C");
- UNICODE_CHARS.put("\u010B", "c");
- UNICODE_CHARS.put("\u010C", "C");
- UNICODE_CHARS.put("\u010D", "c");
- UNICODE_CHARS.put("\u010E", "D");
- UNICODE_CHARS.put("\u010F", "d");
- UNICODE_CHARS.put("\u0110", "D");
- UNICODE_CHARS.put("\u0111", "d");
- UNICODE_CHARS.put("\u0112", "E");
- UNICODE_CHARS.put("\u0113", "e");
- UNICODE_CHARS.put("\u0114", "E");
- UNICODE_CHARS.put("\u0115", "e");
- UNICODE_CHARS.put("\u0116", "E");
- UNICODE_CHARS.put("\u0117", "e");
- UNICODE_CHARS.put("\u0118", "E");
- UNICODE_CHARS.put("\u0119", "e");
- UNICODE_CHARS.put("\u011A", "E");
- UNICODE_CHARS.put("\u011B", "e");
- UNICODE_CHARS.put("\u011C", "G");
- UNICODE_CHARS.put("\u011D", "g");
- UNICODE_CHARS.put("\u011E", "G");
- UNICODE_CHARS.put("\u011F", "g");
- UNICODE_CHARS.put("\u0120", "G");
- UNICODE_CHARS.put("\u0121", "g");
- UNICODE_CHARS.put("\u0122", "G");
- UNICODE_CHARS.put("\u0123", "g");
- UNICODE_CHARS.put("\u0124", "H");
- UNICODE_CHARS.put("\u0125", "h");
- UNICODE_CHARS.put("\u0127", "h");
- UNICODE_CHARS.put("\u0128", "I");
- UNICODE_CHARS.put("\u0129", "i");
- UNICODE_CHARS.put("\u012A", "I");
- UNICODE_CHARS.put("\u012B", "i");
- UNICODE_CHARS.put("\u012C", "I");
- UNICODE_CHARS.put("\u012D", "i");
- //UNICODE_CHARS.put("\u0100", "");
-
- RTFCHARS.put("`a", "\\'e0");
- RTFCHARS.put("`e", "\\'e8");
- RTFCHARS.put("`i", "\\'ec");
- RTFCHARS.put("`o", "\\'f2");
- RTFCHARS.put("`u", "\\'f9");
- RTFCHARS.put("?a", "\\'e1");
- RTFCHARS.put("?e", "\\'e9");
- RTFCHARS.put("?i", "\\'ed");
- RTFCHARS.put("?o", "\\'f3");
- RTFCHARS.put("?u", "\\'fa");
- RTFCHARS.put("^a", "\\'e2");
- RTFCHARS.put("^e", "\\'ea");
- RTFCHARS.put("^i", "\\'ee");
- RTFCHARS.put("^o", "\\'f4");
- RTFCHARS.put("^u", "\\'fa");
- RTFCHARS.put("\"a", "\\'e4");
- RTFCHARS.put("\"e", "\\'eb");
- RTFCHARS.put("\"i", "\\'ef");
- RTFCHARS.put("\"o", "\\'f6");
- RTFCHARS.put("\"u", "\\uc0\\u252");
- RTFCHARS.put("~n", "\\'f1");
- RTFCHARS.put("`A", "\\'c0");
- RTFCHARS.put("`E", "\\'c8");
- RTFCHARS.put("`I", "\\'cc");
- RTFCHARS.put("`O", "\\'d2");
- RTFCHARS.put("`U", "\\'d9");
- RTFCHARS.put("?A", "\\'c1");
- RTFCHARS.put("?E", "\\'c9");
- RTFCHARS.put("?I", "\\'cd");
- RTFCHARS.put("?O", "\\'d3");
- RTFCHARS.put("?U", "\\'da");
- RTFCHARS.put("^A", "\\'c2");
- RTFCHARS.put("^E", "\\'ca");
- RTFCHARS.put("^I", "\\'ce");
- RTFCHARS.put("^O", "\\'d4");
- RTFCHARS.put("^U", "\\'db");
- RTFCHARS.put("\"A", "\\'c4");
- RTFCHARS.put("\"E", "\\'cb");
- RTFCHARS.put("\"I", "\\'cf");
- RTFCHARS.put("\"O", "\\'d6");
- RTFCHARS.put("\"U", "\\'dc");
- // Use UNICODE characters for RTF-Chars which can not be found in the standard codepage
-
- // RTFCHARS.put("`A", "\\uc0\\u192"); // "Agrave" exists in standard codepage
- RTFCHARS.put("'A", "\\uc0\\u193"); // "Aacute"
-// RTFCHARS.put("^A", "\\uc0\\u194"); // "Acirc" exists in standard codepage
- RTFCHARS.put("~A", "\\uc0\\u195"); // "Atilde"
-// RTFCHARS.put("\"A", "\\uc0\\u196"); // "Auml" exists in standard codepage
- RTFCHARS.put("AA", "\\uc0\\u197"); // "Aring"
- RTFCHARS.put("AE", "\\uc0\\u198"); // "AElig"
- RTFCHARS.put("cC", "\\uc0\\u199"); // "Ccedil"
-// RTFCHARS.put("`E", "\\uc0\\u200"); // "Egrave" exists in standard codepage
- RTFCHARS.put("'E", "\\uc0\\u201"); // "Eacute"
-// RTFCHARS.put("^E", "\\uc0\\u202"); // "Ecirc" exists in standard codepage
-// RTFCHARS.put("\"E", "\\uc0\\u203"); // "Euml" exists in standard codepage
-// RTFCHARS.put("`I", "\\uc0\\u204"); // "Igrave" exists in standard codepage
- RTFCHARS.put("'I", "\\uc0\\u205"); // "Iacute"
-// RTFCHARS.put("^I", "\\uc0\\u206"); // "Icirc" exists in standard codepage
-// RTFCHARS.put("\"I", "\\uc0\\u207"); // "Iuml" exists in standard codepage
- RTFCHARS.put("DH", "\\uc0\\u208"); // "ETH"
- RTFCHARS.put("~N", "\\uc0\\u209"); // "Ntilde"
-// RTFCHARS.put("`O", "\\uc0\\u210"); // "Ograve" exists in standard codepage
- RTFCHARS.put("'O", "\\uc0\\u211"); // "Oacute"
-// RTFCHARS.put("^O", "\\uc0\\u212"); // "Ocirc" exists in standard codepage
- RTFCHARS.put("~O", "\\uc0\\u213"); // "Otilde"
-// RTFCHARS.put("\"O", "\\uc0\\u214"); // "Ouml" exists in standard codepage
- // According to ISO 8859-1 the "\times" symbol should be placed here (#215).
- // Omitting this, because it is a mathematical symbol.
- RTFCHARS.put("O", "\\uc0\\u216"); // "OSlash"
-// RTFCHARS.put("`U", "\\uc0\\u217"); // "Ugrave" exists in standard codepage
- RTFCHARS.put("'U", "\\uc0\\u218"); // "Uacute"
-// RTFCHARS.put("^U", "\\uc0\\u219"); // "Ucirc" exists in standard codepage
-// RTFCHARS.put("\"U", "\\uc0\\u220"); // "Uuml" exists in standard codepage
- RTFCHARS.put("'Y", "\\uc0\\u221"); // "Yacute"
- RTFCHARS.put("TH", "\\uc0\\u222"); // "THORN"
- RTFCHARS.put("ss", "\\uc0\\u223"); // "szlig"
-// RTFCHARS.put("`a", "\\uc0\\u224"); // "agrave" exists in standard codepage
- RTFCHARS.put("'a", "\\uc0\\u225"); // "aacute"
-// RTFCHARS.put("^a", "\\uc0\\u226"); // "acirc" exists in standard codepage
- RTFCHARS.put("~a", "\\uc0\\u227"); // "atilde"
-// RTFCHARS.put("\"a", "\\uc0\\u228"); // "auml" exists in standard codepage
- RTFCHARS.put("aa", "\\uc0\\u229"); // "aring"
- RTFCHARS.put("ae", "\\uc0\\u230"); // "aelig"
- RTFCHARS.put("cc", "\\uc0\\u231"); // "ccedil"
-// RTFCHARS.put("`e", "\\uc0\\u232"); // "egrave" exists in standard codepage
- RTFCHARS.put("'e", "\\uc0\\u233"); // "eacute"
-// RTFCHARS.put("^e", "\\uc0\\u234"); // "ecirc" exists in standard codepage
-// RTFCHARS.put("\"e", "\\uc0\\u235"); // "euml" exists in standard codepage
-// RTFCHARS.put("`i", "\\uc0\\u236"); // "igrave" exists in standard codepage
- RTFCHARS.put("'i", "\\uc0\\u237"); // "iacute"
-// RTFCHARS.put("^i", "\\uc0\\u238"); // "icirc" exists in standard codepage
-// RTFCHARS.put("\"i", "\\uc0\\u239"); // "iuml" exists in standard codepage
- RTFCHARS.put("dh", "\\uc0\\u240"); // "eth"
-// RTFCHARS.put("~n", "\\uc0\\u241"); // "ntilde" exists in standard codepage
-// RTFCHARS.put("`o", "\\uc0\\u242"); // "ograve" exists in standard codepage
- RTFCHARS.put("'o", "\\uc0\\u243"); // "oacute"
-// RTFCHARS.put("^o", "\\uc0\\u244"); // "ocirc" exists in standard codepage
- RTFCHARS.put("~o", "\\uc0\\u245"); // "otilde"
-// RTFCHARS.put("\"o", "\\uc0\\u246"); // "ouml" exists in standard codepage
- // According to ISO 8859-1 the "\div" symbol should be placed here (#247).
- // Omitting this, because it is a mathematical symbol.
- RTFCHARS.put("o", "\\uc0\\u248"); // "oslash"
-// RTFCHARS.put("`u", "\\uc0\\u249"); // "ugrave" exists in standard codepage
- RTFCHARS.put("'u", "\\uc0\\u250"); // "uacute"
-// RTFCHARS.put("^u", "\\uc0\\u251"); // "ucirc" exists in standard codepage
-// RTFCHARS.put("\"u", "\\uc0\\u252"); // "uuml" exists in standard codepage
- RTFCHARS.put("'y", "\\uc0\\u253"); // "yacute"
- RTFCHARS.put("th", "\\uc0\\u254"); // "thorn"
- RTFCHARS.put("\"y", "\\uc0\\u255"); // "yuml"
-
- RTFCHARS.put("=A", "\\uc0\\u256"); // "Amacr"
- RTFCHARS.put("=a", "\\uc0\\u257"); // "amacr"
- RTFCHARS.put("uA", "\\uc0\\u258"); // "Abreve"
- RTFCHARS.put("ua", "\\uc0\\u259"); // "abreve"
- RTFCHARS.put("kA", "\\uc0\\u260"); // "Aogon"
- RTFCHARS.put("ka", "\\uc0\\u261"); // "aogon"
- RTFCHARS.put("'C", "\\uc0\\u262"); // "Cacute"
- RTFCHARS.put("'c", "\\uc0\\u263"); // "cacute"
- RTFCHARS.put("^C", "\\uc0\\u264"); // "Ccirc"
- RTFCHARS.put("^c", "\\uc0\\u265"); // "ccirc"
- RTFCHARS.put(".C", "\\uc0\\u266"); // "Cdot"
- RTFCHARS.put(".c", "\\uc0\\u267"); // "cdot"
- RTFCHARS.put("vC", "\\uc0\\u268"); // "Ccaron"
- RTFCHARS.put("vc", "\\uc0\\u269"); // "ccaron"
- RTFCHARS.put("vD", "\\uc0\\u270"); // "Dcaron"
- // Symbol #271 (d�) has no special Latex command
- RTFCHARS.put("DJ", "\\uc0\\u272"); // "Dstrok"
- RTFCHARS.put("dj", "\\uc0\\u273"); // "dstrok"
- RTFCHARS.put("=E", "\\uc0\\u274"); // "Emacr"
- RTFCHARS.put("=e", "\\uc0\\u275"); // "emacr"
- RTFCHARS.put("uE", "\\uc0\\u276"); // "Ebreve"
- RTFCHARS.put("ue", "\\uc0\\u277"); // "ebreve"
- RTFCHARS.put(".E", "\\uc0\\u278"); // "Edot"
- RTFCHARS.put(".e", "\\uc0\\u279"); // "edot"
- RTFCHARS.put("kE", "\\uc0\\u280"); // "Eogon"
- RTFCHARS.put("ke", "\\uc0\\u281"); // "eogon"
- RTFCHARS.put("vE", "\\uc0\\u282"); // "Ecaron"
- RTFCHARS.put("ve", "\\uc0\\u283"); // "ecaron"
- RTFCHARS.put("^G", "\\uc0\\u284"); // "Gcirc"
- RTFCHARS.put("^g", "\\uc0\\u285"); // "gcirc"
- RTFCHARS.put("uG", "\\uc0\\u286"); // "Gbreve"
- RTFCHARS.put("ug", "\\uc0\\u287"); // "gbreve"
- RTFCHARS.put(".G", "\\uc0\\u288"); // "Gdot"
- RTFCHARS.put(".g", "\\uc0\\u289"); // "gdot"
- RTFCHARS.put("cG", "\\uc0\\u290"); // "Gcedil"
- RTFCHARS.put("'g", "\\uc0\\u291"); // "gacute"
- RTFCHARS.put("^H", "\\uc0\\u292"); // "Hcirc"
- RTFCHARS.put("^h", "\\uc0\\u293"); // "hcirc"
- RTFCHARS.put("Hstrok", "\\uc0\\u294"); // "Hstrok"
- RTFCHARS.put("hstrok", "\\uc0\\u295"); // "hstrok"
- RTFCHARS.put("~I", "\\uc0\\u296"); // "Itilde"
- RTFCHARS.put("~i", "\\uc0\\u297"); // "itilde"
- RTFCHARS.put("=I", "\\uc0\\u298"); // "Imacr"
- RTFCHARS.put("=i", "\\uc0\\u299"); // "imacr"
- RTFCHARS.put("uI", "\\uc0\\u300"); // "Ibreve"
- RTFCHARS.put("ui", "\\uc0\\u301"); // "ibreve"
- RTFCHARS.put("kI", "\\uc0\\u302"); // "Iogon"
- RTFCHARS.put("ki", "\\uc0\\u303"); // "iogon"
- RTFCHARS.put(".I", "\\uc0\\u304"); // "Idot"
- RTFCHARS.put("i", "\\uc0\\u305"); // "inodot"
- // Symbol #306 (IJ) has no special Latex command
- // Symbol #307 (ij) has no special Latex command
- RTFCHARS.put("^J", "\\uc0\\u308"); // "Jcirc"
- RTFCHARS.put("^j", "\\uc0\\u309"); // "jcirc"
- RTFCHARS.put("cK", "\\uc0\\u310"); // "Kcedil"
- RTFCHARS.put("ck", "\\uc0\\u311"); // "kcedil"
- // Symbol #312 (k) has no special Latex command
- RTFCHARS.put("'L", "\\uc0\\u313"); // "Lacute"
- RTFCHARS.put("'l", "\\uc0\\u314"); // "lacute"
- RTFCHARS.put("cL", "\\uc0\\u315"); // "Lcedil"
- RTFCHARS.put("cl", "\\uc0\\u316"); // "lcedil"
- // Symbol #317 (L�) has no special Latex command
- // Symbol #318 (l�) has no special Latex command
- RTFCHARS.put("Lmidot", "\\uc0\\u319"); // "Lmidot"
- RTFCHARS.put("lmidot", "\\uc0\\u320"); // "lmidot"
- RTFCHARS.put("L", "\\uc0\\u321"); // "Lstrok"
- RTFCHARS.put("l", "\\uc0\\u322"); // "lstrok"
- RTFCHARS.put("'N", "\\uc0\\u323"); // "Nacute"
- RTFCHARS.put("'n", "\\uc0\\u324"); // "nacute"
- RTFCHARS.put("cN", "\\uc0\\u325"); // "Ncedil"
- RTFCHARS.put("cn", "\\uc0\\u326"); // "ncedil"
- RTFCHARS.put("vN", "\\uc0\\u327"); // "Ncaron"
- RTFCHARS.put("vn", "\\uc0\\u328"); // "ncaron"
- // Symbol #329 (�n) has no special Latex command
- RTFCHARS.put("NG", "\\uc0\\u330"); // "ENG"
- RTFCHARS.put("ng", "\\uc0\\u331"); // "eng"
- RTFCHARS.put("=O", "\\uc0\\u332"); // "Omacr"
- RTFCHARS.put("=o", "\\uc0\\u333"); // "omacr"
- RTFCHARS.put("uO", "\\uc0\\u334"); // "Obreve"
- RTFCHARS.put("uo", "\\uc0\\u335"); // "obreve"
- RTFCHARS.put("HO", "\\uc0\\u336"); // "Odblac"
- RTFCHARS.put("Ho", "\\uc0\\u337"); // "odblac"
- RTFCHARS.put("OE", "\\uc0\\u338"); // "OElig"
- RTFCHARS.put("oe", "\\uc0\\u339"); // "oelig"
- RTFCHARS.put("'R", "\\uc0\\u340"); // "Racute"
- RTFCHARS.put("'r", "\\uc0\\u341"); // "racute"
- RTFCHARS.put("cR", "\\uc0\\u342"); // "Rcedil"
- RTFCHARS.put("cr", "\\uc0\\u343"); // "rcedil"
- RTFCHARS.put("vR", "\\uc0\\u344"); // "Rcaron"
- RTFCHARS.put("vr", "\\uc0\\u345"); // "rcaron"
- RTFCHARS.put("'S", "\\uc0\\u346"); // "Sacute"
- RTFCHARS.put("'s", "\\uc0\\u347"); // "sacute"
- RTFCHARS.put("^S", "\\uc0\\u348"); // "Scirc"
- RTFCHARS.put("^s", "\\uc0\\u349"); // "scirc"
- RTFCHARS.put("cS", "\\uc0\\u350"); // "Scedil"
- RTFCHARS.put("cs", "\\uc0\\u351"); // "scedil"
- RTFCHARS.put("vS", "\\uc0\\u352"); // "Scaron"
- RTFCHARS.put("vs", "\\uc0\\u353"); // "scaron"
- RTFCHARS.put("cT", "\\uc0\\u354"); // "Tcedil"
- RTFCHARS.put("ct", "\\uc0\\u355"); // "tcedil"
- RTFCHARS.put("vT", "\\uc0\\u356"); // "Tcaron"
- // Symbol #357 (t�) has no special Latex command
- RTFCHARS.put("Tstrok", "\\uc0\\u358"); // "Tstrok"
- RTFCHARS.put("tstrok", "\\uc0\\u359"); // "tstrok"
- RTFCHARS.put("~U", "\\uc0\\u360"); // "Utilde"
- RTFCHARS.put("~u", "\\uc0\\u361"); // "utilde"
- RTFCHARS.put("=U", "\\uc0\\u362"); // "Umacr"
- RTFCHARS.put("=u", "\\uc0\\u363"); // "umacr"
- RTFCHARS.put("uU", "\\uc0\\u364"); // "Ubreve"
- RTFCHARS.put("uu", "\\uc0\\u365"); // "ubreve"
- RTFCHARS.put("rU", "\\uc0\\u366"); // "Uring"
- RTFCHARS.put("ru", "\\uc0\\u367"); // "uring"
- RTFCHARS.put("HU", "\\uc0\\u368"); // "Odblac"
- RTFCHARS.put("Hu", "\\uc0\\u369"); // "odblac"
- RTFCHARS.put("kU", "\\uc0\\u370"); // "Uogon"
- RTFCHARS.put("ku", "\\uc0\\u371"); // "uogon"
- RTFCHARS.put("^W", "\\uc0\\u372"); // "Wcirc"
- RTFCHARS.put("^w", "\\uc0\\u373"); // "wcirc"
- RTFCHARS.put("^Y", "\\uc0\\u374"); // "Ycirc"
- RTFCHARS.put("^y", "\\uc0\\u375"); // "ycirc"
- RTFCHARS.put("\"Y", "\\uc0\\u376"); // "Yuml"
- RTFCHARS.put("'Z", "\\uc0\\u377"); // "Zacute"
- RTFCHARS.put("'z", "\\uc0\\u378"); // "zacute"
- RTFCHARS.put(".Z", "\\uc0\\u379"); // "Zdot"
- RTFCHARS.put(".z", "\\uc0\\u380"); // "zdot"
- RTFCHARS.put("vZ", "\\uc0\\u381"); // "Zcaron"
- RTFCHARS.put("vz", "\\uc0\\u382"); // "zcaron"
- // Symbol #383 (f) has no special Latex command
-
- //XML_CHARS.put("\\u00E1", "á");
- }
-
- public static void initializeJournalNames() {
- journalAbbrev = new JournalAbbreviations();//"/resource/journalList.txt");
-
- // Read external lists, if any (in reverse order, so the upper lists override the lower):
- String[] lists = prefs.getStringArray("externalJournalLists");
- if ((lists != null) && (lists.length > 0)) {
- for (int i=lists.length-1; i>=0; i--) {
- try {
- journalAbbrev.readJournalList(new File(lists[i]));
- } catch (FileNotFoundException e) {
- // The file couldn't be found... should we tell anyone?
- Globals.logger(e.getMessage());
- }
- }
- }
-
- // Read personal list, if set up:
- if (prefs.get("personalJournalList") != null) {
- try {
- journalAbbrev.readJournalList(new File(prefs.get("personalJournalList")));
- } catch (FileNotFoundException e) {
- Globals.logger("Personal journal list file '"+prefs.get("personalJournalList")+
- "' not found.");
- }
- }
-
-
- }
+ public static int SHORTCUT_MASK,// =
+ // Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
+ FUTURE_YEAR = 2050, // Needs to give a year definitely in the future.
+ // Used for guessing the
+ // year field when parsing textual data. :-)
+
+ STANDARD_EXPORT_COUNT = 5, // The number of standard export formats.
+ METADATA_LINE_LENGTH = 70; // The line length used to wrap metadata.
+
+ private static String resourcePrefix = "resource/JabRef", menuResourcePrefix = "resource/Menu",
+ integrityResourcePrefix = "resource/IntegrityMessage";
+
+ private static final String buildInfos = "/resource/build.properties";
+
+ /*
+ * some extra field definitions
+ */
+ public static final String additionalFields = "/resource/fields/fields.xml";
+
+ public static ResourceBundle messages, menuTitles, intMessages;
+
+ public static FileUpdateMonitor fileUpdateMonitor = new FileUpdateMonitor();
+
+ public static ImportFormatReader importFormatReader = new ImportFormatReader();
+
+ public static ErrorConsole errorConsole;
+
+ public static String VERSION, BUILD, BUILD_DATE;
+
+ static {
+ TBuildInfo bi = new TBuildInfo(buildInfos);
+ VERSION = bi.getBUILD_VERSION();
+ BUILD = bi.getBUILD_NUMBER();
+ BUILD_DATE = bi.getBUILD_DATE();
+
+ // TODO: Error console initialization here. When should it be used?
+ errorConsole = ErrorConsole.getInstance();
+ }
+
+ // public static ResourceBundle preferences =
+ // ResourceBundle.getBundle("resource/defaultPrefs");
+ public static Locale locale;
+
+ public static final String FILETYPE_PREFS_EXT = "_dir", SELECTOR_META_PREFIX = "selector_",
+ LAYOUT_PREFIX = "/resource/layout/", MAC = "Mac OS X",
+ DOI_LOOKUP_PREFIX = "http://dx.doi.org/", NONE = "_non__",
+ FORMATTER_PACKAGE = "net.sf.jabref.export.layout.format.";
+
+ public static float duplicateThreshold = 0.75f;
+
+ private static Handler consoleHandler = new java.util.logging.ConsoleHandler();
+
+ public static String[] ENCODINGS, ALL_ENCODINGS = // (String[])
+ // Charset.availableCharsets().keySet().toArray(new
+ // String[]{});
+ new String[] { "ISO8859_1", "UTF8", "UTF-16", "ASCII", "Cp1250", "Cp1251", "Cp1252",
+ "Cp1253", "Cp1254", "Cp1257", "JIS", "SJIS",
+ "EUC_JP", // Added Japanese encodings.
+ "Big5", "Big5_HKSCS", "GBK", "ISO8859_2", "ISO8859_3", "ISO8859_4", "ISO8859_5",
+ "ISO8859_6", "ISO8859_7", "ISO8859_8", "ISO8859_9", "ISO8859_13", "ISO8859_15" };
+
+ // String array that maps from month number to month string label:
+ public static String[] MONTHS = new String[] { "jan", "feb", "mar", "apr", "may", "jun", "jul",
+ "aug", "sep", "oct", "nov", "dec" };
+
+ // Map that maps from month string labels to
+ public static Map MONTH_STRINGS = new HashMap();
+ static {
+ MONTH_STRINGS.put("jan", "January");
+ MONTH_STRINGS.put("feb", "February");
+ MONTH_STRINGS.put("mar", "March");
+ MONTH_STRINGS.put("apr", "April");
+ MONTH_STRINGS.put("may", "May");
+ MONTH_STRINGS.put("jun", "June");
+ MONTH_STRINGS.put("jul", "July");
+ MONTH_STRINGS.put("aug", "August");
+ MONTH_STRINGS.put("sep", "September");
+ MONTH_STRINGS.put("oct", "October");
+ MONTH_STRINGS.put("nov", "November");
+ MONTH_STRINGS.put("dec", "December");
+
+ // Build list of encodings, by filtering out all that are not supported
+ // on this system:
+ List encodings = new ArrayList();
+ for (int i = 0; i < ALL_ENCODINGS.length; i++) {
+ if (Charset.isSupported(ALL_ENCODINGS[i])) {
+ encodings.add(ALL_ENCODINGS[i]);
+ }
+ }
+ ENCODINGS = (String[]) encodings.toArray(new String[0]);
+
+ }
+
+ public static GlobalFocusListener focusListener = new GlobalFocusListener();
+
+ public static JabRefPreferences prefs = null;
+
+ public static HelpDialog helpDiag = null;
+
+ public static String osName = System.getProperty("os.name", "def");
+
+ public static boolean ON_MAC = (osName.equals(MAC)), ON_WIN = osName.startsWith("Windows");
+
+ public static String[] SKIP_WORDS = { "a", "an", "the", "for", "on" };
+
+ public static SidePaneManager sidePaneManager;
+
+ public static final String NEWLINE = System.getProperty("line.separator");
+
+ /**
+ * true if we have unix newlines
+ */
+ public static final boolean UNIX_NEWLINE = NEWLINE.equals("\n");
+
+ public static final String BIBTEX_STRING = "__string";
+
+ // "Fieldname" to indicate that a field should be treated as a bibtex
+ // string. Used when writing database to file.
+
+ public static void logger(String s) {
+ Logger.global.info(s);
+ }
+
+ public static void turnOffLogging() { // only log exceptions
+ Logger.global.setLevel(java.util.logging.Level.SEVERE);
+ }
+
+ // should be only called once
+ public static void turnOnConsoleLogging() {
+ Logger.global.addHandler(consoleHandler);
+
+ }
+
+ public static void turnOnFileLogging() {
+ Logger.global.setLevel(java.util.logging.Level.ALL);
+ java.util.logging.Handler handler;
+ handler = new ConsoleHandler();
+ /*
+ * try { handler = new FileHandler(logfile); // this will overwrite }
+ * catch (IOException e) { //can't open log file so use console
+ * e.printStackTrace(); }
+ */
+ Logger.global.addHandler(handler);
+
+ handler.setFilter(new Filter() { // select what gets logged
+ public boolean isLoggable(LogRecord record) {
+ return true;
+ }
+ });
+ }
+
+ public static void setLanguage(String language, String country) {
+ locale = new Locale(language, country);
+ messages = ResourceBundle.getBundle(resourcePrefix, locale);
+ menuTitles = ResourceBundle.getBundle(menuResourcePrefix, locale);
+ intMessages = ResourceBundle.getBundle(integrityResourcePrefix, locale);
+ Locale.setDefault(locale);
+ javax.swing.JComponent.setDefaultLocale(locale);
+ }
+
+ public static JournalAbbreviations journalAbbrev;
+
+ public static String lang(String key, String[] params) {
+ String translation = null;
+ try {
+ if (Globals.messages != null) {
+ translation = Globals.messages.getString(key.replaceAll(" ", "_"));
+ }
+ } catch (MissingResourceException ex) {
+ translation = key;
+
+ // Thread.dumpStack(); // For debugging
+ logger("Warning: could not get translation for \"" + key + "\"");
+ }
+ if ((translation != null) && (translation.length() != 0)) {
+ translation = translation.replaceAll("_", " ");
+ StringBuffer sb = new StringBuffer();
+ boolean b = false;
+ char c;
+ for (int i = 0; i < translation.length(); ++i) {
+ c = translation.charAt(i);
+ if (c == '%') {
+ b = true;
+ } else {
+ if (!b) {
+ sb.append(c);
+ } else {
+ b = false;
+ try {
+ int index = Integer.parseInt(String.valueOf(c));
+ if (params != null && index >= 0 && index <= params.length)
+ sb.append(params[index]);
+ } catch (NumberFormatException e) {
+ // append literally (for quoting) or insert special
+ // symbol
+ switch (c) {
+ case 'c': // colon
+ sb.append(':');
+ break;
+ case 'e': // equal
+ sb.append('=');
+ break;
+ default: // anything else, e.g. %
+ sb.append(c);
+ }
+ }
+ }
+ }
+ }
+ return sb.toString();
+ }
+ return key;
+ }
+
+ public static String lang(String key) {
+ return lang(key, (String[]) null);
+ }
+
+ public static String lang(String key, String s1) {
+ return lang(key, new String[] { s1 });
+ }
+
+ public static String lang(String key, String s1, String s2) {
+ return lang(key, new String[] { s1, s2 });
+ }
+
+ public static String lang(String key, String s1, String s2, String s3) {
+ return lang(key, new String[] { s1, s2, s3 });
+ }
+
+ public static String menuTitle(String key) {
+ String translation = null;
+ try {
+ if (Globals.messages != null) {
+ translation = Globals.menuTitles.getString(key.replaceAll(" ", "_"));
+ }
+ } catch (MissingResourceException ex) {
+ translation = key;
+
+ // System.err.println("Warning: could not get menu item translation
+ // for \""
+ // + key + "\"");
+
+ }
+ if ((translation != null) && (translation.length() != 0)) {
+ return translation.replaceAll("_", " ");
+ } else {
+ return key;
+ }
+ }
+
+ public static String getIntegrityMessage(String key) {
+ String translation = null;
+ try {
+ if (Globals.intMessages != null) {
+ translation = Globals.intMessages.getString(key);
+ }
+ } catch (MissingResourceException ex) {
+ translation = key;
+
+ // System.err.println("Warning: could not get menu item translation
+ // for \""
+ // + key + "\"");
+ }
+ if ((translation != null) && (translation.length() != 0)) {
+ return translation;
+ } else {
+ return key;
+ }
+ }
+
+ // ============================================================
+ // Using the hashmap of entry types found in BibtexEntryType
+ // ============================================================
+ public static BibtexEntryType getEntryType(String type) {
+ // decide which entryType object to return
+ Object o = BibtexEntryType.ALL_TYPES.get(type);
+ if (o != null) {
+ return (BibtexEntryType) o;
+ } else {
+ return BibtexEntryType.OTHER;
+ }
+ /*
+ * if(type.equals("article")) return BibtexEntryType.ARTICLE; else
+ * if(type.equals("book")) return BibtexEntryType.BOOK; else
+ * if(type.equals("inproceedings")) return
+ * BibtexEntryType.INPROCEEDINGS;
+ */
+ }
+
+ /**
+ * This method provides the correct opening brace to use when writing a
+ * field to BibTeX format.
+ *
+ * @return A String containing the braces to use.
+ */
+ public static String getOpeningBrace() {
+ return "{";
+ /*
+ * As of version 2.0, storing all fields with double braces is no longer
+ * supported, because it causes problems with e.g. the author field.
+ *
+ * if (prefs.getBoolean("autoDoubleBraces")) return "{{"; else return
+ * "{";
+ */
+ }
+
+ /**
+ * This method provides the correct closing brace to use when writing a
+ * field to BibTeX format.
+ *
+ * @return A String containing the braces to use.
+ */
+ public static String getClosingBrace() {
+ return "}";
+ /*
+ * As of version 2.0, storing all fields with double braces is no longer
+ * supported, because it causes problems with e.g. the author field.
+ *
+ * if (prefs.getBoolean("autoDoubleBraces")) return "}}"; else
+ */
+
+ }
+
+ /**
+ * Will return the names of multiple files selected in the given directory
+ * and the given extensions.
+ *
+ * Will return an empty String array if no entry is found.
+ *
+ * @param owner
+ * @param directory
+ * @param extension
+ * @param updateWorkingdirectory
+ * @return
+ */
+ public static String[] getMultipleFiles(JFrame owner, File directory, String extension,
+ boolean updateWorkingdirectory) {
+
+ OpenFileFilter off = null;
+ if (extension == null)
+ off = new OpenFileFilter();
+ else if (!extension.equals(NONE))
+ off = new OpenFileFilter(extension);
+
+ Object files = getNewFileImpl(owner, directory, extension, null, off,
+ JFileChooser.OPEN_DIALOG, updateWorkingdirectory, false, true);
+
+ if (files instanceof String[]) {
+ return (String[]) files;
+ }
+ // Fix for:
+ // http://sourceforge.net/tracker/index.php?func=detail&aid=1538769&group_id=92314&atid=600306
+ if (files != null) {
+ return new String[] { (String) files };
+ }
+ return new String[0];
+ }
+
+ public static String getNewFile(JFrame owner, File directory, String extension, int dialogType,
+ boolean updateWorkingDirectory) {
+ return getNewFile(owner, directory, extension, null, dialogType, updateWorkingDirectory,
+ false);
+ }
+
+ public static String getNewFile(JFrame owner, File directory, String extension,
+ String description, int dialogType, boolean updateWorkingDirectory) {
+ return getNewFile(owner, directory, extension, description, dialogType,
+ updateWorkingDirectory, false);
+ }
+
+ public static String getNewDir(JFrame owner, File directory, String extension, int dialogType,
+ boolean updateWorkingDirectory) {
+ return getNewFile(owner, directory, extension, null, dialogType, updateWorkingDirectory,
+ true);
+ }
+
+ public static String getNewDir(JFrame owner, File directory, String extension,
+ String description, int dialogType, boolean updateWorkingDirectory) {
+ return getNewFile(owner, directory, extension, description, dialogType,
+ updateWorkingDirectory, true);
+ }
+
+ private static String getNewFile(JFrame owner, File directory, String extension,
+ String description, int dialogType, boolean updateWorkingDirectory, boolean dirOnly) {
+
+ OpenFileFilter off = null;
+
+ if (extension == null)
+ off = new OpenFileFilter();
+ else if (!extension.equals(NONE))
+ off = new OpenFileFilter(extension);
+
+ return (String) getNewFileImpl(owner, directory, extension, description, off, dialogType,
+ updateWorkingDirectory, dirOnly, false);
+ }
+
+ private static Object getNewFileImpl(JFrame owner, File directory, String extension,
+ String description, OpenFileFilter off, int dialogType, boolean updateWorkingDirectory,
+ boolean dirOnly, boolean multipleSelection) {
+
+ if (ON_MAC && prefs.getBoolean("useNativeFileDialogOnMac")) {
+
+ return getNewFileForMac(owner, directory, extension, dialogType,
+ updateWorkingDirectory, dirOnly, off);
+ }
+
+ JFileChooser fc = null;
+ try {
+ fc = new JabRefFileChooser(directory);
+ } catch (InternalError errl) {
+ // This try/catch clause was added because a user reported an
+ // InternalError getting thrown on WinNT, presumably because of a
+ // bug in JGoodies Windows PLAF. This clause can be removed if the
+ // bug is fixed, but for now we just resort to the native file
+ // dialog, using the same method as is always used on Mac:
+ return getNewFileForMac(owner, directory, extension, dialogType,
+ updateWorkingDirectory, dirOnly, off);
+ }
+
+ if (dirOnly) {
+ fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
+
+ }
+
+ fc.setMultiSelectionEnabled(multipleSelection);
+
+ fc.addChoosableFileFilter(off);
+ fc.setDialogType(dialogType);
+ int dialogResult;
+ if (dialogType == JFileChooser.OPEN_DIALOG) {
+ dialogResult = fc.showOpenDialog(owner);
+ } else if (dialogType == JFileChooser.SAVE_DIALOG) {
+ dialogResult = fc.showSaveDialog(owner);
+ } else {
+ dialogResult = fc.showDialog(owner, description);
+ }
+
+ // the getSelectedFile method returns a valid fileselection
+ // (if something is selected) indepentently from dialog return status
+ if (dialogResult != JFileChooser.APPROVE_OPTION)
+ return null;
+
+ // okay button
+ File selectedFile = fc.getSelectedFile();
+ if (selectedFile == null) { // cancel
+ return null;
+ }
+
+ // If this is a save dialog, and the user has not chosen "All files" as
+ // filter
+ // we enforce the given extension. But only if extension is not null.
+ if ((extension != null) && (dialogType == JFileChooser.SAVE_DIALOG)
+ && (fc.getFileFilter() == off) && !off.accept(selectedFile)) {
+
+ // add the first extension if there are multiple extensions
+ selectedFile = new File(selectedFile.getPath() + extension.split("[, ]+", 0)[0]);
+ }
+
+ if (updateWorkingDirectory) {
+ prefs.put("workingDirectory", selectedFile.getPath());
+ }
+
+ if (!multipleSelection)
+ return selectedFile.getAbsolutePath();
+ else {
+ File[] files = fc.getSelectedFiles();
+ String[] filenames = new String[files.length];
+ for (int i = 0; i < files.length; i++)
+ filenames[i] = files[i].getAbsolutePath();
+ return filenames;
+ }
+ }
+
+ private static String getNewFileForMac(JFrame owner, File directory, String extensions,
+ int dialogType, boolean updateWorkingDirectory, boolean dirOnly, FilenameFilter filter) {
+
+ FileDialog fc = new FileDialog(owner);
+
+ // fc.setFilenameFilter(filter);
+ if (directory != null) {
+ fc.setDirectory(directory.getParent());
+ }
+ if (dialogType == JFileChooser.OPEN_DIALOG) {
+ fc.setMode(FileDialog.LOAD);
+ } else {
+ fc.setMode(FileDialog.SAVE);
+ }
+
+ fc.setVisible(true); // fc.show(); -> deprecated since 1.5
+
+ if (fc.getFile() != null) {
+ Globals.prefs.put("workingDirectory", fc.getDirectory() + fc.getFile());
+ return fc.getDirectory() + fc.getFile();
+ } else {
+ return null;
+ }
+ }
+
+ public static String SPECIAL_COMMAND_CHARS = "\"`^~'c";
+
+ public static HashMap HTML_CHARS = new HashMap(), HTMLCHARS = new HashMap(),
+ XML_CHARS = new HashMap(), ASCII2XML_CHARS = new HashMap(), UNICODE_CHARS = new HashMap(),
+ RTFCHARS = new HashMap(), URL_CHARS = new HashMap();
+ static {
+
+ // System.out.println(journalAbbrev.getAbbreviatedName("Journal of Fish
+ // Biology", true));
+ // System.out.println(journalAbbrev.getAbbreviatedName("Journal of Fish
+ // Biology", false));
+ // System.out.println(journalAbbrev.getFullName("Aquaculture Eng."));
+ /*
+ * for (Iterator i=journalAbbrev.fullNameIterator(); i.hasNext();) {
+ * String s = (String)i.next();
+ * System.out.println(journalAbbrev.getFullName(s)+" :
+ * "+journalAbbrev.getAbbreviatedName(s, true)); }
+ */
+
+ // Start the thread that monitors file time stamps.
+ // Util.pr("Starting FileUpdateMonitor thread. Globals line 293.");
+ fileUpdateMonitor.start();
+
+ try {
+ SHORTCUT_MASK = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
+ } catch (Throwable t) {
+
+ }
+
+ // Special characters in URLs need to be replaced to ensure that the URL
+ // opens properly on all platforms:
+ URL_CHARS.put("<", "%3c");
+ URL_CHARS.put(">", "%3e");
+ URL_CHARS.put("(", "%28");
+ URL_CHARS.put(")", "%29");
+ URL_CHARS.put(" ", "%20");
+ URL_CHARS.put("&", "%26");
+ URL_CHARS.put("$", "%24");
+
+ // HTMLCHARS.put("\"a", "ä");
+ // HTMLCHARS.put("\"A", "Ä");
+ // HTMLCHARS.put("\"e", "ë");
+ // HTMLCHARS.put("\"E", "Ë");
+ // HTMLCHARS.put("\"i", "ï");
+ // HTMLCHARS.put("\"I", "Ï");
+ // HTMLCHARS.put("\"o", "ö");
+ // HTMLCHARS.put("\"O", "Ö");
+ // HTMLCHARS.put("\"u", "ü");
+ // HTMLCHARS.put("\"U", "Ü");
+ // HTMLCHARS.put("`a", "à");
+ // HTMLCHARS.put("`A", "À");
+ // HTMLCHARS.put("`e", "è");
+ // HTMLCHARS.put("`E", "È");
+ // HTMLCHARS.put("`i", "ì");
+ // HTMLCHARS.put("`I", "Ì");
+ // HTMLCHARS.put("`o", "ò");
+ // HTMLCHARS.put("`O", "Ò");
+ // HTMLCHARS.put("`u", "ù");
+ // HTMLCHARS.put("`U", "Ù");
+ // HTMLCHARS.put("'e", "é");
+ // HTMLCHARS.put("'E", "É");
+ // HTMLCHARS.put("'i", "í");
+ // HTMLCHARS.put("'I", "Í");
+ // HTMLCHARS.put("'o", "ó");
+ // HTMLCHARS.put("'O", "Ó");
+ // HTMLCHARS.put("'u", "ú");
+ // HTMLCHARS.put("'U", "Ú");
+ // HTMLCHARS.put("'a", "á");
+ // HTMLCHARS.put("'A", "Á");
+ // HTMLCHARS.put("^a", "ô");
+ // HTMLCHARS.put("^A", "Ô");
+ // HTMLCHARS.put("^o", "ô");
+ // HTMLCHARS.put("^O", "Ô");
+ // HTMLCHARS.put("^u", "û");
+ // HTMLCHARS.put("^U", "Û");
+ // HTMLCHARS.put("^e", "ê");
+ // HTMLCHARS.put("^E", "Ê");
+ // HTMLCHARS.put("^i", "î");
+ // HTMLCHARS.put("^I", "Î");
+ // HTMLCHARS.put("~o", "õ");
+ // HTMLCHARS.put("~O", "Õ");
+ // HTMLCHARS.put("~n", "ñ");
+ // HTMLCHARS.put("~N", "Ñ");
+ // HTMLCHARS.put("~a", "ã");
+ // HTMLCHARS.put("~A", "Ã");
+ // HTMLCHARS.put("cc", "ç");
+ // HTMLCHARS.put("cC", "Ç");
+
+ // Following character definitions contributed by Ervin Kolenovic:
+ // HTML named entities from #192 - #255 (UNICODE Latin-1)
+ HTMLCHARS.put("`A", "À"); // #192
+ HTMLCHARS.put("'A", "Á"); // #193
+ HTMLCHARS.put("^A", "Â"); // #194
+ HTMLCHARS.put("~A", "Ã"); // #195
+ HTMLCHARS.put("\"A", "Ä"); // #196
+ HTMLCHARS.put("AA", "Å"); // #197
+ HTMLCHARS.put("AE", "Æ"); // #198
+ HTMLCHARS.put("cC", "Ç"); // #199
+ HTMLCHARS.put("`E", "È"); // #200
+ HTMLCHARS.put("'E", "É"); // #201
+ HTMLCHARS.put("^E", "Ê"); // #202
+ HTMLCHARS.put("\"E", "Ë"); // #203
+ HTMLCHARS.put("`I", "Ì"); // #204
+ HTMLCHARS.put("'I", "Í"); // #205
+ HTMLCHARS.put("^I", "Î"); // #206
+ HTMLCHARS.put("\"I", "Ï"); // #207
+ HTMLCHARS.put("DH", "Ð"); // #208
+ HTMLCHARS.put("~N", "Ñ"); // #209
+ HTMLCHARS.put("`O", "Ò"); // #210
+ HTMLCHARS.put("'O", "Ó"); // #211
+ HTMLCHARS.put("^O", "Ô"); // #212
+ HTMLCHARS.put("~O", "Õ"); // #213
+ HTMLCHARS.put("\"O", "Ö"); // #214
+ // According to ISO 8859-1 the "\times" symbol should be placed here
+ // (#215).
+ // Omitting this, because it is a mathematical symbol.
+ HTMLCHARS.put("O", "&OSlash;"); // #216
+ HTMLCHARS.put("`U", "Ù"); // #217
+ HTMLCHARS.put("'U", "Ú"); // #218
+ HTMLCHARS.put("^U", "Û"); // #219
+ HTMLCHARS.put("\"U", "Ü"); // #220
+ HTMLCHARS.put("'Y", "Ý"); // #221
+ HTMLCHARS.put("TH", "Þ"); // #222
+ HTMLCHARS.put("ss", "ß"); // #223
+ HTMLCHARS.put("`a", "à"); // #224
+ HTMLCHARS.put("'a", "á"); // #225
+ HTMLCHARS.put("^a", "â"); // #226
+ HTMLCHARS.put("~a", "ã"); // #227
+ HTMLCHARS.put("\"a", "ä"); // #228
+ HTMLCHARS.put("aa", "å"); // #229
+ HTMLCHARS.put("ae", "æ"); // #230
+ HTMLCHARS.put("cc", "ç"); // #231
+ HTMLCHARS.put("`e", "è"); // #232
+ HTMLCHARS.put("'e", "é"); // #233
+ HTMLCHARS.put("^e", "ê"); // #234
+ HTMLCHARS.put("\"e", "ë"); // #235
+ HTMLCHARS.put("`i", "ì"); // #236
+ HTMLCHARS.put("'i", "í"); // #237
+ HTMLCHARS.put("^i", "î"); // #238
+ HTMLCHARS.put("\"i", "ï"); // #239
+ HTMLCHARS.put("dh", "ð"); // #240
+ HTMLCHARS.put("~n", "ñ"); // #241
+ HTMLCHARS.put("`o", "ò"); // #242
+ HTMLCHARS.put("'o", "ó"); // #243
+ HTMLCHARS.put("^o", "ô"); // #244
+ HTMLCHARS.put("~o", "õ"); // #245
+ HTMLCHARS.put("\"o", "ö"); // #246
+ // According to ISO 8859-1 the "\div" symbol should be placed here
+ // (#247).
+ // Omitting this, because it is a mathematical symbol.
+ HTMLCHARS.put("o", "ø"); // #248
+ HTMLCHARS.put("`u", "ù"); // #249
+ HTMLCHARS.put("'u", "ú"); // #250
+ HTMLCHARS.put("^u", "û"); // #251
+ HTMLCHARS.put("\"u", "ü"); // #252
+ HTMLCHARS.put("'y", "ý"); // #253
+ HTMLCHARS.put("th", "þ"); // #254
+ HTMLCHARS.put("\"y", "ÿ"); // #255
+
+ // HTML special characters without names (UNICODE Latin Extended-A),
+ // indicated by UNICODE number
+ HTMLCHARS.put("=A", "Ā"); // "Amacr"
+ HTMLCHARS.put("=a", "ā"); // "amacr"
+ HTMLCHARS.put("uA", "Ă"); // "Abreve"
+ HTMLCHARS.put("ua", "ă"); // "abreve"
+ HTMLCHARS.put("kA", "Ą"); // "Aogon"
+ HTMLCHARS.put("ka", "ą"); // "aogon"
+ HTMLCHARS.put("'C", "Ć"); // "Cacute"
+ HTMLCHARS.put("'c", "ć"); // "cacute"
+ HTMLCHARS.put("^C", "Ĉ"); // "Ccirc"
+ HTMLCHARS.put("^c", "ĉ"); // "ccirc"
+ HTMLCHARS.put(".C", "Ċ"); // "Cdot"
+ HTMLCHARS.put(".c", "ċ"); // "cdot"
+ HTMLCHARS.put("vC", "Č"); // "Ccaron"
+ HTMLCHARS.put("vc", "č"); // "ccaron"
+ HTMLCHARS.put("vD", "Ď"); // "Dcaron"
+ // Symbol #271 (d�) has no special Latex command
+ HTMLCHARS.put("DJ", "Đ"); // "Dstrok"
+ HTMLCHARS.put("dj", "đ"); // "dstrok"
+ HTMLCHARS.put("=E", "Ē"); // "Emacr"
+ HTMLCHARS.put("=e", "ē"); // "emacr"
+ HTMLCHARS.put("uE", "Ĕ"); // "Ebreve"
+ HTMLCHARS.put("ue", "ĕ"); // "ebreve"
+ HTMLCHARS.put(".E", "Ė"); // "Edot"
+ HTMLCHARS.put(".e", "ė"); // "edot"
+ HTMLCHARS.put("kE", "Ę"); // "Eogon"
+ HTMLCHARS.put("ke", "ę"); // "eogon"
+ HTMLCHARS.put("vE", "Ě"); // "Ecaron"
+ HTMLCHARS.put("ve", "ě"); // "ecaron"
+ HTMLCHARS.put("^G", "Ĝ"); // "Gcirc"
+ HTMLCHARS.put("^g", "ĝ"); // "gcirc"
+ HTMLCHARS.put("uG", "Ğ"); // "Gbreve"
+ HTMLCHARS.put("ug", "ğ"); // "gbreve"
+ HTMLCHARS.put(".G", "Ġ"); // "Gdot"
+ HTMLCHARS.put(".g", "ġ"); // "gdot"
+ HTMLCHARS.put("cG", "Ģ"); // "Gcedil"
+ HTMLCHARS.put("'g", "ģ"); // "gacute"
+ HTMLCHARS.put("^H", "Ĥ"); // "Hcirc"
+ HTMLCHARS.put("^h", "ĥ"); // "hcirc"
+ HTMLCHARS.put("Hstrok", "Ħ"); // "Hstrok"
+ HTMLCHARS.put("hstrok", "ħ"); // "hstrok"
+ HTMLCHARS.put("~I", "Ĩ"); // "Itilde"
+ HTMLCHARS.put("~i", "ĩ"); // "itilde"
+ HTMLCHARS.put("=I", "Ī"); // "Imacr"
+ HTMLCHARS.put("=i", "ī"); // "imacr"
+ HTMLCHARS.put("uI", "Ĭ"); // "Ibreve"
+ HTMLCHARS.put("ui", "ĭ"); // "ibreve"
+ HTMLCHARS.put("kI", "Į"); // "Iogon"
+ HTMLCHARS.put("ki", "į"); // "iogon"
+ HTMLCHARS.put(".I", "İ"); // "Idot"
+ HTMLCHARS.put("i", "ı"); // "inodot"
+ // Symbol #306 (IJ) has no special Latex command
+ // Symbol #307 (ij) has no special Latex command
+ HTMLCHARS.put("^J", "Ĵ"); // "Jcirc"
+ HTMLCHARS.put("^j", "ĵ"); // "jcirc"
+ HTMLCHARS.put("cK", "Ķ"); // "Kcedil"
+ HTMLCHARS.put("ck", "ķ"); // "kcedil"
+ // Symbol #312 (k) has no special Latex command
+ HTMLCHARS.put("'L", "Ĺ"); // "Lacute"
+ HTMLCHARS.put("'l", "ĺ"); // "lacute"
+ HTMLCHARS.put("cL", "Ļ"); // "Lcedil"
+ HTMLCHARS.put("cl", "ļ"); // "lcedil"
+ // Symbol #317 (L�) has no special Latex command
+ // Symbol #318 (l�) has no special Latex command
+ HTMLCHARS.put("Lmidot", "Ŀ"); // "Lmidot"
+ HTMLCHARS.put("lmidot", "ŀ"); // "lmidot"
+ HTMLCHARS.put("L", "Ł"); // "Lstrok"
+ HTMLCHARS.put("l", "ł"); // "lstrok"
+ HTMLCHARS.put("'N", "Ń"); // "Nacute"
+ HTMLCHARS.put("'n", "ń"); // "nacute"
+ HTMLCHARS.put("cN", "Ņ"); // "Ncedil"
+ HTMLCHARS.put("cn", "ņ"); // "ncedil"
+ HTMLCHARS.put("vN", "Ň"); // "Ncaron"
+ HTMLCHARS.put("vn", "ň"); // "ncaron"
+ // Symbol #329 (�n) has no special Latex command
+ HTMLCHARS.put("NG", "Ŋ"); // "ENG"
+ HTMLCHARS.put("ng", "ŋ"); // "eng"
+ HTMLCHARS.put("=O", "Ō"); // "Omacr"
+ HTMLCHARS.put("=o", "ō"); // "omacr"
+ HTMLCHARS.put("uO", "Ŏ"); // "Obreve"
+ HTMLCHARS.put("uo", "ŏ"); // "obreve"
+ HTMLCHARS.put("HO", "Ő"); // "Odblac"
+ HTMLCHARS.put("Ho", "ő"); // "odblac"
+ HTMLCHARS.put("OE", "Œ"); // "OElig"
+ HTMLCHARS.put("oe", "œ"); // "oelig"
+ HTMLCHARS.put("'R", "Ŕ"); // "Racute"
+ HTMLCHARS.put("'r", "ŕ"); // "racute"
+ HTMLCHARS.put("cR", "Ŗ"); // "Rcedil"
+ HTMLCHARS.put("cr", "ŗ"); // "rcedil"
+ HTMLCHARS.put("vR", "Ř"); // "Rcaron"
+ HTMLCHARS.put("vr", "ř"); // "rcaron"
+ HTMLCHARS.put("'S", "Ś"); // "Sacute"
+ HTMLCHARS.put("'s", "ś"); // "sacute"
+ HTMLCHARS.put("^S", "Ŝ"); // "Scirc"
+ HTMLCHARS.put("^s", "ŝ"); // "scirc"
+ HTMLCHARS.put("cS", "Ş"); // "Scedil"
+ HTMLCHARS.put("cs", "ş"); // "scedil"
+ HTMLCHARS.put("vS", "Š"); // "Scaron"
+ HTMLCHARS.put("vs", "š"); // "scaron"
+ HTMLCHARS.put("cT", "Ţ"); // "Tcedil"
+ HTMLCHARS.put("ct", "ţ"); // "tcedil"
+ HTMLCHARS.put("vT", "Ť"); // "Tcaron"
+ // Symbol #357 (t�) has no special Latex command
+ HTMLCHARS.put("Tstrok", "Ŧ"); // "Tstrok"
+ HTMLCHARS.put("tstrok", "ŧ"); // "tstrok"
+ HTMLCHARS.put("~U", "Ũ"); // "Utilde"
+ HTMLCHARS.put("~u", "ũ"); // "utilde"
+ HTMLCHARS.put("=U", "Ū"); // "Umacr"
+ HTMLCHARS.put("=u", "ū"); // "umacr"
+ HTMLCHARS.put("uU", "Ŭ"); // "Ubreve"
+ HTMLCHARS.put("uu", "ŭ"); // "ubreve"
+ HTMLCHARS.put("rU", "Ů"); // "Uring"
+ HTMLCHARS.put("ru", "ů"); // "uring"
+ HTMLCHARS.put("HU", "Ű"); // "Odblac"
+ HTMLCHARS.put("Hu", "ű"); // "odblac"
+ HTMLCHARS.put("kU", "Ų"); // "Uogon"
+ HTMLCHARS.put("ku", "ų"); // "uogon"
+ HTMLCHARS.put("^W", "Ŵ"); // "Wcirc"
+ HTMLCHARS.put("^w", "ŵ"); // "wcirc"
+ HTMLCHARS.put("^Y", "Ŷ"); // "Ycirc"
+ HTMLCHARS.put("^y", "ŷ"); // "ycirc"
+ HTMLCHARS.put("\"Y", "Ÿ"); // "Yuml"
+ HTMLCHARS.put("'Z", "Ź"); // "Zacute"
+ HTMLCHARS.put("'z", "ź"); // "zacute"
+ HTMLCHARS.put(".Z", "Ż"); // "Zdot"
+ HTMLCHARS.put(".z", "ż"); // "zdot"
+ HTMLCHARS.put("vZ", "Ž"); // "Zcaron"
+ HTMLCHARS.put("vz", "ž"); // "zcaron"
+ // Symbol #383 (f) has no special Latex command
+
+ XML_CHARS.put("\\{\\\\\\\"\\{a\\}\\}", "ä");
+ XML_CHARS.put("\\{\\\\\\\"\\{A\\}\\}", "Ä");
+ XML_CHARS.put("\\{\\\\\\\"\\{e\\}\\}", "ë");
+ XML_CHARS.put("\\{\\\\\\\"\\{E\\}\\}", "Ë");
+ XML_CHARS.put("\\{\\\\\\\"\\{i\\}\\}", "ï");
+ XML_CHARS.put("\\{\\\\\\\"\\{I\\}\\}", "Ï");
+ XML_CHARS.put("\\{\\\\\\\"\\{o\\}\\}", "ö");
+ XML_CHARS.put("\\{\\\\\\\"\\{O\\}\\}", "Ö");
+ XML_CHARS.put("\\{\\\\\\\"\\{u\\}\\}", "ü");
+ XML_CHARS.put("\\{\\\\\\\"\\{U\\}\\}", "Ü");
+
+ XML_CHARS.put("\\{\\\\\\`\\{e\\}\\}", "è");
+ XML_CHARS.put("\\{\\\\\\`\\{E\\}\\}", "È");
+ XML_CHARS.put("\\{\\\\\\`\\{i\\}\\}", "ì");
+ XML_CHARS.put("\\{\\\\\\`\\{I\\}\\}", "Ì");
+ XML_CHARS.put("\\{\\\\\\`\\{o\\}\\}", "ò");
+ XML_CHARS.put("\\{\\\\\\`\\{O\\}\\}", "Ò");
+ XML_CHARS.put("\\{\\\\\\`\\{u\\}\\}", "ù");
+ XML_CHARS.put("\\{\\\\\\`\\{U\\}\\}", "Ù");
+ XML_CHARS.put("\\{\\\\\\'\\{e\\}\\}", "é");
+ XML_CHARS.put("\\{\\\\\\\uFFFD\\{E\\}\\}", "É");
+ XML_CHARS.put("\\{\\\\\\\uFFFD\\{i\\}\\}", "í");
+ XML_CHARS.put("\\{\\\\\\\uFFFD\\{I\\}\\}", "Í");
+ XML_CHARS.put("\\{\\\\\\\uFFFD\\{o\\}\\}", "ó");
+ XML_CHARS.put("\\{\\\\\\\uFFFD\\{O\\}\\}", "Ó");
+ XML_CHARS.put("\\{\\\\\\\uFFFD\\{u\\}\\}", "ú");
+ XML_CHARS.put("\\{\\\\\\\uFFFD\\{U\\}\\}", "Ú");
+ XML_CHARS.put("\\{\\\\\\\uFFFD\\{a\\}\\}", "á");
+ XML_CHARS.put("\\{\\\\\\\uFFFD\\{A\\}\\}", "Á");
+
+ XML_CHARS.put("\\{\\\\\\^\\{o\\}\\}", "ô");
+ XML_CHARS.put("\\{\\\\\\^\\{O\\}\\}", "Ô");
+ XML_CHARS.put("\\{\\\\\\^\\{u\\}\\}", "ù");
+ XML_CHARS.put("\\{\\\\\\^\\{U\\}\\}", "Ù");
+ XML_CHARS.put("\\{\\\\\\^\\{e\\}\\}", "ê");
+ XML_CHARS.put("\\{\\\\\\^\\{E\\}\\}", "Ê");
+ XML_CHARS.put("\\{\\\\\\^\\{i\\}\\}", "î");
+ XML_CHARS.put("\\{\\\\\\^\\{I\\}\\}", "Î");
+ XML_CHARS.put("\\{\\\\\\~\\{o\\}\\}", "õ");
+ XML_CHARS.put("\\{\\\\\\~\\{O\\}\\}", "Õ");
+ XML_CHARS.put("\\{\\\\\\~\\{n\\}\\}", "ñ");
+ XML_CHARS.put("\\{\\\\\\~\\{N\\}\\}", "Ñ");
+ XML_CHARS.put("\\{\\\\\\~\\{a\\}\\}", "ã");
+ XML_CHARS.put("\\{\\\\\\~\\{A\\}\\}", "Ã");
+
+ XML_CHARS.put("\\{\\\\\\\"a\\}", "ä");
+ XML_CHARS.put("\\{\\\\\\\"A\\}", "Ä");
+ XML_CHARS.put("\\{\\\\\\\"e\\}", "ë");
+ XML_CHARS.put("\\{\\\\\\\"E\\}", "Ë");
+ XML_CHARS.put("\\{\\\\\\\"i\\}", "ï");
+ XML_CHARS.put("\\{\\\\\\\"I\\}", "Ï");
+ XML_CHARS.put("\\{\\\\\\\"o\\}", "ö");
+ XML_CHARS.put("\\{\\\\\\\"O\\}", "Ö");
+ XML_CHARS.put("\\{\\\\\\\"u\\}", "ü");
+ XML_CHARS.put("\\{\\\\\\\"U\\}", "Ü");
+
+ XML_CHARS.put("\\{\\\\\\`e\\}", "è");
+ XML_CHARS.put("\\{\\\\\\`E\\}", "È");
+ XML_CHARS.put("\\{\\\\\\`i\\}", "ì");
+ XML_CHARS.put("\\{\\\\\\`I\\}", "Ì");
+ XML_CHARS.put("\\{\\\\\\`o\\}", "ò");
+ XML_CHARS.put("\\{\\\\\\`O\\}", "Ò");
+ XML_CHARS.put("\\{\\\\\\`u\\}", "ù");
+ XML_CHARS.put("\\{\\\\\\`U\\}", "Ù");
+ XML_CHARS.put("\\{\\\\\\'e\\}", "é");
+ XML_CHARS.put("\\{\\\\\\'E\\}", "É");
+ XML_CHARS.put("\\{\\\\\\'i\\}", "í");
+ XML_CHARS.put("\\{\\\\\\'I\\}", "Í");
+ XML_CHARS.put("\\{\\\\\\'o\\}", "ó");
+ XML_CHARS.put("\\{\\\\\\'O\\}", "Ó");
+ XML_CHARS.put("\\{\\\\\\'u\\}", "ú");
+ XML_CHARS.put("\\{\\\\\\'U\\}", "Ú");
+ XML_CHARS.put("\\{\\\\\\'a\\}", "á");
+ XML_CHARS.put("\\{\\\\\\'A\\}", "Á");
+
+ XML_CHARS.put("\\{\\\\\\^a\\}", "ô");
+ XML_CHARS.put("\\{\\\\\\^A\\}", "Ô");
+ XML_CHARS.put("\\{\\\\\\^o\\}", "ô");
+ XML_CHARS.put("\\{\\\\\\^O\\}", "Ô");
+ XML_CHARS.put("\\{\\\\\\^u\\}", "ù");
+ XML_CHARS.put("\\{\\\\\\^U\\}", "Ù");
+ XML_CHARS.put("\\{\\\\\\^e\\}", "ê");
+ XML_CHARS.put("\\{\\\\\\^E\\}", "Ê");
+ XML_CHARS.put("\\{\\\\\\^i\\}", "î");
+ XML_CHARS.put("\\{\\\\\\^I\\}", "Î");
+ XML_CHARS.put("\\{\\\\\\~o\\}", "õ");
+ XML_CHARS.put("\\{\\\\\\~O\\}", "Õ");
+ XML_CHARS.put("\\{\\\\\\~n\\}", "ñ");
+ XML_CHARS.put("\\{\\\\\\~N\\}", "Ñ");
+ XML_CHARS.put("\\{\\\\\\~a\\}", "ã");
+ XML_CHARS.put("\\{\\\\\\~A\\}", "Ã");
+
+ ASCII2XML_CHARS.put("<", "<");
+ ASCII2XML_CHARS.put("\"", """);
+ ASCII2XML_CHARS.put(">", ">");
+
+ UNICODE_CHARS.put("\u00C0", "A");
+ UNICODE_CHARS.put("\u00C1", "A");
+ UNICODE_CHARS.put("\u00C2", "A");
+ UNICODE_CHARS.put("\u00C3", "A");
+ UNICODE_CHARS.put("\u00C4", "Ae");
+ UNICODE_CHARS.put("\u00C5", "Aa");
+ UNICODE_CHARS.put("\u00C6", "Ae");
+ UNICODE_CHARS.put("\u00C7", "C");
+ UNICODE_CHARS.put("\u00C8", "E");
+ UNICODE_CHARS.put("\u00C9", "E");
+ UNICODE_CHARS.put("\u00CA", "E");
+ UNICODE_CHARS.put("\u00CB", "E");
+ UNICODE_CHARS.put("\u00CC", "I");
+ UNICODE_CHARS.put("\u00CD", "I");
+ UNICODE_CHARS.put("\u00CE", "I");
+ UNICODE_CHARS.put("\u00CF", "I");
+ UNICODE_CHARS.put("\u00D0", "D");
+ UNICODE_CHARS.put("\u00D1", "N");
+ UNICODE_CHARS.put("\u00D2", "O");
+ UNICODE_CHARS.put("\u00D3", "O");
+ UNICODE_CHARS.put("\u00D4", "O");
+ UNICODE_CHARS.put("\u00D5", "O");
+ UNICODE_CHARS.put("\u00D6", "Oe");
+ UNICODE_CHARS.put("\u00D8", "Oe");
+ UNICODE_CHARS.put("\u00D9", "U");
+ UNICODE_CHARS.put("\u00DA", "U");
+ UNICODE_CHARS.put("\u00DB", "U");
+ UNICODE_CHARS.put("\u00DC", "Ue"); // U umlaut ..
+ UNICODE_CHARS.put("\u00DD", "Y");
+ UNICODE_CHARS.put("\u00DF", "ss");
+ UNICODE_CHARS.put("\u00E0", "a");
+ UNICODE_CHARS.put("\u00E1", "a");
+ UNICODE_CHARS.put("\u00E2", "a");
+ UNICODE_CHARS.put("\u00E3", "a");
+ UNICODE_CHARS.put("\u00E4", "ae");
+ UNICODE_CHARS.put("\u00E5", "aa");
+ UNICODE_CHARS.put("\u00E6", "ae");
+ UNICODE_CHARS.put("\u00E7", "c");
+ UNICODE_CHARS.put("\u00E8", "e");
+ UNICODE_CHARS.put("\u00E9", "e");
+ UNICODE_CHARS.put("\u00EA", "e");
+ UNICODE_CHARS.put("\u00EB", "e");
+ UNICODE_CHARS.put("\u00EC", "i");
+ UNICODE_CHARS.put("\u00ED", "i");
+ UNICODE_CHARS.put("\u00EE", "i");
+ UNICODE_CHARS.put("\u00EF", "i");
+ UNICODE_CHARS.put("\u00F0", "o");
+ UNICODE_CHARS.put("\u00F1", "n");
+ UNICODE_CHARS.put("\u00F2", "o");
+ UNICODE_CHARS.put("\u00F3", "o");
+ UNICODE_CHARS.put("\u00F4", "o");
+ UNICODE_CHARS.put("\u00F5", "o");
+ UNICODE_CHARS.put("\u00F6", "oe");
+ UNICODE_CHARS.put("\u00F8", "oe");
+ UNICODE_CHARS.put("\u00F9", "u");
+ UNICODE_CHARS.put("\u00FA", "u");
+ UNICODE_CHARS.put("\u00FB", "u");
+ UNICODE_CHARS.put("\u00FC", "ue"); // u umlaut...
+ UNICODE_CHARS.put("\u00FD", "y");
+ UNICODE_CHARS.put("\u00FF", "y");
+ UNICODE_CHARS.put("\u0100", "A");
+ UNICODE_CHARS.put("\u0101", "a");
+ UNICODE_CHARS.put("\u0102", "A");
+ UNICODE_CHARS.put("\u0103", "a");
+ UNICODE_CHARS.put("\u0104", "A");
+ UNICODE_CHARS.put("\u0105", "a");
+ UNICODE_CHARS.put("\u0106", "C");
+ UNICODE_CHARS.put("\u0107", "c");
+ UNICODE_CHARS.put("\u0108", "C");
+ UNICODE_CHARS.put("\u0109", "c");
+ UNICODE_CHARS.put("\u010A", "C");
+ UNICODE_CHARS.put("\u010B", "c");
+ UNICODE_CHARS.put("\u010C", "C");
+ UNICODE_CHARS.put("\u010D", "c");
+ UNICODE_CHARS.put("\u010E", "D");
+ UNICODE_CHARS.put("\u010F", "d");
+ UNICODE_CHARS.put("\u0110", "D");
+ UNICODE_CHARS.put("\u0111", "d");
+ UNICODE_CHARS.put("\u0112", "E");
+ UNICODE_CHARS.put("\u0113", "e");
+ UNICODE_CHARS.put("\u0114", "E");
+ UNICODE_CHARS.put("\u0115", "e");
+ UNICODE_CHARS.put("\u0116", "E");
+ UNICODE_CHARS.put("\u0117", "e");
+ UNICODE_CHARS.put("\u0118", "E");
+ UNICODE_CHARS.put("\u0119", "e");
+ UNICODE_CHARS.put("\u011A", "E");
+ UNICODE_CHARS.put("\u011B", "e");
+ UNICODE_CHARS.put("\u011C", "G");
+ UNICODE_CHARS.put("\u011D", "g");
+ UNICODE_CHARS.put("\u011E", "G");
+ UNICODE_CHARS.put("\u011F", "g");
+ UNICODE_CHARS.put("\u0120", "G");
+ UNICODE_CHARS.put("\u0121", "g");
+ UNICODE_CHARS.put("\u0122", "G");
+ UNICODE_CHARS.put("\u0123", "g");
+ UNICODE_CHARS.put("\u0124", "H");
+ UNICODE_CHARS.put("\u0125", "h");
+ UNICODE_CHARS.put("\u0127", "h");
+ UNICODE_CHARS.put("\u0128", "I");
+ UNICODE_CHARS.put("\u0129", "i");
+ UNICODE_CHARS.put("\u012A", "I");
+ UNICODE_CHARS.put("\u012B", "i");
+ UNICODE_CHARS.put("\u012C", "I");
+ UNICODE_CHARS.put("\u012D", "i");
+ // UNICODE_CHARS.put("\u0100", "");
+
+ RTFCHARS.put("`a", "\\'e0");
+ RTFCHARS.put("`e", "\\'e8");
+ RTFCHARS.put("`i", "\\'ec");
+ RTFCHARS.put("`o", "\\'f2");
+ RTFCHARS.put("`u", "\\'f9");
+ RTFCHARS.put("?a", "\\'e1");
+ RTFCHARS.put("?e", "\\'e9");
+ RTFCHARS.put("?i", "\\'ed");
+ RTFCHARS.put("?o", "\\'f3");
+ RTFCHARS.put("?u", "\\'fa");
+ RTFCHARS.put("^a", "\\'e2");
+ RTFCHARS.put("^e", "\\'ea");
+ RTFCHARS.put("^i", "\\'ee");
+ RTFCHARS.put("^o", "\\'f4");
+ RTFCHARS.put("^u", "\\'fa");
+ RTFCHARS.put("\"a", "\\'e4");
+ RTFCHARS.put("\"e", "\\'eb");
+ RTFCHARS.put("\"i", "\\'ef");
+ RTFCHARS.put("\"o", "\\'f6");
+ RTFCHARS.put("\"u", "\\u252u");
+ RTFCHARS.put("~n", "\\'f1");
+ RTFCHARS.put("`A", "\\'c0");
+ RTFCHARS.put("`E", "\\'c8");
+ RTFCHARS.put("`I", "\\'cc");
+ RTFCHARS.put("`O", "\\'d2");
+ RTFCHARS.put("`U", "\\'d9");
+ RTFCHARS.put("?A", "\\'c1");
+ RTFCHARS.put("?E", "\\'c9");
+ RTFCHARS.put("?I", "\\'cd");
+ RTFCHARS.put("?O", "\\'d3");
+ RTFCHARS.put("?U", "\\'da");
+ RTFCHARS.put("^A", "\\'c2");
+ RTFCHARS.put("^E", "\\'ca");
+ RTFCHARS.put("^I", "\\'ce");
+ RTFCHARS.put("^O", "\\'d4");
+ RTFCHARS.put("^U", "\\'db");
+ RTFCHARS.put("\"A", "\\'c4");
+ RTFCHARS.put("\"E", "\\'cb");
+ RTFCHARS.put("\"I", "\\'cf");
+ RTFCHARS.put("\"O", "\\'d6");
+ RTFCHARS.put("\"U", "\\'dc");
+
+ // Use UNICODE characters for RTF-Chars which can not be found in the
+ // standard codepage
+
+ // RTFCHARS.put("`A", "\\u192"); // "Agrave" exists in standard
+ // codepage
+ RTFCHARS.put("'A", "\\u193A"); // "Aacute"
+ // RTFCHARS.put("^A", "\\u194"); // "Acirc" exists in standard
+ // codepage
+ RTFCHARS.put("~A", "\\u195A"); // "Atilde"
+ // RTFCHARS.put("\"A", "\\u196"); // "Auml" exists in standard
+ // codepage
+ RTFCHARS.put("AA", "\\u197A"); // "Aring"
+ RTFCHARS.put("AE", "{\\uc2\\u198AE}"); // "AElig"
+ RTFCHARS.put("cC", "\\u199C"); // "Ccedil"
+ // RTFCHARS.put("`E", "\\u200"); // "Egrave" exists in standard
+ // codepage
+ RTFCHARS.put("'E", "\\u201E"); // "Eacute"
+ // RTFCHARS.put("^E", "\\u202"); // "Ecirc" exists in standard
+ // codepage
+ // RTFCHARS.put("\"E", "\\u203"); // "Euml" exists in standard
+ // codepage
+ // RTFCHARS.put("`I", "\\u204"); // "Igrave" exists in standard
+ // codepage
+ RTFCHARS.put("'I", "\\u205I"); // "Iacute"
+ // RTFCHARS.put("^I", "\\u206"); // "Icirc" exists in standard
+ // codepage
+ // RTFCHARS.put("\"I", "\\u207"); // "Iuml" exists in standard
+ // codepage
+ RTFCHARS.put("DH", "\\u208D"); // "ETH"
+ RTFCHARS.put("~N", "\\u209N"); // "Ntilde"
+ // RTFCHARS.put("`O", "\\u210"); // "Ograve" exists in standard
+ // codepage
+ RTFCHARS.put("'O", "\\u211O"); // "Oacute"
+ // RTFCHARS.put("^O", "\\u212"); // "Ocirc" exists in standard
+ // codepage
+ RTFCHARS.put("~O", "\\u213O"); // "Otilde"
+ // RTFCHARS.put("\"O", "\\u214"); // "Ouml" exists in standard
+ // codepage
+ // According to ISO 8859-1 the "\times" symbol should be placed here
+ // (#215).
+ // Omitting this, because it is a mathematical symbol.
+ RTFCHARS.put("O", "\\u216O"); // "OSlash"
+ // RTFCHARS.put("`U", "\\u217"); // "Ugrave" exists in standard
+ // codepage
+ RTFCHARS.put("'U", "\\u218U"); // "Uacute"
+ // RTFCHARS.put("^U", "\\u219"); // "Ucirc" exists in standard
+ // codepage
+ // RTFCHARS.put("\"U", "\\u220"); // "Uuml" exists in standard
+ // codepage
+ RTFCHARS.put("'Y", "\\u221Y"); // "Yacute"
+ RTFCHARS.put("TH", "{\\uc2\\u222TH}"); // "THORN"
+ RTFCHARS.put("ss", "{\\uc2\\u223ss"); // "szlig"
+ // RTFCHARS.put("`a", "\\u224"); // "agrave" exists in standard
+ // codepage
+ RTFCHARS.put("'a", "\\u225a"); // "aacute"
+ // RTFCHARS.put("^a", "\\u226"); // "acirc" exists in standard
+ // codepage
+ RTFCHARS.put("~a", "\\u227a"); // "atilde"
+ // RTFCHARS.put("\"a", "\\u228"); // "auml" exists in standard
+ // codepage
+ RTFCHARS.put("aa", "\\u229a"); // "aring"
+ RTFCHARS.put("ae", "{\\uc2\\u230ae}"); // "aelig"
+ RTFCHARS.put("cc", "\\u231c"); // "ccedil"
+ // RTFCHARS.put("`e", "\\u232"); // "egrave" exists in standard
+ // codepage
+ RTFCHARS.put("'e", "\\u233e"); // "eacute"
+ // RTFCHARS.put("^e", "\\u234"); // "ecirc" exists in standard
+ // codepage
+ // RTFCHARS.put("\"e", "\\u235"); // "euml" exists in standard
+ // codepage
+ // RTFCHARS.put("`i", "\\u236"); // "igrave" exists in standard
+ // codepage
+ RTFCHARS.put("'i", "\\u237i"); // "iacute"
+ // RTFCHARS.put("^i", "\\u238"); // "icirc" exists in standard
+ // codepage
+ // RTFCHARS.put("\"i", "\\u239"); // "iuml" exists in standard
+ // codepage
+ RTFCHARS.put("dh", "\\u240d"); // "eth"
+ // RTFCHARS.put("~n", "\\u241"); // "ntilde" exists in standard
+ // codepage
+ // RTFCHARS.put("`o", "\\u242"); // "ograve" exists in standard
+ // codepage
+ RTFCHARS.put("'o", "\\u243o"); // "oacute"
+ // RTFCHARS.put("^o", "\\u244"); // "ocirc" exists in standard
+ // codepage
+ RTFCHARS.put("~o", "\\u245o"); // "otilde"
+ // RTFCHARS.put("\"o", "\\u246"); // "ouml" exists in standard
+ // codepage
+ // According to ISO 8859-1 the "\div" symbol should be placed here
+ // (#247).
+ // Omitting this, because it is a mathematical symbol.
+ RTFCHARS.put("o", "\\u248o"); // "oslash"
+ // RTFCHARS.put("`u", "\\u249"); // "ugrave" exists in standard
+ // codepage
+ RTFCHARS.put("'u", "\\u250u"); // "uacute"
+ // RTFCHARS.put("^u", "\\u251"); // "ucirc" exists in standard
+ // codepage
+ // RTFCHARS.put("\"u", "\\u252"); // "uuml" exists in standard
+ // codepage
+ RTFCHARS.put("'y", "\\u253y"); // "yacute"
+ RTFCHARS.put("th", "{\\uc2\\u254th}"); // "thorn"
+ RTFCHARS.put("\"y", "\\u255y"); // "yuml"
+
+ RTFCHARS.put("=A", "\\u256A"); // "Amacr"
+ RTFCHARS.put("=a", "\\u257a"); // "amacr"
+ RTFCHARS.put("uA", "\\u258A"); // "Abreve"
+ RTFCHARS.put("ua", "\\u259a"); // "abreve"
+ RTFCHARS.put("kA", "\\u260A"); // "Aogon"
+ RTFCHARS.put("ka", "\\u261a"); // "aogon"
+ RTFCHARS.put("'C", "\\u262C"); // "Cacute"
+ RTFCHARS.put("'c", "\\u263c"); // "cacute"
+ RTFCHARS.put("^C", "\\u264C"); // "Ccirc"
+ RTFCHARS.put("^c", "\\u265c"); // "ccirc"
+ RTFCHARS.put(".C", "\\u266C"); // "Cdot"
+ RTFCHARS.put(".c", "\\u267c"); // "cdot"
+ RTFCHARS.put("vC", "\\u268C"); // "Ccaron"
+ RTFCHARS.put("vc", "\\u269c"); // "ccaron"
+ RTFCHARS.put("vD", "\\u270D"); // "Dcaron"
+ // Symbol #271 (d�) has no special Latex command
+ RTFCHARS.put("DJ", "\\u272D"); // "Dstrok"
+ RTFCHARS.put("dj", "\\u273d"); // "dstrok"
+ RTFCHARS.put("=E", "\\u274E"); // "Emacr"
+ RTFCHARS.put("=e", "\\u275e"); // "emacr"
+ RTFCHARS.put("uE", "\\u276E"); // "Ebreve"
+ RTFCHARS.put("ue", "\\u277e"); // "ebreve"
+ RTFCHARS.put(".E", "\\u278E"); // "Edot"
+ RTFCHARS.put(".e", "\\u279e"); // "edot"
+ RTFCHARS.put("kE", "\\u280E"); // "Eogon"
+ RTFCHARS.put("ke", "\\u281e"); // "eogon"
+ RTFCHARS.put("vE", "\\u282E"); // "Ecaron"
+ RTFCHARS.put("ve", "\\u283e"); // "ecaron"
+ RTFCHARS.put("^G", "\\u284G"); // "Gcirc"
+ RTFCHARS.put("^g", "\\u285g"); // "gcirc"
+ RTFCHARS.put("uG", "\\u286G"); // "Gbreve"
+ RTFCHARS.put("ug", "\\u287g"); // "gbreve"
+ RTFCHARS.put(".G", "\\u288G"); // "Gdot"
+ RTFCHARS.put(".g", "\\u289g"); // "gdot"
+ RTFCHARS.put("cG", "\\u290G"); // "Gcedil"
+ RTFCHARS.put("'g", "\\u291g"); // "gacute"
+ RTFCHARS.put("^H", "\\u292H"); // "Hcirc"
+ RTFCHARS.put("^h", "\\u293h"); // "hcirc"
+ RTFCHARS.put("Hstrok", "\\u294H"); // "Hstrok"
+ RTFCHARS.put("hstrok", "\\u295h"); // "hstrok"
+ RTFCHARS.put("~I", "\\u296I"); // "Itilde"
+ RTFCHARS.put("~i", "\\u297i"); // "itilde"
+ RTFCHARS.put("=I", "\\u298I"); // "Imacr"
+ RTFCHARS.put("=i", "\\u299i"); // "imacr"
+ RTFCHARS.put("uI", "\\u300I"); // "Ibreve"
+ RTFCHARS.put("ui", "\\u301i"); // "ibreve"
+ RTFCHARS.put("kI", "\\u302I"); // "Iogon"
+ RTFCHARS.put("ki", "\\u303i"); // "iogon"
+ RTFCHARS.put(".I", "\\u304I"); // "Idot"
+ RTFCHARS.put("i", "\\u305i"); // "inodot"
+ // Symbol #306 (IJ) has no special Latex command
+ // Symbol #307 (ij) has no special Latex command
+ RTFCHARS.put("^J", "\\u308J"); // "Jcirc"
+ RTFCHARS.put("^j", "\\u309j"); // "jcirc"
+ RTFCHARS.put("cK", "\\u310K"); // "Kcedil"
+ RTFCHARS.put("ck", "\\u311k"); // "kcedil"
+ // Symbol #312 (k) has no special Latex command
+ RTFCHARS.put("'L", "\\u313L"); // "Lacute"
+ RTFCHARS.put("'l", "\\u314l"); // "lacute"
+ RTFCHARS.put("cL", "\\u315L"); // "Lcedil"
+ RTFCHARS.put("cl", "\\u316l"); // "lcedil"
+ // Symbol #317 (L�) has no special Latex command
+ // Symbol #318 (l�) has no special Latex command
+ RTFCHARS.put("Lmidot", "\\u319L"); // "Lmidot"
+ RTFCHARS.put("lmidot", "\\u320l"); // "lmidot"
+ RTFCHARS.put("L", "\\u321L"); // "Lstrok"
+ RTFCHARS.put("l", "\\u322l"); // "lstrok"
+ RTFCHARS.put("'N", "\\u323N"); // "Nacute"
+ RTFCHARS.put("'n", "\\u324n"); // "nacute"
+ RTFCHARS.put("cN", "\\u325N"); // "Ncedil"
+ RTFCHARS.put("cn", "\\u326n"); // "ncedil"
+ RTFCHARS.put("vN", "\\u327N"); // "Ncaron"
+ RTFCHARS.put("vn", "\\u328n"); // "ncaron"
+ // Symbol #329 (�n) has no special Latex command
+ RTFCHARS.put("NG", "\\u330G"); // "ENG"
+ RTFCHARS.put("ng", "\\u331g"); // "eng"
+ RTFCHARS.put("=O", "\\u332O"); // "Omacr"
+ RTFCHARS.put("=o", "\\u333o"); // "omacr"
+ RTFCHARS.put("uO", "\\u334O"); // "Obreve"
+ RTFCHARS.put("uo", "\\u335o"); // "obreve"
+ RTFCHARS.put("HO", "\\u336?"); // "Odblac"
+ RTFCHARS.put("Ho", "\\u337?"); // "odblac"
+ RTFCHARS.put("OE", "{\\uc2\\u338OE}"); // "OElig"
+ RTFCHARS.put("oe", "{\\uc2\\u339oe}"); // "oelig"
+ RTFCHARS.put("'R", "\\u340R"); // "Racute"
+ RTFCHARS.put("'r", "\\u341r"); // "racute"
+ RTFCHARS.put("cR", "\\u342R"); // "Rcedil"
+ RTFCHARS.put("cr", "\\u343r"); // "rcedil"
+ RTFCHARS.put("vR", "\\u344R"); // "Rcaron"
+ RTFCHARS.put("vr", "\\u345r"); // "rcaron"
+ RTFCHARS.put("'S", "\\u346S"); // "Sacute"
+ RTFCHARS.put("'s", "\\u347s"); // "sacute"
+ RTFCHARS.put("^S", "\\u348S"); // "Scirc"
+ RTFCHARS.put("^s", "\\u349s"); // "scirc"
+ RTFCHARS.put("cS", "\\u350S"); // "Scedil"
+ RTFCHARS.put("cs", "\\u351s"); // "scedil"
+ RTFCHARS.put("vS", "\\u352S"); // "Scaron"
+ RTFCHARS.put("vs", "\\u353s"); // "scaron"
+ RTFCHARS.put("cT", "\\u354T"); // "Tcedil"
+ RTFCHARS.put("ct", "\\u355t"); // "tcedil"
+ RTFCHARS.put("vT", "\\u356T"); // "Tcaron"
+ // Symbol #357 (t�) has no special Latex command
+ RTFCHARS.put("Tstrok", "\\u358T"); // "Tstrok"
+ RTFCHARS.put("tstrok", "\\u359t"); // "tstrok"
+ RTFCHARS.put("~U", "\\u360U"); // "Utilde"
+ RTFCHARS.put("~u", "\\u361u"); // "utilde"
+ RTFCHARS.put("=U", "\\u362U"); // "Umacr"
+ RTFCHARS.put("=u", "\\u363u"); // "umacr"
+ RTFCHARS.put("uU", "\\u364U"); // "Ubreve"
+ RTFCHARS.put("uu", "\\u365u"); // "ubreve"
+ RTFCHARS.put("rU", "\\u366U"); // "Uring"
+ RTFCHARS.put("ru", "\\u367u"); // "uring"
+ RTFCHARS.put("HU", "\\u368?"); // "Odblac"
+ RTFCHARS.put("Hu", "\\u369?"); // "odblac"
+ RTFCHARS.put("kU", "\\u370U"); // "Uogon"
+ RTFCHARS.put("ku", "\\u371u"); // "uogon"
+ RTFCHARS.put("^W", "\\u372W"); // "Wcirc"
+ RTFCHARS.put("^w", "\\u373w"); // "wcirc"
+ RTFCHARS.put("^Y", "\\u374Y"); // "Ycirc"
+ RTFCHARS.put("^y", "\\u375y"); // "ycirc"
+ RTFCHARS.put("\"Y","\\u376Y"); // "Yuml"
+ RTFCHARS.put("'Z", "\\u377Z"); // "Zacute"
+ RTFCHARS.put("'z", "\\u378z"); // "zacute"
+ RTFCHARS.put(".Z", "\\u379Z"); // "Zdot"
+ RTFCHARS.put(".z", "\\u380z"); // "zdot"
+ RTFCHARS.put("vZ", "\\u381Z"); // "Zcaron"
+ RTFCHARS.put("vz", "\\u382z"); // "zcaron"
+ // Symbol #383 (f) has no special Latex command
+
+ // XML_CHARS.put("\\u00E1", "á");
+ }
+
+ public static void initializeJournalNames() {
+ journalAbbrev = new JournalAbbreviations();// "/resource/journalList.txt");
+
+ // Read external lists, if any (in reverse order, so the upper lists
+ // override the lower):
+ String[] lists = prefs.getStringArray("externalJournalLists");
+ if ((lists != null) && (lists.length > 0)) {
+ for (int i = lists.length - 1; i >= 0; i--) {
+ try {
+ journalAbbrev.readJournalList(new File(lists[i]));
+ } catch (FileNotFoundException e) {
+ // The file couldn't be found... should we tell anyone?
+ Globals.logger(e.getMessage());
+ }
+ }
+ }
+
+ // Read personal list, if set up:
+ if (prefs.get("personalJournalList") != null) {
+ try {
+ journalAbbrev.readJournalList(new File(prefs.get("personalJournalList")));
+ } catch (FileNotFoundException e) {
+ Globals.logger("Personal journal list file '" + prefs.get("personalJournalList")
+ + "' not found.");
+ }
+ }
+
+ }
}
diff --git a/src/java/net/sf/jabref/Globals.java~ b/src/java/net/sf/jabref/Globals.java~
deleted file mode 100644
index 9dc3ac8..0000000
--- a/src/java/net/sf/jabref/Globals.java~
+++ /dev/null
@@ -1,1324 +0,0 @@
-/* (C) 2003 Nizar N. Batada, Morten O. Alver
-
- All programs in this directory and
- subdirectories are published under the GNU General Public License as
- described below.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or (at
- your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
- USA
-
- Further information about the GNU GPL is available at:
- http://www.gnu.org/copyleft/gpl.ja.html
-
- */
-package net.sf.jabref;
-
-import java.io.* ;
-import java.nio.charset.Charset;
-import java.util.* ;
-import java.util.List;
-import java.util.logging.* ;
-import java.util.logging.Filter ;
-
-import java.awt.* ;
-import javax.swing.* ;
-
-import net.sf.jabref.collab.* ;
-import net.sf.jabref.imports.* ;
-import net.sf.jabref.util.* ;
-import net.sf.jabref.journals.JournalAbbreviations;
-
-public class Globals {
-
- public static int SHORTCUT_MASK,// = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
- FUTURE_YEAR = 2050, // Needs to give a year definitely in the future. Used for guessing the
- // year field when parsing textual data. :-)
-
- STANDARD_EXPORT_COUNT = 5, // The number of standard export formats.
- METADATA_LINE_LENGTH = 70; // The line length used to wrap metadata.
-
- private static String resourcePrefix = "resource/JabRef",
- menuResourcePrefix = "resource/Menu",
- integrityResourcePrefix = "resource/IntegrityMessage";
- private static final String buildInfos = "/resource/build.properties" ;
- public static final String additionalFields = "/resource/fields/fields.xml" ; // some extra field definitions
- private static String logfile = "jabref.log";
- public static ResourceBundle messages, menuTitles, intMessages ;
- public static FileUpdateMonitor fileUpdateMonitor = new FileUpdateMonitor();
- public static ImportFormatReader importFormatReader = new ImportFormatReader();
-
- public static ErrorConsole errorConsole;
-
- public static String VERSION,
- BUILD,
- BUILD_DATE ;
-
- static
- {
- TBuildInfo bi = new TBuildInfo(buildInfos) ;
- VERSION = bi.getBUILD_VERSION() ;
- BUILD = bi.getBUILD_NUMBER() ;
- BUILD_DATE = bi.getBUILD_DATE() ;
-
- // TODO: Error console initialization here. When should it be used?
- errorConsole = ErrorConsole.getInstance();
- }
-
-
-
- //public static ResourceBundle preferences = ResourceBundle.getBundle("resource/defaultPrefs");
- public static Locale locale;
- public static final String FILETYPE_PREFS_EXT = "_dir",
- SELECTOR_META_PREFIX = "selector_",
- LAYOUT_PREFIX = "/resource/layout/",
- MAC = "Mac OS X",
- DOI_LOOKUP_PREFIX = "http://dx.doi.org/",
- NONE = "_non__",
- FORMATTER_PACKAGE = "net.sf.jabref.export.layout.format.";
- public static float duplicateThreshold = 0.75f;
- private static Handler consoleHandler = new java.util.logging.ConsoleHandler();
- public static String[] ENCODINGS,
- ALL_ENCODINGS = //(String[]) Charset.availableCharsets().keySet().toArray(new String[]{});
- new String[] {"ISO8859_1", "UTF8", "UTF-16", "ASCII",
- "Cp1250", "Cp1251", "Cp1252", "Cp1253", "Cp1254", "Cp1257",
- "JIS", "SJIS", "EUC-JP", // Added Japanese encodings.
- "Big5", "Big5_HKSCS", "GBK",
- "ISO8859_2", "ISO8859_3", "ISO8859_4", "ISO8859_5", "ISO8859_6",
- "ISO8859_7", "ISO8859_8", "ISO8859_9", "ISO8859_13", "ISO8859_15"};
-
- // String array that maps from month number to month string label:
- public static String[] MONTHS = new String[] {"jan", "feb", "mar", "apr", "may", "jun",
- "jul", "aug", "sep", "oct", "nov", "dec"};
-
- // Map that maps from month string labels to
- public static Map MONTH_STRINGS = new HashMap();
- static {
- MONTH_STRINGS.put("jan", "January");
- MONTH_STRINGS.put("feb", "February");
- MONTH_STRINGS.put("mar", "March");
- MONTH_STRINGS.put("apr", "April");
- MONTH_STRINGS.put("may", "May");
- MONTH_STRINGS.put("jun", "June");
- MONTH_STRINGS.put("jul", "July");
- MONTH_STRINGS.put("aug", "August");
- MONTH_STRINGS.put("sep", "September");
- MONTH_STRINGS.put("oct", "October");
- MONTH_STRINGS.put("nov", "November");
- MONTH_STRINGS.put("dec", "December");
-
- // Build list of encodings, by filtering out all that are not supported
- // on this system:
- List encodings = new ArrayList();
- for (int i=0; i<ALL_ENCODINGS.length; i++) {
- if (Charset.isSupported(ALL_ENCODINGS[i]))
- encodings.add(ALL_ENCODINGS[i]);
- }
- ENCODINGS = (String[])encodings.toArray(new String[0]);
-
- }
-
-
- public static GlobalFocusListener focusListener = new GlobalFocusListener();
- public static JabRefPreferences prefs = null;
- public static HelpDialog helpDiag = null;
- public static String osName = System.getProperty("os.name", "def");
- public static boolean ON_MAC = (osName.equals(MAC)),
- ON_WIN = osName.startsWith("Windows");
-
-
- public static String[] SKIP_WORDS = {"a", "an", "the", "for", "on"};
- public static SidePaneManager sidePaneManager;
- public static final String NEWLINE = System.getProperty("line.separator");
- public static final boolean UNIX_NEWLINE = NEWLINE.equals("\n"); // true if we have unix newlines.
-
- public static final String BIBTEX_STRING = "__string";
- // "Fieldname" to indicate that a field should be treated as a bibtex string. Used when writing database to file.
-
- public static void logger(String s) {
- Logger.global.info(s);
- }
-
- public static void turnOffLogging() { // only log exceptions
- Logger.global.setLevel(java.util.logging.Level.SEVERE);
- }
-
- // should be only called once
- public static void turnOnConsoleLogging() {
- Logger.global.addHandler(consoleHandler);
-
- }
-
-
-
- public static void turnOnFileLogging() {
- Logger.global.setLevel(java.util.logging.Level.ALL);
- java.util.logging.Handler handler;
- handler = new ConsoleHandler();
- /*try {
- handler = new FileHandler(logfile); // this will overwrite
- }
- catch (IOException e) { //can't open log file so use console
- e.printStackTrace();
-
- } */
- Logger.global.addHandler(handler);
-
- handler.setFilter(new Filter() { // select what gets logged
- public boolean isLoggable(LogRecord record) {
- return true;
- }
- });
- }
-
- public static void setLanguage(String language, String country) {
- locale = new Locale(language, country);
- messages = ResourceBundle.getBundle(resourcePrefix, locale);
- menuTitles = ResourceBundle.getBundle(menuResourcePrefix, locale);
- intMessages = ResourceBundle.getBundle(integrityResourcePrefix, locale);
- Locale.setDefault(locale);
- javax.swing.JComponent.setDefaultLocale(locale);
- }
-
-
- public static JournalAbbreviations journalAbbrev;
-
-
- public static String lang(String key, String[] params) {
- String translation = null;
- try {
- if (Globals.messages != null) {
- translation = Globals.messages.getString(key.replaceAll(" ", "_"));
- }
- }
- catch (MissingResourceException ex) {
- translation = key;
-
- //Thread.dumpStack(); // For debugging
- logger("Warning: could not get translation for \""
- + key + "\"");
- }
- if ((translation != null) && (translation.length() != 0)) {
- translation = translation.replaceAll("_", " ");
- StringBuffer sb = new StringBuffer();
- boolean b = false;
- char c;
- for (int i = 0; i < translation.length(); ++i) {
- c = translation.charAt(i);
- if (c == '%') {
- b = true;
- } else {
- if (!b) {
- sb.append(c);
- } else {
- b = false;
- try {
- int index = Integer.parseInt(String.valueOf(c));
- if (params != null && index >= 0 && index <= params.length)
- sb.append(params[index]);
- } catch (NumberFormatException e) {
- // append literally (for quoting) or insert special symbol
- switch (c) {
- case 'c': // colon
- sb.append(':');
- break;
- case 'e': // equal
- sb.append('=');
- break;
- default: // anything else, e.g. %
- sb.append(c);
- }
- }
- }
- }
- }
- return sb.toString();
- }
- return key;
- }
-
- public static String lang(String key) {
- return lang(key, (String[])null);
- }
-
- public static String lang(String key, String s1) {
- return lang(key, new String[]{s1});
- }
-
- public static String lang(String key, String s1, String s2) {
- return lang(key, new String[]{s1, s2});
- }
-
- public static String lang(String key, String s1, String s2, String s3) {
- return lang(key, new String[]{s1, s2, s3});
- }
-
- public static String menuTitle(String key) {
- String translation = null;
- try {
- if (Globals.messages != null) {
- translation = Globals.menuTitles.getString(key.replaceAll(" ", "_"));
- }
- }
- catch (MissingResourceException ex) {
- translation = key;
-
- //System.err.println("Warning: could not get menu item translation for \""
- // + key + "\"");
-
- }
- if ((translation != null) && (translation.length() != 0)) {
- return translation.replaceAll("_", " ");
- }
- else {
- return key;
- }
- }
-
- public static String getIntegrityMessage(String key)
- {
- String translation = null;
- try {
- if (Globals.intMessages != null) {
- translation = Globals.intMessages.getString(key);
- }
- }
- catch (MissingResourceException ex) {
- translation = key;
-
-// System.err.println("Warning: could not get menu item translation for \""
-// + key + "\"");
- }
- if ((translation != null) && (translation.length() != 0)) {
- return translation ;
- }
- else {
- return key;
- }
- }
-
-
- //============================================================
- // Using the hashmap of entry types found in BibtexEntryType
- //============================================================
- public static BibtexEntryType getEntryType(String type) {
- // decide which entryType object to return
- Object o = BibtexEntryType.ALL_TYPES.get(type);
- if (o != null) {
- return (BibtexEntryType) o;
- }
- else {
- return BibtexEntryType.OTHER;
- }
- /*
- if(type.equals("article"))
- return BibtexEntryType.ARTICLE;
- else if(type.equals("book"))
- return BibtexEntryType.BOOK;
- else if(type.equals("inproceedings"))
- return BibtexEntryType.INPROCEEDINGS;
- */
- }
-
- /**
- * This method provides the correct opening brace to use when writing a field
- * to BibTeX format.
- * @return A String containing the braces to use.
- */
- public static String getOpeningBrace() {
- return "{";
- /*
- As of version 2.0, storing all fields with double braces is no longer supported, because
- it causes problems with e.g. the author field.
-
- if (prefs.getBoolean("autoDoubleBraces"))
- return "{{";
- else
- return "{";
- */
- }
-
- /**
- * This method provides the correct closing brace to use when writing a field
- * to BibTeX format.
- * @return A String containing the braces to use.
- */
- public static String getClosingBrace() {
- return "}";
- /*
- As of version 2.0, storing all fields with double braces is no longer supported, because
- it causes problems with e.g. the author field.
-
- if (prefs.getBoolean("autoDoubleBraces"))
- return "}}";
- else
- */
-
- }
-
- /* public static void setupKeyBindings(JabRefPreferences prefs) {
- }*/
-
-
- public static String[] getMultipleFiles(JFrame owner,
- File directory, String extension,
- boolean updateWorkingdirectory) {
-
- OpenFileFilter off = null;
- if (extension == null)
- off = new OpenFileFilter();
- else if (!extension.equals(NONE))
- off = new OpenFileFilter(extension);
- Object o = getNewFileImpl(owner, directory, extension, null, off,
- JFileChooser.OPEN_DIALOG, updateWorkingdirectory, false, true);
- String[] toReturn;
- if (o instanceof String[])
- toReturn = (String[])o;
- else toReturn = new String[] {(String)o};
-
- return toReturn;
- }
-
- public static String getNewFile(JFrame owner,
- File directory, String extension,
- int dialogType,
- boolean updateWorkingDirectory) {
- return getNewFile(owner, directory, extension, null, dialogType,
- updateWorkingDirectory, false);
- }
-
-
- public static String getNewFile(JFrame owner,
- File directory, String extension,
- String description,
- int dialogType,
- boolean updateWorkingDirectory) {
- return getNewFile(owner, directory, extension, description, dialogType,
- updateWorkingDirectory, false);
- }
-
-
- public static String getNewDir(JFrame owner,
- File directory, String extension,
- int dialogType, boolean updateWorkingDirectory) {
- return getNewFile(owner, directory, extension, null, dialogType,
- updateWorkingDirectory, true);
- }
-
- public static String getNewDir(JFrame owner,
- File directory, String extension,
- String description,
- int dialogType, boolean updateWorkingDirectory) {
- return getNewFile(owner, directory, extension, description, dialogType,
- updateWorkingDirectory, true);
- }
-
- private static String getNewFile(JFrame owner,
- File directory, String extension,
- String description,
- int dialogType,
- boolean updateWorkingDirectory,
- boolean dirOnly) {
-
- OpenFileFilter off = null;
-
- if (extension == null)
- off = new OpenFileFilter();
- else if (!extension.equals(NONE))
- off = new OpenFileFilter(extension);
-
- return (String)getNewFileImpl(owner, directory, extension, description, off,
- dialogType, updateWorkingDirectory, dirOnly, false);
- }
-
- private static Object getNewFileImpl(JFrame owner,
- File directory, String extension,
- String description,
- OpenFileFilter off,
- int dialogType,
- boolean updateWorkingDirectory,
- boolean dirOnly,
- boolean multipleSelection) {
-
- if (ON_MAC && prefs.getBoolean("useNativeFileDialogOnMac")) {
-
- return getNewFileForMac(owner, directory, extension, dialogType,
- updateWorkingDirectory, dirOnly, off);
- }
-
- JFileChooser fc = null;
- try {
- fc = new JabRefFileChooser(directory);
- } catch (InternalError errl) {
- // This try/catch clause was added because a user reported an
- // InternalError getting thrown on WinNT, presumably because of a
- // bug in JGoodies Windows PLAF. This clause can be removed if the
- // bug is fixed, but for now we just resort to the native file
- // dialog, using the same method as is always used on Mac:
- return getNewFileForMac(owner, directory, extension, dialogType,
- updateWorkingDirectory, dirOnly, off);
- }
-
- if (dirOnly) {
- fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
-
- }
-
- fc.setMultiSelectionEnabled(multipleSelection);
-
- fc.addChoosableFileFilter(off);
- fc.setDialogType(dialogType);
- int dialogResult;
- if (dialogType == JFileChooser.OPEN_DIALOG) {
- dialogResult = fc.showOpenDialog(owner);
- } else if (dialogType == JFileChooser.SAVE_DIALOG) {
- dialogResult = fc.showSaveDialog(owner);
- } else {
- dialogResult = fc.showDialog(owner, description);
- }
-
- // the getSelectedFile method returns a valid fileselection
- // (if something is selected) indepentently from dialog return status
- if (dialogResult != JFileChooser.APPROVE_OPTION)
- return null;
-
- // okay button
- File selectedFile = fc.getSelectedFile();
- if (selectedFile == null) { // cancel
- return null;
- }
-
- // If this is a save dialog, and the user has not chosen "All files" as filter
- // we enforce the given extension. But only if extension is not null.
- if ((extension != null) && (dialogType == JFileChooser.SAVE_DIALOG) && (fc.getFileFilter() == off) &&
- !off.accept(selectedFile)) {
-
- // add the first extension if there are multiple extensions
- selectedFile = new File(selectedFile.getPath() + extension.split("[, ]+", 0)[0]);
- }
-
- if (updateWorkingDirectory) {
- prefs.put("workingDirectory", selectedFile.getPath());
- }
-
- if (!multipleSelection)
- return selectedFile.getAbsolutePath();
- else {
- File[] files = fc.getSelectedFiles();
- String[] filenames = new String[files.length];
- for (int i=0; i<files.length; i++)
- filenames[i] = files[i].getAbsolutePath();
- return filenames;
- }
- }
-
- private static String getNewFileForMac(JFrame owner,
- File directory, String extensions,
- int dialogType,
- boolean updateWorkingDirectory,
- boolean dirOnly,
- FilenameFilter filter) {
-
- FileDialog fc = new FileDialog(owner);
-
- //fc.setFilenameFilter(filter);
- if (directory != null) {
- fc.setDirectory(directory.getParent());
- }
- if (dialogType == JFileChooser.OPEN_DIALOG) {
- fc.setMode(FileDialog.LOAD);
- }
- else {
- fc.setMode(FileDialog.SAVE);
- }
-
- fc.setVisible(true); // fc.show(); -> deprecated since 1.5
-
- if (fc.getFile() != null) {
- Globals.prefs.put("workingDirectory", fc.getDirectory() + fc.getFile());
- return fc.getDirectory() + fc.getFile();
- }
- else {
- return null;
- }
- }
-
-
- public static String SPECIAL_COMMAND_CHARS = "\"`^~'c";
- public static HashMap HTML_CHARS = new HashMap(),
- HTMLCHARS = new HashMap(),
- XML_CHARS = new HashMap(),
- ASCII2XML_CHARS = new HashMap(),
- UNICODE_CHARS = new HashMap(),
- RTFCHARS = new HashMap(),
- URL_CHARS = new HashMap();
- static {
-
- //System.out.println(journalAbbrev.getAbbreviatedName("Journal of Fish Biology", true));
- //System.out.println(journalAbbrev.getAbbreviatedName("Journal of Fish Biology", false));
- //System.out.println(journalAbbrev.getFullName("Aquaculture Eng."));
- /*for (Iterator i=journalAbbrev.fullNameIterator(); i.hasNext();) {
- String s = (String)i.next();
- System.out.println(journalAbbrev.getFullName(s)+" : "+journalAbbrev.getAbbreviatedName(s, true));
- } */
-
- // Start the thread that monitors file time stamps.
- //Util.pr("Starting FileUpdateMonitor thread. Globals line 293.");
- fileUpdateMonitor.start();
-
- try {
- SHORTCUT_MASK = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
- } catch (Throwable t) {
-
- }
-
- // Special characters in URLs need to be replaced to ensure that the URL
- // opens properly on all platforms:
- URL_CHARS.put("<", "%3c");
- URL_CHARS.put(">", "%3e");
- URL_CHARS.put("(", "%28");
- URL_CHARS.put(")", "%29");
- URL_CHARS.put(" ", "%20");
- URL_CHARS.put("&", "%26");
- URL_CHARS.put("$", "%24");
-
-
-
-// HTMLCHARS.put("\"a", "ä");
-// HTMLCHARS.put("\"A", "Ä");
-// HTMLCHARS.put("\"e", "ë");
-// HTMLCHARS.put("\"E", "Ë");
-// HTMLCHARS.put("\"i", "ï");
-// HTMLCHARS.put("\"I", "Ï");
-// HTMLCHARS.put("\"o", "ö");
-// HTMLCHARS.put("\"O", "Ö");
-// HTMLCHARS.put("\"u", "ü");
-// HTMLCHARS.put("\"U", "Ü");
-// HTMLCHARS.put("`a", "à");
-// HTMLCHARS.put("`A", "À");
-// HTMLCHARS.put("`e", "è");
-// HTMLCHARS.put("`E", "È");
-// HTMLCHARS.put("`i", "ì");
-// HTMLCHARS.put("`I", "Ì");
-// HTMLCHARS.put("`o", "ò");
-// HTMLCHARS.put("`O", "Ò");
-// HTMLCHARS.put("`u", "ù");
-// HTMLCHARS.put("`U", "Ù");
-// HTMLCHARS.put("'e", "é");
-// HTMLCHARS.put("'E", "É");
-// HTMLCHARS.put("'i", "í");
-// HTMLCHARS.put("'I", "Í");
-// HTMLCHARS.put("'o", "ó");
-// HTMLCHARS.put("'O", "Ó");
-// HTMLCHARS.put("'u", "ú");
-// HTMLCHARS.put("'U", "Ú");
-// HTMLCHARS.put("'a", "á");
-// HTMLCHARS.put("'A", "Á");
-// HTMLCHARS.put("^a", "ô");
-// HTMLCHARS.put("^A", "Ô");
-// HTMLCHARS.put("^o", "ô");
-// HTMLCHARS.put("^O", "Ô");
-// HTMLCHARS.put("^u", "û");
-// HTMLCHARS.put("^U", "Û");
-// HTMLCHARS.put("^e", "ê");
-// HTMLCHARS.put("^E", "Ê");
-// HTMLCHARS.put("^i", "î");
-// HTMLCHARS.put("^I", "Î");
-// HTMLCHARS.put("~o", "õ");
-// HTMLCHARS.put("~O", "Õ");
-// HTMLCHARS.put("~n", "ñ");
-// HTMLCHARS.put("~N", "Ñ");
-// HTMLCHARS.put("~a", "ã");
-// HTMLCHARS.put("~A", "Ã");
-// HTMLCHARS.put("cc", "ç");
-// HTMLCHARS.put("cC", "Ç");
-
-
- // Following character definitions contributed by Ervin Kolenovic:
- // HTML named entities from #192 - #255 (UNICODE Latin-1)
- HTMLCHARS.put("`A", "À"); // #192
- HTMLCHARS.put("'A", "Á"); // #193
- HTMLCHARS.put("^A", "Â"); // #194
- HTMLCHARS.put("~A", "Ã"); // #195
- HTMLCHARS.put("\"A", "Ä"); // #196
- HTMLCHARS.put("AA", "Å"); // #197
- HTMLCHARS.put("AE", "Æ"); // #198
- HTMLCHARS.put("cC", "Ç"); // #199
- HTMLCHARS.put("`E", "È"); // #200
- HTMLCHARS.put("'E", "É"); // #201
- HTMLCHARS.put("^E", "Ê"); // #202
- HTMLCHARS.put("\"E", "Ë"); // #203
- HTMLCHARS.put("`I", "Ì"); // #204
- HTMLCHARS.put("'I", "Í"); // #205
- HTMLCHARS.put("^I", "Î"); // #206
- HTMLCHARS.put("\"I", "Ï"); // #207
- HTMLCHARS.put("DH", "Ð"); // #208
- HTMLCHARS.put("~N", "Ñ"); // #209
- HTMLCHARS.put("`O", "Ò"); // #210
- HTMLCHARS.put("'O", "Ó"); // #211
- HTMLCHARS.put("^O", "Ô"); // #212
- HTMLCHARS.put("~O", "Õ"); // #213
- HTMLCHARS.put("\"O", "Ö"); // #214
- // According to ISO 8859-1 the "\times" symbol should be placed here (#215).
- // Omitting this, because it is a mathematical symbol.
- HTMLCHARS.put("O", "&OSlash;"); // #216
- HTMLCHARS.put("`U", "Ù"); // #217
- HTMLCHARS.put("'U", "Ú"); // #218
- HTMLCHARS.put("^U", "Û"); // #219
- HTMLCHARS.put("\"U", "Ü"); // #220
- HTMLCHARS.put("'Y", "Ý"); // #221
- HTMLCHARS.put("TH", "Þ"); // #222
- HTMLCHARS.put("ss", "ß"); // #223
- HTMLCHARS.put("`a", "à"); // #224
- HTMLCHARS.put("'a", "á"); // #225
- HTMLCHARS.put("^a", "â"); // #226
- HTMLCHARS.put("~a", "ã"); // #227
- HTMLCHARS.put("\"a", "ä"); // #228
- HTMLCHARS.put("aa", "å"); // #229
- HTMLCHARS.put("ae", "æ"); // #230
- HTMLCHARS.put("cc", "ç"); // #231
- HTMLCHARS.put("`e", "è"); // #232
- HTMLCHARS.put("'e", "é"); // #233
- HTMLCHARS.put("^e", "ê"); // #234
- HTMLCHARS.put("\"e", "ë"); // #235
- HTMLCHARS.put("`i", "ì"); // #236
- HTMLCHARS.put("'i", "í"); // #237
- HTMLCHARS.put("^i", "î"); // #238
- HTMLCHARS.put("\"i", "ï"); // #239
- HTMLCHARS.put("dh", "ð"); // #240
- HTMLCHARS.put("~n", "ñ"); // #241
- HTMLCHARS.put("`o", "ò"); // #242
- HTMLCHARS.put("'o", "ó"); // #243
- HTMLCHARS.put("^o", "ô"); // #244
- HTMLCHARS.put("~o", "õ"); // #245
- HTMLCHARS.put("\"o", "ö"); // #246
- // According to ISO 8859-1 the "\div" symbol should be placed here (#247).
- // Omitting this, because it is a mathematical symbol.
- HTMLCHARS.put("o", "ø"); // #248
- HTMLCHARS.put("`u", "ù"); // #249
- HTMLCHARS.put("'u", "ú"); // #250
- HTMLCHARS.put("^u", "û"); // #251
- HTMLCHARS.put("\"u", "ü"); // #252
- HTMLCHARS.put("'y", "ý"); // #253
- HTMLCHARS.put("th", "þ"); // #254
- HTMLCHARS.put("\"y", "ÿ"); // #255
-
- // HTML special characters without names (UNICODE Latin Extended-A), indicated by UNICODE number
- HTMLCHARS.put("=A", "Ā"); // "Amacr"
- HTMLCHARS.put("=a", "ā"); // "amacr"
- HTMLCHARS.put("uA", "Ă"); // "Abreve"
- HTMLCHARS.put("ua", "ă"); // "abreve"
- HTMLCHARS.put("kA", "Ą"); // "Aogon"
- HTMLCHARS.put("ka", "ą"); // "aogon"
- HTMLCHARS.put("'C", "Ć"); // "Cacute"
- HTMLCHARS.put("'c", "ć"); // "cacute"
- HTMLCHARS.put("^C", "Ĉ"); // "Ccirc"
- HTMLCHARS.put("^c", "ĉ"); // "ccirc"
- HTMLCHARS.put(".C", "Ċ"); // "Cdot"
- HTMLCHARS.put(".c", "ċ"); // "cdot"
- HTMLCHARS.put("vC", "Č"); // "Ccaron"
- HTMLCHARS.put("vc", "č"); // "ccaron"
- HTMLCHARS.put("vD", "Ď"); // "Dcaron"
- // Symbol #271 (d�) has no special Latex command
- HTMLCHARS.put("DJ", "Đ"); // "Dstrok"
- HTMLCHARS.put("dj", "đ"); // "dstrok"
- HTMLCHARS.put("=E", "Ē"); // "Emacr"
- HTMLCHARS.put("=e", "ē"); // "emacr"
- HTMLCHARS.put("uE", "Ĕ"); // "Ebreve"
- HTMLCHARS.put("ue", "ĕ"); // "ebreve"
- HTMLCHARS.put(".E", "Ė"); // "Edot"
- HTMLCHARS.put(".e", "ė"); // "edot"
- HTMLCHARS.put("kE", "Ę"); // "Eogon"
- HTMLCHARS.put("ke", "ę"); // "eogon"
- HTMLCHARS.put("vE", "Ě"); // "Ecaron"
- HTMLCHARS.put("ve", "ě"); // "ecaron"
- HTMLCHARS.put("^G", "Ĝ"); // "Gcirc"
- HTMLCHARS.put("^g", "ĝ"); // "gcirc"
- HTMLCHARS.put("uG", "Ğ"); // "Gbreve"
- HTMLCHARS.put("ug", "ğ"); // "gbreve"
- HTMLCHARS.put(".G", "Ġ"); // "Gdot"
- HTMLCHARS.put(".g", "ġ"); // "gdot"
- HTMLCHARS.put("cG", "Ģ"); // "Gcedil"
- HTMLCHARS.put("'g", "ģ"); // "gacute"
- HTMLCHARS.put("^H", "Ĥ"); // "Hcirc"
- HTMLCHARS.put("^h", "ĥ"); // "hcirc"
- HTMLCHARS.put("Hstrok", "Ħ"); // "Hstrok"
- HTMLCHARS.put("hstrok", "ħ"); // "hstrok"
- HTMLCHARS.put("~I", "Ĩ"); // "Itilde"
- HTMLCHARS.put("~i", "ĩ"); // "itilde"
- HTMLCHARS.put("=I", "Ī"); // "Imacr"
- HTMLCHARS.put("=i", "ī"); // "imacr"
- HTMLCHARS.put("uI", "Ĭ"); // "Ibreve"
- HTMLCHARS.put("ui", "ĭ"); // "ibreve"
- HTMLCHARS.put("kI", "Į"); // "Iogon"
- HTMLCHARS.put("ki", "į"); // "iogon"
- HTMLCHARS.put(".I", "İ"); // "Idot"
- HTMLCHARS.put("i", "ı"); // "inodot"
- // Symbol #306 (IJ) has no special Latex command
- // Symbol #307 (ij) has no special Latex command
- HTMLCHARS.put("^J", "Ĵ"); // "Jcirc"
- HTMLCHARS.put("^j", "ĵ"); // "jcirc"
- HTMLCHARS.put("cK", "Ķ"); // "Kcedil"
- HTMLCHARS.put("ck", "ķ"); // "kcedil"
- // Symbol #312 (k) has no special Latex command
- HTMLCHARS.put("'L", "Ĺ"); // "Lacute"
- HTMLCHARS.put("'l", "ĺ"); // "lacute"
- HTMLCHARS.put("cL", "Ļ"); // "Lcedil"
- HTMLCHARS.put("cl", "ļ"); // "lcedil"
- // Symbol #317 (L�) has no special Latex command
- // Symbol #318 (l�) has no special Latex command
- HTMLCHARS.put("Lmidot", "Ŀ"); // "Lmidot"
- HTMLCHARS.put("lmidot", "ŀ"); // "lmidot"
- HTMLCHARS.put("L", "Ł"); // "Lstrok"
- HTMLCHARS.put("l", "ł"); // "lstrok"
- HTMLCHARS.put("'N", "Ń"); // "Nacute"
- HTMLCHARS.put("'n", "ń"); // "nacute"
- HTMLCHARS.put("cN", "Ņ"); // "Ncedil"
- HTMLCHARS.put("cn", "ņ"); // "ncedil"
- HTMLCHARS.put("vN", "Ň"); // "Ncaron"
- HTMLCHARS.put("vn", "ň"); // "ncaron"
- // Symbol #329 (�n) has no special Latex command
- HTMLCHARS.put("NG", "Ŋ"); // "ENG"
- HTMLCHARS.put("ng", "ŋ"); // "eng"
- HTMLCHARS.put("=O", "Ō"); // "Omacr"
- HTMLCHARS.put("=o", "ō"); // "omacr"
- HTMLCHARS.put("uO", "Ŏ"); // "Obreve"
- HTMLCHARS.put("uo", "ŏ"); // "obreve"
- HTMLCHARS.put("HO", "Ő"); // "Odblac"
- HTMLCHARS.put("Ho", "ő"); // "odblac"
- HTMLCHARS.put("OE", "Œ"); // "OElig"
- HTMLCHARS.put("oe", "œ"); // "oelig"
- HTMLCHARS.put("'R", "Ŕ"); // "Racute"
- HTMLCHARS.put("'r", "ŕ"); // "racute"
- HTMLCHARS.put("cR", "Ŗ"); // "Rcedil"
- HTMLCHARS.put("cr", "ŗ"); // "rcedil"
- HTMLCHARS.put("vR", "Ř"); // "Rcaron"
- HTMLCHARS.put("vr", "ř"); // "rcaron"
- HTMLCHARS.put("'S", "Ś"); // "Sacute"
- HTMLCHARS.put("'s", "ś"); // "sacute"
- HTMLCHARS.put("^S", "Ŝ"); // "Scirc"
- HTMLCHARS.put("^s", "ŝ"); // "scirc"
- HTMLCHARS.put("cS", "Ş"); // "Scedil"
- HTMLCHARS.put("cs", "ş"); // "scedil"
- HTMLCHARS.put("vS", "Š"); // "Scaron"
- HTMLCHARS.put("vs", "š"); // "scaron"
- HTMLCHARS.put("cT", "Ţ"); // "Tcedil"
- HTMLCHARS.put("ct", "ţ"); // "tcedil"
- HTMLCHARS.put("vT", "Ť"); // "Tcaron"
- // Symbol #357 (t�) has no special Latex command
- HTMLCHARS.put("Tstrok", "Ŧ"); // "Tstrok"
- HTMLCHARS.put("tstrok", "ŧ"); // "tstrok"
- HTMLCHARS.put("~U", "Ũ"); // "Utilde"
- HTMLCHARS.put("~u", "ũ"); // "utilde"
- HTMLCHARS.put("=U", "Ū"); // "Umacr"
- HTMLCHARS.put("=u", "ū"); // "umacr"
- HTMLCHARS.put("uU", "Ŭ"); // "Ubreve"
- HTMLCHARS.put("uu", "ŭ"); // "ubreve"
- HTMLCHARS.put("rU", "Ů"); // "Uring"
- HTMLCHARS.put("ru", "ů"); // "uring"
- HTMLCHARS.put("HU", "Ű"); // "Odblac"
- HTMLCHARS.put("Hu", "ű"); // "odblac"
- HTMLCHARS.put("kU", "Ų"); // "Uogon"
- HTMLCHARS.put("ku", "ų"); // "uogon"
- HTMLCHARS.put("^W", "Ŵ"); // "Wcirc"
- HTMLCHARS.put("^w", "ŵ"); // "wcirc"
- HTMLCHARS.put("^Y", "Ŷ"); // "Ycirc"
- HTMLCHARS.put("^y", "ŷ"); // "ycirc"
- HTMLCHARS.put("\"Y", "Ÿ"); // "Yuml"
- HTMLCHARS.put("'Z", "Ź"); // "Zacute"
- HTMLCHARS.put("'z", "ź"); // "zacute"
- HTMLCHARS.put(".Z", "Ż"); // "Zdot"
- HTMLCHARS.put(".z", "ż"); // "zdot"
- HTMLCHARS.put("vZ", "Ž"); // "Zcaron"
- HTMLCHARS.put("vz", "ž"); // "zcaron"
- // Symbol #383 (f) has no special Latex command
-
-
- XML_CHARS.put("\\{\\\\\\\"\\{a\\}\\}", "ä");
- XML_CHARS.put("\\{\\\\\\\"\\{A\\}\\}", "Ä");
- XML_CHARS.put("\\{\\\\\\\"\\{e\\}\\}", "ë");
- XML_CHARS.put("\\{\\\\\\\"\\{E\\}\\}", "Ë");
- XML_CHARS.put("\\{\\\\\\\"\\{i\\}\\}", "ï");
- XML_CHARS.put("\\{\\\\\\\"\\{I\\}\\}", "Ï");
- XML_CHARS.put("\\{\\\\\\\"\\{o\\}\\}", "ö");
- XML_CHARS.put("\\{\\\\\\\"\\{O\\}\\}", "Ö");
- XML_CHARS.put("\\{\\\\\\\"\\{u\\}\\}", "ü");
- XML_CHARS.put("\\{\\\\\\\"\\{U\\}\\}", "Ü");
-
- XML_CHARS.put("\\{\\\\\\`\\{e\\}\\}", "è");
- XML_CHARS.put("\\{\\\\\\`\\{E\\}\\}", "È");
- XML_CHARS.put("\\{\\\\\\`\\{i\\}\\}", "ì");
- XML_CHARS.put("\\{\\\\\\`\\{I\\}\\}", "Ì");
- XML_CHARS.put("\\{\\\\\\`\\{o\\}\\}", "ò");
- XML_CHARS.put("\\{\\\\\\`\\{O\\}\\}", "Ò");
- XML_CHARS.put("\\{\\\\\\`\\{u\\}\\}", "ù");
- XML_CHARS.put("\\{\\\\\\`\\{U\\}\\}", "Ù");
- XML_CHARS.put("\\{\\\\\\'\\{e\\}\\}", "é");
- XML_CHARS.put("\\{\\\\\\\uFFFD\\{E\\}\\}", "É");
- XML_CHARS.put("\\{\\\\\\\uFFFD\\{i\\}\\}", "í");
- XML_CHARS.put("\\{\\\\\\\uFFFD\\{I\\}\\}", "Í");
- XML_CHARS.put("\\{\\\\\\\uFFFD\\{o\\}\\}", "ó");
- XML_CHARS.put("\\{\\\\\\\uFFFD\\{O\\}\\}", "Ó");
- XML_CHARS.put("\\{\\\\\\\uFFFD\\{u\\}\\}", "ú");
- XML_CHARS.put("\\{\\\\\\\uFFFD\\{U\\}\\}", "Ú");
- XML_CHARS.put("\\{\\\\\\\uFFFD\\{a\\}\\}", "á");
- XML_CHARS.put("\\{\\\\\\\uFFFD\\{A\\}\\}", "Á");
-
- XML_CHARS.put("\\{\\\\\\^\\{o\\}\\}", "ô");
- XML_CHARS.put("\\{\\\\\\^\\{O\\}\\}", "Ô");
- XML_CHARS.put("\\{\\\\\\^\\{u\\}\\}", "ù");
- XML_CHARS.put("\\{\\\\\\^\\{U\\}\\}", "Ù");
- XML_CHARS.put("\\{\\\\\\^\\{e\\}\\}", "ê");
- XML_CHARS.put("\\{\\\\\\^\\{E\\}\\}", "Ê");
- XML_CHARS.put("\\{\\\\\\^\\{i\\}\\}", "î");
- XML_CHARS.put("\\{\\\\\\^\\{I\\}\\}", "Î");
- XML_CHARS.put("\\{\\\\\\~\\{o\\}\\}", "õ");
- XML_CHARS.put("\\{\\\\\\~\\{O\\}\\}", "Õ");
- XML_CHARS.put("\\{\\\\\\~\\{n\\}\\}", "ñ");
- XML_CHARS.put("\\{\\\\\\~\\{N\\}\\}", "Ñ");
- XML_CHARS.put("\\{\\\\\\~\\{a\\}\\}", "ã");
- XML_CHARS.put("\\{\\\\\\~\\{A\\}\\}", "Ã");
-
-
- XML_CHARS.put("\\{\\\\\\\"a\\}", "ä");
- XML_CHARS.put("\\{\\\\\\\"A\\}", "Ä");
- XML_CHARS.put("\\{\\\\\\\"e\\}", "ë");
- XML_CHARS.put("\\{\\\\\\\"E\\}", "Ë");
- XML_CHARS.put("\\{\\\\\\\"i\\}", "ï");
- XML_CHARS.put("\\{\\\\\\\"I\\}", "Ï");
- XML_CHARS.put("\\{\\\\\\\"o\\}", "ö");
- XML_CHARS.put("\\{\\\\\\\"O\\}", "Ö");
- XML_CHARS.put("\\{\\\\\\\"u\\}", "ü");
- XML_CHARS.put("\\{\\\\\\\"U\\}", "Ü");
-
- XML_CHARS.put("\\{\\\\\\`e\\}", "è");
- XML_CHARS.put("\\{\\\\\\`E\\}", "È");
- XML_CHARS.put("\\{\\\\\\`i\\}", "ì");
- XML_CHARS.put("\\{\\\\\\`I\\}", "Ì");
- XML_CHARS.put("\\{\\\\\\`o\\}", "ò");
- XML_CHARS.put("\\{\\\\\\`O\\}", "Ò");
- XML_CHARS.put("\\{\\\\\\`u\\}", "ù");
- XML_CHARS.put("\\{\\\\\\`U\\}", "Ù");
- XML_CHARS.put("\\{\\\\\\'e\\}", "é");
- XML_CHARS.put("\\{\\\\\\'E\\}", "É");
- XML_CHARS.put("\\{\\\\\\'i\\}", "í");
- XML_CHARS.put("\\{\\\\\\'I\\}", "Í");
- XML_CHARS.put("\\{\\\\\\'o\\}", "ó");
- XML_CHARS.put("\\{\\\\\\'O\\}", "Ó");
- XML_CHARS.put("\\{\\\\\\'u\\}", "ú");
- XML_CHARS.put("\\{\\\\\\'U\\}", "Ú");
- XML_CHARS.put("\\{\\\\\\'a\\}", "á");
- XML_CHARS.put("\\{\\\\\\'A\\}", "Á");
-
- XML_CHARS.put("\\{\\\\\\^a\\}", "ô");
- XML_CHARS.put("\\{\\\\\\^A\\}", "Ô");
- XML_CHARS.put("\\{\\\\\\^o\\}", "ô");
- XML_CHARS.put("\\{\\\\\\^O\\}", "Ô");
- XML_CHARS.put("\\{\\\\\\^u\\}", "ù");
- XML_CHARS.put("\\{\\\\\\^U\\}", "Ù");
- XML_CHARS.put("\\{\\\\\\^e\\}", "ê");
- XML_CHARS.put("\\{\\\\\\^E\\}", "Ê");
- XML_CHARS.put("\\{\\\\\\^i\\}", "î");
- XML_CHARS.put("\\{\\\\\\^I\\}", "Î");
- XML_CHARS.put("\\{\\\\\\~o\\}", "õ");
- XML_CHARS.put("\\{\\\\\\~O\\}", "Õ");
- XML_CHARS.put("\\{\\\\\\~n\\}", "ñ");
- XML_CHARS.put("\\{\\\\\\~N\\}", "Ñ");
- XML_CHARS.put("\\{\\\\\\~a\\}", "ã");
- XML_CHARS.put("\\{\\\\\\~A\\}", "Ã");
-
- ASCII2XML_CHARS.put("<", "<");
- ASCII2XML_CHARS.put("\"", """);
- ASCII2XML_CHARS.put(">", ">");
-
-
- UNICODE_CHARS.put("\u00C0", "A");
- UNICODE_CHARS.put("\u00C1", "A");
- UNICODE_CHARS.put("\u00C2", "A");
- UNICODE_CHARS.put("\u00C3", "A");
- UNICODE_CHARS.put("\u00C4", "A");
- UNICODE_CHARS.put("\u00C5", "Aa");
- UNICODE_CHARS.put("\u00C6", "Ae");
- UNICODE_CHARS.put("\u00C7", "C");
- UNICODE_CHARS.put("\u00C8", "E");
- UNICODE_CHARS.put("\u00C9", "E");
- UNICODE_CHARS.put("\u00CA", "E");
- UNICODE_CHARS.put("\u00CB", "E");
- UNICODE_CHARS.put("\u00CC", "I");
- UNICODE_CHARS.put("\u00CD", "I");
- UNICODE_CHARS.put("\u00CE", "I");
- UNICODE_CHARS.put("\u00CF", "I");
- UNICODE_CHARS.put("\u00D0", "D");
- UNICODE_CHARS.put("\u00D1", "N");
- UNICODE_CHARS.put("\u00D2", "O");
- UNICODE_CHARS.put("\u00D3", "O");
- UNICODE_CHARS.put("\u00D4", "O");
- UNICODE_CHARS.put("\u00D5", "O");
- UNICODE_CHARS.put("\u00D6", "Oe");
- UNICODE_CHARS.put("\u00D8", "Oe");
- UNICODE_CHARS.put("\u00D9", "U");
- UNICODE_CHARS.put("\u00DA", "U");
- UNICODE_CHARS.put("\u00DB", "U");
- UNICODE_CHARS.put("\u00DC", "Ue"); // U umlaut ..
- UNICODE_CHARS.put("\u00DD", "Y");
- UNICODE_CHARS.put("\u00DF", "ss");
- UNICODE_CHARS.put("\u00E0", "a");
- UNICODE_CHARS.put("\u00E1", "a");
- UNICODE_CHARS.put("\u00E2", "a");
- UNICODE_CHARS.put("\u00E3", "a");
- UNICODE_CHARS.put("\u00E4", "ae");
- UNICODE_CHARS.put("\u00E5", "aa");
- UNICODE_CHARS.put("\u00E6", "ae");
- UNICODE_CHARS.put("\u00E7", "c");
- UNICODE_CHARS.put("\u00E8", "e");
- UNICODE_CHARS.put("\u00E9", "e");
- UNICODE_CHARS.put("\u00EA", "e");
- UNICODE_CHARS.put("\u00EB", "e");
- UNICODE_CHARS.put("\u00EC", "i");
- UNICODE_CHARS.put("\u00ED", "i");
- UNICODE_CHARS.put("\u00EE", "i");
- UNICODE_CHARS.put("\u00EF", "i");
- UNICODE_CHARS.put("\u00F0", "o");
- UNICODE_CHARS.put("\u00F1", "n");
- UNICODE_CHARS.put("\u00F2", "o");
- UNICODE_CHARS.put("\u00F3", "o");
- UNICODE_CHARS.put("\u00F4", "o");
- UNICODE_CHARS.put("\u00F5", "o");
- UNICODE_CHARS.put("\u00F6", "oe");
- UNICODE_CHARS.put("\u00F8", "oe");
- UNICODE_CHARS.put("\u00F9", "u");
- UNICODE_CHARS.put("\u00FA", "u");
- UNICODE_CHARS.put("\u00FB", "u");
- UNICODE_CHARS.put("\u00FC", "ue"); // u umlaut...
- UNICODE_CHARS.put("\u00FD", "y");
- UNICODE_CHARS.put("\u00FF", "y");
- UNICODE_CHARS.put("\u0100", "A");
- UNICODE_CHARS.put("\u0101", "a");
- UNICODE_CHARS.put("\u0102", "A");
- UNICODE_CHARS.put("\u0103", "a");
- UNICODE_CHARS.put("\u0104", "A");
- UNICODE_CHARS.put("\u0105", "a");
- UNICODE_CHARS.put("\u0106", "C");
- UNICODE_CHARS.put("\u0107", "c");
- UNICODE_CHARS.put("\u0108", "C");
- UNICODE_CHARS.put("\u0109", "c");
- UNICODE_CHARS.put("\u010A", "C");
- UNICODE_CHARS.put("\u010B", "c");
- UNICODE_CHARS.put("\u010C", "C");
- UNICODE_CHARS.put("\u010D", "c");
- UNICODE_CHARS.put("\u010E", "D");
- UNICODE_CHARS.put("\u010F", "d");
- UNICODE_CHARS.put("\u0110", "D");
- UNICODE_CHARS.put("\u0111", "d");
- UNICODE_CHARS.put("\u0112", "E");
- UNICODE_CHARS.put("\u0113", "e");
- UNICODE_CHARS.put("\u0114", "E");
- UNICODE_CHARS.put("\u0115", "e");
- UNICODE_CHARS.put("\u0116", "E");
- UNICODE_CHARS.put("\u0117", "e");
- UNICODE_CHARS.put("\u0118", "E");
- UNICODE_CHARS.put("\u0119", "e");
- UNICODE_CHARS.put("\u011A", "E");
- UNICODE_CHARS.put("\u011B", "e");
- UNICODE_CHARS.put("\u011C", "G");
- UNICODE_CHARS.put("\u011D", "g");
- UNICODE_CHARS.put("\u011E", "G");
- UNICODE_CHARS.put("\u011F", "g");
- UNICODE_CHARS.put("\u0120", "G");
- UNICODE_CHARS.put("\u0121", "g");
- UNICODE_CHARS.put("\u0122", "G");
- UNICODE_CHARS.put("\u0123", "g");
- UNICODE_CHARS.put("\u0124", "H");
- UNICODE_CHARS.put("\u0125", "h");
- UNICODE_CHARS.put("\u0127", "h");
- UNICODE_CHARS.put("\u0128", "I");
- UNICODE_CHARS.put("\u0129", "i");
- UNICODE_CHARS.put("\u012A", "I");
- UNICODE_CHARS.put("\u012B", "i");
- UNICODE_CHARS.put("\u012C", "I");
- UNICODE_CHARS.put("\u012D", "i");
- //UNICODE_CHARS.put("\u0100", "");
-
- RTFCHARS.put("`a", "\\'e0");
- RTFCHARS.put("`e", "\\'e8");
- RTFCHARS.put("`i", "\\'ec");
- RTFCHARS.put("`o", "\\'f2");
- RTFCHARS.put("`u", "\\'f9");
- RTFCHARS.put("?a", "\\'e1");
- RTFCHARS.put("?e", "\\'e9");
- RTFCHARS.put("?i", "\\'ed");
- RTFCHARS.put("?o", "\\'f3");
- RTFCHARS.put("?u", "\\'fa");
- RTFCHARS.put("^a", "\\'e2");
- RTFCHARS.put("^e", "\\'ea");
- RTFCHARS.put("^i", "\\'ee");
- RTFCHARS.put("^o", "\\'f4");
- RTFCHARS.put("^u", "\\'fa");
- RTFCHARS.put("\"a", "\\'e4");
- RTFCHARS.put("\"e", "\\'eb");
- RTFCHARS.put("\"i", "\\'ef");
- RTFCHARS.put("\"o", "\\'f6");
- RTFCHARS.put("\"u", "\\uc0\\u252");
- RTFCHARS.put("~n", "\\'f1");
- RTFCHARS.put("`A", "\\'c0");
- RTFCHARS.put("`E", "\\'c8");
- RTFCHARS.put("`I", "\\'cc");
- RTFCHARS.put("`O", "\\'d2");
- RTFCHARS.put("`U", "\\'d9");
- RTFCHARS.put("?A", "\\'c1");
- RTFCHARS.put("?E", "\\'c9");
- RTFCHARS.put("?I", "\\'cd");
- RTFCHARS.put("?O", "\\'d3");
- RTFCHARS.put("?U", "\\'da");
- RTFCHARS.put("^A", "\\'c2");
- RTFCHARS.put("^E", "\\'ca");
- RTFCHARS.put("^I", "\\'ce");
- RTFCHARS.put("^O", "\\'d4");
- RTFCHARS.put("^U", "\\'db");
- RTFCHARS.put("\"A", "\\'c4");
- RTFCHARS.put("\"E", "\\'cb");
- RTFCHARS.put("\"I", "\\'cf");
- RTFCHARS.put("\"O", "\\'d6");
- RTFCHARS.put("\"U", "\\'dc");
- // Use UNICODE characters for RTF-Chars which can not be found in the standard codepage
-
- // RTFCHARS.put("`A", "\\uc0\\u192"); // "Agrave" exists in standard codepage
- RTFCHARS.put("'A", "\\uc0\\u193"); // "Aacute"
-// RTFCHARS.put("^A", "\\uc0\\u194"); // "Acirc" exists in standard codepage
- RTFCHARS.put("~A", "\\uc0\\u195"); // "Atilde"
-// RTFCHARS.put("\"A", "\\uc0\\u196"); // "Auml" exists in standard codepage
- RTFCHARS.put("AA", "\\uc0\\u197"); // "Aring"
- RTFCHARS.put("AE", "\\uc0\\u198"); // "AElig"
- RTFCHARS.put("cC", "\\uc0\\u199"); // "Ccedil"
-// RTFCHARS.put("`E", "\\uc0\\u200"); // "Egrave" exists in standard codepage
- RTFCHARS.put("'E", "\\uc0\\u201"); // "Eacute"
-// RTFCHARS.put("^E", "\\uc0\\u202"); // "Ecirc" exists in standard codepage
-// RTFCHARS.put("\"E", "\\uc0\\u203"); // "Euml" exists in standard codepage
-// RTFCHARS.put("`I", "\\uc0\\u204"); // "Igrave" exists in standard codepage
- RTFCHARS.put("'I", "\\uc0\\u205"); // "Iacute"
-// RTFCHARS.put("^I", "\\uc0\\u206"); // "Icirc" exists in standard codepage
-// RTFCHARS.put("\"I", "\\uc0\\u207"); // "Iuml" exists in standard codepage
- RTFCHARS.put("DH", "\\uc0\\u208"); // "ETH"
- RTFCHARS.put("~N", "\\uc0\\u209"); // "Ntilde"
-// RTFCHARS.put("`O", "\\uc0\\u210"); // "Ograve" exists in standard codepage
- RTFCHARS.put("'O", "\\uc0\\u211"); // "Oacute"
-// RTFCHARS.put("^O", "\\uc0\\u212"); // "Ocirc" exists in standard codepage
- RTFCHARS.put("~O", "\\uc0\\u213"); // "Otilde"
-// RTFCHARS.put("\"O", "\\uc0\\u214"); // "Ouml" exists in standard codepage
- // According to ISO 8859-1 the "\times" symbol should be placed here (#215).
- // Omitting this, because it is a mathematical symbol.
- RTFCHARS.put("O", "\\uc0\\u216"); // "OSlash"
-// RTFCHARS.put("`U", "\\uc0\\u217"); // "Ugrave" exists in standard codepage
- RTFCHARS.put("'U", "\\uc0\\u218"); // "Uacute"
-// RTFCHARS.put("^U", "\\uc0\\u219"); // "Ucirc" exists in standard codepage
-// RTFCHARS.put("\"U", "\\uc0\\u220"); // "Uuml" exists in standard codepage
- RTFCHARS.put("'Y", "\\uc0\\u221"); // "Yacute"
- RTFCHARS.put("TH", "\\uc0\\u222"); // "THORN"
- RTFCHARS.put("ss", "\\uc0\\u223"); // "szlig"
-// RTFCHARS.put("`a", "\\uc0\\u224"); // "agrave" exists in standard codepage
- RTFCHARS.put("'a", "\\uc0\\u225"); // "aacute"
-// RTFCHARS.put("^a", "\\uc0\\u226"); // "acirc" exists in standard codepage
- RTFCHARS.put("~a", "\\uc0\\u227"); // "atilde"
-// RTFCHARS.put("\"a", "\\uc0\\u228"); // "auml" exists in standard codepage
- RTFCHARS.put("aa", "\\uc0\\u229"); // "aring"
- RTFCHARS.put("ae", "\\uc0\\u230"); // "aelig"
- RTFCHARS.put("cc", "\\uc0\\u231"); // "ccedil"
-// RTFCHARS.put("`e", "\\uc0\\u232"); // "egrave" exists in standard codepage
- RTFCHARS.put("'e", "\\uc0\\u233"); // "eacute"
-// RTFCHARS.put("^e", "\\uc0\\u234"); // "ecirc" exists in standard codepage
-// RTFCHARS.put("\"e", "\\uc0\\u235"); // "euml" exists in standard codepage
-// RTFCHARS.put("`i", "\\uc0\\u236"); // "igrave" exists in standard codepage
- RTFCHARS.put("'i", "\\uc0\\u237"); // "iacute"
-// RTFCHARS.put("^i", "\\uc0\\u238"); // "icirc" exists in standard codepage
-// RTFCHARS.put("\"i", "\\uc0\\u239"); // "iuml" exists in standard codepage
- RTFCHARS.put("dh", "\\uc0\\u240"); // "eth"
-// RTFCHARS.put("~n", "\\uc0\\u241"); // "ntilde" exists in standard codepage
-// RTFCHARS.put("`o", "\\uc0\\u242"); // "ograve" exists in standard codepage
- RTFCHARS.put("'o", "\\uc0\\u243"); // "oacute"
-// RTFCHARS.put("^o", "\\uc0\\u244"); // "ocirc" exists in standard codepage
- RTFCHARS.put("~o", "\\uc0\\u245"); // "otilde"
-// RTFCHARS.put("\"o", "\\uc0\\u246"); // "ouml" exists in standard codepage
- // According to ISO 8859-1 the "\div" symbol should be placed here (#247).
- // Omitting this, because it is a mathematical symbol.
- RTFCHARS.put("o", "\\uc0\\u248"); // "oslash"
-// RTFCHARS.put("`u", "\\uc0\\u249"); // "ugrave" exists in standard codepage
- RTFCHARS.put("'u", "\\uc0\\u250"); // "uacute"
-// RTFCHARS.put("^u", "\\uc0\\u251"); // "ucirc" exists in standard codepage
-// RTFCHARS.put("\"u", "\\uc0\\u252"); // "uuml" exists in standard codepage
- RTFCHARS.put("'y", "\\uc0\\u253"); // "yacute"
- RTFCHARS.put("th", "\\uc0\\u254"); // "thorn"
- RTFCHARS.put("\"y", "\\uc0\\u255"); // "yuml"
-
- RTFCHARS.put("=A", "\\uc0\\u256"); // "Amacr"
- RTFCHARS.put("=a", "\\uc0\\u257"); // "amacr"
- RTFCHARS.put("uA", "\\uc0\\u258"); // "Abreve"
- RTFCHARS.put("ua", "\\uc0\\u259"); // "abreve"
- RTFCHARS.put("kA", "\\uc0\\u260"); // "Aogon"
- RTFCHARS.put("ka", "\\uc0\\u261"); // "aogon"
- RTFCHARS.put("'C", "\\uc0\\u262"); // "Cacute"
- RTFCHARS.put("'c", "\\uc0\\u263"); // "cacute"
- RTFCHARS.put("^C", "\\uc0\\u264"); // "Ccirc"
- RTFCHARS.put("^c", "\\uc0\\u265"); // "ccirc"
- RTFCHARS.put(".C", "\\uc0\\u266"); // "Cdot"
- RTFCHARS.put(".c", "\\uc0\\u267"); // "cdot"
- RTFCHARS.put("vC", "\\uc0\\u268"); // "Ccaron"
- RTFCHARS.put("vc", "\\uc0\\u269"); // "ccaron"
- RTFCHARS.put("vD", "\\uc0\\u270"); // "Dcaron"
- // Symbol #271 (d�) has no special Latex command
- RTFCHARS.put("DJ", "\\uc0\\u272"); // "Dstrok"
- RTFCHARS.put("dj", "\\uc0\\u273"); // "dstrok"
- RTFCHARS.put("=E", "\\uc0\\u274"); // "Emacr"
- RTFCHARS.put("=e", "\\uc0\\u275"); // "emacr"
- RTFCHARS.put("uE", "\\uc0\\u276"); // "Ebreve"
- RTFCHARS.put("ue", "\\uc0\\u277"); // "ebreve"
- RTFCHARS.put(".E", "\\uc0\\u278"); // "Edot"
- RTFCHARS.put(".e", "\\uc0\\u279"); // "edot"
- RTFCHARS.put("kE", "\\uc0\\u280"); // "Eogon"
- RTFCHARS.put("ke", "\\uc0\\u281"); // "eogon"
- RTFCHARS.put("vE", "\\uc0\\u282"); // "Ecaron"
- RTFCHARS.put("ve", "\\uc0\\u283"); // "ecaron"
- RTFCHARS.put("^G", "\\uc0\\u284"); // "Gcirc"
- RTFCHARS.put("^g", "\\uc0\\u285"); // "gcirc"
- RTFCHARS.put("uG", "\\uc0\\u286"); // "Gbreve"
- RTFCHARS.put("ug", "\\uc0\\u287"); // "gbreve"
- RTFCHARS.put(".G", "\\uc0\\u288"); // "Gdot"
- RTFCHARS.put(".g", "\\uc0\\u289"); // "gdot"
- RTFCHARS.put("cG", "\\uc0\\u290"); // "Gcedil"
- RTFCHARS.put("'g", "\\uc0\\u291"); // "gacute"
- RTFCHARS.put("^H", "\\uc0\\u292"); // "Hcirc"
- RTFCHARS.put("^h", "\\uc0\\u293"); // "hcirc"
- RTFCHARS.put("Hstrok", "\\uc0\\u294"); // "Hstrok"
- RTFCHARS.put("hstrok", "\\uc0\\u295"); // "hstrok"
- RTFCHARS.put("~I", "\\uc0\\u296"); // "Itilde"
- RTFCHARS.put("~i", "\\uc0\\u297"); // "itilde"
- RTFCHARS.put("=I", "\\uc0\\u298"); // "Imacr"
- RTFCHARS.put("=i", "\\uc0\\u299"); // "imacr"
- RTFCHARS.put("uI", "\\uc0\\u300"); // "Ibreve"
- RTFCHARS.put("ui", "\\uc0\\u301"); // "ibreve"
- RTFCHARS.put("kI", "\\uc0\\u302"); // "Iogon"
- RTFCHARS.put("ki", "\\uc0\\u303"); // "iogon"
- RTFCHARS.put(".I", "\\uc0\\u304"); // "Idot"
- RTFCHARS.put("i", "\\uc0\\u305"); // "inodot"
- // Symbol #306 (IJ) has no special Latex command
- // Symbol #307 (ij) has no special Latex command
- RTFCHARS.put("^J", "\\uc0\\u308"); // "Jcirc"
- RTFCHARS.put("^j", "\\uc0\\u309"); // "jcirc"
- RTFCHARS.put("cK", "\\uc0\\u310"); // "Kcedil"
- RTFCHARS.put("ck", "\\uc0\\u311"); // "kcedil"
- // Symbol #312 (k) has no special Latex command
- RTFCHARS.put("'L", "\\uc0\\u313"); // "Lacute"
- RTFCHARS.put("'l", "\\uc0\\u314"); // "lacute"
- RTFCHARS.put("cL", "\\uc0\\u315"); // "Lcedil"
- RTFCHARS.put("cl", "\\uc0\\u316"); // "lcedil"
- // Symbol #317 (L�) has no special Latex command
- // Symbol #318 (l�) has no special Latex command
- RTFCHARS.put("Lmidot", "\\uc0\\u319"); // "Lmidot"
- RTFCHARS.put("lmidot", "\\uc0\\u320"); // "lmidot"
- RTFCHARS.put("L", "\\uc0\\u321"); // "Lstrok"
- RTFCHARS.put("l", "\\uc0\\u322"); // "lstrok"
- RTFCHARS.put("'N", "\\uc0\\u323"); // "Nacute"
- RTFCHARS.put("'n", "\\uc0\\u324"); // "nacute"
- RTFCHARS.put("cN", "\\uc0\\u325"); // "Ncedil"
- RTFCHARS.put("cn", "\\uc0\\u326"); // "ncedil"
- RTFCHARS.put("vN", "\\uc0\\u327"); // "Ncaron"
- RTFCHARS.put("vn", "\\uc0\\u328"); // "ncaron"
- // Symbol #329 (�n) has no special Latex command
- RTFCHARS.put("NG", "\\uc0\\u330"); // "ENG"
- RTFCHARS.put("ng", "\\uc0\\u331"); // "eng"
- RTFCHARS.put("=O", "\\uc0\\u332"); // "Omacr"
- RTFCHARS.put("=o", "\\uc0\\u333"); // "omacr"
- RTFCHARS.put("uO", "\\uc0\\u334"); // "Obreve"
- RTFCHARS.put("uo", "\\uc0\\u335"); // "obreve"
- RTFCHARS.put("HO", "\\uc0\\u336"); // "Odblac"
- RTFCHARS.put("Ho", "\\uc0\\u337"); // "odblac"
- RTFCHARS.put("OE", "\\uc0\\u338"); // "OElig"
- RTFCHARS.put("oe", "\\uc0\\u339"); // "oelig"
- RTFCHARS.put("'R", "\\uc0\\u340"); // "Racute"
- RTFCHARS.put("'r", "\\uc0\\u341"); // "racute"
- RTFCHARS.put("cR", "\\uc0\\u342"); // "Rcedil"
- RTFCHARS.put("cr", "\\uc0\\u343"); // "rcedil"
- RTFCHARS.put("vR", "\\uc0\\u344"); // "Rcaron"
- RTFCHARS.put("vr", "\\uc0\\u345"); // "rcaron"
- RTFCHARS.put("'S", "\\uc0\\u346"); // "Sacute"
- RTFCHARS.put("'s", "\\uc0\\u347"); // "sacute"
- RTFCHARS.put("^S", "\\uc0\\u348"); // "Scirc"
- RTFCHARS.put("^s", "\\uc0\\u349"); // "scirc"
- RTFCHARS.put("cS", "\\uc0\\u350"); // "Scedil"
- RTFCHARS.put("cs", "\\uc0\\u351"); // "scedil"
- RTFCHARS.put("vS", "\\uc0\\u352"); // "Scaron"
- RTFCHARS.put("vs", "\\uc0\\u353"); // "scaron"
- RTFCHARS.put("cT", "\\uc0\\u354"); // "Tcedil"
- RTFCHARS.put("ct", "\\uc0\\u355"); // "tcedil"
- RTFCHARS.put("vT", "\\uc0\\u356"); // "Tcaron"
- // Symbol #357 (t�) has no special Latex command
- RTFCHARS.put("Tstrok", "\\uc0\\u358"); // "Tstrok"
- RTFCHARS.put("tstrok", "\\uc0\\u359"); // "tstrok"
- RTFCHARS.put("~U", "\\uc0\\u360"); // "Utilde"
- RTFCHARS.put("~u", "\\uc0\\u361"); // "utilde"
- RTFCHARS.put("=U", "\\uc0\\u362"); // "Umacr"
- RTFCHARS.put("=u", "\\uc0\\u363"); // "umacr"
- RTFCHARS.put("uU", "\\uc0\\u364"); // "Ubreve"
- RTFCHARS.put("uu", "\\uc0\\u365"); // "ubreve"
- RTFCHARS.put("rU", "\\uc0\\u366"); // "Uring"
- RTFCHARS.put("ru", "\\uc0\\u367"); // "uring"
- RTFCHARS.put("HU", "\\uc0\\u368"); // "Odblac"
- RTFCHARS.put("Hu", "\\uc0\\u369"); // "odblac"
- RTFCHARS.put("kU", "\\uc0\\u370"); // "Uogon"
- RTFCHARS.put("ku", "\\uc0\\u371"); // "uogon"
- RTFCHARS.put("^W", "\\uc0\\u372"); // "Wcirc"
- RTFCHARS.put("^w", "\\uc0\\u373"); // "wcirc"
- RTFCHARS.put("^Y", "\\uc0\\u374"); // "Ycirc"
- RTFCHARS.put("^y", "\\uc0\\u375"); // "ycirc"
- RTFCHARS.put("\"Y", "\\uc0\\u376"); // "Yuml"
- RTFCHARS.put("'Z", "\\uc0\\u377"); // "Zacute"
- RTFCHARS.put("'z", "\\uc0\\u378"); // "zacute"
- RTFCHARS.put(".Z", "\\uc0\\u379"); // "Zdot"
- RTFCHARS.put(".z", "\\uc0\\u380"); // "zdot"
- RTFCHARS.put("vZ", "\\uc0\\u381"); // "Zcaron"
- RTFCHARS.put("vz", "\\uc0\\u382"); // "zcaron"
- // Symbol #383 (f) has no special Latex command
-
- //XML_CHARS.put("\\u00E1", "á");
- }
-
- public static void initializeJournalNames() {
- journalAbbrev = new JournalAbbreviations();//"/resource/journalList.txt");
-
- // Read external lists, if any (in reverse order, so the upper lists override the lower):
- String[] lists = prefs.getStringArray("externalJournalLists");
- if ((lists != null) && (lists.length > 0)) {
- for (int i=lists.length-1; i>=0; i--) {
- try {
- journalAbbrev.readJournalList(new File(lists[i]));
- } catch (FileNotFoundException e) {
- // The file couldn't be found... should we tell anyone?
- Globals.logger(e.getMessage());
- }
- }
- }
-
- // Read personal list, if set up:
- if (prefs.get("personalJournalList") != null) {
- try {
- journalAbbrev.readJournalList(new File(prefs.get("personalJournalList")));
- } catch (FileNotFoundException e) {
- Globals.logger("Personal journal list file '"+prefs.get("personalJournalList")+
- "' not found.");
- }
- }
-
-
- }
-
-}
diff --git a/src/java/net/sf/jabref/HelpAction.java b/src/java/net/sf/jabref/HelpAction.java
index a8c9eca..b5c3c67 100644
--- a/src/java/net/sf/jabref/HelpAction.java
+++ b/src/java/net/sf/jabref/HelpAction.java
@@ -1,144 +1,107 @@
/*
-Copyright (C) 2003 Morten O. Alver, Nizar N. Batada
+ Copyright (C) 2003 Morten O. Alver, Nizar N. Batada
-All programs in this directory and
-subdirectories are published under the GNU General Public License as
-described below.
+ All programs in this directory and
+ subdirectories are published under the GNU General Public License as
+ described below.
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or (at
-your option) any later version.
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or (at
+ your option) any later version.
-This program is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
-USA
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA
-Further information about the GNU GPL is available at:
-http://www.gnu.org/copyleft/gpl.ja.html
+ Further information about the GNU GPL is available at:
+ http://www.gnu.org/copyleft/gpl.ja.html
-*/
+ */
package net.sf.jabref;
-import java.awt.*;
-import java.awt.event.*;
-import javax.swing.*;
-import javax.swing.event.HyperlinkListener;
-import javax.swing.event.HyperlinkEvent;
+import java.awt.Dimension;
+import java.awt.event.ActionEvent;
import java.net.URL;
+import javax.swing.ImageIcon;
+import javax.swing.JButton;
+import javax.swing.KeyStroke;
+
/**
* This Action keeps a reference to a URL. When activated, it shows the help
* Dialog unless it is already visible, and shows the URL in it.
*/
public class HelpAction extends MnemonicAwareAction {
- protected HelpDialog diag;
- protected URL helpfile;
- protected String helpFile;
-
- public HelpAction(HelpDialog diag, String helpFile) {
- super(GUIGlobals.getImage("help"));
- putValue(NAME, "Help");
- this.diag = diag;
- this.helpFile = helpFile;
- }
-
- public HelpAction(HelpDialog diag, String helpFile, String tooltip) {
- super(GUIGlobals.getImage("help"));
- putValue(NAME, "Help");
- putValue(SHORT_DESCRIPTION, Globals.lang(tooltip));
- this.diag = diag;
- this.helpFile = helpFile;
- }
-
- public HelpAction(HelpDialog diag, String helpFile, String tooltip,
- URL iconFile) {
- super(new ImageIcon(iconFile));
- putValue(NAME, "Help");
- putValue(SHORT_DESCRIPTION, Globals.lang(tooltip));
- this.diag = diag;
- this.helpFile = helpFile;
- }
-
- public HelpAction(String title, HelpDialog diag, String helpFile, String tooltip) {
- super(GUIGlobals.getImage("help"));
- putValue(NAME, title);
- putValue(SHORT_DESCRIPTION, Globals.lang(tooltip));
- this.diag = diag;
- this.helpFile = helpFile;
- }
-
- public HelpAction(String title, HelpDialog diag, String helpFile, String tooltip,
- KeyStroke key) {
- super(GUIGlobals.getImage("help"));
- putValue(NAME, title);
- putValue(SHORT_DESCRIPTION, Globals.lang(tooltip));
- putValue(ACCELERATOR_KEY, key);
- this.diag = diag;
- this.helpFile = helpFile;
- }
-
- public HelpAction(String title, HelpDialog diag, String helpFile, String tooltip,
- URL iconFile) {
- super(new ImageIcon(iconFile));
- putValue(NAME, title);
- putValue(SHORT_DESCRIPTION, Globals.lang(tooltip));
- this.diag = diag;
- this.helpFile = helpFile;
- }
-/*
- public HelpAction(HelpDialog diag, URL helpfile, String tooltip) {
- super(Globals.lang("Help"), new ImageIcon(GUIGlobals.helpIconFile));
- putValue(SHORT_DESCRIPTION, Globals.lang(tooltip));
- this.diag = diag;
- this.helpfile = helpfile;
- Util.pr("6. HelpAction: "+helpFile+" "+helpfile);
- }
-
- public HelpAction(HelpDialog diag, URL helpfile, String tooltip,
- URL iconFile) {
- super(Globals.lang("Help"), new ImageIcon(iconFile));
- putValue(SHORT_DESCRIPTION, Globals.lang(tooltip));
- this.diag = diag;
- this.helpfile = helpfile;
- Util.pr("7. HelpAction: "+helpFile+" "+helpfile);
- }
-
- public HelpAction(String title, HelpDialog diag, URL helpfile, String tooltip) {
- super(Globals.lang(title), new ImageIcon(GUIGlobals.helpIconFile));
- putValue(SHORT_DESCRIPTION, Globals.lang(tooltip));
- this.diag = diag;
- this.helpfile = helpfile;
- Util.pr("8. HelpAction: "+helpFile+" "+helpfile);
- }
-
- public HelpAction(String title, HelpDialog diag, URL helpfile, String tooltip,
- KeyStroke key) {
- super(Globals.lang(title), new ImageIcon(GUIGlobals.helpIconFile));
- putValue(SHORT_DESCRIPTION, Globals.lang(tooltip));
- putValue(ACCELERATOR_KEY, key);
- this.diag = diag;
- this.helpfile = helpfile;
- Util.pr("9. HelpAction: "+helpFile+" "+helpfile);
- }
-*/
-
- public JButton getIconButton() {
- JButton hlp = new JButton(this);
- hlp.setText(null);
- hlp.setPreferredSize(new Dimension(24, 24));
- return hlp;
- }
-
- public void actionPerformed(ActionEvent e) {
- diag.showPage(helpFile);
- }
-
+ protected HelpDialog diag;
+
+ protected URL helpfile;
+
+ protected String helpFile;
+
+ public HelpAction(HelpDialog diag, String helpFile) {
+ super(GUIGlobals.getImage("help"));
+ putValue(NAME, "Help");
+ this.diag = diag;
+ this.helpFile = helpFile;
+ }
+
+ public HelpAction(HelpDialog diag, String helpFile, String tooltip) {
+ super(GUIGlobals.getImage("help"));
+ putValue(NAME, "Help");
+ putValue(SHORT_DESCRIPTION, Globals.lang(tooltip));
+ this.diag = diag;
+ this.helpFile = helpFile;
+ }
+
+ public HelpAction(HelpDialog diag, String helpFile, String tooltip, URL iconFile) {
+ super(new ImageIcon(iconFile));
+ putValue(NAME, "Help");
+ putValue(SHORT_DESCRIPTION, Globals.lang(tooltip));
+ this.diag = diag;
+ this.helpFile = helpFile;
+ }
+
+ public HelpAction(String title, HelpDialog diag, String helpFile, String tooltip) {
+ super(GUIGlobals.getImage("help"));
+ putValue(NAME, title);
+ putValue(SHORT_DESCRIPTION, Globals.lang(tooltip));
+ this.diag = diag;
+ this.helpFile = helpFile;
+ }
+
+ public HelpAction(String title, HelpDialog diag, String helpFile, String tooltip, KeyStroke key) {
+ super(GUIGlobals.getImage("help"));
+ putValue(NAME, title);
+ putValue(SHORT_DESCRIPTION, Globals.lang(tooltip));
+ putValue(ACCELERATOR_KEY, key);
+ this.diag = diag;
+ this.helpFile = helpFile;
+ }
+
+ public HelpAction(String title, HelpDialog diag, String helpFile, String tooltip, URL iconFile) {
+ super(new ImageIcon(iconFile));
+ putValue(NAME, title);
+ putValue(SHORT_DESCRIPTION, Globals.lang(tooltip));
+ this.diag = diag;
+ this.helpFile = helpFile;
+ }
+
+ public JButton getIconButton() {
+ JButton hlp = new JButton(this);
+ hlp.setText(null);
+ hlp.setPreferredSize(new Dimension(24, 24));
+ return hlp;
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ diag.showPage(helpFile);
+ }
}
diff --git a/src/java/net/sf/jabref/HelpContent.java b/src/java/net/sf/jabref/HelpContent.java
index 0bf4a62..8e39aad 100644
--- a/src/java/net/sf/jabref/HelpContent.java
+++ b/src/java/net/sf/jabref/HelpContent.java
@@ -1,202 +1,245 @@
/*
-Copyright (C) 2003 Nizar N. Batada, Morten O. Alver
+ Copyright (C) 2003 Nizar N. Batada, Morten O. Alver
-All programs in this directory and
-subdirectories are published under the GNU General Public License as
-described below.
+ All programs in this directory and
+ subdirectories are published under the GNU General Public License as
+ described below.
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or (at
-your option) any later version.
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or (at
+ your option) any later version.
-This program is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
-USA
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA
-Further information about the GNU GPL is available at:
-http://www.gnu.org/copyleft/gpl.ja.html
+ Further information about the GNU GPL is available at:
+ http://www.gnu.org/copyleft/gpl.ja.html
-*/
+ */
package net.sf.jabref;
-import java.awt.*;
-import java.awt.event.*;
-import javax.swing.*;
-import javax.swing.text.TextAction;
-import javax.swing.text.JTextComponent;
-import javax.swing.text.DefaultEditorKit;
-import javax.swing.text.html.HTMLEditorKit;
-import java.net.*;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.Point;
+import java.awt.RenderingHints;
+import java.awt.event.ActionEvent;
+import java.io.File;
import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
import java.util.Stack;
+
+import javax.swing.Action;
+import javax.swing.JComponent;
+import javax.swing.JScrollPane;
+import javax.swing.JTextPane;
+import javax.swing.JViewport;
+import javax.swing.SwingConstants;
+import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkListener;
-import java.io.File;
+import javax.swing.text.DefaultEditorKit;
+import javax.swing.text.JTextComponent;
+import javax.swing.text.TextAction;
+import javax.swing.text.html.HTMLEditorKit;
public class HelpContent extends JTextPane {
- JScrollPane pane;
- private Stack history, forw;
- JabRefPreferences prefs;
-
- public HelpContent(JabRefPreferences prefs_) {
- pane = new JScrollPane(this, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
- JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
- prefs = prefs_;
- history = new Stack();
- forw = new Stack();
- setEditorKitForContentType("text/html", new MyEditorKit());
- setContentType("text/html");
- setText("");
- setEditable(false);
- }
-
- public boolean back() {
- if (!history.empty()) {
- URL prev = (URL)(history.pop());
- forw.push(getPage());
- setPageOnly(prev);
- }
- //System.out.println("HelpContent: "+history.empty());
- return !history.empty();
- }
-
- public boolean forward() {
- if (!forw.empty()) {
- URL next = (URL)(forw.pop());
- history.push(getPage());
- setPageOnly(next);
- }
- return !forw.empty();
-
-
- }
-
- public void reset() {
- forw.removeAllElements();
- history.removeAllElements();
- }
-
- public void setPage(String filename) {
- String middle = prefs.get("language")+"/";
- if (middle.equals("en/")) middle = ""; // english in base help dir.
- URL old = getPage() ;
- URL translatedFile = JabRef.class.getResource
- (GUIGlobals.helpPre+middle+filename);
- try {
- super.setPage(translatedFile);
- } catch (IOException ex) {
- //System.err.println("Could not load '"+prefs.get("language")
- // +"' translated version of "+filename+".");
-
- URL file = /*GUIGlobals.class.*/HelpContent.class.getResource
- (GUIGlobals.helpPre+filename);
-
- setPageOnly(file);
- forw.removeAllElements();
- if (old != null)
- history.push(old);
- return;
- }
-
- forw.removeAllElements();
- if (old != null)
- history.push(old);
-
- }
-
- public void setPage(URL url) {
- File f = new File(url.getPath());
- setPage(f.getName());
- //String lang = prefs.get("language");
- /*URL old = getPage();
- setPageOnly(url);
- forw.removeAllElements();
- if (old != null)
- history.push(old);*/
- }
-
- private void setPageOnly(URL url) {
- try {
- super.setPage(url);
- } catch (IOException ex) {
- System.out.println("Error: could not read help file: '"
- +url.getFile()+"'");
- }
- }
-
- public JComponent getPane() {
- return pane;
- }
-
- public void paintComponent(Graphics g) {
- Graphics2D g2 = (Graphics2D)g;
- g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
- RenderingHints.VALUE_ANTIALIAS_ON);
- g2.setRenderingHint(RenderingHints.KEY_RENDERING,
- RenderingHints.VALUE_RENDER_QUALITY);
- super.paintComponent(g2);
- }
-
- public class MyNextVisualPositionAction extends TextAction {
- private Action textActn;
- private int direction;
-
- private MyNextVisualPositionAction(Action textActn, int direction) {
- super((String) textActn.getValue(Action.NAME));
- this.textActn = textActn;
- this.direction = direction;
- }
-
- public void actionPerformed(ActionEvent e) {
- JTextComponent c = getTextComponent(e);
-
- if (c.getParent() instanceof JViewport) {
- JViewport viewport = (JViewport) c.getParent();
- Point p = viewport.getViewPosition();
-
- if (this.direction == SwingConstants.NORTH) {
- c.setCaretPosition(c.viewToModel(p));
- } else {
- p.y += viewport.getExtentSize().height;
- c.setCaretPosition(c.viewToModel(p));
- }
+ JScrollPane pane;
+
+ private Stack history, forw;
+
+ JabRefPreferences prefs;
+
+ public HelpContent(JabRefPreferences prefs_) {
+ super();
+ pane = new JScrollPane(this, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
+ JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
+ pane.setDoubleBuffered(true);
+ prefs = prefs_;
+ history = new Stack();
+ forw = new Stack();
+ setEditorKitForContentType("text/html", new MyEditorKit());
+ setContentType("text/html");
+ setText("");
+ setEditable(false);
+
+ // Handles Anchors
+ final HyperlinkListener hyperLinkListener = new HyperlinkListener() {
+ public void hyperlinkUpdate(final HyperlinkEvent e) {
+ if (e.getDescription().startsWith("#")) {
+ scrollToReference(e.getDescription().substring(1));
+ }
+ }
+ };
+ addHyperlinkListener(hyperLinkListener);
+ }
+
+ public boolean back() {
+ if (!history.empty()) {
+ URL prev = (URL) (history.pop());
+ forw.push(getPage());
+ setPageOnly(prev);
+ }
+ return !history.empty();
+ }
+
+ public boolean forward() {
+ if (!forw.empty()) {
+ URL next = (URL) (forw.pop());
+ history.push(getPage());
+ setPageOnly(next);
+ }
+ return !forw.empty();
+ }
+
+ public void reset() {
+ forw.removeAllElements();
+ history.removeAllElements();
+ }
+
+ public void setPage(String filename) {
+
+ // Check for anchor
+ int indexOf = filename.indexOf('#');
+ String file;
+ String reference;
+
+ if (indexOf != -1) {
+ file = filename.substring(0, indexOf);
+ reference = filename.substring(indexOf + 1);
+ } else {
+ file = filename;
+ reference = "";
+ }
+
+ String middle = prefs.get("language") + "/";
+ if (middle.equals("en/"))
+ middle = ""; // english in base help dir.
+
+ URL old = getPage();
+ try {
+ URL resource = JabRef.class.getResource(GUIGlobals.helpPre + middle + file);
+ // Because of the call to toString(), we must test for null, or the fallback
+ // to english won't work if the page is missing in the selected langugage:
+ if (resource != null) {
+ super.setPage(new URL(resource.toString() + "#" + reference));
}
-
- textActn.actionPerformed(e);
- }
- }
-
- public class MyEditorKit extends HTMLEditorKit {
- private Action[] myActions;
-
- public Action[] getActions() {
- if (myActions == null) {
- Action[] actions = super.getActions();
- Action[] newActions = new Action[2];
-
- for (int i = 0; i < actions.length; i++) {
- Action actn = actions[i];
-
- String name = (String) actn.getValue(Action.NAME);
-
- if (name.equals(DefaultEditorKit.upAction)) {
- newActions[0] = new MyNextVisualPositionAction(actions[i], SwingConstants.NORTH);
- } else if (name.equals(DefaultEditorKit.downAction)) {
- newActions[1] = new MyNextVisualPositionAction(actions[i], SwingConstants.SOUTH);
- }
- }
-
- myActions = TextAction.augmentList(actions, newActions);
+ else {
+ setPageOnly(new URL(HelpContent.class.getResource(GUIGlobals.helpPre + file) + "#" + reference));
}
-
- return myActions;
- }
- }
+ } catch (IOException ex) {
+ ex.printStackTrace();
+ // The fallback below shouldn't bee needed any more, because of the null
+ // check above.
+ /*
+ try {
+ setPageOnly(new URL(HelpContent.class.getResource(GUIGlobals.helpPre + file) + "#" + reference));
+ } catch (MalformedURLException e) {
+ setPageOnly(HelpContent.class.getResource(GUIGlobals.helpPre + file));
+ }*/
+ }
+
+ forw.removeAllElements();
+ if (old != null)
+ history.push(old);
+
+ }
+
+ /**
+ * Convenience method for setPage(String)
+ */
+ public void setPage(URL url) {
+ File f = new File(url.getPath());
+ setPage(f.getName());
+ }
+
+ private void setPageOnly(URL url) {
+ try {
+ super.setPage(url);
+ } catch (IOException ex) {
+ if (url == null) {
+ System.out.println("Error: Help file not set");
+ } else {
+ System.out.println("Error: Help file not found '" + url.getFile() + "'");
+ }
+ }
+ }
+
+ public JComponent getPane() {
+ return pane;
+ }
+
+ public void paintComponent(Graphics g) {
+ Graphics2D g2 = (Graphics2D) g;
+ g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+ g2.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
+ super.paintComponent(g2);
+ }
+
+ public class MyNextVisualPositionAction extends TextAction {
+ private Action textActn;
+
+ private int direction;
+
+ private MyNextVisualPositionAction(Action textActn, int direction) {
+ super((String) textActn.getValue(Action.NAME));
+ this.textActn = textActn;
+ this.direction = direction;
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ JTextComponent c = getTextComponent(e);
+
+ if (c.getParent() instanceof JViewport) {
+ JViewport viewport = (JViewport) c.getParent();
+ Point p = viewport.getViewPosition();
+
+ if (this.direction == SwingConstants.NORTH) {
+ c.setCaretPosition(c.viewToModel(p));
+ } else {
+ p.y += viewport.getExtentSize().height;
+ c.setCaretPosition(c.viewToModel(p));
+ }
+ }
+
+ textActn.actionPerformed(e);
+ }
+ }
+
+ public class MyEditorKit extends HTMLEditorKit {
+ private Action[] myActions;
+
+ public Action[] getActions() {
+ if (myActions == null) {
+ Action[] actions = super.getActions();
+ Action[] newActions = new Action[2];
+
+ for (int i = 0; i < actions.length; i++) {
+ Action actn = actions[i];
+
+ String name = (String) actn.getValue(Action.NAME);
+
+ if (name.equals(DefaultEditorKit.upAction)) {
+ newActions[0] = new MyNextVisualPositionAction(actions[i],
+ SwingConstants.NORTH);
+ } else if (name.equals(DefaultEditorKit.downAction)) {
+ newActions[1] = new MyNextVisualPositionAction(actions[i],
+ SwingConstants.SOUTH);
+ }
+ }
+
+ myActions = TextAction.augmentList(actions, newActions);
+ }
+
+ return myActions;
+ }
+ }
}
diff --git a/src/java/net/sf/jabref/HelpDialog.java b/src/java/net/sf/jabref/HelpDialog.java
index eb60f75..dbf136f 100644
--- a/src/java/net/sf/jabref/HelpDialog.java
+++ b/src/java/net/sf/jabref/HelpDialog.java
@@ -1,167 +1,167 @@
/*
-Copyright (C) 2003 Morten O. Alver, Nizar N. Batada
+ Copyright (C) 2003 Morten O. Alver, Nizar N. Batada
-All programs in this directory and
-subdirectories are published under the GNU General Public License as
-described below.
+ All programs in this directory and
+ subdirectories are published under the GNU General Public License as
+ described below.
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or (at
-your option) any later version.
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or (at
+ your option) any later version.
-This program is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
-USA
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA
-Further information about the GNU GPL is available at:
-http://www.gnu.org/copyleft/gpl.ja.html
+ Further information about the GNU GPL is available at:
+ http://www.gnu.org/copyleft/gpl.ja.html
-*/
+ */
package net.sf.jabref;
-import java.awt.*;
-import java.awt.event.*;
-import javax.swing.*;
-import javax.swing.event.HyperlinkListener;
+import java.awt.BorderLayout;
+import java.awt.event.ActionEvent;
+
+import javax.swing.AbstractAction;
+import javax.swing.ActionMap;
+import javax.swing.InputMap;
+import javax.swing.JComponent;
+import javax.swing.JDialog;
+import javax.swing.JToolBar;
import javax.swing.event.HyperlinkEvent;
-import java.net.URL;
+import javax.swing.event.HyperlinkListener;
/**
- * This is a non-modal help Dialog. The contents of the help is specified
- * by calling
+ *
+ * This is a non-modal help Dialog. The contents of the help is specified by
+ * calling showPage().
+ *
+ * @version $Revision: 1.9 $ ($Date: 2006/08/26 21:24:39 $)
+ *
*/
public class HelpDialog extends JDialog implements HyperlinkListener {
- private JabRefFrame frame;
- private HelpContent content;
- private BackAction back = new BackAction();
- private ForwardAction forward = new ForwardAction();
- private ContentsAction contents = new ContentsAction();
-
- // Initializes, but does not show the help dialog.
- public HelpDialog(JabRefFrame bf) {
- super(bf, Globals.lang("JabRef help"), false);
- frame = bf;
- content = new HelpContent(bf.prefs);
- content.addHyperlinkListener(this);
- setSize(GUIGlobals.helpSize);
-
- /* There is probably no need for a window listener now, so
- * it's commented out.
- diag.addWindowListener(new WindowAdapter() {
- public void windowClosing(WindowEvent e) {
- open = null;
+ private JabRefFrame frame;
+
+ private HelpContent content;
+
+ private BackAction back = new BackAction();
+
+ private ForwardAction forward = new ForwardAction();
+
+ private ContentsAction contents = new ContentsAction();
+
+ // Initializes, but does not show the help dialog.
+ public HelpDialog(JabRefFrame bf) {
+ super(bf, Globals.lang("JabRef help"), false);
+ frame = bf;
+ content = new HelpContent(bf.prefs);
+ content.addHyperlinkListener(this);
+ setSize(GUIGlobals.helpSize);
+
+ JToolBar tlb = new JToolBar();
+ tlb.add(back);
+ tlb.add(forward);
+ tlb.addSeparator();
+ tlb.add(contents);
+ tlb.setFloatable(false);
+
+ // Make ESC close dialog, and set shortkeys for back and forward.
+ InputMap im = tlb.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
+ ActionMap am = tlb.getActionMap();
+ im.put(bf.prefs.getKey("Close dialog"), "close");
+ am.put("close", new CloseAction());
+ im.put(bf.prefs.getKey("Back, help dialog"), "left");
+ am.put("left", back);
+ im.put(bf.prefs.getKey("Forward, help dialog"), "right");
+ am.put("right", forward);
+
+ // Set shortkeys for back and forward specifically for the EditorPane.
+ im = content.getInputMap(JComponent.WHEN_FOCUSED);
+ am = content.getActionMap();
+ im.put(bf.prefs.getKey("Back, help dialog"), "left");
+ am.put("left", back);
+ im.put(bf.prefs.getKey("Forward, help dialog"), "right");
+ am.put("right", forward);
+
+ getContentPane().add(tlb, BorderLayout.NORTH);
+ getContentPane().add(content.getPane());
+ forward.setEnabled(false);
+ back.setEnabled(false);
+ }
+
+ public void showPage(String url) {
+ if (!isVisible()) {
+ Util.placeDialog(this, frame);
+ content.reset();
+ back.setEnabled(false);
+ setVisible(true);
+ } else {
+ back.setEnabled(true);
}
- });*/
-
- JToolBar tlb = new JToolBar();
- //tlb.add(new CloseAction());
- //tlb.addSeparator();
- tlb.add(back);
- tlb.add(forward);
- tlb.addSeparator();
- tlb.add(contents);
- tlb.setFloatable(false);
-
- // Make ESC close dialog, and set shortkeys for back and forward.
- InputMap im = tlb.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
- ActionMap am = tlb.getActionMap();
- im.put(bf.prefs.getKey("Close dialog"), "close");
- am.put("close", new CloseAction());
- im.put(bf.prefs.getKey("Back, help dialog"), "left");
- am.put("left", back);
- im.put(bf.prefs.getKey("Forward, help dialog"), "right");
- am.put("right", forward);
-
- // Set shortkeys for back and forward specifically for the EditorPane.
- im = content.getInputMap(JComponent.WHEN_FOCUSED);
- am = content.getActionMap();
- im.put(bf.prefs.getKey("Back, help dialog"), "left");
- am.put("left", back);
- im.put(bf.prefs.getKey("Forward, help dialog"), "right");
- am.put("right", forward);
-
- getContentPane().add(tlb, BorderLayout.NORTH);
- getContentPane().add(content.getPane());
- forward.setEnabled(false);
- back.setEnabled(false);
- }
-
- public void showPage(String url) {
- if (!isVisible()) {
- Util.placeDialog(this, frame);
- setVisible(true);
- content.reset();
- forward.setEnabled(false);
- back.setEnabled(false);
- } else {
- setVisible(true);
- forward.setEnabled(false);
- back.setEnabled(true);
+ forward.setEnabled(false);
+ content.setPage(url);
+ content.requestFocus();
}
- content.setPage(url);
- content.requestFocus();
- //setVisible(true);
- }
-
- public void hyperlinkUpdate(HyperlinkEvent e) {
- if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
- content.setPage(e.getURL());
- back.setEnabled(true);
- forward.setEnabled(false);
+
+ public void hyperlinkUpdate(HyperlinkEvent e) {
+ if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
+ content.setPage(e.getURL());
+ back.setEnabled(true);
+ forward.setEnabled(false);
+ }
}
- }
- class CloseAction extends AbstractAction {
- public CloseAction() {
- super(Globals.lang("Close"));
- //, new ImageIcon(GUIGlobals.closeIconFile));
- putValue(SHORT_DESCRIPTION, Globals.lang("Close the help window"));
+ class CloseAction extends AbstractAction {
+ public CloseAction() {
+ super(Globals.lang("Close"));
+ // , new ImageIcon(GUIGlobals.closeIconFile));
+ putValue(SHORT_DESCRIPTION, Globals.lang("Close the help window"));
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ dispose();
+ }
}
- public void actionPerformed(ActionEvent e) {
- dispose();
+ class BackAction extends AbstractAction {
+ public BackAction() {
+ super("Back", GUIGlobals.getImage("left"));
+ // putValue(SHORT_DESCRIPTION, "Show the previous page");
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ setEnabled(content.back());
+ forward.setEnabled(true);
+ }
}
- }
- class BackAction extends AbstractAction {
- public BackAction() {
- super("Back", GUIGlobals.getImage("left"));
- //putValue(SHORT_DESCRIPTION, "Show the previous page");
+ class ForwardAction extends AbstractAction {
+ public ForwardAction() {
+ super("Forward", GUIGlobals.getImage("right"));
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ setEnabled(content.forward());
+ back.setEnabled(true);
+ }
}
- public void actionPerformed(ActionEvent e) {
- setEnabled(content.back());
- forward.setEnabled(true);
+ class ContentsAction extends AbstractAction {
+ public ContentsAction() {
+ super("Contents", GUIGlobals.getImage("helpContents"));
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ content.setPage(GUIGlobals.helpContents);
+ back.setEnabled(true);
+ }
}
- }
-
- class ForwardAction extends AbstractAction {
- public ForwardAction() {
- super("Forward", GUIGlobals.getImage("right"));
- }
-
- public void actionPerformed(ActionEvent e) {
- setEnabled(content.forward());
- back.setEnabled(true);
- }
- }
-
- class ContentsAction extends AbstractAction {
- public ContentsAction() {
- super("Contents", GUIGlobals.getImage("helpContents"));
- }
-
- public void actionPerformed(ActionEvent e) {
- content.setPage(GUIGlobals.helpContents);
- back.setEnabled(true);
- }
- }
}
diff --git a/src/java/net/sf/jabref/JabRef.java b/src/java/net/sf/jabref/JabRef.java
index 3d048c4..c3448da 100644
--- a/src/java/net/sf/jabref/JabRef.java
+++ b/src/java/net/sf/jabref/JabRef.java
@@ -31,12 +31,15 @@ import net.sf.jabref.remote.RemoteListener;
import gnu.dtools.ritopt.*;
import java.awt.*;
+import java.awt.event.KeyEvent;
import java.io.*;
import java.io.File;
import java.util.*;
import java.util.List;
+import java.lang.reflect.Method;
+import java.lang.reflect.InvocationTargetException;
import javax.swing.*;
import javax.swing.plaf.metal.MetalLookAndFeel;
@@ -76,14 +79,16 @@ public class JabRef {
public JabRef(String[] args) {
-
- ths = this;
+ ths = this;
JabRefPreferences prefs = JabRefPreferences.getInstance();
Globals.prefs = prefs;
Globals.setLanguage(prefs.get("language"), "");
Globals.importFormatReader.resetImportFormats();
BibtexEntryType.loadCustomEntryTypes(prefs);
+ // Build the list of available export formats:
+ ExportFormats.initAllExports();
+
// Read list(s) of journal names and abbreviations:
//Globals.turnOnFileLogging();
@@ -199,27 +204,8 @@ public class JabRef {
System.out.println(Globals.lang("Available import formats") + ":\n"
+ importFormats);
- // + ": biblioscape, bibtexml, endnote, inspec,\n\tisi, medline, ovid,
- // ris, scifinder, sixpack, jstor, silverplatter.");
- // To specify export formats, we need to take the custom export formats
- // into account.
- // So we iterate through the custom formats and add them.
- String outFormats = ": bibtexml, docbook, endnote, harvard, html, mods, ods, oocalc, simplehtml";
- int length = outFormats.length();
-
- for (int i = 0; i < Globals.prefs.customExports.size(); i++) {
- String[] format = Globals.prefs.customExports.getElementAt(i);
-
- if ((length + format[0].length()) > 50) {
- outFormats = outFormats + ",\n\t" + format[0];
- length = format[0].length();
- } else {
- outFormats = outFormats + ", " + format[0];
- length += (1 + format[0].length());
- }
- }
-
- System.out.println(Globals.lang("Available export formats") + outFormats
+ String outFormats = ExportFormats.getConsoleExportList(70, 20, "\t");
+ System.out.println(Globals.lang("Available export formats") + ": " + outFormats
+ ".");
System.exit(0);
}
@@ -377,53 +363,21 @@ public class JabRef {
// This signals that the latest import should be stored in the given
// format to the given file.
ParserResult pr = (ParserResult) loaded.elementAt(loaded.size() - 1);
-
- // We first try to find a matching custom export format.
- boolean foundCustom = false;
-
- for (int i = 0; i < Globals.prefs.customExports.size(); i++) {
- String[] format = Globals.prefs.customExports.getElementAt(i);
-
- if (format[0].equals(data[1])) {
- // Found the correct export format here.
-
- try {
- File lfFile = new File(format[1]);
-
- //System.out.println(lfFile.getName());
- String fname = (lfFile.getName().split("\\."))[0];
- FileActions.exportDatabase(pr.getDatabase(),
- lfFile.getParent() + File.separator, fname,
- new File(data[0]), pr.getEncoding());
- System.out.println(Globals.lang("Exporting") + ": "
- + data[0]);
- } catch (Exception ex) {
- //ex.printStackTrace();
- System.err.println(Globals.lang("Could not export file")
- + " '" + data[0] + "': " + ex.getMessage());
- }
-
- foundCustom = true;
-
- break;
- }
- }
-
- if (!foundCustom) {
+ System.out.println(Globals.lang("Exporting") + ": " + data[0]);
+ ExportFormat format = ExportFormats.getExportFormat(data[1]);
+ if (format != null) {
+ // We have an ExportFormat instance:
try {
- System.out.println(Globals.lang("Exporting") + ": " + data[0]);
- FileActions.performExport(pr.getDatabase(), data[1], data[0],
- pr.getEncoding());
- //FileActions.exportDatabase(pr.getDatabase(), data[1],
- // new File(data[0]), pr.getEncoding());
- } catch (NullPointerException ex2) {
- System.err.println(Globals.lang("Unknown export format")
- + ": " + data[1]);
+ format.performExport(pr.getDatabase(), data[0], pr.getEncoding(), null);
} catch (Exception ex) {
System.err.println(Globals.lang("Could not export file")
+ " '" + data[0] + "': " + ex.getMessage());
}
}
+ else
+ System.err.println(Globals.lang("Unknown export format")
+ + ": " + data[1]);
+
}
} else
System.err.println(Globals.lang(
@@ -642,17 +596,25 @@ public class JabRef {
FontPolicy fixedPolicy = FontPolicies.createFixedPolicy(fontSet);
WindowsLookAndFeel.setFontPolicy(fixedPolicy);
}
-
+
//WindowsLookAndFeel plLnf = (WindowsLookAndFeel) lnf;
}
if (lnf != null) {
try {
+
UIManager.setLookAndFeel(lnf);
-
+
if (!Globals.ON_WIN) {
UIManager.put("SimpleInternalFrame.activeTitleBackground", GUIGlobals.gradientBlue);
- //UIManager.put("TabbedPane.selected", Color.red);
+ }
+
+ if (!Globals.ON_WIN && !Globals.ON_MAC) {
+ // For Linux, add Enter as button click key:
+ UIDefaults def = UIManager.getDefaults();
+ InputMap im = (InputMap)def.get("Button.focusInputMap");
+ im.put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0, false), "pressed");
+ im.put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0, true), "released");
}
} catch (Throwable ex) {
ex.printStackTrace();
@@ -738,6 +700,9 @@ lastEdLoop:
//Util.pr(": Showing frame");
jrf.setVisible(true);
+ // TEST TEST TEST TEST TEST TEST
+ startOOPlugin(jrf);
+
for (int i = 0; i < loaded.size(); i++) {
ParserResult pr = (ParserResult) loaded.elementAt(i);
if (Globals.prefs.getBoolean("displayKeyWarningDialogAtStartup") && pr.hasWarnings()) {
@@ -764,6 +729,34 @@ lastEdLoop:
System.exit(0);
}
+ /**
+ * Morten Alver (sept. 06): I'm adding this to run the functionality for
+ * OpenOffice integration. I'm not sure yet how to handle deployment issues,
+ * because the OO stuff requires several OO jars on the classpath, which we
+ * shouldn't distribute because OO installations already have them.
+ *
+ * To avoid introducing dependencies on these jars for the time being,
+ * I'm keeping OO "plugin" files separate, only invoking them through reflection.
+ *
+ * @param jrf The JabRefFrame.
+ */
+ private void startOOPlugin(JabRefFrame jrf) {
+
+
+ try {
+ Class c = Class.forName("net.sf.jabref.oo.OOTestPanel");
+ Method m = c.getDeclaredMethod("open",
+ new Class[] {JabRefFrame.class});
+ Object i = c.newInstance();
+ Object r = m.invoke(i, new Object[] {jrf});
+ } catch (Exception e) {
+ // Do nothing.
+ //System.out.println("OO plugin not found.");
+ //e.printStackTrace();
+ }
+
+ }
+
public static ParserResult openBibFile(String name) {
System.out.println(Globals.lang("Opening") + ": " + name);
diff --git a/src/java/net/sf/jabref/JabRefFrame.java b/src/java/net/sf/jabref/JabRefFrame.java
index a9da5da..010ef49 100644
--- a/src/java/net/sf/jabref/JabRefFrame.java
+++ b/src/java/net/sf/jabref/JabRefFrame.java
@@ -25,13 +25,6 @@
*/
-// created by : ?
-//
-// modified : r.nagel 23.08.2004
-// - insert new Menuitem New Database -> New Database from Aux
-// modified : juan 10.02.2005
-// - insert new Menuitem to the Export menu -> Openoffice
-// export filter
package net.sf.jabref;
import net.sf.jabref.gui.*;
@@ -53,6 +46,8 @@ import net.sf.jabref.undo.NamedCompound;
import net.sf.jabref.undo.UndoableInsertEntry;
import net.sf.jabref.undo.UndoableRemoveEntry;
import net.sf.jabref.export.ExportCustomizationDialog;
+import net.sf.jabref.export.ExportFormats;
+
import java.lang.reflect.*;
import javax.swing.event.*;
import net.sf.jabref.wizard.integrity.gui.*;
@@ -60,6 +55,7 @@ import net.sf.jabref.groups.GroupSelector;
import net.sf.jabref.groups.EntryTableTransferHandler;
import net.sf.jabref.journals.ManageJournalsAction;
import net.sf.jabref.external.*;
+import net.sf.jabref.util.MassSetFieldAction;
import com.jgoodies.uif_lite.component.UIFSplitPane;
import com.jgoodies.looks.Options;
import com.jgoodies.looks.HeaderStyle;
@@ -68,22 +64,23 @@ import com.jgoodies.looks.HeaderStyle;
/**
* The main window of the application.
*/
-public class JabRefFrame
- extends JFrame {
+public class JabRefFrame extends JFrame {
- JabRefFrame ths = this;
+ // CO: Code Smells...
+ JabRefFrame ths = this;
UIFSplitPane contentPane = new UIFSplitPane();
- JabRefPreferences prefs = Globals.prefs; //new JabRefPreferences();
+ JabRefPreferences prefs = Globals.prefs; //new JabRefPreferences();
PrefsDialog3 prefsDialog = null;
- private int lastTabbedPanelSelectionIndex = -1 ;
+
+ private int lastTabbedPanelSelectionIndex = -1 ;
// The sidepane manager takes care of populating the sidepane.
public SidePaneManager sidePaneManager;
JTabbedPane tabbedPane = new JTabbedPane();
- final Insets marg = new Insets(1,0,2,0);
-
+
+ final Insets marg = new Insets(1,0,2,0);
class ToolBar extends JToolBar {
void addAction(Action a) {
@@ -94,30 +91,33 @@ public class JabRefFrame
add(b);
}
}
- ToolBar tlb = new ToolBar();
+ ToolBar tlb = new ToolBar();
+
+ JMenuBar mb = new JMenuBar();
+
+ GridBagLayout gbl = new GridBagLayout();
+
+ GridBagConstraints con = new GridBagConstraints();
- JMenuBar mb = new JMenuBar();
- GridBagLayout gbl = new GridBagLayout();
- GridBagConstraints con = new GridBagConstraints();
+ JLabel statusLine = new JLabel("", SwingConstants.LEFT), statusLabel = new JLabel(Globals
+ .lang("Status")
+ + ":", SwingConstants.LEFT);
- JLabel statusLine = new JLabel("", SwingConstants.LEFT),
- statusLabel = new JLabel(Globals.lang("Status") + ":",
- SwingConstants.LEFT);
- //SearchManager searchManager = new SearchManager(ths, prefs);
+ // SearchManager searchManager = new SearchManager(ths, prefs);
- private FileHistory fileHistory = new FileHistory(prefs, this);
+ private FileHistory fileHistory = new FileHistory(prefs, this);
- LabelMaker labelMaker;
+ LabelMaker labelMaker;
- // The help window.
- public HelpDialog helpDiag = new HelpDialog(this);
+ // The help window.
+ public HelpDialog helpDiag = new HelpDialog(this);
- // Here we instantiate menu/toolbar actions. Actions regarding
- // the currently open database are defined as a GeneralAction
- // with a unique command string. This causes the appropriate
- // BasePanel's runCommand() method to be called with that command.
- // Note: GeneralAction's constructor automatically gets translations
- // for the name and message strings.
+ // Here we instantiate menu/toolbar actions. Actions regarding
+ // the currently open database are defined as a GeneralAction
+ // with a unique command string. This causes the appropriate
+ // BasePanel's runCommand() method to be called with that command.
+ // Note: GeneralAction's constructor automatically gets translations
+ // for the name and message strings.
// References to the toggle buttons in the toolbar:
public JToggleButton groupToggle, searchToggle, previewToggle, highlightAny,
@@ -138,12 +138,9 @@ public class JabRefFrame
contents = new HelpAction("Help contents", helpDiag,
GUIGlobals.helpContents, "Help contents",
GUIGlobals.getIconUrl("helpContents")),
-/* old about*/
about = new HelpAction("About JabRef", helpDiag,
GUIGlobals.aboutPage, "About JabRef",
GUIGlobals.getIconUrl("about")),
-/**/
- // about2 = new NewAboutAction(),
editEntry = new GeneralAction("edit", "Edit entry",
"Edit entry",
prefs.getKey("Edit entry")),
@@ -157,6 +154,10 @@ public class JabRefFrame
"Save selected as ...",
"Save selected as ...",
GUIGlobals.getIconUrl("saveAs")),
+ exportAll = ExportFormats.getExportAction(this, false),
+ exportSelected = ExportFormats.getExportAction(this, true),
+ importCurrent = ImportFormats.getImportAction(this, false),
+ importNew = ImportFormats.getImportAction(this, true),
nextTab = new ChangeTabAction(true),
prevTab = new ChangeTabAction(false),
sortTabs = new SortTabsAction(this),
@@ -247,6 +248,9 @@ public class JabRefFrame
winEdtPushAction = new PushToApplicationAction(ths, new PushToWinEdt()),
latexEditorPushAction = new PushToApplicationAction(ths, new PushToLatexEditor()),
+
+ writeXmpAction = new GeneralAction("writeXMP", "Write XMP-metadata to PDFs", "Will write XMP-metadata to the PDFs linked from selected entries.", prefs.getKey("Write XMP")),
+
openFile = new GeneralAction("openFile", "Open PDF or PS",
"Open PDF or PS",
prefs.getKey("Open PDF or PS")),
@@ -285,6 +289,7 @@ public class JabRefFrame
errorConsole = Globals.errorConsole.getAction(this),
test = new GeneralAction("test", "Test");
+ PushToApplicationButton pushExternalButton;
/*setupSelector = new GeneralAction("setupSelector", "", "",
GUIGlobals.pasteIconFile,
prefs.getKey(")),*/
@@ -294,6 +299,9 @@ public class JabRefFrame
CiteSeerFetcher citeSeerFetcher;
CiteSeerFetcherPanel citeSeerFetcherPanel;
IEEEXploreFetcher ieeexplorerFetcher;
+ GeneralFetcher ieex;
+ OAI2Fetcher arxivFetcher;
+ GeneralFetcher arxiv;
SearchManager2 searchManager;
public GroupSelector groupSelector;
@@ -332,104 +340,96 @@ public class JabRefFrame
public JabRefFrame() {
init();
- setEmptyState();
+ updateEnabledState();
}
private void init() {
- /*try {
- //UIManager.setLookAndFeel("com.jgoodies.plaf.windows.ExtWindowsLookAndFeel");
- UIManager.setLookAndFeel(new PlasticXPLookAndFeel());
- } catch (Exception e) { e.printStackTrace();}*/
-
- //Globals.setLanguage("no", "");
-
- macOSXRegistration();
- MyGlassPane glassPane = new MyGlassPane();
- setGlassPane(glassPane);
- // glassPane.setVisible(true);
-
- setTitle(GUIGlobals.frameTitle);
- setIconImage(GUIGlobals.getImage("jabrefIcon").getImage());
- setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
- addWindowListener(new WindowAdapter() {
- public void windowClosing(WindowEvent e) {
- (new CloseAction()).actionPerformed(null);
- }
- });
-
- initLabelMaker();
-
- sidePaneManager = new SidePaneManager(this);
-
- Globals.sidePaneManager = this.sidePaneManager;
- Globals.helpDiag = this.helpDiag;
-
- medlineFetcher = new MedlineFetcher(sidePaneManager);
- citeSeerFetcher = new CiteSeerFetcher(sidePaneManager);
- citeSeerFetcherPanel = new CiteSeerFetcherPanel(sidePaneManager, (CiteSeerFetcher)citeSeerFetcher);
- ieeexplorerFetcher = new IEEEXploreFetcher();
- searchManager = new SearchManager2(this, sidePaneManager);
- // Groups
- /*if (metaData.getGroups() != null) {
- panel.groupSelector = new GroupSelector(frame, panel, metaData
- .getGroups(), this, prefs);
- register("groups", panel.groupSelector);
- if (prefs.getBoolean("groupSelectorVisible"))
- ensureVisible("groups");
- } else*/
- {
-
- groupSelector = new GroupSelector(this, sidePaneManager);
- sidePaneManager.register("groups", groupSelector);
- }
-
- sidePaneManager.register("fetchMedline", medlineFetcher);
- //medlineAuthorFetcher = new MedlineAuthorFetcher(this, sidePaneManager);
- //sidePaneManager.register("fetchAuthorMedline", medlineAuthorFetcher);
-
- sidePaneManager.register("search", searchManager);
- // Show the search panel if it was visible at last shutdown:
- if (Globals.prefs.getBoolean("searchPanelVisible"))
- sidePaneManager.ensureVisible("search");
- sidePaneManager.register("CiteSeerPanel", citeSeerFetcherPanel);
- sidePaneManager.register("CiteSeerProgress", citeSeerFetcher);
- sidePaneManager.populatePanel();
-
-
-
- setupLayout();
- setSize(new Dimension(prefs.getInt("sizeX"),
- prefs.getInt("sizeY")));
- setLocation(new Point(prefs.getInt("posX"),
- prefs.getInt("posY")));
- tabbedPane.setBorder(null);
- tabbedPane.setForeground(GUIGlobals.inActiveTabbed);
-
- // The following state listener makes sure focus is registered with the correct database
- // when the user switches tabs. Without this, cut/paste/copy operations would some times
- // occur in the wrong tab.
- tabbedPane.addChangeListener(new ChangeListener() {
- public void stateChanged(ChangeEvent e)
- {
- markActiveBasePanel() ;
-
- BasePanel bp = basePanel();
- if (bp != null) {
- groupToggle.setSelected(sidePaneManager.isPanelVisible("groups"));
- searchToggle.setSelected(sidePaneManager.isPanelVisible("search"));
- previewToggle.setSelected(Globals.prefs.getBoolean("previewEnabled"));
- highlightAny.setSelected(Globals.prefs.getBoolean("highlightGroupsMatchingAny"));
- highlightAll.setSelected(Globals.prefs.getBoolean("highlightGroupsMatchingAll"));
- Globals.focusListener.setFocused(bp.mainTable);
- new FocusRequester(bp.mainTable);
- }
- }
- });
- }
-
-// -------------------- !!!! NECESSARY ???? OBSOLETE ??? ----------------------
- AboutAction aboutAction = new AboutAction();
+ macOSXRegistration();
+ MyGlassPane glassPane = new MyGlassPane();
+ setGlassPane(glassPane);
+ // glassPane.setVisible(true);
+
+ setTitle(GUIGlobals.frameTitle);
+ setIconImage(GUIGlobals.getImage("jabrefIcon").getImage());
+ setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
+ addWindowListener(new WindowAdapter() {
+ public void windowClosing(WindowEvent e) {
+ (new CloseAction()).actionPerformed(null);
+ }
+ });
+
+ initLabelMaker();
+
+ initSidePane();
+
+ initLayout();
+
+ initActions();
+
+ if (Globals.prefs.getBoolean("rememberWindowLocation")) {
+ setSize(new Dimension(prefs.getInt("sizeX"), prefs.getInt("sizeY")));
+ setLocation(new Point(prefs.getInt("posX"), prefs.getInt("posY")));
+ }
+ tabbedPane.setBorder(null);
+ tabbedPane.setForeground(GUIGlobals.inActiveTabbed);
+
+ /*
+ * The following state listener makes sure focus is registered with the
+ * correct database when the user switches tabs. Without this,
+ * cut/paste/copy operations would some times occur in the wrong tab.
+ */
+ tabbedPane.addChangeListener(new ChangeListener() {
+ public void stateChanged(ChangeEvent e) {
+ markActiveBasePanel();
+
+ BasePanel bp = basePanel();
+ if (bp != null) {
+ groupToggle.setSelected(sidePaneManager.isComponentVisible("groups"));
+ searchToggle.setSelected(sidePaneManager.isComponentVisible("search"));
+ previewToggle.setSelected(Globals.prefs.getBoolean("previewEnabled"));
+ highlightAny
+ .setSelected(Globals.prefs.getBoolean("highlightGroupsMatchingAny"));
+ highlightAll
+ .setSelected(Globals.prefs.getBoolean("highlightGroupsMatchingAll"));
+ Globals.focusListener.setFocused(bp.mainTable);
+
+ new FocusRequester(bp.mainTable);
+ }
+ }
+ });
+ }
+
+
+
+ private void initSidePane() {
+ sidePaneManager = new SidePaneManager(this);
+
+ Globals.sidePaneManager = this.sidePaneManager;
+ Globals.helpDiag = this.helpDiag;
+
+ ieeexplorerFetcher = new IEEEXploreFetcher();
+ arxivFetcher = new OAI2Fetcher();
+ medlineFetcher = new MedlineFetcher(sidePaneManager);
+ citeSeerFetcher = new CiteSeerFetcher(sidePaneManager);
+ citeSeerFetcherPanel = new CiteSeerFetcherPanel(sidePaneManager,
+ (CiteSeerFetcher) citeSeerFetcher);
+ groupSelector = new GroupSelector(this, sidePaneManager);
+ searchManager = new SearchManager2(this, sidePaneManager);
+
+ sidePaneManager.register("fetchMedline", medlineFetcher);
+ sidePaneManager.register("CiteSeerProgress", citeSeerFetcher);
+ sidePaneManager.register("CiteSeerPanel", citeSeerFetcherPanel);
+ sidePaneManager.register("groups", groupSelector);
+ sidePaneManager.register("search", searchManager);
+
+ // Show the search panel if it was visible at last shutdown:
+ if (Globals.prefs.getBoolean("searchPanelVisible"))
+ sidePaneManager.show("search");
+ }
+
+
+AboutAction aboutAction = new AboutAction();
class AboutAction
extends AbstractAction {
public AboutAction() {
@@ -442,7 +442,7 @@ public class JabRefFrame
}
}
- // -------------------- !!!! NECESSARY ???? OBSOLETE ??? ----------------------
+
// General info dialog. The OSXAdapter calls this method when "About OSXAdapter"
// is selected from the application menu.
public void about() {
@@ -545,8 +545,8 @@ public JabRefPreferences prefs() {
}
}
}
- if (baseAt(i).file != null) {
- filenames.add(baseAt(i).file.getPath());
+ if (baseAt(i).getFile() != null) {
+ filenames.add(baseAt(i).getFile().getPath());
}
}
}
@@ -557,7 +557,7 @@ public JabRefPreferences prefs() {
prefs.putInt("posY", ths.getLocation().y);
prefs.putInt("sizeX", ths.getSize().width);
prefs.putInt("sizeY", ths.getSize().height);
- prefs.putBoolean("searchPanelVisible", sidePaneManager.isPanelVisible("search"));
+ prefs.putBoolean("searchPanelVisible", sidePaneManager.isComponentVisible("search"));
if (prefs.getBoolean("openLastEdited")) {
// Here we store the names of allcurrent filea. If
@@ -592,6 +592,8 @@ public JabRefPreferences prefs() {
}
}
+
+
private void macOSXRegistration() {
if (Globals.osName.equals(Globals.MAC)) {
try {
@@ -637,8 +639,11 @@ public JabRefPreferences prefs() {
}
}
- private void setupLayout() {
+ private void initLayout() {
tabbedPane.putClientProperty(Options.NO_CONTENT_BORDER_KEY, Boolean.TRUE);
+
+ pushExternalButton = new PushToApplicationButton(this,
+ PushToApplicationButton.applications);
fillMenu();
createToolBar();
getContentPane().setLayout(gbl);
@@ -712,7 +717,7 @@ public JabRefPreferences prefs() {
// Drag and drop for tabbedPane:
- TransferHandler xfer = new EntryTableTransferHandler(null, this);
+ TransferHandler xfer = new EntryTableTransferHandler(null, this, null);
tabbedPane.setTransferHandler(xfer);
tlb.setTransferHandler(xfer);
mb.setTransferHandler(xfer);
@@ -780,8 +785,14 @@ public JabRefPreferences prefs() {
return tabbedPane.getTitleAt(getTabIndex(comp));
}
- public void setTabTitle(JComponent comp, String s) {
- tabbedPane.setTitleAt(getTabIndex(comp), s);
+ public String getTabTooltip(JComponent comp) {
+ return tabbedPane.getToolTipTextAt(getTabIndex(comp));
+ }
+
+ public void setTabTitle(JComponent comp, String title, String toolTip) {
+ int index = getTabIndex(comp);
+ tabbedPane.setTitleAt(index, title);
+ tabbedPane.setToolTipTextAt(index, toolTip);
}
class GeneralAction
@@ -849,7 +860,7 @@ public JabRefPreferences prefs() {
public void actionPerformed(ActionEvent e) {
if (tabbedPane.getTabCount() > 0) {
try {
- ( (BasePanel) (tabbedPane.getSelectedComponent()))
+ ( (BasePanel) (tabbedPane.getSelectedComponent ()))
.runCommand(command);
}
catch (Throwable ex) {
@@ -966,187 +977,196 @@ public JabRefPreferences prefs() {
}
private void fillMenu() {
- //mb.putClientProperty(Options.HEADER_STYLE_KEY, HeaderStyle.BOTH);
+ //mb.putClientProperty(Options.HEADER_STYLE_KEY, HeaderStyle.BOTH);
mb.setBorder(null);
- JMenu file = subMenu("File"),
- edit = subMenu("Edit"),
- bibtex = subMenu("BibTeX"),
- view = subMenu("View"),
- tools = subMenu("Tools"),
- web = subMenu("Web search"),
- options = subMenu("Options"),
- newSpec = subMenu("New entry..."),
- helpMenu = subMenu("Help");
-
- setUpImportMenus();
- setUpExportMenu(exportMenu);
- setUpCustomExportMenu();
-
- newDatabaseMenu.add(newDatabaseAction) ;
- newDatabaseMenu.add(newSubDatabaseAction) ;
-
- file.add(newDatabaseAction);
- file.add(open); //opendatabaseaction
- file.add(mergeDatabaseAction);
- file.add(importMenu);
- //file.add(importMenu);
- file.add(importNewMenu);
- file.add(save);
- file.add(saveAs);
- file.add(saveSelectedAs);
- file.add(exportMenu);
- file.add(customExportMenu);
- file.addSeparator();
- file.add(databaseProperties);
+ JMenu file = subMenu("File"),
+ sessions = subMenu("Sessions"),
+ edit = subMenu("Edit"),
+ bibtex = subMenu("BibTeX"),
+ view = subMenu("View"),
+ tools = subMenu("Tools"),
+ web = subMenu("Web search"),
+ options = subMenu("Options"),
+ newSpec = subMenu("New entry..."),
+ helpMenu = subMenu("Help");
+
+ setUpImportMenus();
+
+ newDatabaseMenu.add(newDatabaseAction);
+ newDatabaseMenu.add(newSubDatabaseAction);
+
+ file.add(newDatabaseAction);
+ file.add(open); //opendatabaseaction
+ file.add(mergeDatabaseAction);
+ file.add(save);
+ file.add(saveAs);
+ file.add(saveSelectedAs);
+ file.addSeparator();
+ //file.add(importMenu);
+ //file.add(importNewMenu);
+ file.add(importNew);
+ file.add(importCurrent);
+ file.add(exportAll);
+ file.add(exportSelected);
+
+ file.addSeparator();
+ file.add(databaseProperties);
file.addSeparator();
+ sessions.add(loadSessionAction);
+ sessions.add(saveSessionAction);
+ file.add(sessions);
file.add(fileHistory);
- //file.addSeparator();
- file.add(loadSessionAction);
- file.add(saveSessionAction);
- file.addSeparator();
- file.add(close);
- //==============================
- // NB: I added this because my frame borders are so tiny that I cannot click
- // on the "x" close button. Anyways, I think it is good to have and "exit" button
- // I was too lazy to make a new ExitAction
- //JMenuItem exit_mItem = new JMenuItem(Globals.lang("Exit"));
- //exit_mItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Q, KeyEvent.CTRL_MASK)); //Ctrl-Q to exit
- // above keybinding should be from user define
- //exit_mItem.addActionListener(new CloseAction() );
- //file.add( exit_mItem);
- //=====================================
- file.add(quit);
- mb.add(file);
- //edit.add(test);
- edit.add(undo);
- edit.add(redo);
- edit.addSeparator();
-
- edit.add(cut);
- edit.add(copy);
- edit.add(paste);
- //edit.add(remove);
- edit.add(delete);
- edit.add(copyKey);
- edit.add(copyCiteKey);
- //edit.add(exportToClipboard);
- edit.addSeparator();
- edit.add(mark);
- edit.add(unmark);
- edit.add(unmarkAll);
- edit.addSeparator();
- edit.add(selectAll);
- mb.add(edit);
- view.add(nextTab);
- view.add(prevTab);
+ //file.addSeparator();
+
+ file.addSeparator();
+ file.add(close);
+ //==============================
+ // NB: I added this because my frame borders are so tiny that I cannot click
+ // on the "x" close button. Anyways, I think it is good to have an "exit" button
+ // I was too lazy to make a new ExitAction
+ //JMenuItem exit_mItem = new JMenuItem(Globals.lang("Exit"));
+ //exit_mItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Q, KeyEvent.CTRL_MASK)); //Ctrl-Q to exit
+ // above keybinding should be from user define
+ //exit_mItem.addActionListener(new CloseAction() );
+ //file.add( exit_mItem);
+ //=====================================
+ file.add(quit);
+ mb.add(file);
+ //edit.add(test);
+ edit.add(undo);
+ edit.add(redo);
+ edit.addSeparator();
+
+ edit.add(cut);
+ edit.add(copy);
+ edit.add(paste);
+ //edit.add(remove);
+ edit.add(delete);
+ edit.add(copyKey);
+ edit.add(copyCiteKey);
+ //edit.add(exportToClipboard);
+ edit.addSeparator();
+ edit.add(mark);
+ edit.add(unmark);
+ edit.add(unmarkAll);
+ edit.addSeparator();
+ edit.add(selectAll);
+ mb.add(edit);
+ view.add(nextTab);
+ view.add(prevTab);
view.add(sortTabs);
- view.addSeparator();
- view.add(toggleGroups);
- view.add(togglePreview);
- view.add(switchPreview);
- view.addSeparator();
- view.add(toggleHighlightAny);
- view.add(toggleHighlightAll);
- mb.add(view);
-
- bibtex.add(newEntryAction);
- for (int i = 0; i < newSpecificEntryAction.length; i++) {
- newSpec.add(newSpecificEntryAction[i]);
- }
- bibtex.add(newSpec);
- bibtex.add(plainTextImport);
- bibtex.addSeparator();
- bibtex.add(editEntry);
- bibtex.add(importCiteSeer);
- bibtex.add(editPreamble);
- bibtex.add(editStrings);
- mb.add(bibtex);
-
- tools.add(normalSearch);
- tools.add(incrementalSearch);
- tools.add(replaceAll);
-
- tools.add( makeKeyAction);
-
- // [kiar] I think we should group these festures
- tools.add(checkAndFix) ;
- checkAndFix.add(dupliCheck);
- checkAndFix.add(strictDupliCheck);
- checkAndFix.add(autoSetPdf);
- checkAndFix.add(autoSetPs);
- checkAndFix.add(integrityCheckAction) ;
-
-
-
- tools.addSeparator();
- tools.add(manageSelectors);
- tools.add(emacsPushAction);
- tools.add(lyxPushAction);
- tools.add(winEdtPushAction);
- //tools.add(latexEditorPushAction);
- //tools.add(fetchAuthorMedline);
- tools.addSeparator();
- tools.add(openFile);
- tools.add(openUrl);
- tools.addSeparator();
- tools.add(newSubDatabaseAction);
+ view.addSeparator();
+ view.add(toggleGroups);
+ view.add(togglePreview);
+ view.add(switchPreview);
+ view.addSeparator();
+ view.add(toggleHighlightAny);
+ view.add(toggleHighlightAll);
+ mb.add(view);
+
+ bibtex.add(newEntryAction);
+ for (int i = 0; i < newSpecificEntryAction.length; i++) {
+ newSpec.add(newSpecificEntryAction[i]);
+ }
+ bibtex.add(newSpec);
+ bibtex.add(plainTextImport);
+ bibtex.addSeparator();
+ bibtex.add(editEntry);
+ bibtex.add(importCiteSeer);
+ bibtex.add(editPreamble);
+ bibtex.add(editStrings);
+ mb.add(bibtex);
+
+ tools.add(normalSearch);
+ tools.add(incrementalSearch);
+ tools.add(replaceAll);
+ tools.add(new MassSetFieldAction(this));
+ tools.add(makeKeyAction);
+
+ // [kiar] I think we should group these festures
+ tools.add(checkAndFix);
+ checkAndFix.add(dupliCheck);
+ checkAndFix.add(strictDupliCheck);
+ checkAndFix.add(autoSetPdf);
+ checkAndFix.add(autoSetPs);
+ checkAndFix.add(integrityCheckAction);
+
+
+ tools.addSeparator();
+ tools.add(manageSelectors);
+
+ tools.add(pushExternalButton.getMenuAction());
+ tools.add(writeXmpAction);
+
+ //tools.add(emacsPushAction);
+ //tools.add(lyxPushAction);
+ //tools.add(winEdtPushAction);
+ //tools.add(latexEditorPushAction);
+ //tools.add(fetchAuthorMedline);
+ tools.addSeparator();
+ tools.add(openFile);
+ tools.add(openUrl);
+ tools.addSeparator();
+ tools.add(newSubDatabaseAction);
tools.addSeparator();
tools.add(abbreviateIso);
tools.add(abbreviateMedline);
tools.add(unabbreviate);
- mb.add(tools);
+ mb.add(tools);
- web.add(fetchMedline);
- web.add(citeSeerPanelAction);
- web.add(fetchCiteSeer);
- GeneralFetcher ieex = new GeneralFetcher(sidePaneManager, this, ieeexplorerFetcher);
- web.add(ieex.getAction());
+ web.add(fetchMedline);
+ web.add(citeSeerPanelAction);
+ web.add(fetchCiteSeer);
+ ieex = new GeneralFetcher(sidePaneManager, this, ieeexplorerFetcher);
+ arxiv = new GeneralFetcher(sidePaneManager, this, arxivFetcher);
+ web.add(ieex.getAction());
+ web.add(arxiv.getAction());
mb.add(web);
- options.add(showPrefs);
- AbstractAction customizeAction = new CustomizeEntryTypeAction();
- AbstractAction genFieldsCustomization = new GenFieldsCustomizationAction();
- options.add(customizeAction);
- options.add(genFieldsCustomization);
- options.add(customExpAction);
- options.add(customImpAction);
- options.add(manageJournals);
-
- /*options.add(new AbstractAction("Font") {
- public void actionPerformed(ActionEvent e) {
- // JDialog dl = new EntryCustomizationDialog(ths);
- Font f=new FontSelectorDialog
- (ths, GUIGlobals.CURRENTFONT).getSelectedFont();
- if(f==null)
- return;
- else
- GUIGlobals.CURRENTFONT=f;
- // updatefont
- prefs.put("fontFamily", GUIGlobals.CURRENTFONT.getFamily());
- prefs.putInt("fontStyle", GUIGlobals.CURRENTFONT.getStyle());
- prefs.putInt("fontSize", GUIGlobals.CURRENTFONT.getSize());
- if (tabbedPane.getTabCount() > 0) {
- for (int i=0; i<tabbedPane.getTabCount(); i++) {
- baseAt(i).entryTable.updateFont();
- baseAt(i).refreshTable();
+ options.add(showPrefs);
+ AbstractAction customizeAction = new CustomizeEntryTypeAction();
+ AbstractAction genFieldsCustomization = new GenFieldsCustomizationAction();
+ options.add(customizeAction);
+ options.add(genFieldsCustomization);
+ options.add(customExpAction);
+ options.add(customImpAction);
+ options.add(manageJournals);
+
+ /*options.add(new AbstractAction("Font") {
+ public void actionPerformed(ActionEvent e) {
+ // JDialog dl = new EntryCustomizationDialog(ths);
+ Font f=new FontSelectorDialog
+ (ths, GUIGlobals.CURRENTFONT).getSelectedFont();
+ if(f==null)
+ return;
+ else
+ GUIGlobals.CURRENTFONT=f;
+ // updatefont
+ prefs.put("fontFamily", GUIGlobals.CURRENTFONT.getFamily());
+ prefs.putInt("fontStyle", GUIGlobals.CURRENTFONT.getStyle());
+ prefs.putInt("fontSize", GUIGlobals.CURRENTFONT.getSize());
+ if (tabbedPane.getTabCount() > 0) {
+ for (int i=0; i<tabbedPane.getTabCount(); i++) {
+ baseAt(i).entryTable.updateFont();
+ baseAt(i).refreshTable();
+ }
+ }
}
- }
- }
- });*/
+ });*/
- //options.add(selectKeys);
- mb.add(options);
+ //options.add(selectKeys);
+ mb.add(options);
- helpMenu.add(help);
- helpMenu.add(contents);
- helpMenu.addSeparator();
+ helpMenu.add(help);
+ helpMenu.add(contents);
+ helpMenu.addSeparator();
//old about helpMenu.add(about);
- helpMenu.add(about);
- mb.add(helpMenu);
+ helpMenu.add(about);
+ mb.add(helpMenu);
helpMenu.addSeparator();
helpMenu.add(errorConsole);
}
@@ -1230,12 +1250,18 @@ public JabRefPreferences prefs() {
tlb.add(highlightAll);
tlb.addSeparator();
- tlb.addAction(emacsPushAction);
- tlb.addAction(lyxPushAction);
- tlb.addAction(winEdtPushAction);
+
+ // Removing the separate push-to buttons, replacing them by the
+ // multipurpose button:
+ //tlb.addAction(emacsPushAction);
+ //tlb.addAction(lyxPushAction);
+ //tlb.addAction(winEdtPushAction);
+ tlb.add(pushExternalButton.getComponent());
+
tlb.addAction(openFile);
tlb.addAction(openUrl);
+
//tlb.addSeparator();
//tlb.addAction(showPrefs);
tlb.add(Box.createHorizontalGlue());
@@ -1320,157 +1346,65 @@ public JabRefPreferences prefs() {
}
}
- /**
- * Disable actions that demand an open database.
- */
- private void setEmptyState() {
- manageSelectors.setEnabled(false);
- mergeDatabaseAction.setEnabled(false);
- newSubDatabaseAction.setEnabled(false);
- close.setEnabled(false);
- save.setEnabled(false);
- saveAs.setEnabled(false);
- saveSelectedAs.setEnabled(false);
- nextTab.setEnabled(false);
- prevTab.setEnabled(false);
- sortTabs.setEnabled(false);
- undo.setEnabled(false);
- redo.setEnabled(false);
- cut.setEnabled(false);
- delete.setEnabled(false);
- copy.setEnabled(false);
- paste.setEnabled(false);
- mark.setEnabled(false);
- unmark.setEnabled(false);
- unmarkAll.setEnabled(false);
- editEntry.setEnabled(false);
- importCiteSeer.setEnabled(false);
- selectAll.setEnabled(false);
- copyKey.setEnabled(false);
- copyCiteKey.setEnabled(false);
- editPreamble.setEnabled(false);
- editStrings.setEnabled(false);
- toggleGroups.setEnabled(false);
- toggleSearch.setEnabled(false);
- makeKeyAction.setEnabled(false);
- emacsPushAction.setEnabled(false);
- lyxPushAction.setEnabled(false);
- winEdtPushAction.setEnabled(false);
- normalSearch.setEnabled(false);
- incrementalSearch.setEnabled(false);
- replaceAll.setEnabled(false);
- importMenu.setEnabled(false);
- exportMenu.setEnabled(false);
- fetchMedline.setEnabled(false);
- fetchCiteSeer.setEnabled(false);
- openFile.setEnabled(false);
- openUrl.setEnabled(false);
- togglePreview.setEnabled(false);
- dupliCheck.setEnabled(false);
- strictDupliCheck.setEnabled(false);
- highlightAll.setEnabled(false);
- highlightAny.setEnabled(false);
- citeSeerPanelAction.setEnabled(false);
- for (int i = 0; i < newSpecificEntryAction.length; i++) {
- newSpecificEntryAction[i].setEnabled(false);
- }
- newEntryAction.setEnabled(false);
- plainTextImport.setEnabled(false);
- closeDatabaseAction.setEnabled(false);
- switchPreview.setEnabled(false);
- integrityCheckAction.setEnabled(false);
- autoSetPdf.setEnabled(false);
- autoSetPs.setEnabled(false);
- toggleHighlightAny.setEnabled(false);
- toggleHighlightAll.setEnabled(false);
- databaseProperties.setEnabled(false);
- abbreviateIso.setEnabled(false);
- abbreviateMedline.setEnabled(false);
- unabbreviate.setEnabled(false);
- }
-
- /**
- * Enable actions that demand an open database.
- */
- private void setNonEmptyState() {
- manageSelectors.setEnabled(true);
- mergeDatabaseAction.setEnabled(true);
- newSubDatabaseAction.setEnabled(true);
- close.setEnabled(true);
- save.setEnabled(true);
- saveAs.setEnabled(true);
- saveSelectedAs.setEnabled(true);
- undo.setEnabled(true);
- redo.setEnabled(true);
- cut.setEnabled(true);
- delete.setEnabled(true);
- copy.setEnabled(true);
- paste.setEnabled(true);
- mark.setEnabled(true);
- unmark.setEnabled(true);
- unmarkAll.setEnabled(true);
- editEntry.setEnabled(true);
- importCiteSeer.setEnabled(true);
- selectAll.setEnabled(true);
- copyKey.setEnabled(true);
- copyCiteKey.setEnabled(true);
- editPreamble.setEnabled(true);
- editStrings.setEnabled(true);
- toggleGroups.setEnabled(true);
- toggleSearch.setEnabled(true);
- makeKeyAction.setEnabled(true);
- emacsPushAction.setEnabled(true);
- lyxPushAction.setEnabled(true);
- winEdtPushAction.setEnabled(true);
- normalSearch.setEnabled(true);
- incrementalSearch.setEnabled(true);
- replaceAll.setEnabled(true);
- importMenu.setEnabled(true);
- exportMenu.setEnabled(true);
- fetchMedline.setEnabled(true);
- fetchCiteSeer.setEnabled(true);
- openFile.setEnabled(true);
- openUrl.setEnabled(true);
- togglePreview.setEnabled(true);
- dupliCheck.setEnabled(true);
- strictDupliCheck.setEnabled(true);
- highlightAll.setEnabled(true);
- highlightAny.setEnabled(true);
- citeSeerPanelAction.setEnabled(true);
- for (int i = 0; i < newSpecificEntryAction.length; i++) {
- newSpecificEntryAction[i].setEnabled(true);
- }
- newEntryAction.setEnabled(true);
- plainTextImport.setEnabled(true);
- closeDatabaseAction.setEnabled(true);
- switchPreview.setEnabled(true);
- integrityCheckAction.setEnabled(true);
- autoSetPdf.setEnabled(true);
- autoSetPs.setEnabled(true);
- toggleHighlightAny.setEnabled(true);
- toggleHighlightAll.setEnabled(true);
- databaseProperties.setEnabled(true);
- abbreviateIso.setEnabled(true);
- abbreviateMedline.setEnabled(true);
- unabbreviate.setEnabled(true);
- }
-
- /**
- * Disable actions that need more than one database open.
- */
- private void setOnlyOne() {
- nextTab.setEnabled(false);
- prevTab.setEnabled(false);
- sortTabs.setEnabled(false);
- }
-
- /**
- * Disable actions that need more than one database open.
+ protected List openDatabaseOnlyActions = new LinkedList();
+ protected List severalDatabasesOnlyActions = new LinkedList();
+
+ protected void initActions() {
+ openDatabaseOnlyActions = new LinkedList();
+ openDatabaseOnlyActions.addAll(Arrays.asList(new Object[] { manageSelectors,
+ mergeDatabaseAction, newSubDatabaseAction, close, save, saveAs, saveSelectedAs, undo,
+ redo, cut, delete, copy, paste, mark, unmark, unmarkAll, editEntry, importCiteSeer,
+ selectAll, copyKey, copyCiteKey, editPreamble, editStrings, toggleGroups, toggleSearch,
+ makeKeyAction, emacsPushAction, lyxPushAction, winEdtPushAction, normalSearch,
+ incrementalSearch, replaceAll, importMenu, exportMenu, fetchMedline, fetchCiteSeer,
+ openFile, openUrl, togglePreview, dupliCheck, strictDupliCheck, highlightAll,
+ highlightAny, citeSeerPanelAction, newEntryAction, plainTextImport,
+ closeDatabaseAction, switchPreview, integrityCheckAction, autoSetPdf, autoSetPs,
+ toggleHighlightAny, toggleHighlightAll, databaseProperties, abbreviateIso,
+ abbreviateMedline, unabbreviate, ieex.getAction(), arxiv.getAction(), exportAll, exportSelected,
+ importCurrent}));
+
+ openDatabaseOnlyActions.addAll(Arrays.asList(newSpecificEntryAction));
+
+ severalDatabasesOnlyActions = new LinkedList();
+ severalDatabasesOnlyActions.addAll(Arrays
+ .asList(new Object[] { nextTab, prevTab, sortTabs }));
+
+ tabbedPane.addChangeListener(new ChangeListener() {
+ public void stateChanged(ChangeEvent event) {
+ updateEnabledState();
+ }
+ });
+
+
+
+ }
+
+ public static void setEnabled(List l, boolean enabled) {
+ Iterator i = l.iterator();
+ while (i.hasNext()) {
+ Object o = i.next();
+ if (o instanceof Action)
+ ((Action)o).setEnabled(enabled);
+ if (o instanceof Component)
+ ((Component)o).setEnabled(enabled);
+ }
+ }
+
+ protected int previousTabCount = -1;
+
+ /**
+ * Enable or Disable all actions based on the number of open tabs.
+ *
+ * The action that are affected are set in initActions.
*/
- private void setMultiple() {
- nextTab.setEnabled(true);
- prevTab.setEnabled(true);
- sortTabs.setEnabled(true);
+ protected void updateEnabledState() {
+ int tabCount = tabbedPane.getTabCount();
+ if (tabCount != previousTabCount){
+ previousTabCount = tabCount;
+ setEnabled(openDatabaseOnlyActions, tabCount > 0);
+ setEnabled(severalDatabasesOnlyActions, tabCount > 1);
+ }
}
/**
@@ -1506,14 +1440,11 @@ public JabRefPreferences prefs() {
public void addTab(BasePanel bp, File file, boolean raisePanel) {
tabbedPane.add((file != null ? file.getName(): Globals.lang(GUIGlobals.untitledTitle)),
bp);
+ tabbedPane.setToolTipTextAt(tabbedPane.getTabCount()-1,
+ file != null ? file.getAbsolutePath() : null);
if (raisePanel) {
tabbedPane.setSelectedComponent(bp);
}
- if (tabbedPane.getTabCount() == 1) {
- setNonEmptyState();
- } else if (tabbedPane.getTabCount() == 2) {
- setMultiple();
- }
}
class SelectKeysAction
@@ -1563,65 +1494,56 @@ public JabRefPreferences prefs() {
}
// The action for closing the current database and leaving the window open.
- CloseDatabaseAction closeDatabaseAction = new CloseDatabaseAction();
- class CloseDatabaseAction
- extends MnemonicAwareAction {
- public CloseDatabaseAction() {
- super(GUIGlobals.getImage("close"));
- putValue(NAME, "Close database");
- putValue(SHORT_DESCRIPTION,
- Globals.lang("Close the current database"));
- putValue(ACCELERATOR_KEY, prefs.getKey("Close database"));
- }
-
- public void actionPerformed(ActionEvent e) {
- // Ask here if the user really wants to close, if the base
- // has not been saved since last save.
- boolean close = true;
- if (basePanel() == null) { // when it is initially empty
- return; //nbatada nov 7
- }
-
- if (basePanel().baseChanged) {
- int answer = JOptionPane.showConfirmDialog
- (ths, Globals.lang("Database has changed. Do you want to save " +
- "before closing?"),
- Globals.lang("Save before closing"),
- JOptionPane.YES_NO_CANCEL_OPTION);
- if ( (answer == JOptionPane.CANCEL_OPTION) ||
- (answer == JOptionPane.CLOSED_OPTION)) {
- close = false; // The user has cancelled.
- }
- if (answer == JOptionPane.YES_OPTION) {
- // The user wants to save.
- try {
- basePanel().runCommand("save");
- }
- catch (Throwable ex) {
- // Something prevented the file
- // from being saved. Break!!!
- close = false;
- }
-
- }
- }
-
- if (close) {
- basePanel().cleanUp();
- tabbedPane.remove(basePanel());
- if (tabbedPane.getTabCount() == 0) {
- setEmptyState();
- } else
- {
- sidePaneManager.stateChanged(new ChangeEvent(tabbedPane));
- markActiveBasePanel() ;
- if (tabbedPane.getTabCount() == 1) { setOnlyOne() ; }
- }
- output(Globals.lang("Closed database") + ".");
- System.gc(); // Test
- }
- }
- }
+ CloseDatabaseAction closeDatabaseAction = new CloseDatabaseAction();
+
+ class CloseDatabaseAction extends MnemonicAwareAction {
+ public CloseDatabaseAction() {
+ super(GUIGlobals.getImage("close"));
+ putValue(NAME, "Close database");
+ putValue(SHORT_DESCRIPTION, Globals.lang("Close the current database"));
+ putValue(ACCELERATOR_KEY, prefs.getKey("Close database"));
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ // Ask here if the user really wants to close, if the base
+ // has not been saved since last save.
+ boolean close = true;
+ if (basePanel() == null) { // when it is initially empty
+ return; // nbatada nov 7
+ }
+
+ if (basePanel().baseChanged) {
+ int answer = JOptionPane.showConfirmDialog(ths, Globals
+ .lang("Database has changed. Do you want to save " + "before closing?"),
+ Globals.lang("Save before closing"), JOptionPane.YES_NO_CANCEL_OPTION);
+ if ((answer == JOptionPane.CANCEL_OPTION) || (answer == JOptionPane.CLOSED_OPTION)) {
+ close = false; // The user has cancelled.
+ }
+ if (answer == JOptionPane.YES_OPTION) {
+ // The user wants to save.
+ try {
+ basePanel().runCommand("save");
+ } catch (Throwable ex) {
+ // Something prevented the file
+ // from being saved. Break!!!
+ close = false;
+ }
+
+ }
+ }
+
+ if (close) {
+ basePanel().cleanUp();
+ tabbedPane.remove(basePanel());
+ if (tabbedPane.getTabCount() > 0) {
+ markActiveBasePanel();
+ }
+ updateEnabledState(); // Man, this is what I call a bug that this is not called.
+ output(Globals.lang("Closed database") + ".");
+ System.gc(); // Test
+ }
+ }
+ }
// The action concerned with opening a new database.
@@ -1735,7 +1657,7 @@ class FetchCiteSeerAction
public void actionPerformed(ActionEvent e) {
if(citeSeerFetcher.activateCitationFetcher()) {
- sidePaneManager.ensureVisible("CiteSeerProgress");
+ sidePaneManager.show("CiteSeerProgress");
(new Thread() {
BasePanel newBp;
BasePanel targetBp;
@@ -1822,10 +1744,6 @@ class FetchCiteSeerAction
null, Globals.prefs.get("defaultEncoding")); // meta data
tabbedPane.add( Globals.lang( GUIGlobals.untitledTitle ), bp ) ;
tabbedPane.setSelectedComponent( bp ) ;
- if ( tabbedPane.getTabCount() == 1 )
- {
- setNonEmptyState() ;
- }
output( Globals.lang( "New database created." ) ) ;
}
}
@@ -1861,47 +1779,41 @@ class FetchCiteSeerAction
}
}
- class FetchMedlineAction
- extends MnemonicAwareAction {
- public FetchMedlineAction() {
- super(GUIGlobals.getImage("medline"));
- putValue(NAME, "Fetch Medline");
- putValue(ACCELERATOR_KEY, prefs.getKey("Fetch Medline"));
- putValue(SHORT_DESCRIPTION, Globals.lang("Fetch Medline by ID"));
- }
-
- public void actionPerformed(ActionEvent e) {
- if (tabbedPane.getTabCount() > 0) {
- //for (int i = 0; i < tabbedPane.getTabCount(); i++) {
- // ( (BasePanel) tabbedPane.getComponentAt(i)).sidePaneManager.
- sidePaneManager.togglePanel("fetchMedline");// ensureVisible("fetchMedline");
- if (sidePaneManager.isPanelVisible("fetchMedline"))
- new FocusRequester(medlineFetcher.getTextField());
- //}
- }
- }
-
- }
-
- class CiteSeerPanelAction
- extends MnemonicAwareAction {
- public CiteSeerPanelAction() {
- super(GUIGlobals.getImage("medline"));
- putValue(NAME, "Fetch CiteSeer");
- //System.out.println(Globals.menuTitle("Fetch CiteSeer"));
- putValue(ACCELERATOR_KEY, prefs.getKey("Fetch CiteSeer"));
- }
-
- public void actionPerformed(ActionEvent e) {
- if (tabbedPane.getTabCount() > 0) {
- sidePaneManager.togglePanel("CiteSeerPanel");// ensureVisible("fetchMedline");
- if (sidePaneManager.isPanelVisible("CiteSeerPanel"))
- new FocusRequester(citeSeerFetcherPanel.getTextField());
- //}
- }
- }
-
- }
+ class FetchMedlineAction extends MnemonicAwareAction {
+ public FetchMedlineAction() {
+ super(GUIGlobals.getImage("medline"));
+ putValue(NAME, "Fetch Medline");
+ putValue(ACCELERATOR_KEY, prefs.getKey("Fetch Medline"));
+ putValue(SHORT_DESCRIPTION, Globals.lang("Fetch Medline by ID"));
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ if (tabbedPane.getTabCount() > 0) {
+ sidePaneManager.toggle("fetchMedline");
+ if (sidePaneManager.isComponentVisible("fetchMedline")) {
+ new FocusRequester(medlineFetcher.getTextField());
+ }
+ }
+ }
+ }
+
+ class CiteSeerPanelAction extends MnemonicAwareAction {
+ public CiteSeerPanelAction() {
+ super(GUIGlobals.getImage("medline"));
+ putValue(NAME, "Fetch CiteSeer");
+ putValue(ACCELERATOR_KEY, prefs.getKey("Fetch CiteSeer"));
+ putValue(SHORT_DESCRIPTION, Globals.lang("Fetch CiteSeer by ID"));
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ if (tabbedPane.getTabCount() > 0) {
+ sidePaneManager.toggle("CiteSeerPanel");
+ if (sidePaneManager.isComponentVisible("CiteSeerPanel")) {
+ new FocusRequester(citeSeerFetcherPanel.getTextField());
+ }
+ }
+ }
+ }
// The action for opening the preferences dialog.
AbstractAction showPrefs = new ShowPrefsAction();
@@ -2008,12 +1920,9 @@ class FetchCiteSeerAction
}
*/
addedEntries = database.getEntryCount();
- tabbedPane.add(Globals.lang("untitled"), bp);
+ tabbedPane.add(GUIGlobals.untitledTitle, bp);
bp.markBaseChanged();
tabbedPane.setSelectedComponent(bp);
- if (tabbedPane.getTabCount() == 1) {
- setNonEmptyState();
- }
if (filename != null)
output(Globals.lang("Imported database") + " '" + filename + "' " +
Globals.lang("with") + " " +
@@ -2101,16 +2010,19 @@ class FetchCiteSeerAction
SortedSet customImporters = Globals.importFormatReader.getCustomImportFormats();
JMenu submenu = new JMenu(Globals.lang("Custom importers"));
submenu.setMnemonic(KeyEvent.VK_S);
- if (customImporters.size() == 0) {
+ /*if (customImporters.size() == 0) {
submenu.setEnabled(false);
submenu.setToolTipText(Globals.lang("No custom imports registered yet."));
- } else {
+ } else {*/
// Put in all formatters registered in ImportFormatReader:
for (Iterator i=customImporters.iterator(); i.hasNext();) {
ImportFormat imFo = (ImportFormat)i.next();
submenu.add(new ImportMenuItem(ths, intoNew, imFo));
}
- }
+ //}
+ if (customImporters.size() > 0)
+ submenu.addSeparator();
+ submenu.add(customImpAction);
importMenu.add(submenu);
importMenu.addSeparator();
@@ -2127,122 +2039,6 @@ class FetchCiteSeerAction
return fileHistory;
}
- JMenuItem
- htmlItem = new JMenuItem(Globals.lang("HTML")),
- simpleHtmlItem = new JMenuItem(Globals.lang("Simple HTML")),
- //plainTextItem = new JMenuItem(Globals.lang("Plain text")),
- docbookItem = new JMenuItem(Globals.lang("Docbook")),
- bibtexmlItem = new JMenuItem(Globals.lang("BibTeXML")),
- modsItem = new JMenuItem(Globals.lang("MODS")),
- rtfItem = new JMenuItem(Globals.lang("Harvard RTF")),
- endnoteItem = new JMenuItem(Globals.lang("Endnote")),
- openofficeItem = new JMenuItem("OpenOffice Calc"),
- odsItem = new JMenuItem("OpenDocument Spreadsheet");
-
-
-
-
- private void setUpExportMenu(JMenu menu) {
- ActionListener listener = new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- JMenuItem source = (JMenuItem) e.getSource();
- String lfFileName = null, extension = null;
- if (source == htmlItem) {
- lfFileName = "html";
- extension = ".html";
- }
- else if (source == simpleHtmlItem) {
- lfFileName = "simplehtml";
- extension = ".html";
- } else if (source == docbookItem) {
- lfFileName = "docbook";
- extension = ".xml";
- } else if (source == bibtexmlItem) {
- lfFileName = "bibtexml";
- extension = ".xml";
- } else if (source == modsItem) {
- lfFileName = "mods";
- extension = ".xml";
- } else if (source == rtfItem) {
- lfFileName = "harvard";
- extension = ".rtf";
- } else if (source == endnoteItem) {
- lfFileName = "endnote";
- extension = ".txt";
- } else if (source == openofficeItem) {
- lfFileName = "oocalc";
- extension = ".sxc";
- } else if (source == odsItem) {
- lfFileName = "ods";
- extension = ".ods";
- }
- // We need to find out:
- // 1. The layout definition string to use. Or, rather, we
- // must provide a Reader for the layout definition.
- // 2. The preferred extension for the layout format.
- // 3. The name of the file to use.
- final String chosenFile = Globals.getNewFile(ths, new File(prefs.get("workingDirectory")),
- extension, JFileChooser.SAVE_DIALOG, false);
- final String exportName = lfFileName;
- if (chosenFile == null)
- return;
-
- (new Thread() {
- public void run() {
- try {
- FileActions.performExport(basePanel().database(), exportName,
- chosenFile, basePanel().getEncoding());
- output(Globals.lang("Exported database to file") + " '" +
- chosenFile + "'.");
- }
- catch (Exception ex) {
- ex.printStackTrace();
- }
- }
- }).start();
-
- }
- };
-
- htmlItem.addActionListener(listener);
- menu.add(htmlItem);
- simpleHtmlItem.addActionListener(listener);
- menu.add(simpleHtmlItem);
- //plainTextItem.addActionListener(listener);
- //menu.add(plainTextItem);
- bibtexmlItem.addActionListener(listener);
- menu.add(bibtexmlItem);
- docbookItem.addActionListener(listener);
- menu.add(docbookItem);
- modsItem.addActionListener(listener);
- menu.add(modsItem);
- rtfItem.addActionListener(listener);
- menu.add(rtfItem);
- endnoteItem.addActionListener(listener);
- menu.add(endnoteItem);
- openofficeItem.addActionListener(listener);
- odsItem.addActionListener(listener);
- menu.add(openofficeItem);
- menu.add(odsItem);
- menu.add(exportCSV);
-
- menu.addSeparator();
- menu.add(expandEndnoteZip);
-
- }
-
- /**
- * Interrogates the list of custom export formats defined, and adds them to the custom
- * export menu.
- */
- public void setUpCustomExportMenu() {
- customExportMenu.removeAll();
- for (int i=0; i<prefs.customExports.size(); i++) {
- String[] s = prefs.customExports.getElementAt(i);
- customExportMenu.add(new CustomExportAction(s[0], s[2], s[1]));
- }
-
- }
/**
* Set the preview active state for all BasePanel instances.
@@ -2311,8 +2107,8 @@ class SaveSessionAction
catch (Throwable ex) {}
}
}
- if (baseAt(i).file != null) {
- filenames.add(baseAt(i).file.getPath());
+ if (baseAt(i).getFile() != null) {
+ filenames.add(baseAt(i).getFile().getPath());
}
}
}
@@ -2333,61 +2129,6 @@ class SaveSessionAction
}
}
- class CustomExportAction extends AbstractAction {
-
- String extension, lfFileName, directory;
-
- public CustomExportAction(String name, String ext, String lf) {
- super(name);
- File lfFile = new File(lf);
- extension = ext;
- String filename = lfFile.getName();
-
- lfFileName = filename.substring(0, filename.length()-7);
- directory = lfFile.getParent()+File.separator;
- }
-
- public void actionPerformed(ActionEvent e) {
- // We need to find out:
- // 1. The layout definition string to use. Or, rather, we
- // must provide a Reader for the layout definition.
- // 2. The preferred extension for the layout format.
- // 3. The name of the file to use.
- File outFile;
- String chosenFile = Globals.getNewFile(ths,
- new File(prefs.get("workingDirectory")),
- extension,
- JFileChooser.SAVE_DIALOG, false);
-
- if (chosenFile != null)
- outFile = new File(chosenFile);
-
- else {
- return;
- }
-
- final String lfName = lfFileName;
- final File oFile = outFile;
-
- (new Thread() {
- public void run() {
- try {
- FileActions.exportDatabase
- (basePanel().database, directory,
- lfName, oFile, basePanel().getEncoding());
- output(Globals.lang("Exported database to file") + " '" +
- oFile.getPath() + "'.");
- }
- catch (Exception ex) {
- //ex.printStackTrace();
- JOptionPane.showMessageDialog(ths, ex.getMessage(), Globals.lang("Error"),
- JOptionPane.ERROR_MESSAGE);
- }
- }
- }).start();
- }
- }
-
class LoadSessionAction
extends MnemonicAwareAction {
boolean running = false;
@@ -2411,8 +2152,8 @@ class SaveSessionAction
HashSet currentFiles = new HashSet();
if (tabbedPane.getTabCount() > 0) {
for (int i = 0; i < tabbedPane.getTabCount(); i++) {
- if (baseAt(i).file != null)
- currentFiles.add(baseAt(i).file.getPath());
+ if (baseAt(i).getFile() != null)
+ currentFiles.add(baseAt(i).getFile().getPath());
}
}
int i0 = tabbedPane.getTabCount();
@@ -2600,4 +2341,4 @@ class SaveSessionAction
// Override isOpaque() to prevent the glasspane from hiding the window contents:
public boolean isOpaque() { return false; }
}
-}
+}
\ No newline at end of file
diff --git a/src/java/net/sf/jabref/JabRefPreferences.java b/src/java/net/sf/jabref/JabRefPreferences.java
index 1a6d56f..4ea8085 100644
--- a/src/java/net/sf/jabref/JabRefPreferences.java
+++ b/src/java/net/sf/jabref/JabRefPreferences.java
@@ -47,12 +47,11 @@ public class JabRefPreferences {
CUSTOM_TYPE_NAME = "customTypeName_",
CUSTOM_TYPE_REQ = "customTypeReq_",
CUSTOM_TYPE_OPT = "customTypeOpt_",
- CUSTOM_TAB_NAME = "customTabName_",
- CUSTOM_TAB_FIELDS = "customTabFields_";
+ CUSTOM_TAB_NAME = "customTabName_",
+ CUSTOM_TAB_FIELDS = "customTabFields_";
public String WRAPPED_USERNAME;
-
Preferences prefs;
public HashMap defaults = new HashMap(),
keyBinds = new HashMap(),
@@ -75,47 +74,42 @@ public class JabRefPreferences {
private Map externalFileTypes = new HashMap();
// The only instance of this class:
- private static JabRefPreferences INSTANCE = null;
+ private static JabRefPreferences singleton = null;
public static JabRefPreferences getInstance() {
- if (INSTANCE == null)
- INSTANCE = new JabRefPreferences();
- return INSTANCE;
- }
+ if (singleton == null)
+ singleton = new JabRefPreferences();
+ return singleton;
+ }
// The constructor is made private to enforce this as a singleton class:
private JabRefPreferences() {
prefs = Preferences.userNodeForPackage(JabRef.class);
//Util.pr(prefs.toString());
-
+
if (Globals.osName.equals(Globals.MAC)) {
- defaults.put("pdfviewer","/Applications/Preview.app");
- defaults.put("psviewer","/Applications/Preview.app");
- defaults.put("htmlviewer","/Applications/Safari.app");
- }
- else if (Globals.osName.toLowerCase().startsWith("windows")) {
- defaults.put("pdfviewer","cmd.exe /c start /b");
- defaults.put("psviewer","cmd.exe /c start /b");
- defaults.put("htmlviewer","cmd.exe /c start /b");
- defaults.put("lookAndFeel", "com.jgoodies.plaf.windows.ExtWindowsLookAndFeel");
-
-
- }
-
- else {
- defaults.put("pdfviewer","acroread");
- defaults.put("psviewer","gv");
- defaults.put("htmlviewer","mozilla");
- defaults.put("lookAndFeel", "com.jgoodies.plaf.plastic.Plastic3DLookAndFeel");
-
- }
+ defaults.put("pdfviewer", "/Applications/Preview.app");
+ defaults.put("psviewer", "/Applications/Preview.app");
+ defaults.put("htmlviewer", "/Applications/Safari.app");
+ } else if (Globals.osName.toLowerCase().startsWith("windows")) {
+ defaults.put("pdfviewer", "cmd.exe /c start /b");
+ defaults.put("psviewer", "cmd.exe /c start /b");
+ defaults.put("htmlviewer", "cmd.exe /c start /b");
+ defaults.put("lookAndFeel", "com.jgoodies.plaf.windows.ExtWindowsLookAndFeel");
+ } else {
+ defaults.put("pdfviewer", "acroread");
+ defaults.put("psviewer", "gv");
+ defaults.put("htmlviewer", "mozilla");
+ defaults.put("lookAndFeel", "com.jgoodies.plaf.plastic.Plastic3DLookAndFeel");
+ }
defaults.put("useDefaultLookAndFeel", Boolean.TRUE);
defaults.put("lyxpipe", System.getProperty("user.home")+File.separator+".lyx/lyxpipe");
defaults.put("posX", new Integer(0));
defaults.put("posY", new Integer(0));
defaults.put("sizeX", new Integer(840));
defaults.put("sizeY", new Integer(680));
+ defaults.put("rememberWindowLocation", Boolean.TRUE);
defaults.put("autoResizeMode", new Integer(JTable.AUTO_RESIZE_OFF));
defaults.put("tableColorCodesOn", Boolean.TRUE);
defaults.put("namesAsIs", Boolean.FALSE);
@@ -138,6 +132,7 @@ public class JabRefPreferences {
defaults.put("numberColWidth",new Integer(GUIGlobals.NUMBER_COL_LENGTH));
defaults.put("workingDirectory", System.getProperty("user.home"));
defaults.put("exportWorkingDirectory", System.getProperty("user.home"));
+ defaults.put("importWorkingDirectory", System.getProperty("user.home"));
defaults.put("autoOpenForm", Boolean.TRUE);
defaults.put("entryTypeFormHeightFactor", new Integer(1));
defaults.put("entryTypeFormWidth", new Integer(1));
@@ -182,7 +177,6 @@ public class JabRefPreferences {
defaults.put("highlightGroupsMatchingAny", Boolean.FALSE);
defaults.put("highlightGroupsMatchingAll", Boolean.FALSE);
defaults.put("searchPanelVisible", Boolean.FALSE);
-
defaults.put("defaultEncoding", System.getProperty("file.encoding"));
defaults.put("winEdtPath", "C:\\Program Files\\WinEdt Team\\WinEdt\\WinEdt.exe");
defaults.put("latexEditorPath", "C:\\TEMP\\Led.exe");
@@ -305,7 +299,8 @@ public class JabRefPreferences {
defaults.put("floatMarkedEntries", Boolean.TRUE);
defaults.put("useNativeFileDialogOnMac", Boolean.TRUE);
-
+
+ defaults.put("lastUsedExport", null);
//defaults.put("tempDir", System.getProperty("java.io.tmpdir"));
//Util.pr(System.getProperty("java.io.tempdir"));
@@ -321,13 +316,18 @@ public class JabRefPreferences {
WRAPPED_USERNAME = "["+get("defaultOwner")+"]";
// TODO: remove temporary registering of external file types?
- externalFileTypes.put("pdf", new ExternalFileType("PDF", "pdf", "acroread", null));
- externalFileTypes.put("ps", new ExternalFileType("PostScript", "ps", "gs", null));
- externalFileTypes.put("doc", new ExternalFileType("Word file", "doc", "oowriter", null));
- externalFileTypes.put("odt", new ExternalFileType("OpenDocument text", "odt", "oowriter", null));
-
- }
-
+ updateExternalFileTypes();
+
+ String defaultExpression = "**/.*[bibtexkey].*\\\\.[extension]";
+ defaults.put(DEFAULT_REG_EXP_SEARCH_EXPRESSION_KEY, defaultExpression);
+ defaults.put(REG_EXP_SEARCH_EXPRESSION_KEY, defaultExpression);
+ defaults.put(USE_REG_EXP_SEARCH_KEY, Boolean.FALSE);
+ }
+
+ public static final String DEFAULT_REG_EXP_SEARCH_EXPRESSION_KEY = "defaultRegExpSearchExpression";
+ public static final String REG_EXP_SEARCH_EXPRESSION_KEY = "regExpSearchExpression";
+ public static final String USE_REG_EXP_SEARCH_KEY = "useRegExpSearch";
+
public boolean putBracesAroundCapitals(String fieldName) {
return putBracesAroundCapitalsFields.contains(fieldName);
}
@@ -438,7 +438,7 @@ public class JabRefPreferences {
String names = get(key);
if (names == null)
return null;
- //Util.pr(key+"\n"+names);
+
StringReader rd = new StringReader(names);
Vector arr = new Vector();
String rs;
@@ -664,6 +664,7 @@ public class JabRefPreferences {
}
private void defineDefaultKeyBindings() {
+ defKeyBinds.put("Push to application","ctrl L");
defKeyBinds.put("Push to LyX","ctrl L");
defKeyBinds.put("Push to WinEdt","ctrl shift W");
defKeyBinds.put("Push to Emacs","ctrl shift E");
@@ -736,7 +737,8 @@ public class JabRefPreferences {
defKeyBinds.put("Abbreviate", "ctrl alt A");
defKeyBinds.put("Unabbreviate", "ctrl alt shift A");
defKeyBinds.put("Search IEEXplore", "F8");
-
+ defKeyBinds.put("Write XMP", "ctrl F4");
+
//defKeyBinds.put("Select value", "ctrl B");
}
@@ -814,6 +816,16 @@ public class JabRefPreferences {
}
/**
+ *
+ */
+ public void updateExternalFileTypes() {
+ externalFileTypes.put("pdf", new ExternalFileType("PDF", "pdf", get("pdfviewer"), null));
+ externalFileTypes.put("ps", new ExternalFileType("PostScript", "ps", get("psviewer"), null));
+ externalFileTypes.put("doc", new ExternalFileType("Word file", "doc", "oowriter", null));
+ externalFileTypes.put("odt", new ExternalFileType("OpenDocument text", "odt", "oowriter", null));
+ }
+
+ /**
* Look up the external file type registered for this extension, if any.
* @param extension The file extension.
* @return The ExternalFileType registered, or null if none.
@@ -898,7 +910,6 @@ public class JabRefPreferences {
* @return true if the field should not be wrapped.
*/
public boolean isNonWrappableField(String fieldName) {
-
return nonWrappableFields.contains(fieldName);
}
}
diff --git a/src/java/net/sf/jabref/MetaData.java b/src/java/net/sf/jabref/MetaData.java
index 1c6ce60..d40c5ba 100644
--- a/src/java/net/sf/jabref/MetaData.java
+++ b/src/java/net/sf/jabref/MetaData.java
@@ -35,7 +35,8 @@ public class MetaData {
private HashMap metaData = new HashMap();
private StringReader data;
private GroupTreeNode groupsRoot = null;
-
+ private File file = null; // The File where this base gets saved.
+
/**
* The MetaData object stores all meta data sets in Vectors. To ensure that
* the data is written correctly to string, the user of a meta data Vector
@@ -139,11 +140,25 @@ public class MetaData {
String key = fieldName + "Directory";
String dir;
Vector vec = getData(key);
- if ((vec != null) && (vec.size() > 0))
+ if ((vec != null) && (vec.size() > 0)) {
dir = (String)vec.get(0);
+ // If this directory is relative, we try to interpret it as relative to
+ // the file path of this bib file:
+ if (!(new File(dir)).isAbsolute() && (file != null)) {
+ String relDir = new StringBuffer(file.getParent()).
+ append(System.getProperty("file.separator")).
+ append(dir).toString();
+ // If this directory actually exists, it is very likely that the
+ // user wants us to use it:
+ if ((new File(relDir)).exists())
+ dir = relDir;
+ }
+ }
else
dir = Globals.prefs.get(key);
+
+ //System.out.println("MetaData: dir: '"+dir+"' relative: "+(new File(dir)).isAbsolute());
return dir;
}
@@ -252,4 +267,12 @@ public class MetaData {
return res.toString();
return null;
}
+
+ public File getFile() {
+ return file;
+ }
+
+ public void setFile(File file) {
+ this.file = file;
+ }
}
diff --git a/src/java/net/sf/jabref/NameFormatterTab.java b/src/java/net/sf/jabref/NameFormatterTab.java
new file mode 100644
index 0000000..4003868
--- /dev/null
+++ b/src/java/net/sf/jabref/NameFormatterTab.java
@@ -0,0 +1,307 @@
+package net.sf.jabref;
+
+import java.awt.BorderLayout;
+import java.awt.Dimension;
+import java.awt.event.ActionEvent;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Vector;
+
+import javax.swing.AbstractAction;
+import javax.swing.BorderFactory;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTable;
+import javax.swing.JToolBar;
+import javax.swing.SwingConstants;
+import javax.swing.table.AbstractTableModel;
+import javax.swing.table.TableColumnModel;
+import javax.swing.table.TableModel;
+
+import net.sf.jabref.export.layout.format.NameFormat;
+
+import com.jgoodies.forms.builder.DefaultFormBuilder;
+import com.jgoodies.forms.layout.FormLayout;
+
+public class NameFormatterTab extends JPanel implements PrefsTab {
+
+ public static final String NAME_FORMATTER_VALUE = "nameFormatterFormats";
+
+ public static final String NAME_FORMATER_KEY = "nameFormatterNames";
+
+ public static Map getNameFormatters(){
+
+ Map result = new HashMap();
+
+ String[] names = Globals.prefs.getStringArray(NAME_FORMATER_KEY);
+ String[] formats = Globals.prefs.getStringArray(NAME_FORMATTER_VALUE);
+
+ if (names == null){
+ names = new String[]{};
+ }
+ if (formats == null){
+ formats = new String[]{};
+ }
+
+ for (int i = 0; i < names.length; i++) {
+ if (i < formats.length)
+ result.put(names[i], formats[i]);
+ else
+ result.put(names[i], NameFormat.DEFAULT_FORMAT);
+ }
+
+ return result;
+ }
+
+ private boolean tableChanged = false;
+
+ private JTable table;
+
+ private int rowCount = -1;
+
+ private Vector tableRows = new Vector(10);
+
+ class TableRow {
+ String name;
+
+ String format;
+
+ public TableRow() {
+ this("");
+ }
+
+ public TableRow(String name) {
+ this(name, NameFormat.DEFAULT_FORMAT);
+ }
+
+ public TableRow(String name, String format) {
+ this.name = name;
+ this.format = format;
+ }
+ }
+
+ /**
+ * Tab to create custom Name Formatters
+ *
+ */
+ public NameFormatterTab(HelpDialog helpDialog) {
+ setLayout(new BorderLayout());
+
+ TableModel tm = new AbstractTableModel() {
+ public int getRowCount() {
+ return rowCount;
+ }
+
+ public int getColumnCount() {
+ return 2;
+ }
+
+ public Object getValueAt(int row, int column) {
+ if (row >= tableRows.size())
+ return "";
+ TableRow tr = (TableRow) tableRows.elementAt(row);
+ if (tr == null)
+ return "";
+ switch (column) {
+ case 0:
+ return tr.name;
+ case 1:
+ return tr.format;
+ }
+ return null; // Unreachable.
+ }
+
+ public String getColumnName(int col) {
+ return (col == 0 ? Globals.lang("Formatter Name") : Globals.lang("Format String"));
+ }
+
+ public Class getColumnClass(int column) {
+ if (column == 0)
+ return String.class;
+ else
+ return String.class;
+ }
+
+ public boolean isCellEditable(int row, int col) {
+ return true;
+ }
+
+ public void setValueAt(Object value, int row, int col) {
+ tableChanged = true;
+
+ // Make sure the vector is long enough.
+ while (row >= tableRows.size())
+ tableRows.add(new TableRow());
+
+ TableRow rowContent = (TableRow) tableRows.elementAt(row);
+
+ if (col == 0)
+ rowContent.name = value.toString();
+ else
+ rowContent.format = value.toString();
+ }
+ };
+
+ table = new JTable(tm);
+ TableColumnModel cm = table.getColumnModel();
+ cm.getColumn(0).setPreferredWidth(140);
+ cm.getColumn(1).setPreferredWidth(400);
+
+ FormLayout layout = new FormLayout("1dlu, 8dlu, left:pref, 4dlu, fill:pref", "");
+
+ DefaultFormBuilder builder = new DefaultFormBuilder(layout);
+
+ JPanel pan = new JPanel();
+
+ JPanel tabPanel = new JPanel();
+ tabPanel.setLayout(new BorderLayout());
+ JScrollPane sp = new JScrollPane(table, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
+ JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
+ table.setPreferredScrollableViewportSize(new Dimension(250, 200));
+ sp.setMinimumSize(new Dimension(250, 300));
+ sp.setPreferredSize(new Dimension(600, 300));
+ tabPanel.add(sp, BorderLayout.CENTER);
+
+ JToolBar tlb = new JToolBar(SwingConstants.VERTICAL);
+ tlb.setFloatable(false);
+ tlb.setBorder(null);
+ tlb.add(new AddRowAction());
+ tlb.add(new DeleteRowAction());
+ tlb.add(new HelpAction(helpDialog, GUIGlobals.nameFormatterHelp,
+ Globals.lang("Help on Name Formatting"), GUIGlobals.getIconUrl("helpSmall")));
+
+ tabPanel.add(tlb, BorderLayout.EAST);
+
+ builder.appendSeparator(Globals.lang("Special Name Formatters"));
+ builder.nextLine();
+ builder.append(pan);
+ builder.append(tabPanel);
+ builder.nextLine();
+
+ pan = builder.getPanel();
+ pan.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
+ add(pan, BorderLayout.CENTER);
+ }
+
+ public void setValues() {
+ tableRows.clear();
+ String[] names = Globals.prefs.getStringArray(NAME_FORMATER_KEY);
+ String[] formats = Globals.prefs.getStringArray(NAME_FORMATTER_VALUE);
+
+ if (names == null){
+ names = new String[]{};
+ }
+ if (formats == null){
+ formats = new String[]{};
+ }
+
+ for (int i = 0; i < names.length; i++) {
+ if (i < formats.length)
+ tableRows.add(new TableRow(names[i], formats[i]));
+ else
+ tableRows.add(new TableRow(names[i]));
+ }
+ rowCount = tableRows.size() + 5;
+ }
+
+ class DeleteRowAction extends AbstractAction {
+
+ public DeleteRowAction() {
+ super("Delete row", GUIGlobals.getImage("remove"));
+ putValue(SHORT_DESCRIPTION, Globals.lang("Delete rows"));
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ tableChanged = true;
+
+ int[] selectedRows = table.getSelectedRows();
+
+ int numberDeleted = 0;
+
+ for (int i = selectedRows.length - 1; i >= 0; i--) {
+ if (selectedRows[i] < tableRows.size()) {
+ tableRows.remove(selectedRows[i]);
+ numberDeleted++;
+ }
+ }
+
+ rowCount -= numberDeleted;
+
+ if (selectedRows.length > 1)
+ table.clearSelection();
+
+ table.revalidate();
+ table.repaint();
+ }
+ }
+
+ class AddRowAction extends AbstractAction {
+ public AddRowAction() {
+ super("Add row", GUIGlobals.getImage("add"));
+ putValue(SHORT_DESCRIPTION, Globals.lang("Insert rows"));
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ int[] rows = table.getSelectedRows();
+ if (rows.length == 0) {
+ // No rows selected, so we just add one at the end.
+ rowCount++;
+ table.revalidate();
+ table.repaint();
+ return;
+ }
+ for (int i = 0; i < rows.length; i++) {
+ if (rows[i] + i - 1 < tableRows.size())
+ tableRows.add(Math.max(0, rows[i] + i - 1), new TableRow());
+ }
+ rowCount += rows.length;
+ if (rows.length > 1)
+ table.clearSelection();
+ table.revalidate();
+ table.repaint();
+ tableChanged = true;
+ }
+ }
+
+ /**
+ * Store changes to table preferences. This method is called when the user
+ * clicks Ok.
+ *
+ */
+ public void storeSettings() {
+
+ if (table.isEditing()) {
+ int col = table.getEditingColumn(), row = table.getEditingRow();
+ table.getCellEditor(row, col).stopCellEditing();
+ }
+
+ // Now we need to make sense of the contents the user has made to the
+ // table setup table.
+ if (tableChanged) {
+ // First we remove all rows with empty names.
+ int i = 0;
+ while (i < tableRows.size()) {
+ if (((TableRow) tableRows.elementAt(i)).name.equals(""))
+ tableRows.removeElementAt(i);
+ else
+ i++;
+ }
+ // Then we make arrays
+ String[] names = new String[tableRows.size()], formats = new String[tableRows.size()];
+
+ for (i = 0; i < tableRows.size(); i++) {
+ TableRow tr = (TableRow) tableRows.elementAt(i);
+ names[i] = tr.name;
+ formats[i] = tr.format;
+ }
+
+ // Finally, we store the new preferences.
+ Globals.prefs.putStringArray(NAME_FORMATER_KEY, names);
+ Globals.prefs.putStringArray(NAME_FORMATTER_VALUE, formats);
+ }
+ }
+
+ public boolean readyToClose() {
+ return true;
+ }
+}
diff --git a/src/java/net/sf/jabref/PrefsDialog2.java b/src/java/net/sf/jabref/PrefsDialog2.java
index bfe7eed..7064663 100644
--- a/src/java/net/sf/jabref/PrefsDialog2.java
+++ b/src/java/net/sf/jabref/PrefsDialog2.java
@@ -40,6 +40,8 @@ import javax.swing.table.*;
*
* With this design, it should be very easy to add new tabs later.
*
+ * @deprecated Use PrefsDialog3 instead!
+ *
*/
public class PrefsDialog2 extends JDialog {
@@ -71,14 +73,15 @@ public class PrefsDialog2 extends JDialog {
getContentPane().add(lower);
// ----------------------------------------------------------------
- // Add tabs to tabbed here. Remember, tabs must implement PrefsTab.
+ // Add new tabs to be displayed in the preferences here.
+ // Remember, tabs must implement PrefsTab.
// ----------------------------------------------------------------
tabbed.addTab(Globals.lang("General"), new GeneralTab(frame, _prefs));
tabbed.addTab(Globals.lang("Appearance"), new TablePrefsTab(_prefs, parent));
//tabbed.addTab(Globals.lang("External programs"), new ExternalProgramsTab(_prefs));
tabbed.addTab(Globals.lang("Key pattern"), new TabLabelPattern(_prefs, parent.helpDiag));
- tabbed.addTab(Globals.lang("Entry preview"), new PreviewPrefsTab(_prefs, parent.helpDiag));
-
+ tabbed.addTab(Globals.lang("Entry preview"), new PreviewPrefsTab(_prefs));
+
if (!Globals.ON_MAC)
tabbed.addTab(Globals.lang("Advanced"), new AdvancedTab(_prefs, parent.helpDiag));
JButton
diff --git a/src/java/net/sf/jabref/PrefsDialog3.java b/src/java/net/sf/jabref/PrefsDialog3.java
index ff20ac5..27ce8b6 100644
--- a/src/java/net/sf/jabref/PrefsDialog3.java
+++ b/src/java/net/sf/jabref/PrefsDialog3.java
@@ -88,7 +88,8 @@ public class PrefsDialog3 extends JDialog {
KEY = Globals.lang("Key pattern"),
PRE = Globals.lang("Entry preview"),
//JOU = Globals.lang("Journal names"),
- ADV = Globals.lang("Advanced");
+ ADV = Globals.lang("Advanced"),
+ NAM = Globals.lang("Name formatter");
ArrayList al = new ArrayList();
al.add(GEN);
@@ -101,23 +102,22 @@ public class PrefsDialog3 extends JDialog {
//al.add(JOU);
al.add(PRE);
al.add(ADV);
+ al.add(NAM);
+
main.setLayout(cardLayout);
- main.add(new GeneralTab(frame, _prefs), GEN);
-
- main.add(new AdvancedTab(_prefs, parent.helpDiag), ADV);
+ main.add(new GeneralTab(frame, _prefs), GEN);
+ main.add(new AdvancedTab(_prefs, parent.helpDiag), ADV);
+ main.add(new GroupsPrefsTab(_prefs), GRP);
+ main.add(new AppearancePrefsTab(_prefs), APP);
+ main.add(new ExternalTab(frame, _prefs, parent.helpDiag), EXT);
+ main.add(new TablePrefsTab(_prefs, parent), TAB);
+ main.add(new TableColumnsTab(_prefs, parent), COL);
+ main.add(new TabLabelPattern(_prefs, parent.helpDiag), KEY);
+ main.add(new PreviewPrefsTab(_prefs), PRE);
+ main.add(new NameFormatterTab(parent.helpDiag), NAM);
-
-
-
- main.add(new GroupsPrefsTab(_prefs), GRP);
- main.add(new AppearancePrefsTab(_prefs), APP);
- main.add(new ExternalTab(frame, _prefs), EXT);
- main.add(new TablePrefsTab(_prefs, parent), TAB);
- main.add(new TableColumnsTab(_prefs, parent), COL);
- main.add(new TabLabelPattern(_prefs, parent.helpDiag), KEY);
- main.add(new PreviewPrefsTab(_prefs, parent.helpDiag), PRE);
- //main.add(new ManageJournalsPanel(frame), JOU);
+ //main.add(new ManageJournalsPanel(frame), JOU);
upper.setBorder(BorderFactory.createEtchedBorder());
@@ -134,10 +134,7 @@ public class PrefsDialog3 extends JDialog {
if (e.getValueIsAdjusting())
return;
String o = (String)chooser.getSelectedValue();
- //Util.pr(o);
cardLayout.show(main, o);
- //main.revalidate();
- //main.repaint();
}
});
diff --git a/src/java/net/sf/jabref/PreviewPanel.java b/src/java/net/sf/jabref/PreviewPanel.java
index abd3aa5..37dd412 100644
--- a/src/java/net/sf/jabref/PreviewPanel.java
+++ b/src/java/net/sf/jabref/PreviewPanel.java
@@ -1,226 +1,161 @@
package net.sf.jabref;
-import javax.swing.*;
-import javax.swing.event.HyperlinkListener;
-import javax.swing.event.HyperlinkEvent;
-import java.io.*;
-import java.util.HashMap;
-import net.sf.jabref.export.layout.*;
import java.awt.Dimension;
import java.awt.Graphics;
-import java.awt.RenderingHints;
import java.awt.Graphics2D;
+import java.awt.RenderingHints;
+import java.awt.RenderingHints.Key;
+import java.io.IOException;
+import java.io.StringReader;
+
+import javax.swing.JEditorPane;
+import javax.swing.JScrollBar;
+import javax.swing.JScrollPane;
+import javax.swing.SwingUtilities;
+import javax.swing.event.HyperlinkEvent;
+import javax.swing.event.HyperlinkListener;
-public class PreviewPanel extends JEditorPane {
+import net.sf.jabref.export.layout.Layout;
+import net.sf.jabref.export.layout.LayoutHelper;
- public String CONTENT_TYPE = "text/html";
- //LAYOUT_FILE = "simplehtml";
- BibtexEntry entry;
- MetaData metaData;
- BibtexDatabase database = null;
- // If a database is set, the preview will attempt to resolve strings in the previewed
- // entry using that database.
-
- Layout layout;
- String prefix = "", postfix = "";
- Dimension DIM = new Dimension(650, 110);
- HashMap layouts = new HashMap();
- String layoutFile;
- JScrollPane sp;
-
- public PreviewPanel(BibtexDatabase db, MetaData metaData, String layoutFile) {
- this(layoutFile, metaData);
- this.database = db;
- }
-
- public PreviewPanel(BibtexDatabase db, MetaData metaData, BibtexEntry be, String layoutFile) {
- this(be, metaData, layoutFile);
- this.database = db;
- }
-
- public PreviewPanel(BibtexEntry be, MetaData metaData, String layoutFile) {
- entry = be;
- sp = new JScrollPane(this, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
- JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
- sp.setBorder(null);
- //Util.pr(layoutFile);
- init();
- this.layoutFile = layoutFile;
-
- try {
- readLayout();
- }
- catch (Exception ex) {
- ex.printStackTrace();
- }
- update();
-
- }
-
- public PreviewPanel(String layoutFile, MetaData metaData) {
- sp = new JScrollPane(this, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
- JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
- this.layoutFile = layoutFile;
- sp.setBorder(null);
- this.metaData = metaData;
-
- init();
- //setText("<HTML></HTML>");
- }
-
- public void setDatabase(BibtexDatabase db) {
- database = db;
- }
-
- private void init() {
- setEditable(false);
- setContentType(CONTENT_TYPE);
- addHyperlinkListener(new HyperlinkListener () {
- public void hyperlinkUpdate(HyperlinkEvent hyperlinkEvent) {
- if (hyperlinkEvent.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
- try {
- String address = hyperlinkEvent.getURL().toString();
- Util.openExternalViewer(metaData, address, "url");
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
- });
- //setSize(100, 100);
- }
-
- public JScrollPane getPane() {
- return sp;
- }
-
- public void readLayout(String layoutFormat) throws Exception {
- layoutFile = layoutFormat;
- readLayout();
- }
-
- public void readLayout() throws Exception {
- LayoutHelper layoutHelper = null;
- StringReader sr = new StringReader(layoutFile.replaceAll("__NEWLINE__", "\n"));
- layoutHelper = new LayoutHelper(sr);
- layout = layoutHelper.getLayoutFromText(Globals.FORMATTER_PACKAGE);
-
- /*String entryType = entry.getType().getName().toLowerCase();
- if (layouts.get(entryType) != null) {
- layout = (Layout)layouts.get(entryType);
- return;
- }*/
-
-
- //URL reso = JabRefFrame.class.getResource
- // (Globals.LAYOUT_PREFIX+layoutFile+"."+entryType+".layout");
-
- //Util.pr(Globals.LAYOUT_PREFIX+LAYOUT_FILE+"."+entryType+".layout");
-
-
-
- /*try {
- if (reso == null)
- reso = JabRefFrame.class.getResource(Globals.LAYOUT_PREFIX+layoutFile+".layout");
- layoutHelper = new LayoutHelper(new InputStreamReader(reso.openStream()));
- }
- catch (IOException ex) {
- }*/
-
-
-
- //layouts.put(entryType, layout);
-
- /*reso = JabRefFrame.class.getResource
- (Globals.LAYOUT_PREFIX+layoutFile+".begin.layout");
- StringWriter stw = new StringWriter();
- InputStreamReader reader;
- int c;
- if (reso != null) {
- reader = new InputStreamReader(reso.openStream());
- while ((c = reader.read()) != -1) {
- stw.write((char)c);
- }
- reader.close();
- }
- prefix = stw.toString();
-
- reso = JabRefFrame.class.getResource
- (Globals.LAYOUT_PREFIX+layoutFile+".end.layout");
- stw = new StringWriter();
- if (reso != null) {
- reader = new InputStreamReader(reso.openStream());
- while ((c = reader.read()) != -1) {
- stw.write((char)c);
- }
- reader.close();
- }
- postfix = stw.toString();
-*/
- }
-
- public void setEntry(BibtexEntry newEntry) {
- //Util.pr("en");
- entry = newEntry;
- try {
- readLayout();
- update();
- }
- catch (Exception ex) {
- ex.printStackTrace();
- }
-
- }
-
- public void update() {
-
- //StringBuffer sb = new StringBuffer(prefix);
- StringBuffer sb = new StringBuffer();
- sb.append(layout.doLayout(entry, database));
- //sb.append(postfix);
- setText(sb.toString());
- invalidate();
- revalidate();
- // Scroll to top:
- final JScrollBar bar = sp.getVerticalScrollBar();
- SwingUtilities.invokeLater(new Runnable() {
- public void run() {
- bar.setValue(0);
- }
- });
-
-
- //Util.pr(sb.toString());
- //revalidate();
-
- //Util.pr(""+getPreferredSize()+"\t"+getMinimumSize());
-
-
- }
-
- public boolean hasEntry() {
- return (entry != null);
- }
-
- public Dimension getPreferredScrollableViewportSize() {
- return getPreferredSize();
- }
-
-/* public Dimension getPreferredSize() {
- Util.pr(""+super.getPreferredSize());
- return super.getPreferredSize();
- }*/
- /*public Dimension getMinimumSize() { return DIM; }*/
-
- public void paintComponent(Graphics g) {
- Graphics2D g2 = (Graphics2D)g;
- g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
- RenderingHints.VALUE_ANTIALIAS_ON);
- g2.setRenderingHint(RenderingHints.KEY_RENDERING,
- RenderingHints.VALUE_RENDER_QUALITY);
- super.paintComponent(g2);
- g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
- RenderingHints.VALUE_ANTIALIAS_OFF);
- }
+/**
+ * Displays an BibtexEntry using the given layout format.
+ *
+ * @author $Author: coezbek $
+ * @version $Revision: 1.15 $ ($Date: 2006/09/03 19:09:59 $)
+ *
+ */
+public class PreviewPanel extends JEditorPane {
+ public String CONTENT_TYPE = "text/html";
+
+ BibtexEntry entry;
+
+ MetaData metaData;
+
+ /**
+ * If a database is set, the preview will attempt to resolve strings in the
+ * previewed entry using that database.
+ */
+ BibtexDatabase database;
+
+ Layout layout;
+
+ String layoutFile;
+
+ JScrollPane sp;
+
+ public PreviewPanel(BibtexDatabase db, MetaData metaData, String layoutFile) {
+ this(metaData, layoutFile);
+ this.database = db;
+ }
+
+ public PreviewPanel(BibtexDatabase database, MetaData metaData, BibtexEntry entry, String layoutFile) {
+ this(metaData, layoutFile);
+ this.database = database;
+ this.entry = entry;
+
+ try {
+ readLayout();
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ }
+ update();
+ }
+
+ public PreviewPanel(BibtexEntry entry, MetaData metaData, String layoutFile) {
+ this(null, metaData, entry, layoutFile);
+ }
+
+ /**
+ * Emtpy Preview Panel constructor
+ *
+ * @param metaData
+ * @param layoutFile
+ */
+ public PreviewPanel(MetaData metaData, String layoutFile) {
+ this.metaData = metaData;
+ this.layoutFile = layoutFile;
+
+ sp = new JScrollPane(this, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
+ JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
+ sp.setBorder(null);
+
+ setEditable(false);
+ setContentType(CONTENT_TYPE);
+ addHyperlinkListener(new HyperlinkListener() {
+ public void hyperlinkUpdate(HyperlinkEvent hyperlinkEvent) {
+ if (hyperlinkEvent.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
+ try {
+ String address = hyperlinkEvent.getURL().toString();
+ Util.openExternalViewer(PreviewPanel.this.metaData, address, "url");
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ });
+ }
+
+ public void setDatabase(BibtexDatabase db) {
+ database = db;
+ }
+
+ public JScrollPane getPane() {
+ return sp;
+ }
+
+ public void readLayout(String layoutFormat) throws Exception {
+ layoutFile = layoutFormat;
+ readLayout();
+ }
+
+ public void readLayout() throws Exception {
+ StringReader sr = new StringReader(layoutFile.replaceAll("__NEWLINE__", "\n"));
+ layout = new LayoutHelper(sr).getLayoutFromText(Globals.FORMATTER_PACKAGE);
+ }
+
+ public void setEntry(BibtexEntry newEntry) {
+ entry = newEntry;
+ try {
+ readLayout();
+ update();
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ }
+ }
+
+ public void update() {
+
+ StringBuffer sb = new StringBuffer();
+ sb.append(layout.doLayout(entry, database));
+ setText(sb.toString());
+ invalidate();
+ revalidate();
+
+ // Scroll to top:
+ final JScrollBar bar = sp.getVerticalScrollBar();
+ SwingUtilities.invokeLater(new Runnable() {
+ public void run() {
+ bar.setValue(0);
+ }
+ });
+ }
+
+ public boolean hasEntry() {
+ return (entry != null);
+ }
+
+ public Dimension getPreferredScrollableViewportSize() {
+ return getPreferredSize();
+ }
+
+ public void paintComponent(Graphics g) {
+ Graphics2D g2 = (Graphics2D) g;
+ Object hint = g2.getRenderingHint(RenderingHints.KEY_ANTIALIASING);
+ g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+ g2.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
+ super.paintComponent(g2);
+ g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, hint);
+ }
}
diff --git a/src/java/net/sf/jabref/PreviewPrefsTab.java b/src/java/net/sf/jabref/PreviewPrefsTab.java
index 27df1e0..e5cb9b3 100644
--- a/src/java/net/sf/jabref/PreviewPrefsTab.java
+++ b/src/java/net/sf/jabref/PreviewPrefsTab.java
@@ -6,199 +6,213 @@ import java.awt.event.*;
public class PreviewPrefsTab extends JPanel implements PrefsTab {
- JabRefPreferences _prefs;
- JabRefFrame _frame;
- HelpDialog helpDiag;
- JPanel pan = new JPanel();
- GridBagLayout gbl = new GridBagLayout();
- GridBagConstraints con = new GridBagConstraints();
- HelpAction helpAction = new HelpAction(Globals.helpDiag, "PreviewHelp.html");
-
- JTextArea layout1 = new JTextArea("", 1, 1),
- layout2 = new JTextArea("", 1, 1);
- JButton def1 = new JButton(Globals.lang("Default")),
- def2 = new JButton(Globals.lang("Default")),
- test1 = new JButton(Globals.lang("Test")),
- test2 = new JButton(Globals.lang("Test")),
- help = new JButton(Globals.lang("Help"));
- JPanel p1 = new JPanel(),
- p2 = new JPanel();
- JScrollPane sp1 = new JScrollPane(layout1),
- sp2 = new JScrollPane(layout2);
- private static BibtexEntry entry;
-
- public PreviewPrefsTab(JabRefPreferences prefs, HelpDialog diag) {
- _prefs = prefs;
- p1.setLayout(gbl);
- p2.setLayout(gbl);
- help.addActionListener(helpAction);
- /*p1.setBorder(BorderFactory.createTitledBorder
- (BorderFactory.createEtchedBorder(),Globals.lang("Preview")+" 1"));
- p2.setBorder(BorderFactory.createTitledBorder
- (BorderFactory.createEtchedBorder(),Globals.lang("Preview")+" 2")); */
- setLayout(gbl);//new GridLayout(2,1));
- JLabel lab;
- lab = new JLabel(Globals.lang("Preview")+" 1");
- con.anchor = GridBagConstraints.WEST;
- con.gridwidth = GridBagConstraints.REMAINDER;
- con.fill = GridBagConstraints.BOTH;
- con.weightx = 1;
- con.weighty = 0;
- con.insets = new Insets(2,2,2,2);
- gbl.setConstraints(lab, con);
- //p1.add(lab);
- con.weighty = 1;
- gbl.setConstraints(sp1, con);
- p1.add(sp1);
- con.weighty = 0;
- con.gridwidth = 1;
- con.weightx = 0;
- con.fill = GridBagConstraints.NONE;
- con.anchor = GridBagConstraints.WEST;
- gbl.setConstraints(test1, con);
- p1.add(test1);
- gbl.setConstraints(def1, con);
- p1.add(def1);
- con.gridwidth = GridBagConstraints.REMAINDER;
- JPanel pan = new JPanel();
- con.weightx = 1;
- gbl.setConstraints(pan, con);
- p1.add(pan);
- lab = new JLabel(Globals.lang("Preview")+" 2");
- gbl.setConstraints(lab, con);
- //p2.add(lab);
- con.weighty = 1;
- con.fill = GridBagConstraints.BOTH;
- gbl.setConstraints(sp2, con);
- p2.add(sp2);
- con.weighty = 0;
- con.weightx = 0;
- con.fill = GridBagConstraints.NONE;
- con.gridwidth = 1;
- gbl.setConstraints(test2, con);
- p2.add(test2);
- gbl.setConstraints(def2, con);
- p2.add(def2);
- con.gridwidth = 1;
- pan = new JPanel();
- con.weightx = 1;
- gbl.setConstraints(pan, con);
- p2.add(pan);
- con.weightx = 0;
- con.gridwidth = GridBagConstraints.REMAINDER;
- gbl.setConstraints(help, con);
- p2.add(help);
-
-
- con.weightx=1;
- con.weighty=0;
- con.fill=GridBagConstraints.BOTH;
- con.gridwidth=GridBagConstraints.REMAINDER;
- lab = new JLabel(Globals.lang("Preview")+" 1");
- gbl.setConstraints(lab, con);
- add(lab);
- con.weighty=1;
- gbl.setConstraints(p1, con);
- add(p1);
- lab = new JLabel(Globals.lang("Preview")+" 2");
- con.weighty=0;
- JSeparator sep = new JSeparator(JSeparator.HORIZONTAL);
- gbl.setConstraints(sep, con);
- add(sep);
- gbl.setConstraints(lab, con);
- add(lab);
- con.weighty=1;
- gbl.setConstraints(p2, con);
- add(p2);
-
- def1.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- String tmp = layout1.getText().replaceAll("\n", "__NEWLINE__");
- _prefs.remove("preview0");
- layout1.setText(_prefs.get("preview0").replaceAll("__NEWLINE__", "\n"));
- _prefs.put("preview0", tmp);
- }
- });
- def2.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- String tmp = layout2.getText().replaceAll("\n", "__NEWLINE__");
- _prefs.remove("preview1");
- layout2.setText(_prefs.get("preview1").replaceAll("__NEWLINE__", "\n"));
- _prefs.put("preview1", tmp);
- }
- });
-
-
- test1.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- getTestEntry();
- PreviewPanel testPanel = new PreviewPanel(entry, new MetaData(), layout1.getText());
- testPanel.setPreferredSize(new Dimension(800, 350));
- JOptionPane.showMessageDialog(null, testPanel, Globals.lang("Preview"), JOptionPane.PLAIN_MESSAGE);
- }
- });
-
- test2.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- getTestEntry();
- PreviewPanel testPanel = new PreviewPanel(entry, new MetaData(), layout2.getText());
- testPanel.setPreferredSize(new Dimension(800, 350));
- JOptionPane.showMessageDialog(null, new JScrollPane(testPanel), Globals.lang("Preview"), JOptionPane.PLAIN_MESSAGE);
- }
- });
- }
-
- public static BibtexEntry getTestEntry() {
- if (entry != null)
- return entry;
- entry = new BibtexEntry(Util.createNeutralId(), BibtexEntryType.getType("article"));
- entry.setField(BibtexFields.KEY_FIELD, "conceicao1997");
- entry.setField("author", "L. E. C. Conceic{\\~a}o and T. van der Meeren and J. A. J. Verreth and M. S. Evjen and D. F. Houlihan and H. J. Fyhn");
- entry.setField("title", "Amino acid metabolism and protein turnover in larval turbot (Scophthalmus maximus) fed natural zooplankton or Artemia");
- entry.setField("year", "1997");
- entry.setField("journal", "Marine Biology");
- entry.setField("month", "January");
- entry.setField("number", "2");
- entry.setField("volume", "123");
- entry.setField("pdf", "conceicao1997.pdf");
- entry.setField("pages", "255--265");
- entry.setField("keywords", "energetics, artemia, metabolism, amino acid, turbot");
- entry.setField("url", "http://ejournals.ebsco.com/direct.asp?ArticleID=TYY4NT82XA9H7R8PFPPV");
- entry.setField("abstract", "Abstract The present paper studied the influence of different food regimes "+
- "on the free amino acid (FAA) pool, the rate of protein turnover, the flux of amino acids, and "+
- "their relation to growth of larval turbot (Scophthalmus maximus L.) from first feeding until "+
- "metamorphosis. The amino acid profile of protein was stable during the larval period although "+
- "some small, but significant, differences were found. Turbot larvae had proteins which were rich "+
- "in leucine and aspartate, and poor in glutamate, suggesting a high leucine requirement. The "+
- "profile of the FAA pool was highly variable and quite different from the amino acid profile in "+
- "protein. The proportion of essential FAA decreased with development. High contents of free tyrosine "+
- "and phenylalanine were found on Day 3, while free taurine was present at high levels throughout "+
- "the experimental period. Larval growth rates were positively correlated with taurine levels, "+
- "suggesting a dietary dependency for taurine and/or sulphur amino acids.\n\nReduced growth rates in "+
- "Artemia-fed larvae were associated with lower levels of free methionine, indicating that this diet "+
- "is deficient in methionine for turbot larvae. Leucine might also be limiting turbot growth as the "+
- "different diet organisms had lower levels of this amino acid in the free pool than was found in the "+
- "larval protein. A previously presented model was used to describe the flux of amino acids in growing "+
- "turbot larvae. The FAA pool was found to be small and variable. It was estimated that the daily dietary "+
- "amino acid intake might be up to ten times the larval FAA pool. In addition, protein synthesis and "+
- "protein degradation might daily remove and return, respectively, the equivalent of up to 20 and 10 "+
- "times the size of the FAA pool. In an early phase (Day 11) high growth rates were associated with a "+
- "relatively low protein turnover, while at a later stage (Day 17), a much higher turnover was observed.");
- return entry;
- }
-
- public void setValues() {
- layout1.setText(_prefs.get("preview0").replaceAll("__NEWLINE__", "\n"));
- layout2.setText(_prefs.get("preview1").replaceAll("__NEWLINE__", "\n"));
- }
-
- public void storeSettings() {
- _prefs.put("preview0", layout1.getText().replaceAll("\n", "__NEWLINE__"));
- _prefs.put("preview1", layout2.getText().replaceAll("\n", "__NEWLINE__"));
- }
-
- public boolean readyToClose() {
- return true;
- }
+ JabRefPreferences _prefs;
+
+ JabRefFrame _frame;
+
+ JPanel pan = new JPanel();
+
+ GridBagLayout gbl = new GridBagLayout();
+
+ GridBagConstraints con = new GridBagConstraints();
+
+ JTextArea layout1 = new JTextArea("", 1, 1), layout2 = new JTextArea("", 1, 1);
+
+ JButton def1 = new JButton(Globals.lang("Default")),
+ def2 = new JButton(Globals.lang("Default")), test1 = new JButton(Globals.lang("Test")),
+ test2 = new JButton(Globals.lang("Test")), help;
+
+ JPanel p1 = new JPanel(), p2 = new JPanel();
+
+ JScrollPane sp1 = new JScrollPane(layout1), sp2 = new JScrollPane(layout2);
+
+ private static BibtexEntry entry;
+
+ public PreviewPrefsTab(JabRefPreferences prefs) {
+ _prefs = prefs;
+
+ p1.setLayout(gbl);
+ p2.setLayout(gbl);
+
+ setLayout(gbl);
+ JLabel lab;
+ lab = new JLabel(Globals.lang("Preview") + " 1");
+ con.anchor = GridBagConstraints.WEST;
+ con.gridwidth = GridBagConstraints.REMAINDER;
+ con.fill = GridBagConstraints.BOTH;
+ con.weightx = 1;
+ con.weighty = 0;
+ con.insets = new Insets(2, 2, 2, 2);
+ gbl.setConstraints(lab, con);
+ // p1.add(lab);
+ con.weighty = 1;
+ gbl.setConstraints(sp1, con);
+ p1.add(sp1);
+ con.weighty = 0;
+ con.gridwidth = 1;
+ con.weightx = 0;
+ con.fill = GridBagConstraints.NONE;
+ con.anchor = GridBagConstraints.WEST;
+ gbl.setConstraints(test1, con);
+ p1.add(test1);
+ gbl.setConstraints(def1, con);
+ p1.add(def1);
+ con.gridwidth = GridBagConstraints.REMAINDER;
+ JPanel pan = new JPanel();
+ con.weightx = 1;
+ gbl.setConstraints(pan, con);
+ p1.add(pan);
+ lab = new JLabel(Globals.lang("Preview") + " 2");
+ gbl.setConstraints(lab, con);
+ // p2.add(lab);
+ con.weighty = 1;
+ con.fill = GridBagConstraints.BOTH;
+ gbl.setConstraints(sp2, con);
+ p2.add(sp2);
+ con.weighty = 0;
+ con.weightx = 0;
+ con.fill = GridBagConstraints.NONE;
+ con.gridwidth = 1;
+ gbl.setConstraints(test2, con);
+ p2.add(test2);
+ gbl.setConstraints(def2, con);
+ p2.add(def2);
+ con.gridwidth = 1;
+ pan = new JPanel();
+ con.weightx = 1;
+ gbl.setConstraints(pan, con);
+ p2.add(pan);
+
+ { // Help Button
+ HelpAction helpAction = new HelpAction(Globals.helpDiag, GUIGlobals.previewHelp,
+ Globals.lang("Help on Preview Settings"), GUIGlobals.getIconUrl("helpSmall"));
+ JButton help = helpAction.getIconButton();
+ con.weightx = 0;
+ con.gridwidth = GridBagConstraints.REMAINDER;
+ gbl.setConstraints(help, con);
+ p2.add(help);
+ }
+
+ con.weightx = 1;
+ con.weighty = 0;
+ con.fill = GridBagConstraints.BOTH;
+ con.gridwidth = GridBagConstraints.REMAINDER;
+ lab = new JLabel(Globals.lang("Preview") + " 1");
+ gbl.setConstraints(lab, con);
+ add(lab);
+ con.weighty = 1;
+ gbl.setConstraints(p1, con);
+ add(p1);
+ lab = new JLabel(Globals.lang("Preview") + " 2");
+ con.weighty = 0;
+ JSeparator sep = new JSeparator(JSeparator.HORIZONTAL);
+ gbl.setConstraints(sep, con);
+ add(sep);
+ gbl.setConstraints(lab, con);
+ add(lab);
+ con.weighty = 1;
+ gbl.setConstraints(p2, con);
+ add(p2);
+
+ def1.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ String tmp = layout1.getText().replaceAll("\n", "__NEWLINE__");
+ _prefs.remove("preview0");
+ layout1.setText(_prefs.get("preview0").replaceAll("__NEWLINE__", "\n"));
+ _prefs.put("preview0", tmp);
+ }
+ });
+ def2.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ String tmp = layout2.getText().replaceAll("\n", "__NEWLINE__");
+ _prefs.remove("preview1");
+ layout2.setText(_prefs.get("preview1").replaceAll("__NEWLINE__", "\n"));
+ _prefs.put("preview1", tmp);
+ }
+ });
+
+ test1.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ getTestEntry();
+ PreviewPanel testPanel = new PreviewPanel(entry, new MetaData(), layout1.getText());
+ testPanel.setPreferredSize(new Dimension(800, 350));
+ JOptionPane.showMessageDialog(null, testPanel, Globals.lang("Preview"),
+ JOptionPane.PLAIN_MESSAGE);
+ }
+ });
+
+ test2.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ getTestEntry();
+ PreviewPanel testPanel = new PreviewPanel(entry, new MetaData(), layout2.getText());
+ testPanel.setPreferredSize(new Dimension(800, 350));
+ JOptionPane.showMessageDialog(null, new JScrollPane(testPanel), Globals
+ .lang("Preview"), JOptionPane.PLAIN_MESSAGE);
+ }
+ });
+ }
+
+ public static BibtexEntry getTestEntry() {
+ if (entry != null)
+ return entry;
+ entry = new BibtexEntry(Util.createNeutralId(), BibtexEntryType.getType("article"));
+ entry.setField(BibtexFields.KEY_FIELD, "conceicao1997");
+ entry
+ .setField(
+ "author",
+ "L. E. C. Conceic{\\~a}o and T. van der Meeren and J. A. J. Verreth and M. S. Evjen and D. F. Houlihan and H. J. Fyhn");
+ entry
+ .setField(
+ "title",
+ "Amino acid metabolism and protein turnover in larval turbot (Scophthalmus maximus) fed natural zooplankton or Artemia");
+ entry.setField("year", "1997");
+ entry.setField("journal", "Marine Biology");
+ entry.setField("month", "January");
+ entry.setField("number", "2");
+ entry.setField("volume", "123");
+ entry.setField("pdf", "conceicao1997.pdf");
+ entry.setField("pages", "255--265");
+ entry.setField("keywords", "energetics, artemia, metabolism, amino acid, turbot");
+ entry.setField("url",
+ "http://ejournals.ebsco.com/direct.asp?ArticleID=TYY4NT82XA9H7R8PFPPV");
+ entry
+ .setField(
+ "abstract",
+ "Abstract The present paper studied the influence of different food regimes "
+ + "on the free amino acid (FAA) pool, the rate of protein turnover, the flux of amino acids, and "
+ + "their relation to growth of larval turbot (Scophthalmus maximus L.) from first feeding until "
+ + "metamorphosis. The amino acid profile of protein was stable during the larval period although "
+ + "some small, but significant, differences were found. Turbot larvae had proteins which were rich "
+ + "in leucine and aspartate, and poor in glutamate, suggesting a high leucine requirement. The "
+ + "profile of the FAA pool was highly variable and quite different from the amino acid profile in "
+ + "protein. The proportion of essential FAA decreased with development. High contents of free tyrosine "
+ + "and phenylalanine were found on Day 3, while free taurine was present at high levels throughout "
+ + "the experimental period. Larval growth rates were positively correlated with taurine levels, "
+ + "suggesting a dietary dependency for taurine and/or sulphur amino acids.\n\nReduced growth rates in "
+ + "Artemia-fed larvae were associated with lower levels of free methionine, indicating that this diet "
+ + "is deficient in methionine for turbot larvae. Leucine might also be limiting turbot growth as the "
+ + "different diet organisms had lower levels of this amino acid in the free pool than was found in the "
+ + "larval protein. A previously presented model was used to describe the flux of amino acids in growing "
+ + "turbot larvae. The FAA pool was found to be small and variable. It was estimated that the daily dietary "
+ + "amino acid intake might be up to ten times the larval FAA pool. In addition, protein synthesis and "
+ + "protein degradation might daily remove and return, respectively, the equivalent of up to 20 and 10 "
+ + "times the size of the FAA pool. In an early phase (Day 11) high growth rates were associated with a "
+ + "relatively low protein turnover, while at a later stage (Day 17), a much higher turnover was observed.");
+ return entry;
+ }
+
+ public void setValues() {
+ layout1.setText(_prefs.get("preview0").replaceAll("__NEWLINE__", "\n"));
+ layout2.setText(_prefs.get("preview1").replaceAll("__NEWLINE__", "\n"));
+ }
+
+ public void storeSettings() {
+ _prefs.put("preview0", layout1.getText().replaceAll("\n", "__NEWLINE__"));
+ _prefs.put("preview1", layout2.getText().replaceAll("\n", "__NEWLINE__"));
+ }
+
+ public boolean readyToClose() {
+ return true;
+ }
}
diff --git a/src/java/net/sf/jabref/ReplaceStringDialog.java b/src/java/net/sf/jabref/ReplaceStringDialog.java
index 2ca3339..92a0c5e 100644
--- a/src/java/net/sf/jabref/ReplaceStringDialog.java
+++ b/src/java/net/sf/jabref/ReplaceStringDialog.java
@@ -103,12 +103,14 @@ class ReplaceStringDialog extends JDialog {
settings.setLayout(gbl);
opt.setLayout(gbl);
main.setLayout(gbl);
+
settings.setBorder(BorderFactory.createTitledBorder
(BorderFactory.createEtchedBorder(),
Globals.lang("Replace string")));
main.setBorder(BorderFactory.createTitledBorder
(BorderFactory.createEtchedBorder(),
Globals.lang("Strings")));
+
// Settings panel:
/*
@@ -120,11 +122,12 @@ class ReplaceStringDialog extends JDialog {
con.gridy = 2;
gbl.setConstraints(nf, con);
settings.add(nf);*/
-
+ //con.weightx = 1;
+ con.fill = GridBagConstraints.HORIZONTAL;
+ //JSeparator sep = new JSeparator()
con.gridwidth = 2;
con.weightx = 0;
con.anchor = GridBagConstraints.WEST;
- con.fill = GridBagConstraints.HORIZONTAL;
con.gridy = 0;
con.gridx = 0;
con.insets = new Insets(3, 5, 3, 5);
diff --git a/src/java/net/sf/jabref/SearchManager2.java b/src/java/net/sf/jabref/SearchManager2.java
index f7c936d..1d953d5 100644
--- a/src/java/net/sf/jabref/SearchManager2.java
+++ b/src/java/net/sf/jabref/SearchManager2.java
@@ -358,13 +358,20 @@ settings.add(select);
searchOptions.put("option",searchField.getText()) ;
SearchRuleSet searchRules = new SearchRuleSet() ;
SearchRule rule1;
+
+ rule1 = new BasicSearch(Globals.prefs.getBoolean("caseSensitiveSearch"),
+ Globals.prefs.getBoolean("regExpSearch"));
+
+ /*
if (Globals.prefs.getBoolean("regExpSearch"))
rule1 = new RegExpRule(
Globals.prefs.getBoolean("caseSensitiveSearch"));
- else
+ else {
rule1 = new SimpleSearchRule(
Globals.prefs.getBoolean("caseSensitiveSearch"));
+ }
+ */
try {
// this searches specified fields if specified,
// and all fields otherwise
diff --git a/src/java/net/sf/jabref/SidePane.java b/src/java/net/sf/jabref/SidePane.java
index 22eb060..2d01f04 100644
--- a/src/java/net/sf/jabref/SidePane.java
+++ b/src/java/net/sf/jabref/SidePane.java
@@ -1,114 +1,117 @@
/*
-Copyright (C) 2003 Nizar N. Batada, Morten O. Alver
+ Copyright (C) 2003 Nizar N. Batada, Morten O. Alver
-All programs in this directory and
-subdirectories are published under the GNU General Public License as
-described below.
+ All programs in this directory and
+ subdirectories are published under the GNU General Public License as
+ described below.
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or (at
-your option) any later version.
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or (at
+ your option) any later version.
-This program is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
-USA
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA
-Further information about the GNU GPL is available at:
-http://www.gnu.org/copyleft/gpl.ja.html
+ Further information about the GNU GPL is available at:
+ http://www.gnu.org/copyleft/gpl.ja.html
-*/
+ */
package net.sf.jabref;
-import javax.swing.*;
-
import java.awt.BorderLayout;
-import java.awt.GridBagLayout;
-import java.awt.GridBagConstraints;
-import java.awt.Color;
import java.awt.Component;
-import java.awt.Insets;
import java.awt.Dimension;
-import java.awt.event.ActionListener;
-import java.awt.event.ActionEvent;
-import java.util.Vector;
-
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+import java.util.Collection;
+import java.util.Iterator;
+
+import javax.swing.Box;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+
+/**
+ * The side pane is displayed at the right side of JabRef and shows instances of
+ * SidePaneComponents, for instance the GroupSelector, or the SearchManager2.
+ *
+ * @version $Revision: 1.16 $ ($Date: 2006/08/30 20:04:48 $)
+ *
+ */
public class SidePane extends JPanel {
- Dimension PREFERRED_SIZE = new Dimension
- (GUIGlobals.SPLIT_PANE_DIVIDER_LOCATION, 100);
-
- GridBagLayout gbl = new GridBagLayout();
- GridBagConstraints con = new GridBagConstraints();
- JScrollPane sp;
- //JButton close = new JButton("X");
- //JSplitPane parent;
- JPanel mainPanel = new JPanel(),
- pan = new JPanel();
-
- public SidePane() {
- // parent = _parent;
-
- setLayout(new BorderLayout());
- mainPanel.setLayout(gbl);
- //setBackground(GUIGlobals.lightGray);//(Color.white);
- //mainPanel.setBackground(GUIGlobals.lightGray);
-
- /*sp = new JScrollPane
- (mainPanel, JScrollPane.VERTICAL_SCROLLBAR_NEVER,
- JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);*/
-
- //super.add(sp, BorderLayout.CENTER);
- super.add(mainPanel, BorderLayout.NORTH);
- JPanel pan = new JPanel();
- //pan.setBorder(BorderFactory.createMatteBorder(1,1,1,1, Color.red));
- //mainPanel.setBorder(BorderFactory.createMatteBorder(1,1,1,1, Color.yellow));
- //setBorder(BorderFactory.createMatteBorder(1,1,1,1, Color.green));
- //pan.setBackground(GUIGlobals.lightGray);
-
- super.add(pan, BorderLayout.CENTER);
- }
-
- public void setComponents(Vector comps) {
- mainPanel.removeAll();
- con.anchor = GridBagConstraints.NORTH;
- con.fill = GridBagConstraints.BOTH;
- con.gridwidth = GridBagConstraints.REMAINDER;
- con.insets = new Insets(1, 1, 1, 1);
- con.gridheight = 1;
- con.weightx = 1;
- con.weighty = 0;
-
- for (int i=0; i<comps.size(); i++) {
- Component c = (Component)comps.elementAt(i);
- gbl.setConstraints(c, con);
- mainPanel.add(c);
- //System.out.println(c.getPreferredSize().toString());
- }
- con.weighty = 1;
- Component bx = Box.createVerticalGlue();
- gbl.setConstraints(bx, con);
- mainPanel.add(bx);
-
- revalidate();
- repaint();
- }
-
- public void remove(Component c) {
- mainPanel.remove(c);
- }
-
- public Dimension getMaximumSize() {
- return PREFERRED_SIZE;
- }
-
- public Dimension getPreferredSize() {
- return PREFERRED_SIZE;
- }
+ final Dimension PREFERRED_SIZE = new Dimension(GUIGlobals.SPLIT_PANE_DIVIDER_LOCATION, 100);
+
+ GridBagLayout gridBagLayout = new GridBagLayout();
+
+ GridBagConstraints constraint = new GridBagConstraints();
+
+ JPanel mainPanel = new JPanel();
+
+ public SidePane() {
+
+ // For debugging the border:
+ // setBorder(BorderFactory.createLineBorder(Color.BLUE));
+
+ setLayout(new BorderLayout());
+ mainPanel.setLayout(gridBagLayout);
+
+ // Initialize constraint
+ constraint.anchor = GridBagConstraints.NORTH;
+ constraint.fill = GridBagConstraints.BOTH;
+ constraint.gridwidth = GridBagConstraints.REMAINDER;
+ constraint.insets = new Insets(1, 1, 1, 1);
+ constraint.gridheight = 1;
+ constraint.weightx = 1;
+
+ /*
+ * Added Scrollpane to fix:
+ */
+ JScrollPane sp = new JScrollPane(mainPanel, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
+ JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
+ sp.setBorder(null);
+
+ // To remove the scroll panel just change sp to mainPanel and comment
+ // the JScrollPane declaration
+ super.add(sp);
+ }
+
+ public void setComponents(Collection comps) {
+ mainPanel.removeAll();
+
+ constraint.weighty = 0;
+ Iterator i = comps.iterator();
+ while (i.hasNext()){
+ Component c = (Component) i.next();
+ gridBagLayout.setConstraints(c, constraint);
+ mainPanel.add(c);
+ }
+ constraint.weighty = 1;
+ Component bx = Box.createVerticalGlue();
+ gridBagLayout.setConstraints(bx, constraint);
+ mainPanel.add(bx);
+
+ revalidate();
+ repaint();
+ }
+
+ public void remove(Component c) {
+ mainPanel.remove(c);
+ }
+
+ public Dimension getMaximumSize() {
+ return getPreferredSize();
+ }
+
+ public Dimension getPreferredSize() {
+ return PREFERRED_SIZE;
+ }
}
diff --git a/src/java/net/sf/jabref/SidePaneComponent.java b/src/java/net/sf/jabref/SidePaneComponent.java
index 37254d7..aca5648 100644
--- a/src/java/net/sf/jabref/SidePaneComponent.java
+++ b/src/java/net/sf/jabref/SidePaneComponent.java
@@ -1,29 +1,29 @@
/*
-Copyright (C) 2003 Nizar N. Batada, Morten O. Alver
+ Copyright (C) 2003 Nizar N. Batada, Morten O. Alver
-All programs in this directory and
-subdirectories are published under the GNU General Public License as
-described below.
+ All programs in this directory and
+ subdirectories are published under the GNU General Public License as
+ described below.
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or (at
-your option) any later version.
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or (at
+ your option) any later version.
-This program is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
-USA
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA
-Further information about the GNU GPL is available at:
-http://www.gnu.org/copyleft/gpl.ja.html
+ Further information about the GNU GPL is available at:
+ http://www.gnu.org/copyleft/gpl.ja.html
-*/
+ */
package net.sf.jabref;
import javax.swing.*;
@@ -33,83 +33,86 @@ import java.awt.event.*;
import com.jgoodies.uif_lite.panel.SimpleInternalFrame;
import java.net.URL;
-public class SidePaneComponent extends SimpleInternalFrame {
-
- protected JButton close = new JButton(GUIGlobals.getImage("close"));
- protected boolean visible = false;
- protected SidePaneManager manager;
- protected BasePanel panel = null;
-
- public SidePaneComponent(SidePaneManager manager, URL icon, String title) {
- super(new ImageIcon(icon), title);
- this.manager = manager;
- setSelected(true);
- JToolBar tlb = new JToolBar();
- close.setMargin(new Insets(0,0,0,0));
- //tlb.setOpaque(false);
- close.setBorder(null);
- tlb.add(close);
- close.addActionListener(new CloseButtonListener());
- setToolBar(tlb);
- //setBorder(BorderFactory.createEtchedBorder());
-
- //setBorder(BorderFactory.createMatteBorder(1,1,1,1,java.awt.Color.green));
- //setPreferredSize(new java.awt.Dimension
- // (GUIGlobals.SPLIT_PANE_DIVIDER_LOCATION, 200));
- //Util.pr(""+GUIGlobals.SPLIT_PANE_DIVIDER_LOCATION);
- }
-
- public void hideAway() {
- manager.hideAway(this);
- }
-
- /**
- * Used by SidePaneManager only, to keep track of visibility.
- *
- */
- void setVisibility(boolean vis) {
- visible = vis;
- }
-
- /**
- * Used by SidePaneManager only, to keep track of visibility.
- *
- */
- boolean hasVisibility() {
- return visible;
- }
-
- public void setActiveBasePanel(BasePanel panel) {
- this.panel = panel;
- }
-
- public BasePanel getActiveBasePanel() {
- return panel;
- }
-
- /**
- * Override this method if the component needs to make any changes
- * before it can close.
- */
- public void componentClosing() {
-
- }
-
- /**
- * Override this method if the component needs to do any actions
- * when opening.
- */
- public void componentOpening() {
-
- }
-
- public Dimension getMinimumSize() {
- return getPreferredSize();
- }
-
- class CloseButtonListener implements ActionListener {
- public void actionPerformed(ActionEvent e) {
- hideAway();
- }
- }
+public abstract class SidePaneComponent extends SimpleInternalFrame {
+
+ protected JButton close = new JButton(GUIGlobals.getImage("close"));
+
+ protected boolean visible = false;
+
+ protected SidePaneManager manager;
+
+ protected BasePanel panel = null;
+
+ public SidePaneComponent(SidePaneManager manager, URL icon, String title) {
+ super(new ImageIcon(icon), title);
+ this.manager = manager;
+ setSelected(true);
+ JToolBar tlb = new JToolBar();
+ close.setMargin(new Insets(0, 0, 0, 0));
+ // tlb.setOpaque(false);
+ close.setBorder(null);
+ tlb.add(close);
+ close.addActionListener(new CloseButtonListener());
+ setToolBar(tlb);
+ // setBorder(BorderFactory.createEtchedBorder());
+
+ // setBorder(BorderFactory.createMatteBorder(1,1,1,1,java.awt.Color.green));
+ // setPreferredSize(new java.awt.Dimension
+ // (GUIGlobals.SPLIT_PANE_DIVIDER_LOCATION, 200));
+ // Util.pr(""+GUIGlobals.SPLIT_PANE_DIVIDER_LOCATION);
+ }
+
+ public void hideAway() {
+ manager.hideComponent(this);
+ }
+
+ /**
+ * Used by SidePaneManager only, to keep track of visibility.
+ *
+ */
+ void setVisibility(boolean vis) {
+ visible = vis;
+ }
+
+ /**
+ * Used by SidePaneManager only, to keep track of visibility.
+ *
+ */
+ boolean hasVisibility() {
+ return visible;
+ }
+
+ public void setActiveBasePanel(BasePanel panel) {
+ this.panel = panel;
+ }
+
+ public BasePanel getActiveBasePanel() {
+ return panel;
+ }
+
+ /**
+ * Override this method if the component needs to make any changes before it
+ * can close.
+ */
+ public void componentClosing() {
+
+ }
+
+ /**
+ * Override this method if the component needs to do any actions when
+ * opening.
+ */
+ public void componentOpening() {
+
+ }
+
+ public Dimension getMinimumSize() {
+ return getPreferredSize();
+ }
+
+ class CloseButtonListener implements ActionListener {
+ public void actionPerformed(ActionEvent e) {
+ hideAway();
+ }
+ }
}
diff --git a/src/java/net/sf/jabref/SidePaneManager.java b/src/java/net/sf/jabref/SidePaneManager.java
index 7502ae1..34b2ad6 100644
--- a/src/java/net/sf/jabref/SidePaneManager.java
+++ b/src/java/net/sf/jabref/SidePaneManager.java
@@ -1,227 +1,173 @@
/*
-Copyright (C) 2003 Nizar N. Batada, Morten O. Alver
+ Copyright (C) 2003 Nizar N. Batada, Morten O. Alver
-All programs in this directory and
-subdirectories are published under the GNU General Public License as
-described below.
+ All programs in this directory and
+ subdirectories are published under the GNU General Public License as
+ described below.
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or (at
-your option) any later version.
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or (at
+ your option) any later version.
-This program is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
-USA
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA
-Further information about the GNU GPL is available at:
-http://www.gnu.org/copyleft/gpl.ja.html
+ Further information about the GNU GPL is available at:
+ http://www.gnu.org/copyleft/gpl.ja.html
-*/
+ */
package net.sf.jabref;
-import java.util.*;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
-import net.sf.jabref.groups.*;
-
-import javax.swing.event.ChangeListener;
+import javax.swing.SwingUtilities;
import javax.swing.event.ChangeEvent;
-import javax.swing.*;
-
-public class SidePaneManager implements ChangeListener {
-
- JabRefFrame frame;
- BasePanel panel;
- SidePane sidep;
- JabRefPreferences prefs;
- MetaData metaData;
- LinkedHashMap components = new LinkedHashMap();
- Vector visible = new Vector();
- private int visibleComponents = 0;
-
- public SidePaneManager(JabRefFrame frame) {
- this.prefs = Globals.prefs;
- // TODO: tab listener, update all sidepanecomponents.
- this.frame = frame;
- frame.tabbedPane.addChangeListener(this);
- sidep = new SidePane();
- }
-
- public SidePane getPanel() {
- return sidep;
- }
-
- public void populatePanel() {
-
-
- /*
- * if (components.size() > 0) { panel.setLeftComponent(sidep); } else
- * panel.setLeftComponent(null);
- */
- updateView();
-
- if (components.size() > 0)
- sidep.setVisible(true);
- else
- sidep.setVisible(false);
- }
-
- public boolean isPanelVisible(String name) {
- Object o = components.get(name);
- if (o != null) {
- return visible.contains(o);
- } else {
- System.err.println("Side pane component '" + name + "' unknown.");
- return false;
- }
- }
-
- public void togglePanel(String name) {
- Object o = components.get(name);
- if (o != null) {
- if (!visible.contains(o)) {
- visible.add(o);
- //sidep.setComponents(visible);
- updateView();
- ((SidePaneComponent)o).componentOpening();
- } else {
- visible.remove(o);
- //sidep.setComponents(visible);
- updateView();
- ((SidePaneComponent)o).componentClosing();
- }
-
- } else System.err.println("Side pane component '"+name+"' unknown.");
- }
-
- public synchronized void ensureVisible(String name) {
- Object o = components.get(name);
- if (o != null) {
- if (!visible.contains(o)) {
- visible.add(o);
- //sidep.setComponents(visible);
- updateView();
- ((SidePaneComponent)o).componentOpening();
- }
- } else System.err.println("Side pane component '"+name+"' unknown.");
- }
-
- public synchronized void ensureNotVisible(String name) {
- Object o = components.get(name);
- if (o != null) {
- if (visible.contains(o)) {
- visible.remove(o);
- updateView();
- ((SidePaneComponent)o).componentOpening();
- }
- } else System.err.println("Side pane component '"+name+"' unknown.");
- }
-
- public synchronized void add(String name, SidePaneComponent comp) {
- components.put(name, comp);
- visible.add(comp);
- //sidep.setComponents(visible);
- updateView();
- comp.componentOpening();
- /*sidep.add(comp);
- components.put(name, comp);
- visibleComponents++;
- if (visibleComponents == 1)
- panel.setLeftComponent(sidep);
- comp.componentOpening();
- comp.setVisibility(true);*/
- }
-
-
- public synchronized void register(String name, SidePaneComponent comp) {
- components.put(name, comp);
- /*comp.setVisible(false);
- sidep.add(comp);
- components.put(name, comp);*/
- }
-
- public synchronized boolean hasComponent(String name) {
- return (components.get("name") != null);
- }
-
- public synchronized void hideAway(String name) {
- Object o = components.get(name);
- if (o != null) {
- ((SidePaneComponent)o).componentClosing();
- if (visible.contains(o)) {
- visible.remove(o);
- //sidep.setComponents(visible);
- updateView();
- }
- } else System.err.println("Side pane component '"+name+"' unknown.");
- }
-
- public synchronized void hideAway(SidePaneComponent comp) {
- comp.componentClosing();
- visible.remove(comp);
- //sidep.setComponents(visible);
- updateView();
- /*comp.componentClosing();
- comp.setVisible(false); // Swing method to make component invisible.
- comp.setVisibility(false); // Our own boolean to keep track of visibility.
- visibleComponents--;
- if (visibleComponents == 0)
- panel.remove(sidep);
- */
- }
-
- /**
- * Update all side pane components to show information from the given BasePanel.
- * @param panel
- */
- public void setActiveBasePanel(BasePanel panel) {
- for (Iterator i = components.keySet().iterator(); i.hasNext(); ) {
- Object key = i.next();
- ((SidePaneComponent)components.get(key)).setActiveBasePanel(panel);
- }
- }
-
- public void updateView() {
- Vector toShow = new Vector();
-
- for (Iterator i = components.keySet().iterator(); i.hasNext(); ) {
- Object key = i.next();
- if (visible.contains(components.get(key))) {
- toShow.add(components.get(key));
- }
- }
- sidep.setComponents(toShow);
- boolean wasVisible = sidep.isVisible();
- if (visible.size() > 0) {
- sidep.setVisible(true);
- if (!wasVisible)
- frame.contentPane.setDividerLocation(getPanel().getPreferredSize().width);
-
- } else
- sidep.setVisible(false);
-
- }
-
- public void revalidate() {
- sidep.revalidate();
- sidep.repaint();
- }
-
- public void stateChanged(ChangeEvent event) {
- // Change by Morten Alver 2005.12.04:
- // By postponing the updating of the side pane components, we get rid of the annoying
- // latency when switching tabs:
- SwingUtilities.invokeLater(new Runnable() {
- public void run() {
- setActiveBasePanel((BasePanel)frame.tabbedPane.getSelectedComponent());
- }
- });
-
- }
+import javax.swing.event.ChangeListener;
+
+/**
+ * Manages visibility of SideShowComponents in a given newly constructed
+ * sidePane.
+ *
+ * @version $Revision: 1.20 $ ($Date: 2006/08/30 00:04:12 $)
+ *
+ */
+public class SidePaneManager {
+
+ JabRefFrame frame;
+
+ BasePanel panel;
+
+ SidePane sidep;
+
+ Map components = new LinkedHashMap();
+
+ List visible = new LinkedList();
+
+ public SidePaneManager(JabRefFrame frame) {
+ this.frame = frame;
+ /*
+ * Change by Morten Alver 2005.12.04: By postponing the updating of the
+ * side pane components, we get rid of the annoying latency when
+ * switching tabs:
+ */
+ frame.tabbedPane.addChangeListener(new ChangeListener() {
+ public void stateChanged(ChangeEvent event) {
+ SwingUtilities.invokeLater(new Runnable() {
+ public void run() {
+ setActiveBasePanel((BasePanel) SidePaneManager.this.frame.tabbedPane
+ .getSelectedComponent());
+ }
+ });
+ }
+ });
+ sidep = new SidePane();
+ }
+
+ public SidePane getPanel() {
+ return sidep;
+ }
+
+ public synchronized boolean hasComponent(String name) {
+ return (components.get("name") != null);
+ }
+
+ public boolean isComponentVisible(String name) {
+ Object o = components.get(name);
+ if (o != null) {
+ return visible.contains(o);
+ } else {
+ return false;
+ }
+ }
+
+ public synchronized void toggle(String name) {
+ if (isComponentVisible(name)) {
+ hide(name);
+ } else {
+ show(name);
+ }
+ }
+
+ public void show(String name) {
+ Object o = components.get(name);
+ if (o != null) {
+ show((SidePaneComponent) o);
+ } else
+ System.err.println("Side pane component '" + name + "' unknown.");
+ }
+
+ public void hide(String name) {
+ Object o = components.get(name);
+ if (o != null) {
+ hideComponent((SidePaneComponent) o);
+ } else
+ System.err.println("Side pane component '" + name + "' unknown.");
+ }
+
+ public synchronized void register(String name, SidePaneComponent comp) {
+ components.put(name, comp);
+ }
+
+ public synchronized void registerAndShow(String name, SidePaneComponent comp) {
+ register(name, comp);
+ show(name);
+ }
+
+ private synchronized void show(SidePaneComponent component) {
+ if (!visible.contains(component)) {
+ // Put the new component at the top of the group
+ visible.add(0, component);
+ updateView();
+ component.componentOpening();
+ }
+ }
+
+ public synchronized void hideComponent(SidePaneComponent comp) {
+ if (visible.contains(comp)) {
+ comp.componentClosing();
+ visible.remove(comp);
+ updateView();
+ }
+ }
+
+ /**
+ * Update all side pane components to show information from the given
+ * BasePanel.
+ *
+ * @param panel
+ */
+ public void setActiveBasePanel(BasePanel panel) {
+ for (Iterator i = components.keySet().iterator(); i.hasNext();) {
+ Object key = i.next();
+ ((SidePaneComponent) components.get(key)).setActiveBasePanel(panel);
+ }
+ }
+
+ public void updateView() {
+ sidep.setComponents(visible);
+ if (visible.size() > 0) {
+ boolean wasVisible = sidep.isVisible();
+ sidep.setVisible(true);
+ if (!wasVisible)
+ frame.contentPane.setDividerLocation(getPanel().getPreferredSize().width);
+ } else
+ sidep.setVisible(false);
+ }
+
+ public void revalidate() {
+ sidep.revalidate();
+ sidep.repaint();
+ }
}
diff --git a/src/java/net/sf/jabref/SplashScreen.java b/src/java/net/sf/jabref/SplashScreen.java
index 46f06a8..c848998 100644
--- a/src/java/net/sf/jabref/SplashScreen.java
+++ b/src/java/net/sf/jabref/SplashScreen.java
@@ -20,7 +20,7 @@ public class SplashScreen extends Window {
public SplashScreen(Frame owner) {
super(owner);
- URL imageURL = SplashScreen.class.getResource("/images/splash-2.1.png");
+ URL imageURL = SplashScreen.class.getResource("/images/splash.png");
splashImage = Toolkit.getDefaultToolkit().createImage(imageURL);
// Load the image
diff --git a/src/java/net/sf/jabref/SplashScreen.java~ b/src/java/net/sf/jabref/SplashScreen.java~
deleted file mode 100644
index 4f5b6da..0000000
--- a/src/java/net/sf/jabref/SplashScreen.java~
+++ /dev/null
@@ -1,110 +0,0 @@
-package net.sf.jabref;
-
-//import javax.swing.*;
-import java.awt.*;
-import java.awt.event.*;
-import java.net.URL;
-
-/**
- * <p>Title: </p>
- * <p>Description: </p>
- * <p>Copyright: Copyright (c) 2003</p>
- * <p>Company: </p>
- * @author not attributable
- * @version 1.0
- */
-
-public class SplashScreen extends Window {
- private Image splashImage;
- private boolean paintCalled = false;
-
- public SplashScreen(Frame owner) {
- super(owner);
- URL imageURL = SplashScreen.class.getResource("/images/splash-2.1beta.png");
- splashImage = Toolkit.getDefaultToolkit().createImage(imageURL);
-
- // Load the image
- MediaTracker mt = new MediaTracker(this);
- mt.addImage(splashImage,0);
- try {
- mt.waitForID(0);
- } catch(InterruptedException ie) {}
-
-
- // Center the window on the screen.
- int imgWidth = splashImage.getWidth(this);
- int imgHeight = splashImage.getHeight(this);
-
- setSize(imgWidth, imgHeight);
- Dimension screenDim = Toolkit.getDefaultToolkit().getScreenSize();
- setLocation(
- (screenDim.width - imgWidth) / 2,
- (screenDim.height - imgHeight) / 2
- );
-
- }
-
-
- /**
- * Updates the display area of the window.
- */
- public void update(Graphics g) {
- // Note: Since the paint method is going to draw an
- // image that covers the complete area of the component we
- // do not fill the component with its background color
- // here. This avoids flickering.
-
- g.setColor(getForeground());
- paint(g);
- }
- /**
- * Paints the image on the window.
- */
-
- public void paint(Graphics g) {
- g.drawImage(splashImage, 0, 0, this);
-
- // Notify method splash that the window
- // has been painted.
- if (! paintCalled) {
- paintCalled = true;
- synchronized (this) { notifyAll(); }
- }
- }
-
- /**
- * Constructs and displays a SplashWindow.<p>
- * This method is useful for startup splashs.
- * Dispose the returned frame to get rid of the splash window.<p>
- *
- * @param splashImage The image to be displayed.
- * @return Returns the frame that owns the SplashWindow.
- */
-
- public static Frame splash() {
- Frame f = new Frame();
- SplashScreen w = new SplashScreen(f);
-
- // Show the window.
- w.setVisible(true);
- w.toFront();
-
- // Note: To make sure the user gets a chance to see the
- // splash window we wait until its paint method has been
- // called at least once by the AWT event dispatcher thread.
-
- // sebwills adds: However, just in case the paint method never gets called
- // (e.g. if the splashscreen is completely obscured by an 'always on top'
- // window of some other application), we time-out after 5 seconds.
- if (! EventQueue.isDispatchThread()) {
- synchronized (w) {
- if (! w.paintCalled) {
- try {
- w.wait(5000);
- } catch (InterruptedException e) {}
- }
- }
- }
- return f;
- }
-}
diff --git a/src/java/net/sf/jabref/StringDialog.java b/src/java/net/sf/jabref/StringDialog.java
index 826db14..45ac970 100644
--- a/src/java/net/sf/jabref/StringDialog.java
+++ b/src/java/net/sf/jabref/StringDialog.java
@@ -131,8 +131,8 @@ public class StringDialog extends JDialog {
conPane.add(tlb, BorderLayout.NORTH);
conPane.add(pan, BorderLayout.CENTER);
- if (panel.file != null)
- setTitle(Globals.lang(GUIGlobals.stringsTitle)+": "+panel.file.getName());
+ if (panel.getFile() != null)
+ setTitle(Globals.lang(GUIGlobals.stringsTitle)+": "+panel.getFile().getName());
else
setTitle(Globals.lang(GUIGlobals.stringsTitle)+": "+Globals.lang(GUIGlobals.untitledTitle));
diff --git a/src/java/net/sf/jabref/TablePrefsTab.java b/src/java/net/sf/jabref/TablePrefsTab.java
index d96b1ef..6e55c0e 100644
--- a/src/java/net/sf/jabref/TablePrefsTab.java
+++ b/src/java/net/sf/jabref/TablePrefsTab.java
@@ -1,321 +1,327 @@
package net.sf.jabref;
+import java.awt.BorderLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.Arrays;
+import java.util.Collections;
import java.util.Vector;
-import javax.swing.*;
-import javax.swing.event.ChangeListener;
+
+import javax.swing.BorderFactory;
+import javax.swing.ButtonGroup;
+import javax.swing.JCheckBox;
+import javax.swing.JComboBox;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JRadioButton;
+import javax.swing.JTable;
+import javax.swing.JTextField;
import javax.swing.event.ChangeEvent;
-import javax.swing.table.*;
-import java.awt.*;
-import java.awt.event.*;
-import com.jgoodies.forms.layout.*;
-import com.jgoodies.forms.factories.*;
-import com.jgoodies.forms.builder.*;
-import net.sf.jabref.gui.ColorSetupPanel;
+import javax.swing.event.ChangeListener;
+
+import com.jgoodies.forms.builder.DefaultFormBuilder;
+import com.jgoodies.forms.layout.FormLayout;
class TablePrefsTab extends JPanel implements PrefsTab {
- JabRefPreferences _prefs;
- private JCheckBox autoResizeMode, priDesc, secDesc, terDesc, floatMarked,
- pdfColumn, urlColumn, citeseerColumn;
- private JRadioButton namesAsIs, namesFf, namesFl, namesNatbib, abbrNames, noAbbrNames, lastNamesOnly;
- private JComboBox
- priSort = new JComboBox(BibtexFields.getAllFieldNames()),
- secSort = new JComboBox(BibtexFields.getAllFieldNames()),
- terSort = new JComboBox(BibtexFields.getAllFieldNames());
- private JTextField priField, secField, terField;
- private JabRefFrame frame;
-
-
- /**
- * Customization of external program paths.
- *
- * @param prefs a <code>JabRefPreferences</code> value
- */
- public TablePrefsTab(JabRefPreferences prefs, JabRefFrame frame) {
- _prefs = prefs;
- this.frame = frame;
- setLayout(new BorderLayout());
-
-
-
- autoResizeMode = new JCheckBox(Globals.lang
- ("Fit table horizontally on screen"));
-
- namesAsIs = new JRadioButton(Globals.lang("Show names unchanged"));
- namesFf = new JRadioButton(Globals.lang("Show 'Firstname Lastname'"));
- namesFl = new JRadioButton(Globals.lang("Show 'Lastname, Firstname'"));
- namesNatbib = new JRadioButton(Globals.lang("Natbib style"));
- noAbbrNames = new JRadioButton(Globals.lang("Do not abbreviate names"));
- abbrNames = new JRadioButton(Globals.lang("Abbreviate names"));
- lastNamesOnly = new JRadioButton("Show last names only");
- pdfColumn = new JCheckBox(Globals.lang("Show PDF/PS column"));
- urlColumn = new JCheckBox(Globals.lang("Show URL/DOI column"));
- citeseerColumn = new JCheckBox(Globals.lang("Show CiteSeer column"));
-
- floatMarked = new JCheckBox(Globals.lang("Float marked entries"));
-
- priField = new JTextField(10);
- secField = new JTextField(10);
- terField = new JTextField(10);
-
- priSort.insertItemAt(Globals.lang("<select>"), 0);
- secSort.insertItemAt(Globals.lang("<select>"), 0);
- terSort.insertItemAt(Globals.lang("<select>"), 0);
-
- priSort.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- if (priSort.getSelectedIndex() > 0) {
- priField.setText(BibtexFields.getFieldName( priSort.getSelectedIndex() - 1));
- priSort.setSelectedIndex(0);
- }
- }
- });
- secSort.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- if (secSort.getSelectedIndex() > 0) {
- secField.setText(BibtexFields.getFieldName( secSort.getSelectedIndex() - 1));
- secSort.setSelectedIndex(0);
- }
- }
- });
- terSort.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- if (terSort.getSelectedIndex() > 0) {
- terField.setText(BibtexFields.getFieldName( terSort.getSelectedIndex() - 1));
- terSort.setSelectedIndex(0);
- }
- }
- });
-
- ButtonGroup bg = new ButtonGroup();
- bg.add(namesAsIs);
- bg.add(namesNatbib);
- bg.add(namesFf);
- bg.add(namesFl);
- ButtonGroup bg2 = new ButtonGroup();
- bg2.add(lastNamesOnly);
- bg2.add(abbrNames);
- bg2.add(noAbbrNames);
- priDesc = new JCheckBox(Globals.lang("Descending"));
- secDesc = new JCheckBox(Globals.lang("Descending"));
- terDesc = new JCheckBox(Globals.lang("Descending"));
-
- FormLayout layout = new FormLayout
- ("1dlu, 8dlu, left:pref, 4dlu, fill:pref, 4dlu, fill:60dlu, 4dlu, fill:pref",
- "");
- DefaultFormBuilder builder = new DefaultFormBuilder(layout);
- JLabel lab;
- JPanel pan = new JPanel();
- builder.appendSeparator(Globals.lang("Special table columns"));
- builder.nextLine();
- builder.append(pan); builder.append(pdfColumn); builder.nextLine();
- builder.append(pan); builder.append(urlColumn); builder.nextLine();
- builder.append(pan); builder.append(citeseerColumn); builder.nextLine();
- builder.appendSeparator(Globals.lang("Format of author and editor names"));
- DefaultFormBuilder nameBuilder = new DefaultFormBuilder(
- new FormLayout("left:pref, 8dlu, left:pref",""));
-
- nameBuilder.append(namesAsIs); nameBuilder.append(noAbbrNames); nameBuilder.nextLine();
- nameBuilder.append(namesFf); nameBuilder.append(abbrNames); nameBuilder.nextLine();
- nameBuilder.append(namesFl); nameBuilder.append(lastNamesOnly); nameBuilder.nextLine();
- nameBuilder.append(namesNatbib);
- builder.append(pan); builder.append(nameBuilder.getPanel()); builder.nextLine();
- //builder.append(pan); builder.append(noAbbrNames); builder.nextLine();
- //builder.append(pan); builder.append(abbrNames); builder.nextLine();
- //builder.append(pan); builder.append(lastNamesOnly); builder.nextLine();
-
- builder.appendSeparator(Globals.lang("Default sort criteria"));
- // Create a new panel with its own FormLayout for these items:
- FormLayout layout2 = new FormLayout
- ("left:pref, 8dlu, fill:pref, 4dlu, fill:60dlu, 4dlu, left:pref", "");
- DefaultFormBuilder builder2 = new DefaultFormBuilder(layout2);
- lab = new JLabel(Globals.lang("Primary sort criterion"));
- builder2.append(lab);
- builder2.append(priSort);
- builder2.append(priField);
- builder2.append(priDesc);
- builder2.nextLine();
- lab = new JLabel(Globals.lang("Secondary sort criterion"));
- builder2.append(lab);
- builder2.append(secSort);
- builder2.append(secField);
- builder2.append(secDesc);
- builder2.nextLine();
- lab = new JLabel(Globals.lang("Tertiary sort criterion"));
- builder2.append(lab);
- builder2.append(terSort);
- builder2.append(terField);
- builder2.append(terDesc);
- builder.nextLine();
- builder.append(pan);
- builder.append(builder2.getPanel());
- builder.nextLine();
- builder.append(pan);
- builder.append(floatMarked);
- builder.nextLine();
- builder.appendSeparator(Globals.lang("General"));
- builder.append(pan); builder.append(autoResizeMode); builder.nextLine();
-
-
- pan = builder.getPanel();
- pan.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
- add(pan, BorderLayout.CENTER);
-
- namesNatbib.addChangeListener(new ChangeListener() {
- public void stateChanged(ChangeEvent changeEvent) {
- abbrNames.setEnabled(!namesNatbib.isSelected());
- lastNamesOnly.setEnabled(!namesNatbib.isSelected());
- noAbbrNames.setEnabled(!namesNatbib.isSelected());
- }
- });
- }
-
- public void setValues() {
- autoResizeMode.setSelected((_prefs.getInt("autoResizeMode")==JTable.AUTO_RESIZE_ALL_COLUMNS));
- pdfColumn.setSelected(_prefs.getBoolean("pdfColumn"));
- urlColumn.setSelected(_prefs.getBoolean("urlColumn"));
- citeseerColumn.setSelected(_prefs.getBoolean("citeseerColumn"));
-
- priField.setText(_prefs.get("priSort"));
- secField.setText(_prefs.get("secSort"));
- terField.setText(_prefs.get("terSort"));
- priSort.setSelectedIndex(0);
- secSort.setSelectedIndex(0);
- terSort.setSelectedIndex(0);
-
- if (_prefs.getBoolean("namesAsIs"))
- namesAsIs.setSelected(true);
- else if (_prefs.getBoolean("namesFf"))
- namesFf.setSelected(true);
- else if (_prefs.getBoolean("namesNatbib"))
- namesNatbib.setSelected(true);
- else
- namesFl.setSelected(true);
- if (_prefs.getBoolean("abbrAuthorNames"))
- abbrNames.setSelected(true);
- else if (_prefs.getBoolean("namesLastOnly"))
- lastNamesOnly.setSelected(true);
- else
- noAbbrNames.setSelected(true);
- priDesc.setSelected(_prefs.getBoolean("priDescending"));
- secDesc.setSelected(_prefs.getBoolean("secDescending"));
- terDesc.setSelected(_prefs.getBoolean("terDescending"));
-
- floatMarked.setSelected(_prefs.getBoolean("floatMarkedEntries"));
-
- abbrNames.setEnabled(!namesNatbib.isSelected());
- lastNamesOnly.setEnabled(!namesNatbib.isSelected());
- noAbbrNames.setEnabled(!namesNatbib.isSelected());
- }
-
- /**
- * Store changes to table preferences. This method is called when
- * the user clicks Ok.
- *
- */
- public void storeSettings() {
-
- _prefs.putBoolean("namesAsIs", namesAsIs.isSelected());
- _prefs.putBoolean("namesFf", namesFf.isSelected());
- _prefs.putBoolean("namesNatbib", namesNatbib.isSelected());
- _prefs.putBoolean("namesLastOnly", lastNamesOnly.isSelected());
- _prefs.putBoolean("abbrAuthorNames", abbrNames.isSelected());
-
- _prefs.putBoolean("pdfColumn", pdfColumn.isSelected());
- _prefs.putBoolean("urlColumn", urlColumn.isSelected());
- _prefs.putBoolean("citeseerColumn", citeseerColumn.isSelected());
- _prefs.putInt("autoResizeMode",
- autoResizeMode.isSelected() ?
- JTable.AUTO_RESIZE_ALL_COLUMNS :
- JTable.AUTO_RESIZE_OFF);
- _prefs.putBoolean("priDescending", priDesc.isSelected());
- _prefs.putBoolean("secDescending", secDesc.isSelected());
- _prefs.putBoolean("terDescending", terDesc.isSelected());
- //_prefs.put("secSort", GUIGlobals.ALL_FIELDS[secSort.getSelectedIndex()]);
- //_prefs.put("terSort", GUIGlobals.ALL_FIELDS[terSort.getSelectedIndex()]);
- _prefs.put("priSort", priField.getText().toLowerCase().trim());
- _prefs.put("secSort", secField.getText().toLowerCase().trim());
- _prefs.put("terSort", terField.getText().toLowerCase().trim());
-
- _prefs.putBoolean("floatMarkedEntries", floatMarked.isSelected());
- // updatefont
- }
-
- public boolean readyToClose() {
- return true;
- }
+ JabRefPreferences _prefs;
+
+ private JCheckBox autoResizeMode, priDesc, secDesc, terDesc, floatMarked, pdfColumn, urlColumn,
+ citeseerColumn;
+
+ private JRadioButton namesAsIs, namesFf, namesFl, namesNatbib, abbrNames, noAbbrNames,
+ lastNamesOnly;
+
+ private JComboBox priSort, secSort, terSort;
+
+ private JTextField priField, secField, terField;
+
+ private JabRefFrame frame;
+
+ /**
+ * Customization of external program paths.
+ *
+ * @param prefs
+ * a <code>JabRefPreferences</code> value
+ */
+ public TablePrefsTab(JabRefPreferences prefs, JabRefFrame frame) {
+ _prefs = prefs;
+ this.frame = frame;
+ setLayout(new BorderLayout());
+
+ /**
+ * Added Bibtexkey to combobox.
+ *
+ * [ 1540646 ] default sort order: bibtexkey
+ *
+ * http://sourceforge.net/tracker/index.php?func=detail&aid=1540646&group_id=92314&atid=600306
+ */
+ Vector v = new Vector(Arrays.asList(BibtexFields.getAllFieldNames()));
+ v.add(BibtexFields.KEY_FIELD);
+ Collections.sort(v);
+ Object[] allPlusKey = v.toArray();
+ priSort = new JComboBox(allPlusKey);
+ secSort = new JComboBox(allPlusKey);
+ terSort = new JComboBox(allPlusKey);
+
+ autoResizeMode = new JCheckBox(Globals.lang("Fit table horizontally on screen"));
+
+ namesAsIs = new JRadioButton(Globals.lang("Show names unchanged"));
+ namesFf = new JRadioButton(Globals.lang("Show 'Firstname Lastname'"));
+ namesFl = new JRadioButton(Globals.lang("Show 'Lastname, Firstname'"));
+ namesNatbib = new JRadioButton(Globals.lang("Natbib style"));
+ noAbbrNames = new JRadioButton(Globals.lang("Do not abbreviate names"));
+ abbrNames = new JRadioButton(Globals.lang("Abbreviate names"));
+ lastNamesOnly = new JRadioButton(Globals.lang("Show last names only"));
+ pdfColumn = new JCheckBox(Globals.lang("Show PDF/PS column"));
+ urlColumn = new JCheckBox(Globals.lang("Show URL/DOI column"));
+ citeseerColumn = new JCheckBox(Globals.lang("Show CiteSeer column"));
+
+ floatMarked = new JCheckBox(Globals.lang("Float marked entries"));
+
+ priField = new JTextField(10);
+ secField = new JTextField(10);
+ terField = new JTextField(10);
+
+ priSort.insertItemAt(Globals.lang("<select>"), 0);
+ secSort.insertItemAt(Globals.lang("<select>"), 0);
+ terSort.insertItemAt(Globals.lang("<select>"), 0);
+
+ priSort.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ if (priSort.getSelectedIndex() > 0) {
+ priField.setText(BibtexFields.getFieldName(priSort.getSelectedIndex() - 1));
+ priSort.setSelectedIndex(0);
+ }
+ }
+ });
+ secSort.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ if (secSort.getSelectedIndex() > 0) {
+ secField.setText(BibtexFields.getFieldName(secSort.getSelectedIndex() - 1));
+ secSort.setSelectedIndex(0);
+ }
+ }
+ });
+ terSort.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ if (terSort.getSelectedIndex() > 0) {
+ terField.setText(BibtexFields.getFieldName(terSort.getSelectedIndex() - 1));
+ terSort.setSelectedIndex(0);
+ }
+ }
+ });
+
+ ButtonGroup bg = new ButtonGroup();
+ bg.add(namesAsIs);
+ bg.add(namesNatbib);
+ bg.add(namesFf);
+ bg.add(namesFl);
+ ButtonGroup bg2 = new ButtonGroup();
+ bg2.add(lastNamesOnly);
+ bg2.add(abbrNames);
+ bg2.add(noAbbrNames);
+ priDesc = new JCheckBox(Globals.lang("Descending"));
+ secDesc = new JCheckBox(Globals.lang("Descending"));
+ terDesc = new JCheckBox(Globals.lang("Descending"));
+
+ FormLayout layout = new FormLayout(
+ "1dlu, 8dlu, left:pref, 4dlu, fill:pref, 4dlu, fill:60dlu, 4dlu, fill:pref", "");
+ DefaultFormBuilder builder = new DefaultFormBuilder(layout);
+ JLabel lab;
+ JPanel pan = new JPanel();
+ builder.appendSeparator(Globals.lang("Special table columns"));
+ builder.nextLine();
+ builder.append(pan);
+ builder.append(pdfColumn);
+ builder.nextLine();
+ builder.append(pan);
+ builder.append(urlColumn);
+ builder.nextLine();
+ builder.append(pan);
+ builder.append(citeseerColumn);
+ builder.nextLine();
+ builder.appendSeparator(Globals.lang("Format of author and editor names"));
+ DefaultFormBuilder nameBuilder = new DefaultFormBuilder(new FormLayout(
+ "left:pref, 8dlu, left:pref", ""));
+
+ nameBuilder.append(namesAsIs);
+ nameBuilder.append(noAbbrNames);
+ nameBuilder.nextLine();
+ nameBuilder.append(namesFf);
+ nameBuilder.append(abbrNames);
+ nameBuilder.nextLine();
+ nameBuilder.append(namesFl);
+ nameBuilder.append(lastNamesOnly);
+ nameBuilder.nextLine();
+ nameBuilder.append(namesNatbib);
+ builder.append(pan);
+ builder.append(nameBuilder.getPanel());
+ builder.nextLine();
+ // builder.append(pan); builder.append(noAbbrNames); builder.nextLine();
+ // builder.append(pan); builder.append(abbrNames); builder.nextLine();
+ // builder.append(pan); builder.append(lastNamesOnly);
+ // builder.nextLine();
+
+ builder.appendSeparator(Globals.lang("Default sort criteria"));
+ // Create a new panel with its own FormLayout for these items:
+ FormLayout layout2 = new FormLayout(
+ "left:pref, 8dlu, fill:pref, 4dlu, fill:60dlu, 4dlu, left:pref", "");
+ DefaultFormBuilder builder2 = new DefaultFormBuilder(layout2);
+ lab = new JLabel(Globals.lang("Primary sort criterion"));
+ builder2.append(lab);
+ builder2.append(priSort);
+ builder2.append(priField);
+ builder2.append(priDesc);
+ builder2.nextLine();
+ lab = new JLabel(Globals.lang("Secondary sort criterion"));
+ builder2.append(lab);
+ builder2.append(secSort);
+ builder2.append(secField);
+ builder2.append(secDesc);
+ builder2.nextLine();
+ lab = new JLabel(Globals.lang("Tertiary sort criterion"));
+ builder2.append(lab);
+ builder2.append(terSort);
+ builder2.append(terField);
+ builder2.append(terDesc);
+ builder.nextLine();
+ builder.append(pan);
+ builder.append(builder2.getPanel());
+ builder.nextLine();
+ builder.append(pan);
+ builder.append(floatMarked);
+ builder.nextLine();
+ builder.appendSeparator(Globals.lang("General"));
+ builder.append(pan);
+ builder.append(autoResizeMode);
+ builder.nextLine();
+
+ pan = builder.getPanel();
+ pan.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
+ add(pan, BorderLayout.CENTER);
+
+ namesNatbib.addChangeListener(new ChangeListener() {
+ public void stateChanged(ChangeEvent changeEvent) {
+ abbrNames.setEnabled(!namesNatbib.isSelected());
+ lastNamesOnly.setEnabled(!namesNatbib.isSelected());
+ noAbbrNames.setEnabled(!namesNatbib.isSelected());
+ }
+ });
+ }
+
+ public void setValues() {
+ autoResizeMode
+ .setSelected((_prefs.getInt("autoResizeMode") == JTable.AUTO_RESIZE_ALL_COLUMNS));
+ pdfColumn.setSelected(_prefs.getBoolean("pdfColumn"));
+ urlColumn.setSelected(_prefs.getBoolean("urlColumn"));
+ citeseerColumn.setSelected(_prefs.getBoolean("citeseerColumn"));
+
+ priField.setText(_prefs.get("priSort"));
+ secField.setText(_prefs.get("secSort"));
+ terField.setText(_prefs.get("terSort"));
+ priSort.setSelectedIndex(0);
+ secSort.setSelectedIndex(0);
+ terSort.setSelectedIndex(0);
+
+ if (_prefs.getBoolean("namesAsIs"))
+ namesAsIs.setSelected(true);
+ else if (_prefs.getBoolean("namesFf"))
+ namesFf.setSelected(true);
+ else if (_prefs.getBoolean("namesNatbib"))
+ namesNatbib.setSelected(true);
+ else
+ namesFl.setSelected(true);
+ if (_prefs.getBoolean("abbrAuthorNames"))
+ abbrNames.setSelected(true);
+ else if (_prefs.getBoolean("namesLastOnly"))
+ lastNamesOnly.setSelected(true);
+ else
+ noAbbrNames.setSelected(true);
+ priDesc.setSelected(_prefs.getBoolean("priDescending"));
+ secDesc.setSelected(_prefs.getBoolean("secDescending"));
+ terDesc.setSelected(_prefs.getBoolean("terDescending"));
+
+ floatMarked.setSelected(_prefs.getBoolean("floatMarkedEntries"));
+
+ abbrNames.setEnabled(!namesNatbib.isSelected());
+ lastNamesOnly.setEnabled(!namesNatbib.isSelected());
+ noAbbrNames.setEnabled(!namesNatbib.isSelected());
+ }
+
+ /**
+ * Store changes to table preferences. This method is called when the user
+ * clicks Ok.
+ *
+ */
+ public void storeSettings() {
+
+ _prefs.putBoolean("namesAsIs", namesAsIs.isSelected());
+ _prefs.putBoolean("namesFf", namesFf.isSelected());
+ _prefs.putBoolean("namesNatbib", namesNatbib.isSelected());
+ _prefs.putBoolean("namesLastOnly", lastNamesOnly.isSelected());
+ _prefs.putBoolean("abbrAuthorNames", abbrNames.isSelected());
+
+ _prefs.putBoolean("pdfColumn", pdfColumn.isSelected());
+ _prefs.putBoolean("urlColumn", urlColumn.isSelected());
+ _prefs.putBoolean("citeseerColumn", citeseerColumn.isSelected());
+ _prefs.putInt("autoResizeMode",
+ autoResizeMode.isSelected() ? JTable.AUTO_RESIZE_ALL_COLUMNS : JTable.AUTO_RESIZE_OFF);
+ _prefs.putBoolean("priDescending", priDesc.isSelected());
+ _prefs.putBoolean("secDescending", secDesc.isSelected());
+ _prefs.putBoolean("terDescending", terDesc.isSelected());
+ // _prefs.put("secSort",
+ // GUIGlobals.ALL_FIELDS[secSort.getSelectedIndex()]);
+ // _prefs.put("terSort",
+ // GUIGlobals.ALL_FIELDS[terSort.getSelectedIndex()]);
+ _prefs.put("priSort", priField.getText().toLowerCase().trim());
+ _prefs.put("secSort", secField.getText().toLowerCase().trim());
+ _prefs.put("terSort", terField.getText().toLowerCase().trim());
+
+ _prefs.putBoolean("floatMarkedEntries", floatMarked.isSelected());
+ // updatefont
+ }
+
+ public boolean readyToClose() {
+ return true;
+ }
}
- /*
- Boolean[] sel = new Boolean[GUIGlobals.ALL_FIELDS.length];
- boolean found;
- _choices = GUIGlobals.ALL_FIELDS;
- _sel = sel;
- String[] columns = prefs.getStringArray("columnNames");
- for (int i=0; i<_choices.length; i++) {
- found = false;
- for (int j=0; j<columns.length; j++)
- if (columns[j].equals(_choices[i]))
- found = true;
- if (found)
- sel[i] = new Boolean(true);
- else
- sel[i] = new Boolean(false);
- }
-
- TableModel tm = new AbstractTableModel() {
- public int getRowCount() { return (_choices.length-1)/2; }
- public int getColumnCount() { return 4; }
- public Object getValueAt(int row, int column) {
- switch (column) {
- case 0:
- return _choices[row];
- case 1:
- return _sel[row];
- case 2:
- return _choices[getRowCount()+row];
- case 3:
- return _sel[getRowCount()+row];
- }
- return null; // Unreachable.
- }
- public Class getColumnClass(int column) {
- if ((column == 0) || (column == 2)) return String.class;
- else return Boolean.class;
- }
- public boolean isCellEditable(int row, int col) {
- if ((col == 1) || (col == 3)) return true;
- else return false;
- }
- public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
- if (columnIndex == 1)
- _sel[rowIndex] = (Boolean)aValue;
- if (columnIndex == 3)
- _sel[getRowCount()+rowIndex] = (Boolean)aValue;
- }
-
- };
-
- JTable table = new JTable(tm);
- table.setRowSelectionAllowed(false);
- table.setColumnSelectionAllowed(false);
- //table.getInputMap().put(GUIGlobals.exitDialog, "close");
- //table.getActionMap().put("close", new CancelAction());
- JPanel
- tablePanel = new JPanel(),
- innerTablePanel = new JPanel();
-
- table.setShowVerticalLines(false);
- innerTablePanel.setBorder(BorderFactory.createEtchedBorder());
- //innerTablePanel.setBorder(BorderFactory.createLoweredBevelBorder());
- innerTablePanel.add(table);
- tablePanel.add(innerTablePanel);
-
-
- TableColumnModel cm = table.getColumnModel();
- cm.getColumn(0).setPreferredWidth(90);
- cm.getColumn(1).setPreferredWidth(25);
- cm.getColumn(2).setPreferredWidth(90);
- cm.getColumn(3).setPreferredWidth(25);
- */
+/*
+ * Boolean[] sel = new Boolean[GUIGlobals.ALL_FIELDS.length]; boolean found;
+ * _choices = GUIGlobals.ALL_FIELDS; _sel = sel; String[] columns =
+ * prefs.getStringArray("columnNames"); for (int i=0; i<_choices.length; i++) {
+ * found = false; for (int j=0; j<columns.length; j++) if
+ * (columns[j].equals(_choices[i])) found = true; if (found) sel[i] = new
+ * Boolean(true); else sel[i] = new Boolean(false); }
+ *
+ * TableModel tm = new AbstractTableModel() { public int getRowCount() { return
+ * (_choices.length-1)/2; } public int getColumnCount() { return 4; } public
+ * Object getValueAt(int row, int column) { switch (column) { case 0: return
+ * _choices[row]; case 1: return _sel[row]; case 2: return
+ * _choices[getRowCount()+row]; case 3: return _sel[getRowCount()+row]; } return
+ * null; // Unreachable. } public Class getColumnClass(int column) { if ((column ==
+ * 0) || (column == 2)) return String.class; else return Boolean.class; } public
+ * boolean isCellEditable(int row, int col) { if ((col == 1) || (col == 3))
+ * return true; else return false; } public void setValueAt(Object aValue, int
+ * rowIndex, int columnIndex) { if (columnIndex == 1) _sel[rowIndex] =
+ * (Boolean)aValue; if (columnIndex == 3) _sel[getRowCount()+rowIndex] =
+ * (Boolean)aValue; } };
+ *
+ * JTable table = new JTable(tm); table.setRowSelectionAllowed(false);
+ * table.setColumnSelectionAllowed(false);
+ * //table.getInputMap().put(GUIGlobals.exitDialog, "close");
+ * //table.getActionMap().put("close", new CancelAction()); JPanel tablePanel =
+ * new JPanel(), innerTablePanel = new JPanel();
+ *
+ * table.setShowVerticalLines(false);
+ * innerTablePanel.setBorder(BorderFactory.createEtchedBorder());
+ * //innerTablePanel.setBorder(BorderFactory.createLoweredBevelBorder());
+ * innerTablePanel.add(table); tablePanel.add(innerTablePanel);
+ *
+ *
+ * TableColumnModel cm = table.getColumnModel();
+ * cm.getColumn(0).setPreferredWidth(90); cm.getColumn(1).setPreferredWidth(25);
+ * cm.getColumn(2).setPreferredWidth(90); cm.getColumn(3).setPreferredWidth(25);
+ */
diff --git a/src/java/net/sf/jabref/Util.java b/src/java/net/sf/jabref/Util.java
index ea84e79..5f7e582 100644
--- a/src/java/net/sf/jabref/Util.java
+++ b/src/java/net/sf/jabref/Util.java
@@ -34,1530 +34,2245 @@
// make the DateFormatter abstract and splitt the easyDate methode
// (now we cannot change the dateformat dynamicly, sorry)
-
package net.sf.jabref;
-import java.io.* ;
-import java.net.* ;
-import java.nio.charset.* ;
-import java.text.* ;
-import java.util.* ;
-import java.util.List ;
-import java.util.regex.* ;
-
-import java.awt.* ;
-import java.awt.event.* ;
-import javax.swing.* ;
-
-import com.jgoodies.forms.builder.* ;
-import com.jgoodies.forms.layout.* ;
-import net.sf.jabref.external.* ;
-import net.sf.jabref.groups.* ;
-import net.sf.jabref.imports.* ;
-import net.sf.jabref.undo.* ;
+import java.awt.BorderLayout;
+import java.awt.CardLayout;
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.Font;
+import java.awt.Point;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.FilenameFilter;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetEncoder;
+import java.text.NumberFormat;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.Collection;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.SortedSet;
+import java.util.StringTokenizer;
+import java.util.TreeSet;
+import java.util.Vector;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.swing.Box;
+import javax.swing.JButton;
+import javax.swing.JFrame;
+import javax.swing.JLabel;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTextArea;
+import javax.swing.undo.UndoableEdit;
+
+import net.sf.jabref.export.layout.LayoutEntry;
+import net.sf.jabref.export.layout.LayoutFormatter;
+import net.sf.jabref.external.ExternalFileType;
+import net.sf.jabref.groups.AbstractGroup;
+import net.sf.jabref.groups.KeywordGroup;
+import net.sf.jabref.imports.CiteSeerFetcher;
+import net.sf.jabref.undo.NamedCompound;
+import net.sf.jabref.undo.UndoableFieldChange;
+
+import com.jgoodies.forms.builder.DefaultFormBuilder;
+import com.jgoodies.forms.layout.FormLayout;
/**
* Describe class <code>Util</code> here.
- *
+ *
* @author <a href="mailto:"> </a>
* @version 1.0
*/
-public class Util
-{
- // A static Object for date formatting. Please do not create the object here,
- // because there are some references from the Globals class.....
- private static SimpleDateFormat dateFormatter = null ;
-
- // Colors are defined here.
- public static Color fieldsCol = new Color(180, 180, 200);
-
- // Integer values for indicating result of duplicate check (for entries):
- final static int
- TYPE_MISMATCH = -1,
- NOT_EQUAL = 0,
- EQUAL = 1,
- EMPTY_IN_ONE = 2,
- EMPTY_IN_TWO = 3;
-
-
- final static NumberFormat idFormat;
-
- static {
- idFormat = NumberFormat.getInstance();
- idFormat.setMinimumIntegerDigits(8);
- idFormat.setGroupingUsed(false);
- }
-
- public static void bool(boolean b) {
- if (b) System.out.println("true");
- else System.out.println("false");
- }
-
- public static void pr(String s) {
- System.out.println(s);
- }
-
- public static void pr_(String s) {
- System.out.print(s);
- }
-
- public static String nCase(String s) {
- // Make first character of String uppercase, and the
- // rest lowercase.
- if (s.length() > 1) return s.substring(0, 1).toUpperCase()
- + s.substring(1, s.length()).toLowerCase();
- else return s.toUpperCase();
-
- }
-
- public static String checkName(String s) {
- // Append '.bib' to the string unless it ends with that.
- String extension = s.substring(s.length() - 4);
- if (!extension.equalsIgnoreCase(".bib")) return s + ".bib";
- else return s;
- }
-
- private static int idCounter = 0;
-
-
- public synchronized static String createNeutralId() {
- return idFormat.format(idCounter++);
- //return String.valueOf(idCounter++);
- }
-
- /**
- * This method sets the location of a Dialog such that it is centered with
- * regard to another window, but not outside the screen on the left and the
- * top.
- */
- public static void placeDialog(java.awt.Dialog diag,
- java.awt.Container win) {
- Dimension ds = diag.getSize(), df = win.getSize();
- Point pf = win.getLocation();
- diag.setLocation(new Point(Math
- .max(0, pf.x + (df.width - ds.width) / 2), Math.max(0, pf.y
- + (df.height - ds.height) / 2)));
-
- }
-
- /**
- * This method translates a field or string from Bibtex notation, with
- * possibly text contained in " " or { }, and string references,
- * concatenated by '#' characters, into Bibkeeper notation, where string
- * references are enclosed in a pair of '#' characters.
- */
- public static String parseField(String content) {
- if (content.length() == 0) return "";
- String toSet = "";
- boolean string;
- // Keeps track of whether the next item is
- // a reference to a string, or normal content. First we must
- // check which we begin with. We simply check if we can find
- // a '#' before either '"' or '{'.
- int hash = content.indexOf('#'), wr1 = content.indexOf('"'), wr2 = content
- .indexOf('{'), end = content.length();
- if (hash == -1) hash = end;
- if (wr1 == -1) wr1 = end;
- if (wr2 == -1) wr2 = end;
- string = ((wr1 == end) && (wr2 == end)) || (hash < Math.min(wr1, wr2));
-
- //System.out.println("FileLoader: "+content+" "+string+" "+hash+"
- // "+wr1+" "+wr2);
- StringTokenizer tok = new StringTokenizer(content, "#", true);
- // 'tok' splits at the '#' sign, and keeps delimiters
-
- while (tok.hasMoreTokens()) {
- String str = tok.nextToken();
- if (str.equals("#")) string = !string;
- else {
- if (string) {
- // This part should normally be a string, but if it's
- // a pure number, it is not.
- String s = shaveString(str);
- try {
- Integer.parseInt(s);
- // If there's no exception, it's a number.
- toSet = toSet + s;
- } catch (NumberFormatException ex) {
- toSet = toSet + "#" + shaveString(str) + "#";
- }
-
- } else toSet = toSet + shaveString(str);
- }
- }
- return toSet;
- }
-
- public static String shaveString(String s) {
- // returns the string, after shaving off whitespace at the beginning
- // and end, and removing (at most) one pair of braces or " surrounding
- // it.
- if (s == null) return null;
- char ch, ch2;
- int beg = 0, end = s.length();
- // We start out assuming nothing will be removed.
- boolean begok = false, endok = false;
- while (!begok) {
- if (beg < s.length()) {
- ch = s.charAt(beg);
- if (Character.isWhitespace(ch)) beg++;
- else begok = true;
- } else begok = true;
-
- }
- while (!endok) {
- if (end > beg + 1) {
- ch = s.charAt(end - 1);
- if (Character.isWhitespace(ch)) end--;
- else endok = true;
- } else endok = true;
- }
-
- if (end > beg + 1) {
- ch = s.charAt(beg);
- ch2 = s.charAt(end - 1);
- if (((ch == '{') && (ch2 == '}')) || ((ch == '"') && (ch2 == '"'))) {
- beg++;
- end--;
- }
- }
- s = s.substring(beg, end);
- //Util.pr(s);
- return s;
- }
-
- /**
- * This method returns a String similar to the one passed in, except that it is
- * molded into a form that is acceptable for bibtex.
- */
- public static String checkLegalKey(String key) {
- if (key == null) return null;
- StringBuffer newKey = new StringBuffer();
- for (int i = 0; i < key.length(); i++) {
- char c = key.charAt(i);
- if (!Character.isWhitespace(c) && (c != '#') && (c != '{') && (c != '\\')
- && (c != '"')
- && (c != '}') && (c != '~') && (c != ',') && (c != '^')) newKey
- .append(c);
- }
-
- // Replace non-english characters like umlauts etc. with a sensible
- // letter or letter combination that bibtex can accept.
- String newKeyS = replaceSpecialCharacters(newKey.toString());
-
- return newKeyS;
- }
-
- /**
- * Replace non-english characters like umlauts etc. with a sensible
- * letter or letter combination that bibtex can accept. The basis
- * for replacement is the HashMap GLobals.UNICODE_CHARS.
- */
- public static String replaceSpecialCharacters(String s) {
- for (Iterator i = Globals.UNICODE_CHARS.keySet().iterator(); i.hasNext();) {
- String chr = (String) i.next(),
- replacer = (String) Globals.UNICODE_CHARS.get(chr);
- //pr(chr+" "+replacer);
- s = s.replaceAll(chr, replacer);
- }
- return s;
- }
-
- static public String _wrap2(String in, int wrapAmount) {
- // The following line cuts out all whitespace and replaces them with single
- // spaces:
- //in = in.replaceAll("[ ]+"," ").replaceAll("[\\t]+"," ");
- //StringBuffer out = new StringBuffer(in);
- StringBuffer out = new StringBuffer(in.replaceAll("[ \\t\\r]+", " "));
-
-
- int p = in.length() - wrapAmount;
- int lastInserted = -1;
- while (p > 0) {
- p = out.lastIndexOf(" ", p);
- if (p <= 0 || p <= 20) break;
- int lbreak = out.indexOf("\n", p);
- System.out.println(lbreak + " " + lastInserted);
- if ((lbreak > p) && ((lastInserted >= 0) && (lbreak < lastInserted))) {
- p = lbreak - wrapAmount;
- } else {
- out.insert(p, "\n\t");
- lastInserted = p;
- p -= wrapAmount;
- }
- }
- return out.toString();
- }
-
- static public String wrap2(String in, int wrapAmount) {
- return net.sf.jabref.imports.FieldContentParser.wrap(in, wrapAmount);
- }
-
- static public String __wrap2(String in, int wrapAmount) {
- // The following line cuts out all whitespace except line breaks, and replaces
- // with single spaces. Line breaks are padded with a tab character:
- StringBuffer out = new StringBuffer(in.replaceAll("[ \\t\\r]+", " "));
-
- int p = 0;
- //int lastInserted = -1;
- while (p < out.length()) {
- int q = out.indexOf(" ", p + wrapAmount);
- if ((q < 0) || (q >= out.length()))
- break;
- int lbreak = out.indexOf("\n", p);
- //System.out.println(lbreak);
- if ((lbreak > p) && (lbreak < q)) {
- p = lbreak + 1;
- int piv = lbreak + 1;
- if ((out.length() > piv) && !(out.charAt(piv) == '\t'))
- out.insert(piv, "\n\t");
-
- } else {
- //System.out.println(q+" "+out.length());
- out.deleteCharAt(q);
- out.insert(q, "\n\t");
- p = q + 1;
- }
- }
- return out.toString();//.replaceAll("\n", "\n\t");
- }
-
- public static HashSet findDeliminatedWordsInField(BibtexDatabase db,
- String field, String deliminator) {
- HashSet res = new HashSet();
- Iterator i = db.getKeySet().iterator();
- while (i.hasNext()) {
- BibtexEntry be = db.getEntryById(i.next().toString());
- Object o = be.getField(field);
- if (o != null) {
- String fieldValue = o.toString().trim();
- StringTokenizer tok = new StringTokenizer(fieldValue, deliminator);
- while (tok.hasMoreTokens()) res.add(tok.nextToken().trim());
- }
- }
- return res;
- }
-
- /**
- * Returns a HashMap containing all words used in the database in the given
- * field type. Characters in
- *
- * @param remove are not included.
- * @param db a <code>BibtexDatabase</code> value
- * @param field a <code>String</code> value
- * @param remove a <code>String</code> value
- * @return a <code>HashSet</code> value
- */
- public static HashSet findAllWordsInField(BibtexDatabase db, String field,
- String remove) {
- HashSet res = new HashSet();
- StringTokenizer tok;
- Iterator i = db.getKeySet().iterator();
- while (i.hasNext()) {
- BibtexEntry be = db.getEntryById(i.next().toString());
- Object o = be.getField(field);
- if (o != null) {
- tok = new StringTokenizer(o.toString(), remove, false);
- while (tok.hasMoreTokens()) res.add(tok.nextToken());
- }
- }
- return res;
- }
-
- /**
- * Takes a String array and returns a string with the array's elements
- * delimited by a certain String.
- *
- * @param strs String array to convert.
- * @param delimiter String to use as delimiter.
- * @return Delimited String.
- */
- public static String stringArrayToDelimited(String[] strs, String delimiter) {
- if ((strs == null) || (strs.length == 0)) return "";
- if (strs.length == 1) return strs[0];
- StringBuffer sb = new StringBuffer();
- for (int i = 0; i < strs.length - 1; i++) {
- sb.append(strs[i]);
- sb.append(delimiter);
- }
- sb.append(strs[strs.length - 1]);
- return sb.toString();
- }
-
- /**
- * Takes a delimited string, splits it and returns
- *
- * @param names a <code>String</code> value
- * @return a <code>String[]</code> value
- */
- public static String[] delimToStringArray(String names, String delimiter) {
- if (names == null) return null;
- return names.split(delimiter);
- }
-
- /**
- * Open a http/pdf/ps viewer for the given link string.
- */
- public static void openExternalViewer(MetaData metaData, String link, String fieldName
- ) throws IOException {
-
- if (fieldName.equals("ps") || fieldName.equals("pdf")) {
-
- // Find the default directory for this field type:
- String dir = metaData.getFileDirectory(fieldName);
-
- File file = expandFilename(link, dir);
-
- // Check that the file exists:
- if ((file == null) || !file.exists()) {
- throw new IOException(
- Globals.lang("File not found") + " (" + fieldName + "): '" + link + "'.");
- }
- link = file.getCanonicalPath();
-
- // Use the correct viewer even if pdf and ps are mixed up:
- String[] split = file.getName().split("\\.");
- if (split.length >= 2) {
- if (split[split.length - 1].equalsIgnoreCase("pdf"))
- fieldName = "pdf";
- else if (split[split.length - 1].equalsIgnoreCase("ps") ||
- (split.length >= 3 && split[split.length - 2].equalsIgnoreCase("ps")))
- fieldName = "ps";
- }
- } else if (fieldName.equals("doi")) {
- fieldName = "url";
- // Check to see if link field already contains a well formated URL
- if (!link.startsWith("http://")) {
- link = Globals.DOI_LOOKUP_PREFIX + link;
- }
- } else if (fieldName.equals("citeseerurl")) {
- fieldName = "url";
-
- String canonicalLink = CiteSeerFetcher.generateCanonicalURL(link);
- if (canonicalLink != null)
- link = canonicalLink;
- }
-
- String cmdArray[] = new String[2];
- if (fieldName.equals("url")) { // html
- try {
-
- // First check if the url is enclosed in \\url{}. If so, remove
- // the wrapper.
- if (link.startsWith("\\url{") && link.endsWith("}")) link = link
- .substring(5, link.length() - 1);
-
- link = sanitizeUrl(link);
-
- if (Globals.ON_MAC) {
- String[] cmd = {"/usr/bin/open", "-a",
- Globals.prefs.get("htmlviewer"), link};
- Process child = Runtime.getRuntime().exec(cmd);
- } else if (Globals.ON_WIN) {
- openFileOnWindows(link, false);
- /*cmdArray[0] = Globals.prefs.get("htmlviewer");
- cmdArray[1] = link;
- Process child = Runtime.getRuntime().exec(
- cmdArray[0] + " " + cmdArray[1]);
- */
- } else {
- cmdArray[0] = Globals.prefs.get("htmlviewer");
- cmdArray[1] = link;
- Process child = Runtime.getRuntime().exec(cmdArray);
- }
-
- } catch (IOException e) {
- System.err.println("An error occured on the command: "
- + Globals.prefs.get("htmlviewer") + " " + link);
- } catch (URISyntaxException e2) {
- e2.printStackTrace();
- }
- } else if (fieldName.equals("ps")) {
- try {
- if (Globals.ON_MAC) {
- String[] cmd = {"/usr/bin/open", "-a",
- Globals.prefs.get("psviewer"), link};
- Process child = Runtime.getRuntime().exec(cmd);
- } else if (Globals.ON_WIN) {
- openFileOnWindows(link, true);
- /*
- cmdArray[0] = Globals.prefs.get("psviewer");
- cmdArray[1] = link;
- Process child = Runtime.getRuntime().exec(
- cmdArray[0] + " " + cmdArray[1]);
- */
- } else {
- cmdArray[0] = Globals.prefs.get("psviewer");
- cmdArray[1] = link;
- Process child = Runtime.getRuntime().exec(cmdArray);
- }
- } catch (IOException e) {
- System.err.println("An error occured on the command: "
- + Globals.prefs.get("psviewer") + " " + link);
- }
- } else if (fieldName.equals("pdf")) {
- try {
- if (Globals.ON_MAC) {
- String[] cmd = {"/usr/bin/open", "-a",
- Globals.prefs.get("pdfviewer"), link};
- Process child = Runtime.getRuntime().exec(cmd);
- } else if (Globals.ON_WIN) {
- openFileOnWindows(link, true);
- /*
- String[] spl = link.split("\\\\");
- StringBuffer sb = new StringBuffer();
- for (int i = 0; i < spl.length; i++) {
- if (i > 0) sb.append("\\");
- if (spl[i].indexOf(" ") >= 0) spl[i] = "\"" + spl[i]
- + "\"";
- sb.append(spl[i]);
-
- }
- //pr(sb.toString());
- link = sb.toString();
-
- String cmd = "cmd.exe /c start " + link;
-
- Process child = Runtime.getRuntime().exec(cmd);
- */
- } else {
- cmdArray[0] = Globals.prefs.get("pdfviewer");
- cmdArray[1] = link;
- //Process child = Runtime.getRuntime().exec(cmdArray[0]+"
- // "+cmdArray[1]);
- Process child = Runtime.getRuntime().exec(cmdArray);
- }
- } catch (IOException e) {
- e.printStackTrace();
- System.err.println("An error occured on the command: "
- + Globals.prefs.get("pdfviewer") + " #" + link);
- System.err.println(e.getMessage());
- }
- } else {
- System.err
- .println("Message: currently only PDF, PS and HTML files can be opened by double clicking");
- //ignore
- }
- }
-
-
- /**
- * Opens a file on a Windows system, using its default viewer.
- * @param link The file name.
- * @param localFile true if it is a local file, not an URL.
- * @throws IOException
- */
- public static void openFileOnWindows(String link, boolean localFile) throws IOException {
- /*if (localFile) {
- String[] spl = link.split("\\\\");
- StringBuffer sb = new StringBuffer();
- for (int i = 0; i < spl.length; i++) {
- if (i > 0) sb.append("\\");
- if (spl[i].indexOf(" ") >= 0) spl[i] = "\"" + spl[i]
- + "\"";
- sb.append(spl[i]);
- }
- link = sb.toString();
- }*/
- link = link.replaceAll("&", "\"&\"").replaceAll(" ", "\" \"");
- String cmd = "cmd.exe /c start " + link;
- Process child = Runtime.getRuntime().exec(cmd);
- }
-
- /**
- * Open an external file, attempting to use the correct viewer for it.
- * @param metaData The MetaData for the database this file belongs to.
- * @param link The file name.
- */
- public static void openExternalFileAnyFormat(MetaData metaData, String link)
- throws IOException {
+public class Util {
+ // A static Object for date formatting. Please do not create the object
+ // here,
+ // because there are some references from the Globals class.....
+ private static SimpleDateFormat dateFormatter = null;
+
+ // Colors are defined here.
+ public static Color fieldsCol = new Color(180, 180, 200);
+
+ // Integer values for indicating result of duplicate check (for entries):
+ final static int TYPE_MISMATCH = -1, NOT_EQUAL = 0, EQUAL = 1, EMPTY_IN_ONE = 2,
+ EMPTY_IN_TWO = 3;
+
+ final static NumberFormat idFormat;
+
+ static {
+ idFormat = NumberFormat.getInstance();
+ idFormat.setMinimumIntegerDigits(8);
+ idFormat.setGroupingUsed(false);
+ }
+
+ public static void bool(boolean b) {
+ if (b)
+ System.out.println("true");
+ else
+ System.out.println("false");
+ }
+
+ public static void pr(String s) {
+ System.out.println(s);
+ }
+
+ public static void pr_(String s) {
+ System.out.print(s);
+ }
+
+ public static String nCase(String s) {
+ // Make first character of String uppercase, and the
+ // rest lowercase.
+ if (s.length() > 1)
+ return s.substring(0, 1).toUpperCase() + s.substring(1, s.length()).toLowerCase();
+ else
+ return s.toUpperCase();
+
+ }
+
+ public static String checkName(String s) {
+ // Append '.bib' to the string unless it ends with that.
+ if (s.length() < 4 || !s.substring(s.length() - 4).equalsIgnoreCase(".bib")) {
+ return s + ".bib";
+ }
+ return s;
+ }
+
+ private static int idCounter = 0;
+
+ public synchronized static String createNeutralId() {
+ return idFormat.format(idCounter++);
+ // return String.valueOf(idCounter++);
+ }
+
+ /**
+ * This method sets the location of a Dialog such that it is centered with
+ * regard to another window, but not outside the screen on the left and the
+ * top.
+ */
+ public static void placeDialog(java.awt.Dialog diag, java.awt.Container win) {
+ Dimension ds = diag.getSize(), df = win.getSize();
+ Point pf = win.getLocation();
+ diag.setLocation(new Point(Math.max(0, pf.x + (df.width - ds.width) / 2), Math.max(0, pf.y
+ + (df.height - ds.height) / 2)));
+
+ }
+
+ /**
+ * This method translates a field or string from Bibtex notation, with
+ * possibly text contained in " " or { }, and string references,
+ * concatenated by '#' characters, into Bibkeeper notation, where string
+ * references are enclosed in a pair of '#' characters.
+ */
+ public static String parseField(String content) {
+ if (content.length() == 0)
+ return content;
+ String toSet = "";
+ boolean string;
+ // Keeps track of whether the next item is
+ // a reference to a string, or normal content. First we must
+ // check which we begin with. We simply check if we can find
+ // a '#' before either '"' or '{'.
+ int hash = content.indexOf('#'), wr1 = content.indexOf('"'), wr2 = content.indexOf('{'), end = content
+ .length();
+ if (hash == -1)
+ hash = end;
+ if (wr1 == -1)
+ wr1 = end;
+ if (wr2 == -1)
+ wr2 = end;
+ string = ((wr1 == end) && (wr2 == end)) || (hash < Math.min(wr1, wr2));
+
+ // System.out.println("FileLoader: "+content+" "+string+" "+hash+"
+ // "+wr1+" "+wr2);
+ StringTokenizer tok = new StringTokenizer(content, "#", true);
+ // 'tok' splits at the '#' sign, and keeps delimiters
+
+ while (tok.hasMoreTokens()) {
+ String str = tok.nextToken();
+ if (str.equals("#"))
+ string = !string;
+ else {
+ if (string) {
+ // This part should normally be a string, but if it's
+ // a pure number, it is not.
+ String s = shaveString(str);
+ try {
+ Integer.parseInt(s);
+ // If there's no exception, it's a number.
+ toSet = toSet + s;
+ } catch (NumberFormatException ex) {
+ toSet = toSet + "#" + shaveString(str) + "#";
+ }
+
+ } else
+ toSet = toSet + shaveString(str);
+ }
+ }
+ return toSet;
+ }
+
+ public static String shaveString(String s) {
+ // returns the string, after shaving off whitespace at the beginning
+ // and end, and removing (at most) one pair of braces or " surrounding
+ // it.
+ if (s == null)
+ return null;
+ char ch, ch2;
+ int beg = 0, end = s.length();
+ // We start out assuming nothing will be removed.
+ boolean begok = false, endok = false;
+ while (!begok) {
+ if (beg < s.length()) {
+ ch = s.charAt(beg);
+ if (Character.isWhitespace(ch))
+ beg++;
+ else
+ begok = true;
+ } else
+ begok = true;
+
+ }
+ while (!endok) {
+ if (end > beg + 1) {
+ ch = s.charAt(end - 1);
+ if (Character.isWhitespace(ch))
+ end--;
+ else
+ endok = true;
+ } else
+ endok = true;
+ }
+
+ if (end > beg + 1) {
+ ch = s.charAt(beg);
+ ch2 = s.charAt(end - 1);
+ if (((ch == '{') && (ch2 == '}')) || ((ch == '"') && (ch2 == '"'))) {
+ beg++;
+ end--;
+ }
+ }
+ s = s.substring(beg, end);
+ // Util.pr(s);
+ return s;
+ }
+
+ /**
+ * This method returns a String similar to the one passed in, except that it
+ * is molded into a form that is acceptable for bibtex.
+ *
+ * Watch-out that the returned string might be of length 0 afterwards.
+ *
+ * @param key
+ * mayBeNull
+ */
+ public static String checkLegalKey(String key) {
+ if (key == null)
+ return null;
+ StringBuffer newKey = new StringBuffer();
+ for (int i = 0; i < key.length(); i++) {
+ char c = key.charAt(i);
+ if (!Character.isWhitespace(c) && (c != '#') && (c != '{') && (c != '\\') && (c != '"')
+ && (c != '}') && (c != '~') && (c != ',') && (c != '^'))
+ newKey.append(c);
+ }
+
+ // Replace non-english characters like umlauts etc. with a sensible
+ // letter or letter combination that bibtex can accept.
+ String newKeyS = replaceSpecialCharacters(newKey.toString());
+
+ return newKeyS;
+ }
+
+ /**
+ * Replace non-english characters like umlauts etc. with a sensible letter
+ * or letter combination that bibtex can accept. The basis for replacement
+ * is the HashMap GLobals.UNICODE_CHARS.
+ */
+ public static String replaceSpecialCharacters(String s) {
+ for (Iterator i = Globals.UNICODE_CHARS.keySet().iterator(); i.hasNext();) {
+ String chr = (String) i.next(), replacer = (String) Globals.UNICODE_CHARS.get(chr);
+ // pr(chr+" "+replacer);
+ s = s.replaceAll(chr, replacer);
+ }
+ return s;
+ }
+
+ static public String _wrap2(String in, int wrapAmount) {
+ // The following line cuts out all whitespace and replaces them with
+ // single
+ // spaces:
+ // in = in.replaceAll("[ ]+"," ").replaceAll("[\\t]+"," ");
+ // StringBuffer out = new StringBuffer(in);
+ StringBuffer out = new StringBuffer(in.replaceAll("[ \\t\\r]+", " "));
+
+ int p = in.length() - wrapAmount;
+ int lastInserted = -1;
+ while (p > 0) {
+ p = out.lastIndexOf(" ", p);
+ if (p <= 0 || p <= 20)
+ break;
+ int lbreak = out.indexOf("\n", p);
+ System.out.println(lbreak + " " + lastInserted);
+ if ((lbreak > p) && ((lastInserted >= 0) && (lbreak < lastInserted))) {
+ p = lbreak - wrapAmount;
+ } else {
+ out.insert(p, "\n\t");
+ lastInserted = p;
+ p -= wrapAmount;
+ }
+ }
+ return out.toString();
+ }
+
+ static public String wrap2(String in, int wrapAmount) {
+ return net.sf.jabref.imports.FieldContentParser.wrap(in, wrapAmount);
+ }
+
+ static public String __wrap2(String in, int wrapAmount) {
+ // The following line cuts out all whitespace except line breaks, and
+ // replaces
+ // with single spaces. Line breaks are padded with a tab character:
+ StringBuffer out = new StringBuffer(in.replaceAll("[ \\t\\r]+", " "));
+
+ int p = 0;
+ // int lastInserted = -1;
+ while (p < out.length()) {
+ int q = out.indexOf(" ", p + wrapAmount);
+ if ((q < 0) || (q >= out.length()))
+ break;
+ int lbreak = out.indexOf("\n", p);
+ // System.out.println(lbreak);
+ if ((lbreak > p) && (lbreak < q)) {
+ p = lbreak + 1;
+ int piv = lbreak + 1;
+ if ((out.length() > piv) && !(out.charAt(piv) == '\t'))
+ out.insert(piv, "\n\t");
+
+ } else {
+ // System.out.println(q+" "+out.length());
+ out.deleteCharAt(q);
+ out.insert(q, "\n\t");
+ p = q + 1;
+ }
+ }
+ return out.toString();// .replaceAll("\n", "\n\t");
+ }
+
+ public static HashSet findDeliminatedWordsInField(BibtexDatabase db, String field,
+ String deliminator) {
+ HashSet res = new HashSet();
+ Iterator i = db.getKeySet().iterator();
+ while (i.hasNext()) {
+ BibtexEntry be = db.getEntryById(i.next().toString());
+ Object o = be.getField(field);
+ if (o != null) {
+ String fieldValue = o.toString().trim();
+ StringTokenizer tok = new StringTokenizer(fieldValue, deliminator);
+ while (tok.hasMoreTokens())
+ res.add(tok.nextToken().trim());
+ }
+ }
+ return res;
+ }
+
+ /**
+ * Returns a HashMap containing all words used in the database in the given
+ * field type. Characters in
+ *
+ * @param remove
+ * are not included.
+ * @param db
+ * a <code>BibtexDatabase</code> value
+ * @param field
+ * a <code>String</code> value
+ * @param remove
+ * a <code>String</code> value
+ * @return a <code>HashSet</code> value
+ */
+ public static HashSet findAllWordsInField(BibtexDatabase db, String field, String remove) {
+ HashSet res = new HashSet();
+ StringTokenizer tok;
+ Iterator i = db.getKeySet().iterator();
+ while (i.hasNext()) {
+ BibtexEntry be = db.getEntryById(i.next().toString());
+ Object o = be.getField(field);
+ if (o != null) {
+ tok = new StringTokenizer(o.toString(), remove, false);
+ while (tok.hasMoreTokens())
+ res.add(tok.nextToken());
+ }
+ }
+ return res;
+ }
+
+ /**
+ * Takes a String array and returns a string with the array's elements
+ * delimited by a certain String.
+ *
+ * @param strs
+ * String array to convert.
+ * @param delimiter
+ * String to use as delimiter.
+ * @return Delimited String.
+ */
+ public static String stringArrayToDelimited(String[] strs, String delimiter) {
+ if ((strs == null) || (strs.length == 0))
+ return "";
+ if (strs.length == 1)
+ return strs[0];
+ StringBuffer sb = new StringBuffer();
+ for (int i = 0; i < strs.length - 1; i++) {
+ sb.append(strs[i]);
+ sb.append(delimiter);
+ }
+ sb.append(strs[strs.length - 1]);
+ return sb.toString();
+ }
+
+ /**
+ * Takes a delimited string, splits it and returns
+ *
+ * @param names
+ * a <code>String</code> value
+ * @return a <code>String[]</code> value
+ */
+ public static String[] delimToStringArray(String names, String delimiter) {
+ if (names == null)
+ return null;
+ return names.split(delimiter);
+ }
+
+ /**
+ * Open a http/pdf/ps viewer for the given link string.
+ */
+ public static void openExternalViewer(MetaData metaData, String link, String fieldName)
+ throws IOException {
+
+ if (fieldName.equals("ps") || fieldName.equals("pdf")) {
+
+ // Find the default directory for this field type:
+ String dir = metaData.getFileDirectory(fieldName);
+
+ File file = expandFilename(link, new String[]{dir, "."});
+
+ // Check that the file exists:
+ if ((file == null) || !file.exists()) {
+ throw new IOException(Globals.lang("File not found") + " (" + fieldName + "): '"
+ + link + "'.");
+ }
+ link = file.getCanonicalPath();
+
+ // Use the correct viewer even if pdf and ps are mixed up:
+ String[] split = file.getName().split("\\.");
+ if (split.length >= 2) {
+ if (split[split.length - 1].equalsIgnoreCase("pdf"))
+ fieldName = "pdf";
+ else if (split[split.length - 1].equalsIgnoreCase("ps")
+ || (split.length >= 3 && split[split.length - 2].equalsIgnoreCase("ps")))
+ fieldName = "ps";
+ }
+ } else if (fieldName.equals("doi")) {
+ fieldName = "url";
+ // Check to see if link field already contains a well formated URL
+ if (!link.startsWith("http://")) {
+ link = Globals.DOI_LOOKUP_PREFIX + link;
+ }
+ } else if (fieldName.equals("citeseerurl")) {
+ fieldName = "url";
+
+ String canonicalLink = CiteSeerFetcher.generateCanonicalURL(link);
+ if (canonicalLink != null)
+ link = canonicalLink;
+ }
+
+ String cmdArray[] = new String[2];
+ if (fieldName.equals("url")) { // html
+ try {
+
+ // First check if the url is enclosed in \\url{}. If so, remove
+ // the wrapper.
+ if (link.startsWith("\\url{") && link.endsWith("}"))
+ link = link.substring(5, link.length() - 1);
+
+ link = sanitizeUrl(link);
+
+ if (Globals.ON_MAC) {
+ String[] cmd = { "/usr/bin/open", "-a", Globals.prefs.get("htmlviewer"), link };
+ Process child = Runtime.getRuntime().exec(cmd);
+ } else if (Globals.ON_WIN) {
+ openFileOnWindows(link, false);
+ /*
+ * cmdArray[0] = Globals.prefs.get("htmlviewer");
+ * cmdArray[1] = link; Process child =
+ * Runtime.getRuntime().exec( cmdArray[0] + " " +
+ * cmdArray[1]);
+ */
+ } else {
+ cmdArray[0] = Globals.prefs.get("htmlviewer");
+ cmdArray[1] = link;
+ Process child = Runtime.getRuntime().exec(cmdArray);
+ }
+
+ } catch (IOException e) {
+ System.err.println("An error occured on the command: "
+ + Globals.prefs.get("htmlviewer") + " " + link);
+ } catch (URISyntaxException e2) {
+ e2.printStackTrace();
+ }
+ } else if (fieldName.equals("ps")) {
+ try {
+ if (Globals.ON_MAC) {
+ String[] cmd = { "/usr/bin/open", "-a", Globals.prefs.get("psviewer"), link };
+ Process child = Runtime.getRuntime().exec(cmd);
+ } else if (Globals.ON_WIN) {
+ openFileOnWindows(link, true);
+ /*
+ * cmdArray[0] = Globals.prefs.get("psviewer"); cmdArray[1] =
+ * link; Process child = Runtime.getRuntime().exec(
+ * cmdArray[0] + " " + cmdArray[1]);
+ */
+ } else {
+ cmdArray[0] = Globals.prefs.get("psviewer");
+ cmdArray[1] = link;
+ Process child = Runtime.getRuntime().exec(cmdArray);
+ }
+ } catch (IOException e) {
+ System.err.println("An error occured on the command: "
+ + Globals.prefs.get("psviewer") + " " + link);
+ }
+ } else if (fieldName.equals("pdf")) {
+ try {
+ if (Globals.ON_MAC) {
+ String[] cmd = { "/usr/bin/open", "-a", Globals.prefs.get("pdfviewer"), link };
+ Process child = Runtime.getRuntime().exec(cmd);
+ } else if (Globals.ON_WIN) {
+ openFileOnWindows(link, true);
+ /*
+ * String[] spl = link.split("\\\\"); StringBuffer sb = new
+ * StringBuffer(); for (int i = 0; i < spl.length; i++) { if
+ * (i > 0) sb.append("\\"); if (spl[i].indexOf(" ") >= 0)
+ * spl[i] = "\"" + spl[i] + "\""; sb.append(spl[i]);
+ * } //pr(sb.toString()); link = sb.toString();
+ *
+ * String cmd = "cmd.exe /c start " + link;
+ *
+ * Process child = Runtime.getRuntime().exec(cmd);
+ */
+ } else {
+ cmdArray[0] = Globals.prefs.get("pdfviewer");
+ cmdArray[1] = link;
+ // Process child = Runtime.getRuntime().exec(cmdArray[0]+"
+ // "+cmdArray[1]);
+ Process child = Runtime.getRuntime().exec(cmdArray);
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ System.err.println("An error occured on the command: "
+ + Globals.prefs.get("pdfviewer") + " #" + link);
+ System.err.println(e.getMessage());
+ }
+ } else {
+ System.err
+ .println("Message: currently only PDF, PS and HTML files can be opened by double clicking");
+ // ignore
+ }
+ }
+
+ /**
+ * Opens a file on a Windows system, using its default viewer.
+ *
+ * @param link
+ * The file name.
+ * @param localFile
+ * true if it is a local file, not an URL.
+ * @throws IOException
+ */
+ public static void openFileOnWindows(String link, boolean localFile) throws IOException {
+ /*
+ * if (localFile) { String[] spl = link.split("\\\\"); StringBuffer sb =
+ * new StringBuffer(); for (int i = 0; i < spl.length; i++) { if (i > 0)
+ * sb.append("\\"); if (spl[i].indexOf(" ") >= 0) spl[i] = "\"" + spl[i] +
+ * "\""; sb.append(spl[i]); } link = sb.toString(); }
+ */
+ link = link.replaceAll("&", "\"&\"").replaceAll(" ", "\" \"");
+
+ // Bug fix for:
+ // http://sourceforge.net/tracker/index.php?func=detail&aid=1489454&group_id=92314&atid=600306
+ String cmd;
+ if (Globals.osName.startsWith("Windows 9")) {
+ cmd = "command.com /c start " + link;
+ } else {
+ cmd = "cmd.exe /c start " + link;
+ }
+ Process child = Runtime.getRuntime().exec(cmd);
+ }
+
+ /**
+ * Open an external file, attempting to use the correct viewer for it.
+ *
+ * @param metaData
+ * The MetaData for the database this file belongs to.
+ * @param link
+ * The file name.
+ */
+ public static void openExternalFileAnyFormat(MetaData metaData, String link) throws IOException {
+
+ // For other platforms we'll try to find the file type:
+ File file = new File(link);
+
+ // We try to check the extension for the file:
+ String name = file.getName();
+ int pos = name.indexOf('.');
+ String extension = ((pos >= 0) && (pos < name.length() - 1)) ? name.substring(pos + 1)
+ .trim().toLowerCase() : null;
+
+ /*
+ * if ((extension == null) || (extension.length() == 0)) { // No
+ * extension. What to do? throw new IOException(Globals.lang("No file
+ * extension. Could not find viewer for file.")); }
+ */
+
+ // Now we know the extension, check if it is one we know about:
+ ExternalFileType fileType = Globals.prefs.getExternalFileType(extension);
+
+ // Find the default directory for this field type, if any:
+ String dir = metaData.getFileDirectory(extension);
+ if (dir != null) {
+ File tmp = expandFilename(link, new String[]{dir, "."});
+ if (tmp != null)
+ file = tmp;
+ }
+
+ // Check if we have arrived at an existing file:
+ if (file.exists() && (fileType != null)) {
+ // Open the file:
+ try {
+ if (Globals.ON_MAC) {
+ String[] cmd = { "/usr/bin/open", "-a", fileType.getOpenWith(), file.getPath() };
+ Runtime.getRuntime().exec(cmd);
+ } else if (Globals.ON_WIN) {
+ openFileOnWindows(file.getPath(), true);
+ } else {
+ String[] cmdArray = new String[] { fileType.getOpenWith(), file.getPath() };
+ Runtime.getRuntime().exec(cmdArray);
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ System.err.println("An error occured on the command: " + fileType.getOpenWith()
+ + " #" + link);
+ System.err.println(e.getMessage());
+ }
+
+ } else {
+ // No file matched the name, or we didn't know the file type.
+ // Perhaps it is an URL thing.
+
+ // First check if it is enclosed in \\url{}. If so, remove
+ // the wrapper.
+ if (link.startsWith("\\url{") && link.endsWith("}"))
+ link = link.substring(5, link.length() - 1);
+
+ if (link.startsWith("doi:"))
+ link = Globals.DOI_LOOKUP_PREFIX + link;
+
+ try {
+ link = sanitizeUrl(link);
+ } catch (URISyntaxException ex) {
+ ex.printStackTrace();
+ }
+
+ if (Globals.ON_MAC) {
+ String[] cmd = { "/usr/bin/open", "-a", Globals.prefs.get("htmlviewer"), link };
+ Runtime.getRuntime().exec(cmd);
+ } else if (Globals.ON_WIN) {
+ openFileOnWindows(link, false);
+ } else {
+ String[] cmdArray = new String[] { Globals.prefs.get("htmlviewer"), link };
+ Runtime.getRuntime().exec(cmdArray);
+ }
+
+ }
+ }
+
+ /**
+ * Make sure an URL is "portable", in that it doesn't contain bad characters
+ * that break the open command in some OSes.
+ *
+ * @param link
+ * The URL to sanitize.
+ * @return Sanitized URL
+ */
+ public static String sanitizeUrl(String link) throws URISyntaxException {
+ String scheme = "http";
+ String ssp;
+ if (link.indexOf("//") > 0)
+ ssp = "//" + link.substring(2 + link.indexOf("//"));
+ else
+ ssp = "//" + link;
+
+ // The following is an ugly hack to fix the problem where a %20 in the
+ // original string (correct encoding of a space) gets returned as %2520
+ // because the URI constructor doesn't recognize that the % is the start of
+ // a sequence. The problem is that other such sequences will meet the same fate.
+ // If we need to take care of all these up front, we might as well not use URI
+ // at all.
+ // Another option is to do two times, hiding the %xx sequences in one of them,
+ // and see if one of the URLs looks good...
+ ssp = ssp.replaceAll("%20", " ");
- // For other platforms we'll try to find the file type:
- File file = new File(link);
-
- // We try to check the extension for the file:
- String name = file.getName();
- int pos = name.indexOf('.');
- String extension = ((pos >= 0) && (pos < name.length()-1)) ?
- name.substring(pos+1).trim().toLowerCase() : null;
-
- /*if ((extension == null) || (extension.length() == 0)) {
- // No extension. What to do?
- throw new IOException(Globals.lang("No file extension. Could not find viewer for file."));
- } */
-
- // Now we know the extension, check if it is one we know about:
- ExternalFileType fileType = Globals.prefs.getExternalFileType(extension);
-
-
- // Find the default directory for this field type, if any:
- String dir = metaData.getFileDirectory(extension);
- if (dir != null) {
- File tmp = expandFilename(link, dir);
- if (tmp != null)
- file = tmp;
- }
-
- // Check if we have arrived at an existing file:
- if (file.exists() && (fileType != null)) {
- // Open the file:
- try {
- if (Globals.ON_MAC) {
- String[] cmd = {"/usr/bin/open", "-a",
- fileType.getOpenWith(), file.getPath()};
- Runtime.getRuntime().exec(cmd);
- } else if (Globals.ON_WIN) {
- openFileOnWindows(file.getPath(), true);
- } else {
- String[] cmdArray = new String[] {
- fileType.getOpenWith(),
- file.getPath()
- };
- Runtime.getRuntime().exec(cmdArray);
- }
- } catch (IOException e) {
- e.printStackTrace();
- System.err.println("An error occured on the command: "
- + fileType.getOpenWith() + " #" + link);
- System.err.println(e.getMessage());
- }
-
- }
- else {
- // No file matched the name, or we didn't know the file type.
- // Perhaps it is an URL thing.
-
- // First check if it is enclosed in \\url{}. If so, remove
- // the wrapper.
- if (link.startsWith("\\url{") && link.endsWith("}")) link = link
- .substring(5, link.length() - 1);
-
- if (link.startsWith("doi:"))
- link = Globals.DOI_LOOKUP_PREFIX+link;
-
- try {
- link = sanitizeUrl(link);
- } catch (URISyntaxException ex) {
- ex.printStackTrace();
- }
-
- if (Globals.ON_MAC) {
- String[] cmd = {"/usr/bin/open", "-a",
- Globals.prefs.get("htmlviewer"), link};
- Runtime.getRuntime().exec(cmd);
- } else if (Globals.ON_WIN) {
- openFileOnWindows(link, false);
- } else {
- String[] cmdArray = new String[] {
- Globals.prefs.get("htmlviewer"),
- link
- };
- Runtime.getRuntime().exec(cmdArray);
- }
-
- }
- }
-
- /**
- * Make sure an URL is "portable", in that it doesn't contain bad characters
- * that break the open command in some OSes.
- * @param link The URL to sanitize.
- * @return Sanitized URL
- */
- private static String sanitizeUrl(String link) throws URISyntaxException {
- String scheme = "http";
- String ssp;
- if (link.indexOf("//") > 0)
- ssp = "//" + link.substring(2+link.indexOf("//"));
- else
- ssp = "//" + link;
URI uri = new URI(scheme, ssp, null);
- return uri.toASCIIString();
- }
-
- /**
- * Searches the given directory and subdirectories for a pdf file with name
- * as given + ".pdf"
- */
- public static String findPdf(String key, String extension, String directory, OpenFileFilter off) {
- //String filename = key + "."+extension;
-
- /* Simon Fischer's patch for replacing a regexp in keys before converting to filename:
-
- String regex = Globals.prefs.get("basenamePatternRegex");
- if ((regex != null) && (regex.trim().length() > 0)) {
- String replacement = Globals.prefs.get("basenamePatternReplacement");
- key = key.replaceAll(regex, replacement);
- }
- */
- if (!directory.endsWith(System.getProperty("file.separator"))) directory += System
- .getProperty("file.separator");
- String found = findInDir(key, directory, off);
- if (found != null) return found.substring(directory.length());
- else return null;
- }
-
-
- /**
- * Converts a relative filename to an absolute one, if necessary. Returns
- * null if the file does not exist.
- */
- public static File expandFilename(String name, String dir) {
- //System.out.println("expandFilename: name="+name+"\t dir="+dir);
- File file = null;
- if(name==null || name.length()==0)
- return null;
- else
- {
- file = new File(name);
- }
-
- if(file!=null){
- if (!file.exists() && (dir != null)) {
- if (dir.endsWith(System.getProperty("file.separator"))) name = dir
- + name;
- else name = dir + System.getProperty("file.separator") + name;
-
- //System.out.println("expanded to: "+name);
- //if (name.startsWith("ftp"))
-
- file = new File(name);
- if (file.exists()) return file;
- // Ok, try to fix / and \ problems:
- if (Globals.ON_WIN){
- // workaround for catching Java bug in regexp replacer
- // and, why, why, why ... I don't get it - wegner 2006/01/22
- try{
- name = name.replaceAll("/", "\\");
- }
- catch(java.lang.StringIndexOutOfBoundsException exc){
- System.err.println("An internal Java error was caused by the entry "+"\""+name+"\"");
- }
- }
- else name = name.replaceAll("\\\\", "/");
- //System.out.println("expandFilename: "+name);
- file = new File(name);
- if (!file.exists()) file = null;
- }}
- return file;
- }
-
- private static String findInDir(String key, String dir, OpenFileFilter off) {
- File f = new File(dir);
- File[] all = f.listFiles();
- if (all == null)
- return null; // An error occured. We may not have
- // permission to list the files.
-
- int numFiles = all.length;
-
- for (int i = 0; i < numFiles; i++) {
- File curFile = all[i];
-
- if (curFile.isFile()) {
- String name = curFile.getName();
- if (name.startsWith(key + ".") &&
- off.accept(name))
- return curFile.getPath();
-
- } else if (curFile.isDirectory()) {
- String found = findInDir(key, curFile.getPath(), off);
- if (found != null)
- return found;
- }
- }
- return null;
- }
-
- /**
- * Checks if the two entries represent the same publication.
+ return uri.toASCIIString();
+ }
+
+ /**
+ * Searches the given directory and subdirectories for a pdf file with name
+ * as given + ".pdf"
+ */
+ public static String findPdf(String key, String extension, String directory, OpenFileFilter off) {
+ // String filename = key + "."+extension;
+
+ /*
+ * Simon Fischer's patch for replacing a regexp in keys before
+ * converting to filename:
+ *
+ * String regex = Globals.prefs.get("basenamePatternRegex"); if ((regex !=
+ * null) && (regex.trim().length() > 0)) { String replacement =
+ * Globals.prefs.get("basenamePatternReplacement"); key =
+ * key.replaceAll(regex, replacement); }
+ */
+ if (!directory.endsWith(System.getProperty("file.separator")))
+ directory += System.getProperty("file.separator");
+ String found = findInDir(key, directory, off);
+ if (found != null)
+ return found.substring(directory.length());
+ else
+ return null;
+ }
+
+ /**
+ * New version of findPdf that uses findFiles.
+ *
+ * The search pattern will be read from the preferences.
+ *
+ * The [extension]-tags in this pattern will be replace by the given extension parameter.
+ *
+ */
+ public static String findPdf(BibtexEntry entry, String extension, String directory) {
+ return findPdf(entry, extension, new String[]{directory});
+ }
+
+ /**
+ * Convenience method for findPDF. Can search multiple PDF directories.
+ */
+ public static String findPdf(BibtexEntry entry, String extension, String[] directories) {
+
+ String regularExpression;
+ if (Globals.prefs.getBoolean(JabRefPreferences.USE_REG_EXP_SEARCH_KEY)){
+ regularExpression = Globals.prefs.get(JabRefPreferences.REG_EXP_SEARCH_EXPRESSION_KEY);
+ } else {
+ regularExpression = Globals.prefs.get(JabRefPreferences.DEFAULT_REG_EXP_SEARCH_EXPRESSION_KEY);
+ }
+ regularExpression = regularExpression.replaceAll("\\[extension\\]", extension);
+
+ return findFile(entry, null, directories, regularExpression, true);
+ }
+
+
+ /**
+ * Searches the given directory and file name pattern for a file for the
+ * bibtexentry.
+ *
+ * Used to fix:
+ *
+ * http://sourceforge.net/tracker/index.php?func=detail&aid=1503410&group_id=92314&atid=600309
+ *
+ * Requirements:
+ *
+ * - Be able to find the associated PDF in a set of given directories.
+ *
+ * - Be able to return a relative path or absolute path.
+ *
+ * - Be fast.
+ *
+ * - Allow for flexible naming schemes in the PDFs.
+ *
+ * Syntax scheme for file:
+ * <ul>
+ * <li>* Any subDir</li>
+ * <li>** Any subDir (recursiv)</li>
+ * <li>[key] Key from bibtex file and database</li>
+ * <li>.* Anything else is taken to be a Regular expression.</li>
+ * </ul>
+ *
+ * @param entry
+ * non-null
+ * @param database
+ * non-null
+ * @param directory
+ * A set of root directories to start the search from.
+ * Paths are returned relative to these directories if
+ * relative is set to true. These directories will not
+ * be expanded or anything. Use the file attribute for
+ * this.
+ * @param file
+ * non-null
+ *
+ * @param relative
+ * whether to return relative file paths or absolute ones
+ *
+ * @return Will return the first file found to match the given criteria or
+ * null if none was found.
+ */
+ public static String findFile(BibtexEntry entry, BibtexDatabase database, String[] directory,
+ String file, boolean relative) {
+
+ for (int i = 0; i < directory.length; i++){
+
+ String result = findFile(entry, database, directory[i], file, relative);
+ if (result != null){
+ return result;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Removes optional square brackets from the string s
+ *
+ * @param s
+ * @return
+ */
+ public static String stripBrackets(String s) {
+ int beginIndex = (s.startsWith("[") ? 1 : 0);
+ int endIndex = (s.endsWith("]") ? s.length() - 1 : s.length());
+ return s.substring(beginIndex, endIndex);
+ }
+
+ public static ArrayList parseMethodsCalls(String calls) throws RuntimeException {
+
+ ArrayList result = new ArrayList();
+
+ char[] c = calls.toCharArray();
+
+ int i = 0;
+
+ while (i < c.length){
+
+ int start = i;
+ if (Character.isJavaIdentifierStart(c[i])){
+ i++;
+ while (i < c.length && (Character.isJavaIdentifierPart(c[i]) || c[i] == '.')){
+ i++;
+ }
+ if (i < c.length && c[i] == '('){
+
+ String method = calls.substring(start, i);
+
+ i++; i++;
+
+ int startParam = i;
+ i++;
+
+ while (i + 1 < c.length && !(c[i] == '"' && c[i+1] == ')')){
+ i++;
+ }
+
+ String param = calls.substring(startParam, i);
+
+ result.add(new String[]{method, param});
+ } else {
+ String method = calls.substring(start, i);
+ result.add(new String[]{method});
+ }
+ }
+ i++;
+ }
+
+ return result;
+ }
+
+
+ /**
+ * Accepts a string like [author:toLowerCase("escapedstring"),toUpperCase], whereas the first
+ * string signifies the bibtex-field to get while the others are the names
+ * of layouters that will be applied.
+ *
+ * @param fieldAndFormat
+ * @param entry
+ * @param database
+ * @return
+ */
+ public static String getFieldAndFormat(String fieldAndFormat, BibtexEntry entry,
+ BibtexDatabase database) {
+
+ fieldAndFormat = stripBrackets(fieldAndFormat);
+
+ int colon = fieldAndFormat.indexOf(':');
+
+ String beforeColon, afterColon;
+ if (colon == -1){
+ beforeColon = fieldAndFormat;
+ afterColon = null;
+ } else {
+ beforeColon = fieldAndFormat.substring(0, colon);
+ afterColon = fieldAndFormat.substring(colon+1);
+ }
+ beforeColon = beforeColon.trim();
+
+ if (beforeColon.length() == 0){
+ return null;
+ }
+
+ String fieldValue = getField(beforeColon, entry, database);
+
+ if (fieldValue == null)
+ return null;
+
+ if (afterColon == null || afterColon.length() == 0)
+ return fieldValue;
+
+ try {
+ LayoutFormatter[] formatters = LayoutEntry.getOptionalLayout(afterColon, "");
+ for (int i = 0; i < formatters.length; i++) {
+ fieldValue = formatters[i].format(fieldValue);
+ }
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+
+ return fieldValue;
+ }
+
+ public static String getField(String field, BibtexEntry bibtex, BibtexDatabase database) {
+
+ if (field.equals("bibtextype"))
+ return bibtex.getType().getName();
+
+ String res = (String) bibtex.getField(field);
+
+ if ((res != null) && (database != null))
+ res = database.resolveForStrings(res);
+
+ return res;
+ }
+
+ /**
+ * Convenience function for absolute search.
*
- * @param one BibtexEntry
- * @param two BibtexEntry
- * @return boolean
- */
- public static boolean isDuplicate(BibtexEntry one, BibtexEntry two,
- float threshold) {
-
- // First check if they are of the same type - a necessary condition:
- if (one.getType() != two.getType()) return false;
-
- // The check if they have the same required fields:
- String[] fields = one.getType().getRequiredFields();
-
- if (fields == null) return false;
-
- float req = compareFieldSet(fields, one, two);
- fields = one.getType().getOptionalFields();
-
- if (fields != null) {
- float opt = compareFieldSet(fields, one, two);
- return (2 * req + opt) / 3 >= threshold;
- } else {
- return (req >= threshold);
- }
- }
+ * Uses findFile(BibtexEntry, BibtexDatabase, (String)null, String, false).
+ */
+ public static String findFile(BibtexEntry entry, BibtexDatabase database, String file){
+ return findFile(entry, database, (String)null, file, false);
+ }
+
+ /**
+ * Internal Version of findFile, which also accepts a current directory to
+ * base the search on.
+ *
+ */
+ public static String findFile(BibtexEntry entry,
+ BibtexDatabase database, String directory, String file, boolean relative) {
+
+ File root;
+ if (directory == null){
+ root = new File(".");
+ } else {
+ root = new File(directory);
+ }
+ if (!root.exists())
+ return null;
+
+ String found = findFile(entry, database, root, file);
+
+ if (directory == null || !relative){
+ return found;
+ }
+
+ if (found != null){
+ try {
+ /**
+ * [ 1601651 ] PDF subdirectory - missing first character
+ *
+ * http://sourceforge.net/tracker/index.php?func=detail&aid=1601651&group_id=92314&atid=600306
+ */
+ return found.substring(root.getCanonicalPath().length());
+ } catch (IOException e) {
+ return null;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * The actual work-horse. Will find absolute filepaths starting from the given directory using the given regular expression string for search.
+ */
+ protected static String findFile(BibtexEntry entry,
+ BibtexDatabase database, File directory, String file) {
+
+ if (file.startsWith("/")){
+ directory = new File(".");
+ file = file.substring(1);
+ }
+
+ // Escape handling...
+ Matcher m = Pattern.compile("([^\\\\])\\\\([^\\\\])").matcher(file);
+ StringBuffer s = new StringBuffer();
+ while (m.find()) {
+ m.appendReplacement(s, m.group(1) + "/" + m.group(2));
+ }
+ m.appendTail(s);
+ file = s.toString();
+ String[] fileParts = file.split("/");
+
+ if (fileParts.length == 0)
+ return null;
+
+ if (fileParts.length > 1){
+
+ for (int i = 0; i < fileParts.length - 1; i++) {
+
+ String dirToProcess = fileParts[i];
+
+ dirToProcess = expandBrackets(dirToProcess, entry, database);
+
+ if (dirToProcess.matches("^.:$")) { // Windows Drive Letter
+ directory = new File(dirToProcess + "/");
+ continue;
+ }
+ if (dirToProcess.equals(".")) { // Stay in current directory
+ continue;
+ }
+ if (dirToProcess.equals("..")) {
+ directory = new File(directory.getParent());
+ continue;
+ }
+ if (dirToProcess.equals("*")) { // Do for all direct subdirs
+
+ File[] subDirs = directory.listFiles();
+ if (subDirs == null)
+ return null; // No permission?
+
+ String restOfFileString = join(fileParts, "/", i + 1, fileParts.length);
+
+ for (int sub = 0; sub < subDirs.length; sub++) {
+ if (subDirs[sub].isDirectory()) {
+ String result = findFile(entry, database,
+ subDirs[sub], restOfFileString);
+ if (result != null)
+ return result;
+ }
+ }
+ return null;
+ }
+ // Do for all direct and indirect subdirs
+ if (dirToProcess.equals("**")) {
+ List toDo = new LinkedList();
+ toDo.add(directory);
+
+ String restOfFileString = join(fileParts, "/", i + 1, fileParts.length);
+
+ // Before checking the subdirs, we first check the current
+ // dir
+ String result = findFile(entry, database, directory, restOfFileString);
+ if (result != null)
+ return result;
+
+ while (!toDo.isEmpty()) {
+
+ // Get all subdirs of each of the elements found in toDo
+ File[] subDirs = ((File) toDo.remove(0)).listFiles();
+ if (subDirs == null) // No permission?
+ continue;
+
+ toDo.addAll(Arrays.asList(subDirs));
+
+ for (int sub = 0; sub < subDirs.length; sub++) {
+ if (!subDirs[sub].isDirectory())
+ continue;
+ result = findFile(entry, database, subDirs[sub], restOfFileString);
+ if (result != null)
+ return result;
+ }
+ }
+ // We already did the currentDirectory
+ return null;
+ }
+
+ final Pattern toMatch = Pattern.compile(dirToProcess.replaceAll("\\\\\\\\", "\\\\"));
+
+ File[] matches = directory.listFiles(new FilenameFilter() {
+ public boolean accept(File arg0, String arg1) {
+ return toMatch.matcher(arg1).matches();
+ }
+ });
+ if (matches == null || matches.length == 0)
+ return null;
+
+ directory = matches[0];
+
+ if (!directory.exists())
+ return null;
+
+ } // End process directory information
+ }
+ // Last step check if the given file can be found in this directory
+ String filenameToLookFor = expandBrackets(fileParts[fileParts.length - 1], entry, database);
+
+ final Pattern toMatch = Pattern.compile("^" + filenameToLookFor.replaceAll("\\\\\\\\", "\\\\") + "$");
+
+ File[] matches = directory.listFiles(new FilenameFilter() {
+ public boolean accept(File arg0, String arg1) {
+ return toMatch.matcher(arg1).matches();
+ }
+ });
+ if (matches == null || matches.length == 0)
+ return null;
+
+ try {
+ return matches[0].getCanonicalPath();
+ } catch (IOException e) {
+ return null;
+ }
+ }
+
+ static Pattern squareBracketsPattern = Pattern.compile("\\[.*?\\]");
+
+ /**
+ * Takes a string that contains bracketed expression and expands each of
+ * these using getFieldAndFormat.
+ *
+ * Unknown Bracket expressions are silently dropped.
+ *
+ * @param bracketString
+ * @param entry
+ * @param database
+ * @return
+ */
+ public static String expandBrackets(String bracketString, BibtexEntry entry,
+ BibtexDatabase database) {
+ Matcher m = squareBracketsPattern.matcher(bracketString);
+ StringBuffer s = new StringBuffer();
+ while (m.find()) {
+ String replacement = getFieldAndFormat(m.group(), entry, database);
+ if (replacement == null)
+ replacement = "";
+ m.appendReplacement(s, replacement);
+ }
+ m.appendTail(s);
+
+ return s.toString();
+ }
+
+ /**
+ * Concatenate all strings in the array from index 'from' to 'to' (excluding
+ * to) with the given separator.
+ *
+ * Example:
+ *
+ * String[] s = "ab/cd/ed".split("/"); join(s, "\\", 0, s.length) ->
+ * "ab\\cd\\ed"
+ *
+ * @param strings
+ * @param separator
+ * @param from
+ * @param to
+ * Excluding strings[to]
+ * @return
+ */
+ public static String join(String[] strings, String separator, int from, int to) {
+ if (strings.length == 0 || from >= to)
+ return "";
+
+ StringBuffer sb = new StringBuffer();
+ for (int i = from; i < to - 1; i++) {
+ sb.append(strings[i]).append(separator);
+ }
+ return sb.append(strings[to - 1]).toString();
+ }
+
+ /**
+ * Converts a relative filename to an absolute one, if necessary. Returns
+ * null if the file does not exist.
+ *
+ * Will look in each of the given dirs starting from the beginning and returning the first found file to match if any.
+ */
+ public static File expandFilename(String name, String[] dir) {
+
+ for (int i = 0; i < dir.length; i++) {
+ File result = expandFilename(name, dir[i]);
+ if (result != null){
+ return result;
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Converts a relative filename to an absolute one, if necessary. Returns
+ * null if the file does not exist.
+ */
+ public static File expandFilename(String name, String dir) {
+ // System.out.println("expandFilename: name="+name+"\t dir="+dir);
+ File file = null;
+ if (name == null || name.length() == 0)
+ return null;
+ else {
+ file = new File(name);
+ }
+
+ if (file != null) {
+ if (!file.exists() && (dir != null)) {
+ if (dir.endsWith(System.getProperty("file.separator")))
+ name = dir + name;
+ else
+ name = dir + System.getProperty("file.separator") + name;
+
+ // System.out.println("expanded to: "+name);
+ // if (name.startsWith("ftp"))
+
+ file = new File(name);
+ if (file.exists())
+ return file;
+ // Ok, try to fix / and \ problems:
+ if (Globals.ON_WIN) {
+ // workaround for catching Java bug in regexp replacer
+ // and, why, why, why ... I don't get it - wegner 2006/01/22
+ try {
+ name = name.replaceAll("/", "\\\\");
+ } catch (java.lang.StringIndexOutOfBoundsException exc) {
+ System.err.println("An internal Java error was caused by the entry " + "\""
+ + name + "\"");
+ }
+ } else
+ name = name.replaceAll("\\\\", "/");
+ // System.out.println("expandFilename: "+name);
+ file = new File(name);
+ if (!file.exists())
+ file = null;
+ }
+ }
+ return file;
+ }
+
+ private static String findInDir(String key, String dir, OpenFileFilter off) {
+ File f = new File(dir);
+ File[] all = f.listFiles();
+ if (all == null)
+ return null; // An error occured. We may not have
+ // permission to list the files.
+
+ int numFiles = all.length;
+
+ for (int i = 0; i < numFiles; i++) {
+ File curFile = all[i];
+
+ if (curFile.isFile()) {
+ String name = curFile.getName();
+ if (name.startsWith(key + ".") && off.accept(name))
+ return curFile.getPath();
+
+ } else if (curFile.isDirectory()) {
+ String found = findInDir(key, curFile.getPath(), off);
+ if (found != null)
+ return found;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Checks if the two entries represent the same publication.
+ *
+ * @param one
+ * BibtexEntry
+ * @param two
+ * BibtexEntry
+ * @return boolean
+ */
+ public static boolean isDuplicate(BibtexEntry one, BibtexEntry two, float threshold) {
+
+ // First check if they are of the same type - a necessary condition:
+ if (one.getType() != two.getType())
+ return false;
+
+ // The check if they have the same required fields:
+ String[] fields = one.getType().getRequiredFields();
+
+ if (fields == null)
+ return false;
+
+ float req = compareFieldSet(fields, one, two);
+ fields = one.getType().getOptionalFields();
+
+ if (fields != null) {
+ float opt = compareFieldSet(fields, one, two);
+ return (2 * req + opt) / 3 >= threshold;
+ } else {
+ return (req >= threshold);
+ }
+ }
+
+ /**
+ * Goes through all entries in the given database, and if at least one of
+ * them is a duplicate of the given entry, as per
+ * Util.isDuplicate(BibtexEntry, BibtexEntry), the duplicate is returned.
+ * The search is terminated when the first duplicate is found.
+ *
+ * @param database
+ * The database to search.
+ * @param entry
+ * The entry of which we are looking for duplicates.
+ * @return The first duplicate entry found. null if no duplicates are found.
+ */
+ public static BibtexEntry containsDuplicate(BibtexDatabase database, BibtexEntry entry) {
+ Collection entries = database.getEntries();
+ for (Iterator i = entries.iterator(); i.hasNext();) {
+ BibtexEntry other = (BibtexEntry) i.next();
+ if (isDuplicate(entry, other, Globals.duplicateThreshold))
+ return other; // Duplicate found.
+ }
+ return null; // No duplicate found.
+ }
+
+ private static float compareFieldSet(String[] fields, BibtexEntry one, BibtexEntry two) {
+ int res = 0;
+ for (int i = 0; i < fields.length; i++) {
+ // Util.pr(":"+compareSingleField(fields[i], one, two));
+ if (compareSingleField(fields[i], one, two) == EQUAL) {
+ res++;
+ // Util.pr(fields[i]);
+ }
+ }
+ return ((float) res) / ((float) fields.length);
+ }
+
+ private static int compareSingleField(String field, BibtexEntry one, BibtexEntry two) {
+ String s1 = (String) one.getField(field), s2 = (String) two.getField(field);
+ if (s1 == null) {
+ if (s2 == null)
+ return EQUAL;
+ else
+ return EMPTY_IN_ONE;
+ } else if (s2 == null)
+ return EMPTY_IN_TWO;
+ s1 = s1.toLowerCase();
+ s2 = s2.toLowerCase();
+ // Util.pr(field+": '"+s1+"' vs '"+s2+"'");
+ if (field.equals("author") || field.equals("editor")) {
+ // Specific for name fields.
+ // Harmonise case:
+ String[] aus1 = AuthorList.fixAuthor_lastNameFirst(s1).split(" and "), aus2 = AuthorList
+ .fixAuthor_lastNameFirst(s2).split(" and "), au1 = aus1[0].split(","), au2 = aus2[0]
+ .split(",");
+
+ // Can check number of authors, all authors or only the first.
+ if ((aus1.length > 0) && (aus1.length == aus2.length)
+ && au1[0].trim().equals(au2[0].trim()))
+ return EQUAL;
+ else
+ return NOT_EQUAL;
+ } else {
+ if (s1.trim().equals(s2.trim()))
+ return EQUAL;
+ else
+ return NOT_EQUAL;
+ }
+
+ }
+
+ public static double compareEntriesStrictly(BibtexEntry one, BibtexEntry two) {
+ HashSet allFields = new HashSet();// one.getAllFields());
+ Object[] o = one.getAllFields();
+ for (int i = 0; i < o.length; i++)
+ allFields.add(o[i]);
+ o = two.getAllFields();
+ for (int i = 0; i < o.length; i++)
+ allFields.add(o[i]);
+ int score = 0;
+ for (Iterator fld = allFields.iterator(); fld.hasNext();) {
+ String field = (String) fld.next();
+ Object en = one.getField(field), to = two.getField(field);
+ if ((en != null) && (to != null) && (en.equals(to)))
+ score++;
+ else if ((en == null) && (to == null))
+ score++;
+ }
+ if (score == allFields.size())
+ return 1.01; // Just to make sure we can
+ // use score>1 without
+ // trouble.
+ else
+ return ((double) score) / allFields.size();
+ }
+
+ /**
+ * This methods assures all words in the given entry are recorded in their
+ * respective Completers, if any.
+ */
+ /*
+ * public static void updateCompletersForEntry(Hashtable autoCompleters,
+ * BibtexEntry be) {
+ *
+ * for (Iterator j=autoCompleters.keySet().iterator(); j.hasNext();) {
+ * String field = (String)j.next(); Completer comp =
+ * (Completer)autoCompleters.get(field); comp.addAll(be.getField(field)); } }
+ */
+
+ /**
+ * Sets empty or non-existing owner fields of bibtex entries inside a List
+ * to a specified default value. Timestamp field is also set. Preferences
+ * are checked to see if these options are enabled.
+ *
+ * @param bibs
+ * List of bibtex entries
+ */
+ public static void setAutomaticFields(List bibs) {
+ String defaultOwner = Globals.prefs.get("defaultOwner");
+ String timestamp = easyDateFormat();
+ boolean setOwner = Globals.prefs.getBoolean("useOwner"), setTimeStamp = Globals.prefs
+ .getBoolean("useTimeStamp");
+ String timeStampField = Globals.prefs.get("timeStampField");
+ // Iterate through all entries
+ for (int i = 0; i < bibs.size(); i++) {
+ // Get current entry
+ BibtexEntry curEntry = (BibtexEntry) bibs.get(i);
+ setAutomaticFields(curEntry, setOwner, defaultOwner, setTimeStamp, timeStampField,
+ timestamp);
+
+ }
+
+ }
+
+ /**
+ * Sets empty or non-existing owner fields of a bibtex entry to a specified
+ * default value. Timestamp field is also set. Preferences are checked to
+ * see if these options are enabled.
+ *
+ * @param entry
+ * The entry to set fields for.
+ */
+ public static void setAutomaticFields(BibtexEntry entry) {
+ String defaultOwner = Globals.prefs.get("defaultOwner");
+ String timestamp = easyDateFormat();
+ boolean setOwner = Globals.prefs.getBoolean("useOwner"), setTimeStamp = Globals.prefs
+ .getBoolean("useTimeStamp");
+ String timeStampField = Globals.prefs.get("timeStampField");
+ setAutomaticFields(entry, setOwner, defaultOwner, setTimeStamp, timeStampField, timestamp);
+ }
+
+ private static void setAutomaticFields(BibtexEntry entry, boolean setOwner, String owner,
+ boolean setTimeStamp, String timeStampField, String timeStamp) {
+
+ // Set owner field if this option is enabled:
+ if (setOwner) {
+ // No or empty owner field?
+ // if (entry.getField(Globals.OWNER) == null
+ // || ((String) entry.getField(Globals.OWNER)).length() == 0) {
+ // Set owner field to default value
+ entry.setField(BibtexFields.OWNER, owner);
+ // }
+ }
+
+ if (setTimeStamp)
+ entry.setField(timeStampField, timeStamp);
+ }
+
+ /**
+ * Copies a file.
+ *
+ * @param source
+ * File Source file
+ * @param dest
+ * File Destination file
+ * @param deleteIfExists
+ * boolean Determines whether the copy goes on even if the file
+ * exists.
+ * @throws IOException
+ * @return boolean Whether the copy succeeded, or was stopped due to the
+ * file already existing.
+ */
+ public static boolean copyFile(File source, File dest, boolean deleteIfExists)
+ throws IOException {
+
+ BufferedInputStream in = null;
+ BufferedOutputStream out = null;
+ try {
+ // Check if the file already exists.
+ if (dest.exists()) {
+ if (!deleteIfExists)
+ return false;
+ // else dest.delete();
+ }
+
+ in = new BufferedInputStream(new FileInputStream(source));
+ out = new BufferedOutputStream(new FileOutputStream(dest));
+ int el;
+ // int tell = 0;
+ while ((el = in.read()) >= 0) {
+ out.write(el);
+ }
+ } catch (IOException ex) {
+ throw ex;
+ } finally {
+ if (out != null) {
+ out.flush();
+ out.close();
+ }
+ if (in != null)
+ in.close();
+ }
+ return true;
+ }
+
+ /**
+ * This method is called at startup, and makes necessary adaptations to
+ * preferences for users from an earlier version of Jabref.
+ */
+ public static void performCompatibilityUpdate() {
+
+ // Make sure "abstract" is not in General fields, because
+ // Jabref 1.55 moves the abstract to its own tab.
+ String genFields = Globals.prefs.get("generalFields");
+ // pr(genFields+"\t"+genFields.indexOf("abstract"));
+ if (genFields.indexOf("abstract") >= 0) {
+ // pr(genFields+"\t"+genFields.indexOf("abstract"));
+ String newGen;
+ if (genFields.equals("abstract"))
+ newGen = "";
+ else if (genFields.indexOf(";abstract;") >= 0) {
+ newGen = genFields.replaceAll(";abstract;", ";");
+ } else if (genFields.indexOf("abstract;") == 0) {
+ newGen = genFields.replaceAll("abstract;", "");
+ } else if (genFields.indexOf(";abstract") == genFields.length() - 9) {
+ newGen = genFields.replaceAll(";abstract", "");
+ } else
+ newGen = genFields;
+ // pr(newGen);
+ Globals.prefs.put("generalFields", newGen);
+ }
+
+ }
+
+ // -------------------------------------------------------------------------------
+
+ /**
+ * extends the filename with a default Extension, if no Extension '.x' could
+ * be found
+ */
+ public static String getCorrectFileName(String orgName, String defaultExtension) {
+ if (orgName == null)
+ return "";
+
+ String back = orgName;
+ int t = orgName.indexOf(".", 1); // hidden files Linux/Unix (?)
+ if (t < 1)
+ back = back + "." + defaultExtension;
+
+ return back;
+ }
+
+ /**
+ * Quotes each and every character, e.g. '!' as !. Used for verbatim
+ * display of arbitrary strings that may contain HTML entities.
+ */
+ public static String quoteForHTML(String s) {
+ StringBuffer sb = new StringBuffer();
+ for (int i = 0; i < s.length(); ++i) {
+ sb.append("&#" + (int) s.charAt(i) + ";");
+ }
+ return sb.toString();
+ }
+
+ public static String quote(String s, String specials, char quoteChar) {
+ return quote(s, specials, quoteChar, 0);
+ }
+
+ /**
+ * Quote special characters.
+ *
+ * @param s
+ * The String which may contain special characters.
+ * @param specials
+ * A String containing all special characters except the quoting
+ * character itself, which is automatically quoted.
+ * @param quoteChar
+ * The quoting character.
+ * @param linewrap
+ * The number of characters after which a linebreak is inserted
+ * (this linebreak is undone by unquote()). Set to 0 to disable.
+ * @return A String with every special character (including the quoting
+ * character itself) quoted.
+ */
+ public static String quote(String s, String specials, char quoteChar, int linewrap) {
+ StringBuffer sb = new StringBuffer();
+ char c;
+ int linelength = 0;
+ boolean isSpecial;
+ for (int i = 0; i < s.length(); ++i) {
+ c = s.charAt(i);
+ isSpecial = specials.indexOf(c) >= 0 || c == quoteChar;
+ // linebreak?
+ if (linewrap > 0
+ && (++linelength >= linewrap || (isSpecial && linelength >= linewrap - 1))) {
+ sb.append(quoteChar);
+ sb.append('\n');
+ linelength = 0;
+ }
+ if (isSpecial) {
+ sb.append(quoteChar);
+ ++linelength;
+ }
+ sb.append(c);
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Unquote special characters.
+ *
+ * @param s
+ * The String which may contain quoted special characters.
+ * @param quoteChar
+ * The quoting character.
+ * @return A String with all quoted characters unquoted.
+ */
+ public static String unquote(String s, char quoteChar) {
+ StringBuffer sb = new StringBuffer();
+ char c;
+ boolean quoted = false;
+ for (int i = 0; i < s.length(); ++i) {
+ c = s.charAt(i);
+ if (quoted) { // append literally...
+ if (c != '\n') // ...unless newline
+ sb.append(c);
+ quoted = false;
+ } else if (c != quoteChar) {
+ sb.append(c);
+ } else { // quote char
+ quoted = true;
+ }
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Quote all regular expression meta characters in s, in order to search for
+ * s literally.
+ */
+ public static String quoteMeta(String s) {
+ // work around a bug: trailing backslashes have to be quoted
+ // individually
+ int i = s.length() - 1;
+ StringBuffer bs = new StringBuffer("");
+ while ((i >= 0) && (s.charAt(i) == '\\')) {
+ --i;
+ bs.append("\\\\");
+ }
+ s = s.substring(0, i + 1);
+ return "\\Q" + s.replaceAll("\\\\E", "\\\\E\\\\\\\\E\\\\Q") + "\\E" + bs.toString();
+ }
+
+ /*
+ * This method "tidies" up e.g. a keyword string, by alphabetizing the words
+ * and removing all duplicates.
+ */
+ public static String sortWordsAndRemoveDuplicates(String text) {
+
+ String[] words = text.split(", ");
+ SortedSet set = new TreeSet();
+ for (int i = 0; i < words.length; i++)
+ set.add(words[i]);
+ StringBuffer sb = new StringBuffer();
+ for (Iterator i = set.iterator(); i.hasNext();) {
+ sb.append(i.next());
+ sb.append(", ");
+ }
+ if (sb.length() > 2)
+ sb.delete(sb.length() - 2, sb.length());
+ String result = sb.toString();
+ return result.length() > 2 ? result : "";
+ }
+
+ /**
+ * Warns the user of undesired side effects of an explicit
+ * assignment/removal of entries to/from this group. Currently there are
+ * four types of groups: AllEntriesGroup, SearchGroup - do not support
+ * explicit assignment. ExplicitGroup - never modifies entries. KeywordGroup -
+ * only this modifies entries upon assignment/removal. Modifications are
+ * acceptable unless they affect a standard field (such as "author") besides
+ * the "keywords" field.
+ *
+ * @param parent
+ * The Component used as a parent when displaying a confirmation
+ * dialog.
+ * @return true if the assignment has no undesired side effects, or the user
+ * chose to perform it anyway. false otherwise (this indicates that
+ * the user has aborted the assignment).
+ */
+ public static boolean warnAssignmentSideEffects(AbstractGroup[] groups, BibtexEntry[] entries,
+ BibtexDatabase db, Component parent) {
+ Vector affectedFields = new Vector();
+ for (int k = 0; k < groups.length; ++k) {
+ if (groups[k] instanceof KeywordGroup) {
+ KeywordGroup kg = (KeywordGroup) groups[k];
+ String field = kg.getSearchField().toLowerCase();
+ if (field.equals("keywords"))
+ continue; // this is not undesired
+ for (int i = 0, len = BibtexFields.numberOfPublicFields(); i < len; ++i) {
+ if (field.equals(BibtexFields.getFieldName(i))) {
+ affectedFields.add(field);
+ break;
+ }
+ }
+ }
+ }
+ if (affectedFields.size() == 0)
+ return true; // no side effects
+
+ // show a warning, then return
+ StringBuffer message = // JZTODO lyrics...
+ new StringBuffer("This action will modify the following field(s)\n"
+ + "in at least one entry each:\n");
+ for (int i = 0; i < affectedFields.size(); ++i)
+ message.append(affectedFields.elementAt(i)).append("\n");
+ message.append("This could cause undesired changes to "
+ + "your entries, so it is\nrecommended that you change the grouping field "
+ + "in your group\ndefinition to \"keywords\" or a non-standard name."
+ + "\n\nDo you still want to continue?");
+ int choice = JOptionPane.showConfirmDialog(parent, message, Globals.lang("Warning"),
+ JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE);
+ return choice != JOptionPane.NO_OPTION;
+
+ // if (groups instanceof KeywordGroup) {
+ // KeywordGroup kg = (KeywordGroup) groups;
+ // String field = kg.getSearchField().toLowerCase();
+ // if (field.equals("keywords"))
+ // return true; // this is not undesired
+ // for (int i = 0; i < GUIGlobals.ALL_FIELDS.length; ++i) {
+ // if (field.equals(GUIGlobals.ALL_FIELDS[i])) {
+ // // show a warning, then return
+ // String message = Globals // JZTODO lyrics...
+ // .lang(
+ // "This action will modify the \"%0\" field "
+ // + "of your entries.\nThis could cause undesired changes to "
+ // + "your entries, so it is\nrecommended that you change the grouping
+ // field "
+ // + "in your group\ndefinition to \"keywords\" or a non-standard name."
+ // + "\n\nDo you still want to continue?",
+ // field);
+ // int choice = JOptionPane.showConfirmDialog(parent, message,
+ // Globals.lang("Warning"), JOptionPane.YES_NO_OPTION,
+ // JOptionPane.WARNING_MESSAGE);
+ // return choice != JOptionPane.NO_OPTION;
+ // }
+ // }
+ // }
+ // return true; // found no side effects
+ }
+
+ // ========================================================
+ // lot of abreviations in medline
+ // PKC etc convert to {PKC} ...
+ // ========================================================
+ static Pattern titleCapitalPattern = Pattern.compile("[A-Z]+");
+
+ /**
+ * Wrap all uppercase letters, or sequences of uppercase letters, in curly
+ * braces. Ignore letters within a pair of # character, as these are part of
+ * a string label that should not be modified.
+ *
+ * @param s
+ * The string to modify.
+ * @return The resulting string after wrapping capitals.
+ */
+ public static String putBracesAroundCapitals(String s) {
+
+ boolean inString = false, isBracing = false, escaped = false;
+ int inBrace = 0;
+ StringBuffer buf = new StringBuffer();
+ for (int i = 0; i < s.length(); i++) {
+ // Update variables based on special characters:
+ int c = s.charAt(i);
+ if (c == '{')
+ inBrace++;
+ else if (c == '}')
+ inBrace--;
+ else if (!escaped && (c == '#'))
+ inString = !inString;
+
+ // See if we should start bracing:
+ if ((inBrace == 0) && !isBracing && !inString && Character.isLetter((char) c)
+ && Character.isUpperCase((char) c)) {
+
+ buf.append('{');
+ isBracing = true;
+ }
+
+ // See if we should close a brace set:
+ if (isBracing && !(Character.isLetter((char) c) && Character.isUpperCase((char) c))) {
+
+ buf.append('}');
+ isBracing = false;
+ }
+
+ // Add the current character:
+ buf.append((char) c);
+
+ // Check if we are entering an escape sequence:
+ if ((c == '\\') && !escaped)
+ escaped = true;
+ else
+ escaped = false;
+
+ }
+ // Check if we have an unclosed brace:
+ if (isBracing)
+ buf.append('}');
+
+ return buf.toString();
+
+ /*
+ * if (s.length() == 0) return s; // Protect against ArrayIndexOutOf....
+ * StringBuffer buf = new StringBuffer();
+ *
+ * Matcher mcr = titleCapitalPattern.matcher(s.substring(1)); while
+ * (mcr.find()) { String replaceStr = mcr.group();
+ * mcr.appendReplacement(buf, "{" + replaceStr + "}"); }
+ * mcr.appendTail(buf); return s.substring(0, 1) + buf.toString();
+ */
+ }
+
+ static Pattern bracedTitleCapitalPattern = Pattern.compile("\\{[A-Z]+\\}");
+
+ /**
+ * This method looks for occurences of capital letters enclosed in an
+ * arbitrary number of pairs of braces, e.g. "{AB}" or "{{T}}". All of these
+ * pairs of braces are removed.
+ *
+ * @param s
+ * The String to analyze.
+ * @return A new String with braces removed.
+ */
+ public static String removeBracesAroundCapitals(String s) {
+ String previous = s;
+ while ((s = removeSingleBracesAroundCapitals(s)).length() < previous.length()) {
+ previous = s;
+ }
+ return s;
+ }
+
+ /**
+ * This method looks for occurences of capital letters enclosed in one pair
+ * of braces, e.g. "{AB}". All these are replaced by only the capitals in
+ * between the braces.
+ *
+ * @param s
+ * The String to analyze.
+ * @return A new String with braces removed.
+ */
+ public static String removeSingleBracesAroundCapitals(String s) {
+ Matcher mcr = bracedTitleCapitalPattern.matcher(s);
+ StringBuffer buf = new StringBuffer();
+ while (mcr.find()) {
+ String replaceStr = mcr.group();
+ mcr.appendReplacement(buf, replaceStr.substring(1, replaceStr.length() - 1));
+ }
+ mcr.appendTail(buf);
+ return buf.toString();
+ }
+
+ /**
+ * This method looks up what kind of external binding is used for the given
+ * field, and constructs on OpenFileFilter suitable for browsing for an
+ * external file.
+ *
+ * @param fieldName
+ * The BibTeX field in question.
+ * @return The file filter.
+ */
+ public static OpenFileFilter getFileFilterForField(String fieldName) {
+ String s = BibtexFields.getFieldExtras(fieldName);
+ final String ext = "." + fieldName.toLowerCase();
+ final OpenFileFilter off;
+ if (s.equals("browseDocZip"))
+ off = new OpenFileFilter(new String[] { ext, ext + ".gz", ext + ".bz2" });
+ else
+ off = new OpenFileFilter(new String[] { ext });
+ return off;
+ }
+
+ /**
+ * This method can be used to display a "rich" error dialog which offers the
+ * entire stack trace for an exception.
+ *
+ * @param parent
+ * @param e
+ */
+ public static void showQuickErrorDialog(JFrame parent, String title, Exception e) {
+ // create and configure a text area - fill it with exception text.
+ final JPanel pan = new JPanel(), details = new JPanel();
+ final CardLayout crd = new CardLayout();
+ pan.setLayout(crd);
+ final JTextArea textArea = new JTextArea();
+ textArea.setFont(new Font("Sans-Serif", Font.PLAIN, 10));
+ textArea.setEditable(false);
+ StringWriter writer = new StringWriter();
+ e.printStackTrace(new PrintWriter(writer));
+ textArea.setText(writer.toString());
+ JLabel lab = new JLabel(e.getMessage());
+ JButton flip = new JButton(Globals.lang("Details"));
+
+ FormLayout layout = new FormLayout("left:pref", "");
+ DefaultFormBuilder builder = new DefaultFormBuilder(layout);
+ builder.append(lab);
+ builder.nextLine();
+ builder.append(Box.createVerticalGlue());
+ builder.nextLine();
+ builder.append(flip);
+ final JPanel simple = builder.getPanel();
+
+ // stuff it in a scrollpane with a controlled size.
+ JScrollPane scrollPane = new JScrollPane(textArea);
+ scrollPane.setPreferredSize(new Dimension(350, 150));
+ details.setLayout(new BorderLayout());
+ details.add(scrollPane, BorderLayout.CENTER);
+
+ flip.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent event) {
+ crd.show(pan, "details");
+ }
+ });
+ pan.add(simple, "simple");
+ pan.add(details, "details");
+ // pass the scrollpane to the joptionpane.
+ JOptionPane.showMessageDialog(parent, pan, title, JOptionPane.ERROR_MESSAGE);
+ }
+
+ public static String wrapHTML(String s, final int lineWidth) {
+ StringBuffer sb = new StringBuffer();
+ StringTokenizer tok = new StringTokenizer(s);
+ int charsLeft = lineWidth;
+ while (tok.hasMoreTokens()) {
+ String word = tok.nextToken();
+ if (charsLeft == lineWidth) { // fresh line
+ sb.append(word);
+ charsLeft -= word.length();
+ if (charsLeft <= 0) {
+ sb.append("<br>\n");
+ charsLeft = lineWidth;
+ }
+ } else { // continue previous line
+ if (charsLeft < word.length() + 1) {
+ sb.append("<br>\n");
+ sb.append(word);
+ if (word.length() >= lineWidth - 1) {
+ sb.append("<br>\n");
+ charsLeft = lineWidth;
+ } else {
+ sb.append(" ");
+ charsLeft = lineWidth - word.length() - 1;
+ }
+ } else {
+ sb.append(' ').append(word);
+ charsLeft -= word.length() + 1;
+ }
+ }
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Creates a String containing the current date (and possibly time),
+ * formatted according to the format set in preferences under the key
+ * "timeStampFormat".
+ *
+ * @return The date string.
+ */
+ public static String easyDateFormat() {
+ // Date today = new Date();
+ return easyDateFormat(new Date());
+ }
+
+ /**
+ * Creates a readable Date string from the parameter date. The format is set
+ * in preferences under the key "timeStampFormat".
+ *
+ * @return The formatted date string.
+ */
+ public static String easyDateFormat(Date date) {
+ // first use, create an instance
+ if (dateFormatter == null) {
+ String format = Globals.prefs.get("timeStampFormat");
+ dateFormatter = new SimpleDateFormat(format);
+ }
+ return dateFormatter.format(date);
+ }
+
+ public static void markEntry(BibtexEntry be, NamedCompound ce) {
+ Object o = be.getField(BibtexFields.MARKED);
+ if ((o != null) && (o.toString().indexOf(Globals.prefs.WRAPPED_USERNAME) >= 0))
+ return;
+ String newValue;
+ if (o == null) {
+ newValue = Globals.prefs.WRAPPED_USERNAME;
+ } else {
+ StringBuffer sb = new StringBuffer(o.toString());
+ // sb.append(' ');
+ sb.append(Globals.prefs.WRAPPED_USERNAME);
+ newValue = sb.toString();
+ }
+ ce.addEdit(new UndoableFieldChange(be, BibtexFields.MARKED, be
+ .getField(BibtexFields.MARKED), newValue));
+ be.setField(BibtexFields.MARKED, newValue);
+ }
+
+ public static void unmarkEntry(BibtexEntry be, BibtexDatabase database, NamedCompound ce) {
+ Object o = be.getField(BibtexFields.MARKED);
+ if (o != null) {
+ String s = o.toString();
+ if (s.equals("0")) {
+ unmarkOldStyle(be, database, ce);
+ return;
+ }
+
+ int piv = 0, hit;
+ StringBuffer sb = new StringBuffer();
+ while ((hit = s.indexOf(Globals.prefs.WRAPPED_USERNAME, piv)) >= 0) {
+ if (hit > 0)
+ sb.append(s.substring(piv, hit));
+ piv = hit + Globals.prefs.WRAPPED_USERNAME.length();
+ }
+ if (piv < s.length() - 1) {
+ sb.append(s.substring(piv));
+ }
+ String newVal = sb.length() > 0 ? sb.toString() : null;
+ ce.addEdit(new UndoableFieldChange(be, BibtexFields.MARKED, be
+ .getField(BibtexFields.MARKED), newVal));
+ be.setField(BibtexFields.MARKED, newVal);
+ }
+ }
+
+ /**
+ * An entry is marked with a "0", not in the new style with user names. We
+ * want to unmark it as transparently as possible. Since this shouldn't
+ * happen too often, we do it by scanning the "owner" fields of the entire
+ * database, collecting all user names. We then mark the entry for all users
+ * except the current one. Thus only the user who unmarks will see that it
+ * is unmarked, and we get rid of the old-style marking.
+ *
+ * @param be
+ * @param ce
+ */
+ private static void unmarkOldStyle(BibtexEntry be, BibtexDatabase database, NamedCompound ce) {
+ TreeSet owners = new TreeSet();
+ for (Iterator i = database.getEntries().iterator(); i.hasNext();) {
+ BibtexEntry entry = (BibtexEntry) i.next();
+ Object o = entry.getField(BibtexFields.OWNER);
+ if (o != null)
+ owners.add(o);
+ // System.out.println("Owner: "+entry.getField(Globals.OWNER));
+ }
+ owners.remove(Globals.prefs.get("defaultOwner"));
+ StringBuffer sb = new StringBuffer();
+ for (Iterator i = owners.iterator(); i.hasNext();) {
+ sb.append('[');
+ sb.append(i.next().toString());
+ sb.append(']');
+ }
+ String newVal = sb.toString();
+ if (newVal.length() == 0)
+ newVal = null;
+ ce.addEdit(new UndoableFieldChange(be, BibtexFields.MARKED, be
+ .getField(BibtexFields.MARKED), newVal));
+ be.setField(BibtexFields.MARKED, newVal);
+
+ }
+
+ public static boolean isMarked(BibtexEntry be) {
+ Object fieldVal = be.getField(BibtexFields.MARKED);
+ if (fieldVal == null)
+ return false;
+ String s = (String) fieldVal;
+ return (s.equals("0") || (s.indexOf(Globals.prefs.WRAPPED_USERNAME) >= 0));
+ }
/**
- * Goes through all entries in the given database, and if at least one of
- * them is a duplicate of the given entry, as per Util.isDuplicate(BibtexEntry, BibtexEntry),
- * the duplicate is returned. The search is terminated when the first duplicate is found.
+ * Set a given field to a given value for all entries in a Collection.
+ * This method DOES NOT update any UndoManager, but returns a relevant
+ * CompoundEdit that should be registered by the caller.
*
- * @param database The database to search.
- * @param entry The entry of which we are looking for duplicates.
- * @return The first duplicate entry found. null if no duplicates are found.
+ * @param entries The entries to set the field for.
+ * @param field The name of the field to set.
+ * @param text The value to set. This value can be null, indicating that the
+ * field should be cleared.
+ * @param overwriteValues Indicate whether the value should be set even if
+ * an entry already has the field set.
+ * @return A CompoundEdit for the entire operation.
*/
- public static BibtexEntry containsDuplicate(BibtexDatabase database, BibtexEntry entry) {
- Collection entries = database.getEntries();
+ public static UndoableEdit massSetField(Collection entries,
+ String field, String text,
+ boolean overwriteValues) {
+
+ NamedCompound ce = new NamedCompound(Globals.lang("Set field"));
for (Iterator i = entries.iterator(); i.hasNext();) {
- BibtexEntry other = (BibtexEntry) i.next();
- if (isDuplicate(entry, other, Globals.duplicateThreshold))
- return other; // Duplicate found.
- }
- return null; // No duplicate found.
- }
-
- private static float compareFieldSet(String[] fields, BibtexEntry one,
- BibtexEntry two) {
- int res = 0;
- for (int i = 0; i < fields.length; i++) {
- //Util.pr(":"+compareSingleField(fields[i], one, two));
- if (compareSingleField(fields[i], one, two) == EQUAL) {
- res++;
- //Util.pr(fields[i]);
- }
- }
- return ((float) res) / ((float) fields.length);
- }
-
- private static int compareSingleField(String field, BibtexEntry one,
- BibtexEntry two) {
- String s1 = (String) one.getField(field), s2 = (String) two
- .getField(field);
- if (s1 == null) {
- if (s2 == null) return EQUAL;
- else return EMPTY_IN_ONE;
- } else if (s2 == null) return EMPTY_IN_TWO;
- s1 = s1.toLowerCase();
- s2 = s2.toLowerCase();
- //Util.pr(field+": '"+s1+"' vs '"+s2+"'");
- if (field.equals("author") || field.equals("editor")) {
- // Specific for name fields.
- // Harmonise case:
- String[] aus1 = AuthorList.fixAuthor_lastNameFirst(s1)
- .split(" and "), aus2 = AuthorList
- .fixAuthor_lastNameFirst(s2).split(" and "), au1 = aus1[0]
- .split(","), au2 = aus2[0].split(",");
-
- // Can check number of authors, all authors or only the first.
- if ((aus1.length > 0) && (aus1.length == aus2.length)
- && au1[0].trim().equals(au2[0].trim())) return EQUAL;
- else return NOT_EQUAL;
- } else {
- if (s1.trim().equals(s2.trim())) return EQUAL;
- else return NOT_EQUAL;
- }
-
- }
-
- public static double compareEntriesStrictly(BibtexEntry one, BibtexEntry two) {
- HashSet allFields = new HashSet();//one.getAllFields());
- Object[] o = one.getAllFields();
- for (int i = 0; i < o.length; i++)
- allFields.add(o[i]);
- o = two.getAllFields();
- for (int i = 0; i < o.length; i++)
- allFields.add(o[i]);
- int score = 0;
- for (Iterator fld = allFields.iterator(); fld.hasNext();) {
- String field = (String) fld.next();
- Object en = one.getField(field), to = two.getField(field);
- if ((en != null) && (to != null) && (en.equals(to))) score++;
- else if ((en == null) && (to == null)) score++;
- }
- if (score == allFields.size()) return 1.01; // Just to make sure we can
- // use score>1 without
- // trouble.
- else return ((double) score) / allFields.size();
- }
-
- /**
- * This methods assures all words in the given entry are recorded in their
- * respective Completers, if any.
- */
- /*
- * public static void updateCompletersForEntry(Hashtable autoCompleters,
- * BibtexEntry be) {
- *
- * for (Iterator j=autoCompleters.keySet().iterator(); j.hasNext();) {
- * String field = (String)j.next(); Completer comp =
- * (Completer)autoCompleters.get(field); comp.addAll(be.getField(field)); } }
- */
-
- /**
- * Sets empty or non-existing owner fields of bibtex entries inside a List
- * to a specified default value. Timestamp field is also set. Preferences are
- * checked to see if these options are enabled.
- *
- * @param bibs List of bibtex entries
- */
- public static void setAutomaticFields(List bibs) {
- String defaultOwner = Globals.prefs.get("defaultOwner");
- String timestamp = easyDateFormat();
- boolean setOwner = Globals.prefs.getBoolean("useOwner"),
- setTimeStamp = Globals.prefs.getBoolean("useTimeStamp");
- String timeStampField = Globals.prefs.get("timeStampField");
- // Iterate through all entries
- for (int i = 0; i < bibs.size(); i++) {
- // Get current entry
- BibtexEntry curEntry = (BibtexEntry) bibs.get(i);
- setAutomaticFields(curEntry, setOwner, defaultOwner, setTimeStamp,
- timeStampField, timestamp);
-
- }
-
- }
-
- /**
- * Sets empty or non-existing owner fields of a bibtex entry
- * to a specified default value. Timestamp field is also set. Preferences are
- * checked to see if these options are enabled.
- *
- * @param entry The entry to set fields for.
- */
- public static void setAutomaticFields(BibtexEntry entry) {
- String defaultOwner = Globals.prefs.get("defaultOwner");
- String timestamp = easyDateFormat();
- boolean setOwner = Globals.prefs.getBoolean("useOwner"),
- setTimeStamp = Globals.prefs.getBoolean("useTimeStamp");
- String timeStampField = Globals.prefs.get("timeStampField");
- setAutomaticFields(entry, setOwner, defaultOwner, setTimeStamp,
- timeStampField, timestamp);
- }
-
- private static void setAutomaticFields(BibtexEntry entry, boolean setOwner,
- String owner, boolean setTimeStamp,
- String timeStampField, String timeStamp) {
-
- // Set owner field if this option is enabled:
- if (setOwner) {
- // No or empty owner field?
- //if (entry.getField(Globals.OWNER) == null
- // || ((String) entry.getField(Globals.OWNER)).length() == 0) {
- // Set owner field to default value
- entry.setField(BibtexFields.OWNER, owner);
- //}
- }
-
- if (setTimeStamp)
- entry.setField(timeStampField, timeStamp);
- }
-
- /**
- * Copies a file.
- *
- * @param source File Source file
- * @param dest File Destination file
- * @param deleteIfExists boolean Determines whether the copy goes on even if the file
- * exists.
- * @throws IOException
- * @return boolean Whether the copy succeeded, or was stopped due to the
- * file already existing.
- */
- public static boolean copyFile(File source, File dest,
- boolean deleteIfExists) throws IOException {
-
- // Check if the file already exists.
- if (dest.exists()) {
- if (!deleteIfExists) return false;
- //else dest.delete();
- }
-
- BufferedInputStream in = new BufferedInputStream(new FileInputStream(
- source));
- BufferedOutputStream out = new BufferedOutputStream(
- new FileOutputStream(dest));
- int el;
- //int tell = 0;
- while ((el = in.read()) >= 0) {
- out.write(el);
- }
- out.flush(); // Will this make a difference? 2005.09.30
- in.close();
- out.close();
- return true;
- }
-
- /**
- * This method is called at startup, and makes necessary adaptations to
- * preferences for users from an earlier version of Jabref.
- */
- public static void performCompatibilityUpdate() {
-
- // Make sure "abstract" is not in General fields, because
- // Jabref 1.55 moves the abstract to its own tab.
- String genFields = Globals.prefs.get("generalFields");
- //pr(genFields+"\t"+genFields.indexOf("abstract"));
- if (genFields.indexOf("abstract") >= 0) {
- //pr(genFields+"\t"+genFields.indexOf("abstract"));
- String newGen;
- if (genFields.equals("abstract")) newGen = "";
- else if (genFields.indexOf(";abstract;") >= 0) {
- newGen = genFields.replaceAll(";abstract;", ";");
- } else if (genFields.indexOf("abstract;") == 0) {
- newGen = genFields.replaceAll("abstract;", "");
- } else if (genFields.indexOf(";abstract") == genFields.length() - 9) {
- newGen = genFields.replaceAll(";abstract", "");
- } else newGen = genFields;
- //pr(newGen);
- Globals.prefs.put("generalFields", newGen);
- }
-
- }
-
- // -------------------------------------------------------------------------------
-
- /**
- * extends the filename with a default Extension, if no Extension '.x' could
- * be found
- */
- public static String getCorrectFileName(String orgName,
- String defaultExtension) {
- if (orgName == null) return "";
-
- String back = orgName;
- int t = orgName.indexOf(".", 1); // hidden files Linux/Unix (?)
- if (t < 1) back = back + "." + defaultExtension;
-
- return back;
- }
-
- /** Quotes each and every character, e.g. '!' as !. Used for
- * verbatim display of arbitrary strings that may contain HTML entities. */
- public static String quoteForHTML(String s) {
- StringBuffer sb = new StringBuffer();
- for (int i = 0; i < s.length(); ++i) {
- sb.append("&#"+(int)s.charAt(i)+";");
- }
- return sb.toString();
- }
-
- public static String quote(String s, String specials, char quoteChar) {
- return quote(s, specials, quoteChar, 0);
- }
-
- /**
- * Quote special characters.
- *
- * @param s The String which may contain special characters.
- * @param specials A String containing all special characters except the quoting
- * character itself, which is automatically quoted.
- * @param quoteChar The quoting character.
- * @param linewrap The number of characters after which a linebreak is inserted
- * (this linebreak is undone by unquote()). Set to 0 to disable.
- * @return A String with every special character (including the quoting
- * character itself) quoted.
- */
- public static String quote(String s, String specials, char quoteChar,
- int linewrap) {
- StringBuffer sb = new StringBuffer();
- char c;
- int linelength = 0;
- boolean isSpecial;
- for (int i = 0; i < s.length(); ++i) {
- c = s.charAt(i);
- isSpecial = specials.indexOf(c) >= 0 || c == quoteChar;
- // linebreak?
- if (linewrap > 0
- && (++linelength >= linewrap || (isSpecial && linelength >= linewrap - 1))) {
- sb.append(quoteChar);
- sb.append('\n');
- linelength = 0;
- }
- if (isSpecial) {
- sb.append(quoteChar);
- ++linelength;
- }
- sb.append(c);
- }
- return sb.toString();
- }
-
- /**
- * Unquote special characters.
- *
- * @param s The String which may contain quoted special characters.
- * @param quoteChar The quoting character.
- * @return A String with all quoted characters unquoted.
- */
- public static String unquote(String s, char quoteChar) {
- StringBuffer sb = new StringBuffer();
- char c;
- boolean quoted = false;
- for (int i = 0; i < s.length(); ++i) {
- c = s.charAt(i);
- if (quoted) { // append literally...
- if (c != '\n') // ...unless newline
- sb.append(c);
- quoted = false;
- } else if (c != quoteChar) {
- sb.append(c);
- } else { // quote char
- quoted = true;
- }
- }
- return sb.toString();
- }
-
- /**
- * Quote all regular expression meta characters in s, in order to
- * search for s literally.
- */
- public static String quoteMeta(String s) {
- // work around a bug: trailing backslashes have to be quoted individually
- int i = s.length() - 1;
- StringBuffer bs = new StringBuffer("");
- while ((i >= 0) && (s.charAt(i) == '\\')) {
- --i;
- bs.append("\\\\");
- }
- s = s.substring(0, i + 1);
- return "\\Q" + s.replaceAll("\\\\E", "\\\\E\\\\\\\\E\\\\Q") + "\\E" + bs.toString();
- }
-
- /*
- * This method "tidies" up e.g. a keyword string, by alphabetizing the words and
- * removing all duplicates.
- */
- public static String sortWordsAndRemoveDuplicates(String text) {
-
- String[] words = text.split(", ");
- SortedSet set = new TreeSet();
- for (int i = 0; i < words.length; i++)
- set.add(words[i]);
- StringBuffer sb = new StringBuffer();
- for (Iterator i = set.iterator(); i.hasNext();) {
- sb.append(i.next());
- sb.append(", ");
- }
- if (sb.length() > 2)
- sb.delete(sb.length() - 2, sb.length());
- String result = sb.toString();
- return result.length() > 2 ? result : "";
- }
-
- /**
- * Warns the user of undesired side effects of an explicit
- * assignment/removal of entries to/from this group. Currently there are
- * four types of groups: AllEntriesGroup, SearchGroup - do not support
- * explicit assignment. ExplicitGroup - never modifies entries. KeywordGroup -
- * only this modifies entries upon assignment/removal. Modifications are
- * acceptable unless they affect a standard field (such as "author") besides
- * the "keywords" field.
- *
- * @param parent The Component used as a parent when displaying a
- * confirmation dialog.
- * @return true if the assignment has no undesired side effects, or the user
- * chose to perform it anyway. false otherwise (this indicates that
- * the user has aborted the assignment).
- */
- public static boolean warnAssignmentSideEffects(AbstractGroup[] groups,
- BibtexEntry[] entries, BibtexDatabase db, Component parent) {
- Vector affectedFields = new Vector();
- for (int k = 0; k < groups.length; ++k) {
- if (groups[k] instanceof KeywordGroup) {
- KeywordGroup kg = (KeywordGroup) groups[k];
- String field = kg.getSearchField().toLowerCase();
- if (field.equals("keywords"))
- continue; // this is not undesired
- for (int i = 0, len = BibtexFields.numberOfPublicFields(); i < len; ++i)
- {
- if (field.equals( BibtexFields.getFieldName(i)))
- {
- affectedFields.add(field);
- break;
- }
- }
- }
- }
- if (affectedFields.size() == 0)
- return true; // no side effects
-
- // show a warning, then return
- StringBuffer message = // JZTODO lyrics...
- new StringBuffer("This action will modify the following field(s)\n" +
- "in at least one entry each:\n");
- for (int i = 0; i < affectedFields.size(); ++i)
- message.append(affectedFields.elementAt(i)).append("\n");
- message.append("This could cause undesired changes to "
- + "your entries, so it is\nrecommended that you change the grouping field "
- + "in your group\ndefinition to \"keywords\" or a non-standard name."
- + "\n\nDo you still want to continue?");
- int choice = JOptionPane.showConfirmDialog(parent, message,
- Globals.lang("Warning"), JOptionPane.YES_NO_OPTION,
- JOptionPane.WARNING_MESSAGE);
- return choice != JOptionPane.NO_OPTION;
-
-// if (groups instanceof KeywordGroup) {
-// KeywordGroup kg = (KeywordGroup) groups;
-// String field = kg.getSearchField().toLowerCase();
-// if (field.equals("keywords"))
-// return true; // this is not undesired
-// for (int i = 0; i < GUIGlobals.ALL_FIELDS.length; ++i) {
-// if (field.equals(GUIGlobals.ALL_FIELDS[i])) {
-// // show a warning, then return
-// String message = Globals // JZTODO lyrics...
-// .lang(
-// "This action will modify the \"%0\" field "
-// + "of your entries.\nThis could cause undesired changes to "
-// + "your entries, so it is\nrecommended that you change the grouping field "
-// + "in your group\ndefinition to \"keywords\" or a non-standard name."
-// + "\n\nDo you still want to continue?",
-// field);
-// int choice = JOptionPane.showConfirmDialog(parent, message,
-// Globals.lang("Warning"), JOptionPane.YES_NO_OPTION,
-// JOptionPane.WARNING_MESSAGE);
-// return choice != JOptionPane.NO_OPTION;
-// }
-// }
-// }
-// return true; // found no side effects
- }
-
- //========================================================
- // lot of abreviations in medline
- // PKC etc convert to {PKC} ...
- //========================================================
- static Pattern titleCapitalPattern = Pattern.compile("[A-Z]+");
-
- /**
- * Wrap all uppercase letters, or sequences of uppercase letters, in
- * curly braces. Ignore letters within a pair of # character, as these
- * are part of a string label that should not be modified.
- * @param s The string to modify.
- * @return The resulting string after wrapping capitals.
- */
- public static String putBracesAroundCapitals(String s) {
-
- boolean inString=false, isBracing=false, escaped=false;
- int inBrace = 0;
- StringBuffer buf = new StringBuffer();
- for (int i=0; i<s.length(); i++) {
- // Update variables based on special characters:
- int c = s.charAt(i);
- if (c == '{') inBrace++;
- else if (c == '}') inBrace--;
- else if (!escaped && (c == '#'))
- inString = !inString;
-
- // See if we should start bracing:
- if ((inBrace == 0) && !isBracing && !inString
- && Character.isLetter((char)c)
- && Character.isUpperCase((char)c)) {
-
- buf.append('{');
- isBracing = true;
- }
-
- // See if we should close a brace set:
- if (isBracing &&
- !(Character.isLetter((char)c)
- &&Character.isUpperCase((char)c))) {
-
- buf.append('}');
- isBracing = false;
- }
-
- // Add the current character:
- buf.append((char)c);
-
- // Check if we are entering an escape sequence:
- if ((c == '\\') && !escaped)
- escaped = true;
+ BibtexEntry entry = (BibtexEntry) i.next();
+ Object oldVal = entry.getField(field);
+ // If we are not allowed to overwrite values, check if there is a nonempty
+ // value already for this entry:
+ if (!overwriteValues && (oldVal != null) && (((String)oldVal).length() > 0))
+ continue;
+ if (text != null)
+ entry.setField(field, text);
else
- escaped = false;
-
- }
- // Check if we have an unclosed brace:
- if (isBracing)
- buf.append('}');
-
- return buf.toString();
-
- /*if (s.length() == 0) return s; // Protect against ArrayIndexOutOf....
- StringBuffer buf = new StringBuffer();
-
- Matcher mcr = titleCapitalPattern.matcher(s.substring(1));
- while (mcr.find()) {
- String replaceStr = mcr.group();
- mcr.appendReplacement(buf, "{" + replaceStr + "}");
- }
- mcr.appendTail(buf);
- return s.substring(0, 1) + buf.toString();*/
- }
-
- static Pattern bracedTitleCapitalPattern = Pattern.compile("\\{[A-Z]+\\}");
-
- /**
- * This method looks for occurences of capital letters enclosed in an arbitrary number of
- * pairs of braces, e.g. "{AB}" or "{{T}}". All of these pairs of braces are removed.
- * @param s The String to analyze.
- * @return A new String with braces removed.
- */
- public static String removeBracesAroundCapitals(String s) {
- String previous = s;
- while ((s = removeSingleBracesAroundCapitals(s)).length() < previous.length()) {
- previous = s;
- }
- return s;
- }
-
- /**
- * This method looks for occurences of capital letters enclosed in one pair of braces, e.g. "{AB}".
- * All these are replaced by only the capitals in between the braces.
- * @param s The String to analyze.
- * @return A new String with braces removed.
- */
- public static String removeSingleBracesAroundCapitals(String s) {
- Matcher mcr = bracedTitleCapitalPattern.matcher(s);
- StringBuffer buf = new StringBuffer();
- while (mcr.find()) {
- String replaceStr = mcr.group();
- mcr.appendReplacement(buf, replaceStr.substring(1, replaceStr.length()-1));
- }
- mcr.appendTail(buf);
- return buf.toString();
- }
-
- /**
- * This method looks up what kind of external binding is used for the given field,
- * and constructs on OpenFileFilter suitable for browsing for an external file.
- *
- * @param fieldName The BibTeX field in question.
- * @return The file filter.
- */
- public static OpenFileFilter getFileFilterForField(String fieldName) {
- String s = BibtexFields.getFieldExtras( fieldName ) ;
- final String ext = "." + fieldName.toLowerCase();
- final OpenFileFilter off;
- if (s.equals("browseDocZip"))
- off = new OpenFileFilter(new String[]{ext, ext + ".gz", ext + ".bz2"});
- else
- off = new OpenFileFilter(new String[]{ext});
- return off;
- }
-
- /**
- * This method can be used to display a "rich" error dialog which offers the entire
- * stack trace for an exception.
- *
- * @param parent
- * @param e
- */
- public static void showQuickErrorDialog(JFrame parent, String title, Exception e) {
- // create and configure a text area - fill it with exception text.
- final JPanel pan = new JPanel(),
- details = new JPanel();
- final CardLayout crd = new CardLayout();
- pan.setLayout(crd);
- final JTextArea textArea = new JTextArea();
- textArea.setFont(new Font("Sans-Serif", Font.PLAIN, 10));
- textArea.setEditable(false);
- StringWriter writer = new StringWriter();
- e.printStackTrace(new PrintWriter(writer));
- textArea.setText(writer.toString());
- JLabel lab = new JLabel(e.getMessage());
- JButton flip = new JButton(Globals.lang("Details"));
-
- FormLayout layout = new FormLayout("left:pref", "");
- DefaultFormBuilder builder = new DefaultFormBuilder(layout);
- builder.append(lab);
- builder.nextLine();
- builder.append(Box.createVerticalGlue());
- builder.nextLine();
- builder.append(flip);
- final JPanel simple = builder.getPanel();
-
- // stuff it in a scrollpane with a controlled size.
- JScrollPane scrollPane = new JScrollPane(textArea);
- scrollPane.setPreferredSize(new Dimension(350, 150));
- details.setLayout(new BorderLayout());
- details.add(scrollPane, BorderLayout.CENTER);
-
- flip.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent event) {
- crd.show(pan, "details");
- }
- });
- pan.add(simple, "simple");
- pan.add(details, "details");
- // pass the scrollpane to the joptionpane.
- JOptionPane.showMessageDialog(parent, pan, title, JOptionPane.ERROR_MESSAGE);
- }
-
- public static String wrapHTML(String s, final int lineWidth) {
- StringBuffer sb = new StringBuffer();
- StringTokenizer tok = new StringTokenizer(s);
- int charsLeft = lineWidth;
- while (tok.hasMoreTokens()) {
- String word = tok.nextToken();
- if (charsLeft == lineWidth) { // fresh line
- sb.append(word);
- charsLeft -= word.length();
- if (charsLeft <= 0) {
- sb.append("<br>\n");
- charsLeft = lineWidth;
- }
- } else { // continue previous line
- if (charsLeft < word.length() + 1) {
- sb.append("<br>\n");
- sb.append(word);
- if (word.length() >= lineWidth - 1) {
- sb.append("<br>\n");
- charsLeft = lineWidth;
- } else {
- sb.append(" ");
- charsLeft = lineWidth - word.length() - 1;
- }
- } else {
- sb.append(' ').append(word);
- charsLeft -= word.length() + 1;
- }
- }
+ entry.clearField(field);
+ ce.addEdit(new UndoableFieldChange(entry, field, oldVal, text));
}
- return sb.toString();
+ ce.end();
+ return ce;
}
/**
- * Creates a String containing the current date (and possibly time), formatted
- * according to the format set in preferences under the key "timeStampFormat".
- *
- * @return The date string.
- */
- public static String easyDateFormat()
- {
-// Date today = new Date();
- return easyDateFormat( new Date() ) ;
- }
-
- /**
- * Creates a readable Date string from the parameter date.
- * The format is set in preferences under the key "timeStampFormat".
- *
- * @return The formatted date string.
- */
- public static String easyDateFormat(Date date)
- {
- // first use, create an instance
- if (dateFormatter == null)
- {
- String format = Globals.prefs.get( "timeStampFormat" ) ;
- dateFormatter = new SimpleDateFormat( format ) ;
- }
- return dateFormatter.format(date);
- }
-
-
-
- public static void markEntry(BibtexEntry be, NamedCompound ce) {
- Object o = be.getField(BibtexFields.MARKED);
- if ((o != null) && (o.toString().indexOf(Globals.prefs.WRAPPED_USERNAME) >= 0))
- return;
- String newValue;
- if (o == null) {
- newValue = Globals.prefs.WRAPPED_USERNAME;
- } else {
- StringBuffer sb = new StringBuffer(o.toString());
- //sb.append(' ');
- sb.append(Globals.prefs.WRAPPED_USERNAME);
- newValue = sb.toString();
- }
- ce.addEdit(new UndoableFieldChange(be, BibtexFields.MARKED,
- be.getField(BibtexFields.MARKED), newValue));
- be.setField(BibtexFields.MARKED, newValue);
- }
-
- public static void unmarkEntry(BibtexEntry be, BibtexDatabase database, NamedCompound ce) {
- Object o = be.getField(BibtexFields.MARKED);
- if (o != null) {
- String s = o.toString();
- if (s.equals("0")) {
- unmarkOldStyle(be, database, ce);
- return;
- }
-
- int piv=0, hit;
- StringBuffer sb = new StringBuffer();
- while ((hit = s.indexOf(Globals.prefs.WRAPPED_USERNAME, piv)) >= 0) {
- if (hit > 0)
- sb.append(s.substring(piv, hit));
- piv = hit+Globals.prefs.WRAPPED_USERNAME.length();
- }
- if (piv < s.length()-1) {
- sb.append(s.substring(piv));
- }
- String newVal = sb.length()>0 ? sb.toString() : null;
- ce.addEdit(new UndoableFieldChange(be, BibtexFields.MARKED,
- be.getField(BibtexFields.MARKED), newVal));
- be.setField(BibtexFields.MARKED, newVal);
- }
- }
-
- /**
- * An entry is marked with a "0", not in the new style with user names. We want to
- * unmark it as transparently as possible. Since this shouldn't happen too often,
- * we do it by scanning the "owner" fields of the entire database, collecting all
- * user names. We then mark the entry for all users except the current one. Thus
- * only the user who unmarks will see that it is unmarked, and we get rid of the
- * old-style marking.
- * @param be
- * @param ce
- */
- private static void unmarkOldStyle(BibtexEntry be, BibtexDatabase database, NamedCompound ce) {
- TreeSet owners = new TreeSet();
- for (Iterator i=database.getEntries().iterator(); i.hasNext();) {
- BibtexEntry entry = (BibtexEntry)i.next();
- Object o = entry.getField(BibtexFields.OWNER);
- if (o != null)
- owners.add(o);
- //System.out.println("Owner: "+entry.getField(Globals.OWNER));
- }
- owners.remove(Globals.prefs.get("defaultOwner"));
- StringBuffer sb = new StringBuffer();
- for (Iterator i=owners.iterator(); i.hasNext();) {
- sb.append('[');
- sb.append(i.next().toString());
- sb.append(']');
- }
- String newVal = sb.toString();
- if (newVal.length() == 0)
- newVal = null;
- ce.addEdit(new UndoableFieldChange(be, BibtexFields.MARKED, be.getField(BibtexFields.MARKED), newVal));
- be.setField(BibtexFields.MARKED, newVal);
-
- }
-
- public static boolean isMarked(BibtexEntry be) {
- Object fieldVal = be.getField(BibtexFields.MARKED);
- if (fieldVal == null)
- return false;
- String s = (String)fieldVal;
- return (s.equals("0") || (s.indexOf(Globals.prefs.WRAPPED_USERNAME) >= 0));
- }
-
- /**
- * Make a list of supported character encodings that can encode all characters in the given String.
- * @param characters A String of characters that should be supported by the encodings.
- * @return A List of character encodings
- */
- public static List findEncodingsForString(String characters) {
- List encodings = new ArrayList();
- for (int i=0; i<Globals.ENCODINGS.length; i++) {
- CharsetEncoder encoder = Charset.forName(Globals.ENCODINGS[i]).newEncoder();
- if (encoder.canEncode(characters))
- encodings.add(Globals.ENCODINGS[i]);
- }
- return encodings;
- }
-
-}
+ * Make a list of supported character encodings that can encode all
+ * characters in the given String.
+ *
+ * @param characters
+ * A String of characters that should be supported by the
+ * encodings.
+ * @return A List of character encodings
+ */
+ public static List findEncodingsForString(String characters) {
+ List encodings = new ArrayList();
+ for (int i = 0; i < Globals.ENCODINGS.length; i++) {
+ CharsetEncoder encoder = Charset.forName(Globals.ENCODINGS[i]).newEncoder();
+ if (encoder.canEncode(characters))
+ encodings.add(Globals.ENCODINGS[i]);
+ }
+ return encodings;
+ }
+
+
+ /**
+ * Will convert a two digit year using the following scheme (describe at
+ * http://www.filemaker.com/help/02-Adding%20and%20view18.html):
+ *
+ * If a two digit year is encountered they are matched against the last 69
+ * years and future 30 years.
+ *
+ * For instance if it is the year 1992 then entering 23 is taken to be 1923
+ * but if you enter 23 in 1993 then it will evaluate to 2023.
+ *
+ * @param year
+ * The year to convert to 4 digits.
+ * @return
+ */
+ public static String toFourDigitYear(String year) {
+ if (thisYear == 0){
+ thisYear = Calendar.getInstance().get(Calendar.YEAR);
+ }
+ return toFourDigitYear(year, thisYear);
+ }
+
+ public static int thisYear;
+
+ /**
+ * Will convert a two digit year using the following scheme (describe at
+ * http://www.filemaker.com/help/02-Adding%20and%20view18.html):
+ *
+ * If a two digit year is encountered they are matched against the last 69
+ * years and future 30 years.
+ *
+ * For instance if it is the year 1992 then entering 23 is taken to be 1923
+ * but if you enter 23 in 1993 then it will evaluate to 2023.
+ *
+ * @param year
+ * The year to convert to 4 digits.
+ * @return
+ */
+ public static String toFourDigitYear(String year, int thisYear) {
+ if (year.length() != 2)
+ return year;
+ try {
+ int thisYearTwoDigits = thisYear % 100;
+ int thisCentury = thisYear - thisYearTwoDigits;
+
+ int yearNumber = Integer.parseInt(year);
+
+ if (yearNumber == thisYearTwoDigits) {
+ return String.valueOf(thisYear);
+ }
+ // 20 , 90
+ // 99 > 30
+ if ((yearNumber + 100 - thisYearTwoDigits) % 100 > 30) {
+ if (yearNumber < thisYearTwoDigits) {
+ return String.valueOf(thisCentury + yearNumber);
+ } else {
+ return String.valueOf(thisCentury - 100 + yearNumber);
+ }
+ } else {
+ if (yearNumber < thisYearTwoDigits) {
+ return String.valueOf(thisCentury + 100 + yearNumber);
+ } else {
+ return String.valueOf(thisCentury + yearNumber);
+ }
+ }
+ } catch (NumberFormatException e) {
+ return year;
+ }
+ }
+
+ /**
+ * Will return an integer indicating the month of the entry from 0 to 11.
+ *
+ * -1 signals a unknown month string.
+ *
+ * This method accepts three types of months given:
+ *
+ * - Single and Double Digit months from 1 to 12 (01 to 12)
+ *
+ * - 3 Digit BibTex strings (jan
+ *
+ * - Full English Month identifiers.
+ *
+ * @param month
+ * @return
+ */
+ public static int getMonthNumber(String month){
+
+ month = month.toLowerCase();
+
+ for (int i = 0; i < Globals.MONTHS.length; i++){
+ if (month.startsWith(Globals.MONTHS[i])){
+ return i;
+ }
+ }
+
+ try {
+ return Integer.parseInt(month) - 1;
+ } catch (NumberFormatException e){
+ }
+ return -1;
+ }
+}
\ No newline at end of file
diff --git a/src/java/net/sf/jabref/bst/BibtexCaseChanger.java b/src/java/net/sf/jabref/bst/BibtexCaseChanger.java
new file mode 100644
index 0000000..f36316d
--- /dev/null
+++ b/src/java/net/sf/jabref/bst/BibtexCaseChanger.java
@@ -0,0 +1,249 @@
+package net.sf.jabref.bst;
+
+
+public class BibtexCaseChanger {
+
+ String s;
+
+ char format;
+
+ boolean prevColon = true;
+
+ int n;
+
+ Warn warn;
+
+ BibtexCaseChanger(String s, char format, Warn warn) {
+ this.s = s;
+ this.format = format;
+ this.n = s.length();
+ this.warn = warn;
+ }
+
+ public static String changeCase(String s, char format, Warn warn) {
+ return (new BibtexCaseChanger(s, format, warn)).changeCase();
+ }
+
+ private String changeCase() {
+ char[] c = s.toCharArray();
+
+ StringBuffer sb = new StringBuffer();
+
+ int i = 0;
+
+ while (i < n) {
+ if (c[i] == '{') {
+ braceLevel++;
+ if (braceLevel != 1 || i + 4 > n || c[i + 1] != '\\') {
+ prevColon = false;
+ sb.append(c[i]);
+ i++;
+ continue;
+ }
+ if (format == 't' && (i == 0 || (prevColon && Character.isWhitespace(c[i - 1])))) {
+ sb.append(c[i]);
+ i++;
+ prevColon = false;
+ continue;
+ }
+ i = convertSpecialChar(sb, c, i, format);
+ continue;
+ }
+ if (c[i] == '}') {
+ sb.append(c[i]);
+ i++;
+ braceLevel = decrBraceLevel(s, braceLevel);
+ prevColon = false;
+ continue;
+ }
+ if (braceLevel == 0) {
+ i = convertChar0(c, i, sb, format);
+ continue;
+ }
+ sb.append(c[i]);
+ i++;
+ }
+ checkBrace(s, braceLevel);
+ return sb.toString();
+ }
+
+ int braceLevel = 0;
+
+ int decrBraceLevel(String string, int braceLevel) {
+ if (braceLevel == 0) {
+ complain(string);
+ } else {
+ braceLevel--;
+ }
+ return braceLevel;
+ }
+
+ static void complain(String s) {
+ System.out.println("Warning -- String is not brace-balanced: " + s);
+ }
+
+ static void checkBrace(String s, int braceLevel) {
+ if (braceLevel > 0) {
+ complain(s);
+ }
+ }
+
+ /**
+ * We're dealing with a special character (usually either an undotted `\i'
+ * or `\j', or an accent like one in Table~3.1 of the \LaTeX\ manual, or a
+ * foreign character like one in Table~3.2) if the first character after the
+ * |left_brace| is a |backslash|; the special character ends with the
+ * matching |right_brace|. How we handle what's in between depends on the
+ * special character. In general, this code will do reasonably well if there
+ * is other stuff, too, between braces, but it doesn't try to do anything
+ * special with |colon|s.
+ *
+ * @param c
+ * @param i
+ * @param format
+ * @return
+ */
+ public int convertSpecialChar(StringBuffer sb, char[] c, int i, char format) {
+
+ sb.append(c[i]); i++; // skip over open brace
+
+ while (i < c.length && braceLevel > 0) {
+ sb.append(c[i]); i++;
+ // skip over the |backslash|
+
+ String s = findSpecialChar(c, i);
+ if (s != null) {
+ i = convertAccented(c, i, s, sb, format);
+ }
+
+ while (i < c.length && braceLevel > 0 && c[i] != '\\') {
+ if (c[i] == '}')
+ braceLevel--;
+ else if (c[i] == '{') {
+ braceLevel++;
+ }
+ i = convertNonControl(c, i, sb, format);
+ }
+ }
+ return i;
+ }
+
+ /**
+ * Convert the given string according to the format character (title, lower,
+ * up) and append the result to the stringBuffer, return the updated
+ * position.
+ *
+ * @param c
+ * @param pos
+ * @param s
+ * @param sb
+ * @param format
+ * @return
+ */
+ int convertAccented(char[] c, int pos, String s, StringBuffer sb, char format) {
+ pos += s.length();
+
+ switch (format) {
+ case TITLE_LOWERS:
+ case ALL_LOWERS:
+ if ("L O OE AE AA".indexOf(s) != -1)
+ sb.append(s.toLowerCase());
+ else
+ sb.append(s);
+ break;
+ case ALL_UPPERS:
+ if ("l o oe ae aa".indexOf(s) != -1)
+ sb.append(s.toUpperCase());
+ else if ("i j ss".indexOf(s) != -1) {
+
+ sb.deleteCharAt(sb.length() - 1); // Kill backslash
+ sb.append(s.toUpperCase());
+ while (pos < c.length && Character.isWhitespace(c[pos])) {
+ pos++;
+ }
+ } else {
+ sb.append(s);
+ }
+ break;
+ }
+ return pos;
+ }
+
+ int convertNonControl(char[] c, int pos, StringBuffer sb, char format) {
+ switch (format) {
+ case TITLE_LOWERS:
+ case ALL_LOWERS:
+ sb.append(Character.toLowerCase(c[pos]));
+ pos++;
+ break;
+ case ALL_UPPERS:
+ sb.append(Character.toUpperCase(c[pos]));
+ pos++;
+ break;
+ }
+ return pos;
+ }
+
+ public final static char TITLE_LOWERS = 't';
+
+ public final static char ALL_LOWERS = 'l';
+
+ public final static char ALL_UPPERS = 'u';
+
+ int convertChar0(char[] c, int i, StringBuffer sb, char format) {
+ switch (format) {
+ case TITLE_LOWERS:
+ if (i == 0) {
+ sb.append(c[i]);
+ } else if (prevColon && Character.isWhitespace(c[i - 1])) {
+ sb.append(c[i]);
+ } else {
+ sb.append(Character.toLowerCase(c[i]));
+ }
+ if (c[i] == ':')
+ prevColon = true;
+ else if (!Character.isWhitespace(c[i]))
+ prevColon = false;
+ break;
+ case ALL_LOWERS:
+ sb.append(Character.toLowerCase(c[i]));
+ break;
+ case ALL_UPPERS:
+ sb.append(Character.toUpperCase(c[i]));
+ }
+ i++;
+ return i;
+ }
+
+ static String findSpecialChar(char[] c, int pos) {
+ if (pos + 1 < c.length) {
+ if (c[pos] == 'o' && c[pos + 1] == 'e')
+ return "oe";
+ if (c[pos] == 'O' && c[pos + 1] == 'E')
+ return "OE";
+ if (c[pos] == 'a' && c[pos + 1] == 'e')
+ return "ae";
+ if (c[pos] == 'A' && c[pos + 1] == 'E')
+ return "AE";
+ if (c[pos] == 's' && c[pos + 1] == 's')
+ return "ss";
+ if (c[pos] == 'A' && c[pos + 1] == 'A')
+ return "AA";
+ if (c[pos] == 'a' && c[pos + 1] == 'a')
+ return "aa";
+ }
+ if (c[pos] == 'i')
+ return String.valueOf(c[pos]);
+ if (c[pos] == 'j')
+ return String.valueOf(c[pos]);
+ if (c[pos] == 'o')
+ return String.valueOf(c[pos]);
+ if (c[pos] == 'O')
+ return String.valueOf(c[pos]);
+ if (c[pos] == 'l')
+ return String.valueOf(c[pos]);
+ if (c[pos] == 'L')
+ return String.valueOf(c[pos]);
+ return null;
+ }
+}
diff --git a/src/java/net/sf/jabref/bst/BibtexNameFormatter.java b/src/java/net/sf/jabref/bst/BibtexNameFormatter.java
new file mode 100644
index 0000000..b439979
--- /dev/null
+++ b/src/java/net/sf/jabref/bst/BibtexNameFormatter.java
@@ -0,0 +1,304 @@
+package net.sf.jabref.bst;
+
+import net.sf.jabref.AuthorList;
+import net.sf.jabref.AuthorList.Author;
+
+/**
+ * From Bibtex:
+ *
+ * "The |built_in| function {\.{format.name\$}} pops the
+ * top three literals (they are a string, an integer, and a string
+ * literal, in that order). The last string literal represents a
+ * name list (each name corresponding to a person), the integer
+ * literal specifies which name to pick from this list, and the
+ * first string literal specifies how to format this name, as
+ * described in the \BibTeX\ documentation. Finally, this function
+ * pushes the formatted name. If any of the types is incorrect, it
+ * complains and pushes the null string."
+ *
+ * Sounds easy - is a nightmare... X-(
+ *
+ */
+public class BibtexNameFormatter {
+
+ public static String formatName(String authorsNameList, int whichName, String formatString, Warn warn){
+ AuthorList al = AuthorList.getAuthorList(authorsNameList);
+
+ if (whichName < 1 && whichName > al.size()){
+ warn.warn("AuthorList " + authorsNameList + " does not contain an author with number " + whichName);
+ return "";
+ }
+ return formatName(al.getAuthor(whichName-1), formatString, warn);
+ }
+
+ /**
+ *
+ * @param author
+ * @param format
+ * @param warn may-be-null
+ * @return
+ */
+ public static String formatName(Author author, String format, Warn warn) {
+
+ StringBuffer sb = new StringBuffer();
+
+ char[] c = format.toCharArray();
+ int n = c.length;
+ int braceLevel = 0;
+ int group = 0;
+
+ int i = 0;
+ while (i < n){
+ if (c[i] == '{'){
+ group++;
+ int groupStart = sb.length();
+ i++;
+ braceLevel++;
+ StringBuffer level1Chars = new StringBuffer();
+ StringBuffer wholeChar = new StringBuffer();
+ while (i < n && braceLevel > 0){
+ wholeChar.append(c[i]);
+ if (c[i] == '{'){
+ braceLevel++; i++; continue;
+ }
+ if (c[i] == '}'){
+ braceLevel--; i++; continue;
+ }
+ if (braceLevel == 1){
+ if (Character.isLetter(c[i])){
+ if ("fvlj".indexOf(c[i]) == -1){
+ if (warn != null)
+ warn.warn("Format String in format.name$ may only contain fvlj on brace level 1 in group " + group + ": " + format);
+ } else
+ level1Chars.append(c[i]);
+ }
+ }
+ i++;
+ }
+ i--; // unskip last brace (for last i++ at the end)
+ String control = level1Chars.toString().toLowerCase();
+
+ if (control.length() == 0)
+ continue;
+
+ if (control.length() > 2 && warn != null)
+ warn.warn("Format String in format.name$ may only be one or two character long on brace level 1 in group " + group + ": " + format);
+
+ char type = control.charAt(0);
+
+ String tokenS;
+ switch(type){
+ case 'f': tokenS = author.getFirst(); break;
+ case 'v': tokenS = author.getVon(); break;
+ case 'l': tokenS = author.getLast(); break;
+ case 'j': tokenS = author.getJr(); break;
+ default: throw new VMException("Internal error");
+ }
+
+ if (tokenS == null){
+ i++;
+ continue;
+ }
+ String[] tokens = tokenS.split(" ");
+
+ boolean abbreviateThatIsSingleLetter = true;
+
+ if (control.length() == 2){
+ if (control.charAt(1) == control.charAt(0)){
+ abbreviateThatIsSingleLetter = false;
+ } else {
+ if (warn != null)
+ warn.warn("Format String in format.name$ may only contain one type of vlfj on brace level 1 in group " + group + ": " + format);
+ }
+ }
+
+ // Now we know what to do
+
+ if (braceLevel == 0 && wholeChar.charAt(wholeChar.length() - 1) == '}'){
+ wholeChar.deleteCharAt(wholeChar.length() - 1);
+ }
+
+ char[] d = wholeChar.toString().toCharArray();
+
+ int bLevel = 1;
+
+ String interToken = null;
+
+ for (int j = 0; j < d.length; j++){
+
+ if (Character.isLetter(d[j]) && bLevel == 1){
+ groupStart = sb.length();
+ if (!abbreviateThatIsSingleLetter){
+ j++;
+ }
+ if (j+1 < d.length){
+ if (d[j+1] == '{'){
+ StringBuffer interTokenSb = new StringBuffer();
+ j = consumeToMatchingBrace(interTokenSb, d, j+1);
+ interToken = interTokenSb.substring(1,interTokenSb.length()-1);
+ }
+ }
+
+ for (int k = 0; k < tokens.length; k++){
+ String token = tokens[k];
+ if (abbreviateThatIsSingleLetter){
+ String[] dashes = token.split("-");
+
+ StringBuffer abbToken = new StringBuffer();
+ for (int t = 0; t < dashes.length - 1; t++){
+ abbToken.append(getFirstCharOfString(dashes[t])).append(".-");
+ }
+ if (dashes.length > 0)
+ abbToken.append(getFirstCharOfString(dashes[dashes.length - 1]));
+
+ token = abbToken.toString();
+ }
+
+ // Output token
+ sb.append(token);
+
+ if (k < tokens.length - 1){
+ // Output Intertoken String
+ if (interToken == null){
+ if (abbreviateThatIsSingleLetter){
+ sb.append(".");
+ }
+ // No clue what this means (What the hell are tokens anyway???
+ // if (lex_class[name_sep_char[cur_token]] = sep_char) then
+ // append_ex_buf_char_and_check (name_sep_char[cur_token])
+ if (k == tokens.length - 2 || numberOfChars(sb.substring(groupStart, sb.length()), 3) < 3){
+ sb.append("~");
+ } else {
+ sb.append(" ");
+ }
+ } else {
+ sb.append(interToken);
+ }
+ }
+ }
+ } else if (d[j] == '}'){
+ bLevel--;
+ if (bLevel > 0){
+ sb.append('}');
+ }
+ } else if (d[j] == '{'){
+ bLevel++;
+ sb.append('{');
+ } else {
+ sb.append(d[j]);
+ }
+ }
+ if (sb.length() > 0){
+ boolean noDisTie = false;
+ if (sb.charAt(sb.length() - 1) == '~' &&
+ (numberOfChars(sb.substring(groupStart, sb.length()), 4) >= 4 ||
+ (sb.length() > 1 && (noDisTie = sb.charAt(sb.length() - 2) == '~')))){
+ sb.deleteCharAt(sb.length() - 1);
+ if (!noDisTie)
+ sb.append(' ');
+ }
+ }
+ } else if (c[i] == '}'){
+ if (warn != null)
+ warn.warn("Unmatched brace in format string: " + format);
+ } else {
+ sb.append(c[i]); // verbatim
+ }
+ i++;
+ }
+ if (braceLevel != 0)
+ warn.warn("Unbalanced brace in format string for nameFormat: " + format);
+
+ return sb.toString();
+ }
+
+ /**
+ * Including the matching brace.
+ *
+ * @param sb
+ * @param c
+ * @param pos
+ * @return
+ *
+ * assert c[pos] == '{'
+ */
+ public static int consumeToMatchingBrace(StringBuffer sb, char[] c, int pos){
+
+ int braceLevel = 0;
+
+ // assert c[pos] == '{';
+
+ for (int i = pos; i < c.length; i++){
+ if (c[i] == '}'){
+ braceLevel--;
+ if (braceLevel == 0){
+ sb.append('}');
+ return i;
+ }
+ } else if (c[i] == '{'){
+ braceLevel++;
+ }
+ sb.append(c[i]);
+ }
+ return c.length;
+ }
+
+ /**
+ * Takes care of special characters too
+ *
+ * @param s
+ * @return
+ */
+ public static String getFirstCharOfString(String s){
+ char[] c = s.toCharArray();
+ for (int i = 0; i < c.length; i++){
+ if (Character.isLetter(c[i])){
+ return String.valueOf(c[i]);
+ }
+ if (c[i] == '{'){
+ if (i+1 < c.length && c[i+1] == '\\'){
+ StringBuffer sb = new StringBuffer();
+ consumeToMatchingBrace(sb, c, i);
+ return sb.toString();
+ }
+ }
+ }
+ return "";
+ }
+
+ public static int numberOfChars(String token, int stop) {
+
+ if (stop < 0)
+ stop = Integer.MAX_VALUE;
+
+ int result = 0;
+ int i = 0;
+ char[] c = token.toCharArray();
+ int n = c.length;
+
+ int braceLevel = 0;
+ while (i < n && result < stop){
+ i++;
+ if (c[i-1] == '{'){
+ braceLevel++;
+ if (braceLevel == 1 && i < n && c[i] == '\\'){
+ i++;
+ while (i < n && braceLevel > 0){
+ if (c[i] == '}'){
+ braceLevel--;
+ } else if (c[i] == '{'){
+ braceLevel++;
+ }
+ i++;
+ }
+ }
+ } else if (c[i-1] == '}'){
+ braceLevel--;
+ }
+ result++;
+ }
+ return result;
+ }
+
+
+}
diff --git a/src/java/net/sf/jabref/bst/BibtexPurify.java b/src/java/net/sf/jabref/bst/BibtexPurify.java
new file mode 100644
index 0000000..70f5530
--- /dev/null
+++ b/src/java/net/sf/jabref/bst/BibtexPurify.java
@@ -0,0 +1,84 @@
+// $Id: BibtexPurify.java,v 1.1 2006/11/11 17:11:39 coezbek Exp $
+package net.sf.jabref.bst;
+
+
+/**
+ *
+ * The |built_in| function {\.{purify\$}} pops the top (string) literal, removes
+ * nonalphanumeric characters except for |white_space| and |sep_char| characters
+ * (these get converted to a |space|) and removes certain alphabetic characters
+ * contained in the control sequences associated with a special character, and
+ * pushes the resulting string. If the literal isn't a string, it complains and
+ * pushes the null string.
+ *
+ * @author $Author: coezbek $
+ * @version $Revision: 1.1 $ ($Date: 2006/11/11 17:11:39 $)
+ *
+ */
+public class BibtexPurify {
+
+ /**
+ *
+ * @param toPurify
+ * @param warn
+ * may-be-null
+ * @return
+ */
+ public static String purify(String toPurify, Warn warn) {
+
+ StringBuffer sb = new StringBuffer();
+
+ char[] cs = toPurify.toCharArray();
+ int n = cs.length;
+ int i = 0;
+
+ int braceLevel = 0;
+
+ while (i < n) {
+ char c = cs[i];
+ if (Character.isWhitespace(c) || c == '-' || c == '~') {
+ sb.append(' ');
+ } else if (Character.isLetterOrDigit(c)) {
+ sb.append(c);
+ } else if (c == '{') {
+ braceLevel++;
+ if (braceLevel == 1 && i + 1 < n && (cs[i + 1] == '\\')) {
+ i++; // skip brace
+ while (i < n && braceLevel > 0) {
+ i++; // skip backslash
+ String specialStart = BibtexCaseChanger.findSpecialChar(cs, i);
+ if (specialStart != null) {
+ sb.append(specialStart);
+ }
+ while (i < n && Character.isLetter(cs[i])) {
+ i++;
+ }
+ while (i < n && braceLevel > 0 && (c = cs[i]) != '\\') {
+ if (Character.isLetterOrDigit(c)) {
+ sb.append(c);
+ } else if (c == '}') {
+ braceLevel--;
+ } else if (c == '{') {
+ braceLevel++;
+ }
+ i++;
+ }
+ }
+ continue;
+ }
+ } else if (c == '}') {
+ if (braceLevel > 0) {
+ braceLevel--;
+ } else {
+ if (warn != null)
+ warn.warn("Unbalanced brace in string for purify$: " + toPurify);
+ }
+ }
+ i++;
+ }
+ if (braceLevel != 0 && warn != null)
+ warn.warn("Unbalanced brace in string for purify$: " + toPurify);
+
+ return sb.toString();
+ }
+}
diff --git a/src/java/net/sf/jabref/bst/BibtexTextPrefix.java b/src/java/net/sf/jabref/bst/BibtexTextPrefix.java
new file mode 100644
index 0000000..f4e20fb
--- /dev/null
+++ b/src/java/net/sf/jabref/bst/BibtexTextPrefix.java
@@ -0,0 +1,78 @@
+// $Id: BibtexTextPrefix.java,v 1.1 2006/11/11 17:11:39 coezbek Exp $
+package net.sf.jabref.bst;
+
+
+/**
+ * The |built_in| function {\.{text.prefix\$}} pops the top two literals (the
+ * integer literal |pop_lit1| and a string literal, in that order). It pushes
+ * the substring of the (at most) |pop_lit1| consecutive text characters
+ * starting from the beginning of the string. This function is similar to
+ * {\.{substring\$}}, but this one considers an accented character (or more
+ * precisely, a ``special character''$\!$, even if it's missing its matching
+ * |right_brace|) to be a single text character (rather than however many
+ * |ASCII_code| characters it actually comprises), and this function doesn't
+ * consider braces to be text characters; furthermore, this function appends any
+ * needed matching |right_brace|s. If any of the types is incorrect, it
+ * complains and pushes the null string.
+ *
+ * @author $Author: coezbek $
+ * @version $Revision: 1.1 $ ($Date: 2006/11/11 17:11:39 $)
+ *
+ */
+public class BibtexTextPrefix {
+
+ /**
+ *
+ * @param numOfChars
+ * @param toPrefix
+ * @param warn may-be-null
+ * @return
+ */
+ public static String textPrefix(int numOfChars, String toPrefix, Warn warn) {
+
+ StringBuffer sb = new StringBuffer();
+
+ char[] cs = toPrefix.toCharArray();
+ int n = cs.length;
+ int i = 0;
+
+ int braceLevel = 0;
+
+ while (i < n && numOfChars > 0) {
+ char c = cs[i];
+ i++;
+ if (c == '{') {
+ braceLevel++;
+ if (braceLevel == 1 && i < n && (cs[i] == '\\')) {
+ i++; // skip backslash
+ while (i < n && braceLevel > 0) {
+ if (cs[i] == '}') {
+ braceLevel--;
+ } else if (cs[i] == '{') {
+ braceLevel++;
+ }
+ i++;
+ }
+ numOfChars--;
+ }
+ } else if (c == '}') {
+ if (braceLevel > 0) {
+ braceLevel--;
+ } else {
+ if (warn != null)
+ warn.warn("Unbalanced brace in string for purify$: " + toPrefix);
+ }
+ } else {
+ numOfChars--;
+ }
+
+ }
+ sb.append(toPrefix.substring(0, i));
+ while (braceLevel > 0){
+ sb.append('}');
+ braceLevel--;
+ }
+
+ return sb.toString();
+ }
+}
diff --git a/src/java/net/sf/jabref/bst/BibtexWidth.java b/src/java/net/sf/jabref/bst/BibtexWidth.java
new file mode 100644
index 0000000..002762c
--- /dev/null
+++ b/src/java/net/sf/jabref/bst/BibtexWidth.java
@@ -0,0 +1,241 @@
+// $Id: BibtexWidth.java,v 1.1 2006/11/11 17:11:39 coezbek Exp $
+package net.sf.jabref.bst;
+
+
+/**
+ *
+ * The |built_in| function {\.{purify\$}} pops the top (string) literal, removes
+ * nonalphanumeric characters except for |white_space| and |sep_char| characters
+ * (these get converted to a |space|) and removes certain alphabetic characters
+ * contained in the control sequences associated with a special character, and
+ * pushes the resulting string. If the literal isn't a string, it complains and
+ * pushes the null string.
+ *
+ * @author $Author: coezbek $
+ * @version $Revision: 1.1 $ ($Date: 2006/11/11 17:11:39 $)
+ *
+ */
+public class BibtexWidth {
+
+ /*
+ * Quoted from Bibtex:
+ *
+ * Now we initialize the system-dependent |char_width| array, for which
+ * |space| is the only |white_space| character given a nonzero printing
+ * width. The widths here are taken from Stanford's June~'87 $cmr10$~font
+ * and represent hundredths of a point (rounded), but since they're used
+ * only for relative comparisons, the units have no meaning.
+ */
+
+ static int[] widths;
+
+ static int getSpecialCharWidth(char[] c, int pos) {
+ if (pos + 1 < c.length) {
+ if (c[pos] == 'o' && c[pos + 1] == 'e')
+ return 778;
+ if (c[pos] == 'O' && c[pos + 1] == 'E')
+ return 1014;
+ if (c[pos] == 'a' && c[pos + 1] == 'e')
+ return 722;
+ if (c[pos] == 'A' && c[pos + 1] == 'E')
+ return 903;
+ if (c[pos] == 's' && c[pos + 1] == 's')
+ return 500;
+ }
+ return getCharWidth(c[pos]);
+ }
+
+ public static int getCharWidth(char c) {
+
+ if (widths == null) {
+ // Watch out octals!!
+ widths = new int[0200];
+
+ for (int i = 0; i < 0200; i++) {
+ widths[i] = 0;
+ }
+ // Watch out octals!!
+ widths[040] = 278;
+ widths[041] = 278;
+ widths[042] = 500;
+ widths[043] = 833;
+ widths[044] = 500;
+ widths[045] = 833;
+ widths[046] = 778;
+ widths[047] = 278;
+ widths[050] = 389;
+ widths[051] = 389;
+ widths[052] = 500;
+ widths[053] = 778;
+ widths[054] = 278;
+ widths[055] = 333;
+ widths[056] = 278;
+ widths[057] = 500;
+ widths[060] = 500;
+ widths[061] = 500;
+ widths[062] = 500;
+ widths[063] = 500;
+ widths[064] = 500;
+ widths[065] = 500;
+ widths[066] = 500;
+ widths[067] = 500;
+ widths[070] = 500;
+ widths[071] = 500;
+ widths[072] = 278;
+ widths[073] = 278;
+ widths[074] = 278;
+ widths[075] = 778;
+ widths[076] = 472;
+ widths[077] = 472;
+ widths[0100] = 778;
+ widths[0101] = 750;
+ widths[0102] = 708;
+ widths[0103] = 722;
+ widths[0104] = 764;
+ widths[0105] = 681;
+ widths[0106] = 653;
+ widths[0107] = 785;
+ widths[0110] = 750;
+ widths[0111] = 361;
+ widths[0112] = 514;
+ widths[0113] = 778;
+ widths[0114] = 625;
+ widths[0115] = 917;
+ widths[0116] = 750;
+ widths[0117] = 778;
+ widths[0120] = 681;
+ widths[0121] = 778;
+ widths[0122] = 736;
+ widths[0123] = 556;
+ widths[0124] = 722;
+ widths[0125] = 750;
+ widths[0126] = 750;
+ widths[0127] = 1028;
+ widths[0130] = 750;
+ widths[0131] = 750;
+ widths[0132] = 611;
+ widths[0133] = 278;
+ widths[0134] = 500;
+ widths[0135] = 278;
+ widths[0136] = 500;
+ widths[0137] = 278;
+ widths[0140] = 278;
+ widths[0141] = 500;
+ widths[0142] = 556;
+ widths[0143] = 444;
+ widths[0144] = 556;
+ widths[0145] = 444;
+ widths[0146] = 306;
+ widths[0147] = 500;
+ widths[0150] = 556;
+ widths[0151] = 278;
+ widths[0152] = 306;
+ widths[0153] = 528;
+ widths[0154] = 278;
+ widths[0155] = 833;
+ widths[0156] = 556;
+ widths[0157] = 500;
+ widths[0160] = 556;
+ widths[0161] = 528;
+ widths[0162] = 392;
+ widths[0163] = 394;
+ widths[0164] = 389;
+ widths[0165] = 556;
+ widths[0166] = 528;
+ widths[0167] = 722;
+ widths[0170] = 528;
+ widths[0171] = 528;
+ widths[0172] = 444;
+ widths[0173] = 500;
+ widths[0174] = 1000;
+ widths[0175] = 500;
+ widths[0176] = 500;
+ }
+
+ if (0 <= c && c < 0200) {
+ return widths[c];
+ } else {
+ return 0;
+ }
+ }
+
+ /**
+ *
+ * @param toMeasure
+ * @param warn
+ * may-be-null
+ * @return
+ */
+ public static int width(String toMeasure, Warn warn) {
+
+ /*
+ * From Bibtex: We use the natural width for all but special characters,
+ * and we complain if the string isn't brace-balanced.
+ */
+
+ int i = 0;
+ int n = toMeasure.length();
+ int braceLevel = 0;
+ char[] c = toMeasure.toCharArray();
+ int result = 0;
+
+
+ /*
+ * From Bibtex:
+ *
+ * We use the natural widths of all characters except that some
+ * characters have no width: braces, control sequences (except for the
+ * usual 13 accented and foreign characters, whose widths are given in
+ * the next module), and |white_space| following control sequences (even
+ * a null control sequence).
+ *
+ */
+ while (i < n){
+ if (c[i] == '{'){
+ braceLevel++;
+ if (braceLevel == 1 && i + 1 < n && (c[i+1] == '\\')){
+ i++; // skip brace
+ while (i < n && braceLevel > 0){
+ i++; // skip backslash
+
+ int afterBackslash = i;
+ while (i < n && Character.isLetter(c[i])){
+ i++;
+ }
+ if (i < n && i == afterBackslash){
+ i++; // Skip non-alpha control seq
+ } else {
+ if (BibtexCaseChanger.findSpecialChar(c, afterBackslash) != null) {
+ result += getSpecialCharWidth(c, afterBackslash);
+ }
+ }
+ while (i < n && Character.isWhitespace(c[i])){
+ i++;
+ }
+ while (i < n && braceLevel > 0 && c[i] != '\\'){
+ if (c[i] == '}'){
+ braceLevel--;
+ } else
+ if (c[i] == '{'){
+ braceLevel++;
+ } else
+ result += getCharWidth(c[i]);
+ i++;
+ }
+ }
+ continue;
+ }
+ } else if (c[i] == '}'){
+ if (braceLevel > 0){
+ braceLevel--;
+ } else {
+ BibtexCaseChanger.complain(toMeasure);
+ }
+ }
+ result += getCharWidth(c[i]);
+ i++;
+ }
+ BibtexCaseChanger.checkBrace(toMeasure, braceLevel);
+ return result;
+ }
+}
diff --git a/src/java/net/sf/jabref/bst/Bst.java b/src/java/net/sf/jabref/bst/Bst.java
new file mode 100644
index 0000000..708a0c1
--- /dev/null
+++ b/src/java/net/sf/jabref/bst/Bst.java
@@ -0,0 +1,1943 @@
+package net.sf.jabref.bst;
+// $ANTLR 3.0b4 bst.g 2006-09-17 01:45:41
+
+import org.antlr.runtime.*;
+import java.util.Stack;
+import java.util.List;
+import java.util.ArrayList;
+
+
+import org.antlr.runtime.tree.*;
+
+public class Bst extends Parser {
+ public static final String[] tokenNames = new String[] {
+ "<invalid>", "<EOR>", "<DOWN>", "<UP>", "IDLIST", "STACK", "ENTRY", "COMMANDS", "STRINGS", "INTEGERS", "FUNCTION", "MACRO", "STRING", "READ", "EXECUTE", "ITERATE", "REVERSE", "SORT", "IDENTIFIER", "INTEGER", "QUOTED", "LETTER", "NUMERAL", "WS", "LINE_COMMENT", "'{'", "'}'", "'<'", "'>'", "'='", "'+'", "'-'", "':='", "'*'", "'add.period$'", "'call.type$'", "'change.case$'", "'chr.to.int$'", "'cite$'", "'duplicat$'", "'empty$'", "'format.name$'", "'if$'", "'int.to.chr$'", "'int.to. [...]
+ };
+ public static final int LETTER=21;
+ public static final int ENTRY=6;
+ public static final int INTEGERS=9;
+ public static final int WS=23;
+ public static final int COMMANDS=7;
+ public static final int STRING=12;
+ public static final int EXECUTE=14;
+ public static final int LINE_COMMENT=24;
+ public static final int SORT=17;
+ public static final int STACK=5;
+ public static final int REVERSE=16;
+ public static final int QUOTED=20;
+ public static final int INTEGER=19;
+ public static final int ITERATE=15;
+ public static final int FUNCTION=10;
+ public static final int EOF=-1;
+ public static final int STRINGS=8;
+ public static final int IDENTIFIER=18;
+ public static final int MACRO=11;
+ public static final int IDLIST=4;
+ public static final int NUMERAL=22;
+ public static final int READ=13;
+
+ public Bst(TokenStream input) {
+ super(input);
+ }
+
+ protected TreeAdaptor adaptor = new CommonTreeAdaptor();
+
+ public void setTreeAdaptor(TreeAdaptor adaptor) {
+ this.adaptor = adaptor;
+ }
+ public TreeAdaptor getTreeAdaptor() {
+ return adaptor;
+ }
+
+ public String[] getTokenNames() { return tokenNames; }
+ public String getGrammarFileName() { return "bst.g"; }
+
+
+ public static class program_return extends ParserRuleReturnScope {
+ Object tree;
+ public Object getTree() { return tree; }
+ };
+
+ // $ANTLR start program
+ // bst.g:14:1: program : ( commands )+ -> ^( COMMANDS ( commands )+ ) ;
+ public program_return program() throws RecognitionException {
+ program_return retval = new program_return();
+ retval.start = input.LT(1);
+
+ Object root_0 = null;
+
+ commands_return commands1 = null;
+
+ List list_commands=new ArrayList();
+
+ try {
+ // bst.g:14:11: ( ( commands )+ -> ^( COMMANDS ( commands )+ ) )
+ // bst.g:14:11: ( commands )+
+ {
+ // bst.g:14:11: ( commands )+
+ int cnt1=0;
+ loop1:
+ do {
+ int alt1=2;
+ int LA1_0 = input.LA(1);
+ if ( (LA1_0==ENTRY||(LA1_0>=STRINGS && LA1_0<=MACRO)||(LA1_0>=READ && LA1_0<=SORT)) ) {
+ alt1=1;
+ }
+
+
+ switch (alt1) {
+ case 1 :
+ // bst.g:14:11: commands
+ {
+ pushFollow(FOLLOW_commands_in_program45);
+ commands1=commands();
+ _fsp--;
+
+ list_commands.add(commands1.tree);
+
+ }
+ break;
+
+ default :
+ if ( cnt1 >= 1 ) break loop1;
+ EarlyExitException eee =
+ new EarlyExitException(1, input);
+ throw eee;
+ }
+ cnt1++;
+ } while (true);
+
+
+ // AST REWRITE
+ int i_0 = 0;
+ retval.tree = root_0;
+ root_0 = (Object)adaptor.nil();
+ // 14:21: -> ^( COMMANDS ( commands )+ )
+ {
+ // bst.g:14:24: ^( COMMANDS ( commands )+ )
+ {
+ Object root_1 = (Object)adaptor.nil();
+ root_1 = (Object)adaptor.becomeRoot(adaptor.create(COMMANDS, "COMMANDS"), root_1);
+
+ // bst.g:14:35: ( commands )+
+ {
+ int n_1 = list_commands == null ? 0 : list_commands.size();
+
+
+
+ if ( n_1==0 ) throw new RuntimeException("Must have more than one element for (...)+ loops");
+ for (int i_1=0; i_1<n_1; i_1++) {
+ adaptor.addChild(root_1, list_commands.get(i_1));
+
+ }
+ }
+
+ adaptor.addChild(root_0, root_1);
+ }
+
+ }
+
+
+
+ }
+
+ }
+ catch (RecognitionException re) {
+ reportError(re);
+ recover(input,re);
+ }
+ finally {
+ retval.stop = input.LT(-1);
+
+ retval.tree = (Object)adaptor.rulePostProcessing(root_0);
+ adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop);
+
+ }
+ return retval;
+ }
+ // $ANTLR end program
+
+ public static class commands_return extends ParserRuleReturnScope {
+ Object tree;
+ public Object getTree() { return tree; }
+ };
+
+ // $ANTLR start commands
+ // bst.g:16:1: commands : ( STRINGS^^ idList | INTEGERS^^ idList | FUNCTION^^ id stack | MACRO^^ id '{'! STRING '}'! | READ^^ | EXECUTE^^ '{'! function '}'! | ITERATE^^ '{'! function '}'! | REVERSE^^ '{'! function '}'! | ENTRY^^ idList0 idList0 idList0 | SORT^^ );
+ public commands_return commands() throws RecognitionException {
+ commands_return retval = new commands_return();
+ retval.start = input.LT(1);
+
+ Object root_0 = null;
+
+ Token STRINGS2=null;
+ Token INTEGERS4=null;
+ Token FUNCTION6=null;
+ Token MACRO9=null;
+ Token char_literal11=null;
+ Token STRING12=null;
+ Token char_literal13=null;
+ Token READ14=null;
+ Token EXECUTE15=null;
+ Token char_literal16=null;
+ Token char_literal18=null;
+ Token ITERATE19=null;
+ Token char_literal20=null;
+ Token char_literal22=null;
+ Token REVERSE23=null;
+ Token char_literal24=null;
+ Token char_literal26=null;
+ Token ENTRY27=null;
+ Token SORT31=null;
+ idList_return idList3 = null;
+
+ idList_return idList5 = null;
+
+ id_return id7 = null;
+
+ stack_return stack8 = null;
+
+ id_return id10 = null;
+
+ function_return function17 = null;
+
+ function_return function21 = null;
+
+ function_return function25 = null;
+
+ idList0_return idList028 = null;
+
+ idList0_return idList029 = null;
+
+ idList0_return idList030 = null;
+
+
+ Object STRINGS2_tree=null;
+ Object INTEGERS4_tree=null;
+ Object FUNCTION6_tree=null;
+ Object MACRO9_tree=null;
+ Object char_literal11_tree=null;
+ Object STRING12_tree=null;
+ Object char_literal13_tree=null;
+ Object READ14_tree=null;
+ Object EXECUTE15_tree=null;
+ Object char_literal16_tree=null;
+ Object char_literal18_tree=null;
+ Object ITERATE19_tree=null;
+ Object char_literal20_tree=null;
+ Object char_literal22_tree=null;
+ Object REVERSE23_tree=null;
+ Object char_literal24_tree=null;
+ Object char_literal26_tree=null;
+ Object ENTRY27_tree=null;
+ Object SORT31_tree=null;
+
+ try {
+ // bst.g:17:4: ( STRINGS^^ idList | INTEGERS^^ idList | FUNCTION^^ id stack | MACRO^^ id '{'! STRING '}'! | READ^^ | EXECUTE^^ '{'! function '}'! | ITERATE^^ '{'! function '}'! | REVERSE^^ '{'! function '}'! | ENTRY^^ idList0 idList0 idList0 | SORT^^ )
+ int alt2=10;
+ switch ( input.LA(1) ) {
+ case STRINGS:
+ alt2=1;
+ break;
+ case INTEGERS:
+ alt2=2;
+ break;
+ case FUNCTION:
+ alt2=3;
+ break;
+ case MACRO:
+ alt2=4;
+ break;
+ case READ:
+ alt2=5;
+ break;
+ case EXECUTE:
+ alt2=6;
+ break;
+ case ITERATE:
+ alt2=7;
+ break;
+ case REVERSE:
+ alt2=8;
+ break;
+ case ENTRY:
+ alt2=9;
+ break;
+ case SORT:
+ alt2=10;
+ break;
+ default:
+ NoViableAltException nvae =
+ new NoViableAltException("16:1: commands : ( STRINGS^^ idList | INTEGERS^^ idList | FUNCTION^^ id stack | MACRO^^ id '{'! STRING '}'! | READ^^ | EXECUTE^^ '{'! function '}'! | ITERATE^^ '{'! function '}'! | REVERSE^^ '{'! function '}'! | ENTRY^^ idList0 idList0 idList0 | SORT^^ );", 2, 0, input);
+
+ throw nvae;
+ }
+
+ switch (alt2) {
+ case 1 :
+ // bst.g:17:4: STRINGS^^ idList
+ {
+ root_0 = (Object)adaptor.nil();
+
+ STRINGS2=(Token)input.LT(1);
+ match(input,STRINGS,FOLLOW_STRINGS_in_commands65);
+ STRINGS2_tree = (Object)adaptor.create(STRINGS2);
+ root_0 = (Object)adaptor.becomeRoot(STRINGS2_tree, root_0);
+
+ pushFollow(FOLLOW_idList_in_commands68);
+ idList3=idList();
+ _fsp--;
+
+ adaptor.addChild(root_0, idList3.tree);
+
+ }
+ break;
+ case 2 :
+ // bst.g:18:4: INTEGERS^^ idList
+ {
+ root_0 = (Object)adaptor.nil();
+
+ INTEGERS4=(Token)input.LT(1);
+ match(input,INTEGERS,FOLLOW_INTEGERS_in_commands73);
+ INTEGERS4_tree = (Object)adaptor.create(INTEGERS4);
+ root_0 = (Object)adaptor.becomeRoot(INTEGERS4_tree, root_0);
+
+ pushFollow(FOLLOW_idList_in_commands76);
+ idList5=idList();
+ _fsp--;
+
+ adaptor.addChild(root_0, idList5.tree);
+
+ }
+ break;
+ case 3 :
+ // bst.g:19:4: FUNCTION^^ id stack
+ {
+ root_0 = (Object)adaptor.nil();
+
+ FUNCTION6=(Token)input.LT(1);
+ match(input,FUNCTION,FOLLOW_FUNCTION_in_commands81);
+ FUNCTION6_tree = (Object)adaptor.create(FUNCTION6);
+ root_0 = (Object)adaptor.becomeRoot(FUNCTION6_tree, root_0);
+
+ pushFollow(FOLLOW_id_in_commands84);
+ id7=id();
+ _fsp--;
+
+ adaptor.addChild(root_0, id7.tree);
+ pushFollow(FOLLOW_stack_in_commands86);
+ stack8=stack();
+ _fsp--;
+
+ adaptor.addChild(root_0, stack8.tree);
+
+ }
+ break;
+ case 4 :
+ // bst.g:20:4: MACRO^^ id '{'! STRING '}'!
+ {
+ root_0 = (Object)adaptor.nil();
+
+ MACRO9=(Token)input.LT(1);
+ match(input,MACRO,FOLLOW_MACRO_in_commands91);
+ MACRO9_tree = (Object)adaptor.create(MACRO9);
+ root_0 = (Object)adaptor.becomeRoot(MACRO9_tree, root_0);
+
+ pushFollow(FOLLOW_id_in_commands94);
+ id10=id();
+ _fsp--;
+
+ adaptor.addChild(root_0, id10.tree);
+ char_literal11=(Token)input.LT(1);
+ match(input,25,FOLLOW_25_in_commands96);
+ STRING12=(Token)input.LT(1);
+ match(input,STRING,FOLLOW_STRING_in_commands99);
+ STRING12_tree = (Object)adaptor.create(STRING12);
+ adaptor.addChild(root_0, STRING12_tree);
+
+ char_literal13=(Token)input.LT(1);
+ match(input,26,FOLLOW_26_in_commands101);
+
+ }
+ break;
+ case 5 :
+ // bst.g:21:4: READ^^
+ {
+ root_0 = (Object)adaptor.nil();
+
+ READ14=(Token)input.LT(1);
+ match(input,READ,FOLLOW_READ_in_commands107);
+ READ14_tree = (Object)adaptor.create(READ14);
+ root_0 = (Object)adaptor.becomeRoot(READ14_tree, root_0);
+
+
+ }
+ break;
+ case 6 :
+ // bst.g:22:4: EXECUTE^^ '{'! function '}'!
+ {
+ root_0 = (Object)adaptor.nil();
+
+ EXECUTE15=(Token)input.LT(1);
+ match(input,EXECUTE,FOLLOW_EXECUTE_in_commands113);
+ EXECUTE15_tree = (Object)adaptor.create(EXECUTE15);
+ root_0 = (Object)adaptor.becomeRoot(EXECUTE15_tree, root_0);
+
+ char_literal16=(Token)input.LT(1);
+ match(input,25,FOLLOW_25_in_commands116);
+ pushFollow(FOLLOW_function_in_commands119);
+ function17=function();
+ _fsp--;
+
+ adaptor.addChild(root_0, function17.tree);
+ char_literal18=(Token)input.LT(1);
+ match(input,26,FOLLOW_26_in_commands121);
+
+ }
+ break;
+ case 7 :
+ // bst.g:23:4: ITERATE^^ '{'! function '}'!
+ {
+ root_0 = (Object)adaptor.nil();
+
+ ITERATE19=(Token)input.LT(1);
+ match(input,ITERATE,FOLLOW_ITERATE_in_commands127);
+ ITERATE19_tree = (Object)adaptor.create(ITERATE19);
+ root_0 = (Object)adaptor.becomeRoot(ITERATE19_tree, root_0);
+
+ char_literal20=(Token)input.LT(1);
+ match(input,25,FOLLOW_25_in_commands130);
+ pushFollow(FOLLOW_function_in_commands133);
+ function21=function();
+ _fsp--;
+
+ adaptor.addChild(root_0, function21.tree);
+ char_literal22=(Token)input.LT(1);
+ match(input,26,FOLLOW_26_in_commands135);
+
+ }
+ break;
+ case 8 :
+ // bst.g:24:4: REVERSE^^ '{'! function '}'!
+ {
+ root_0 = (Object)adaptor.nil();
+
+ REVERSE23=(Token)input.LT(1);
+ match(input,REVERSE,FOLLOW_REVERSE_in_commands141);
+ REVERSE23_tree = (Object)adaptor.create(REVERSE23);
+ root_0 = (Object)adaptor.becomeRoot(REVERSE23_tree, root_0);
+
+ char_literal24=(Token)input.LT(1);
+ match(input,25,FOLLOW_25_in_commands144);
+ pushFollow(FOLLOW_function_in_commands147);
+ function25=function();
+ _fsp--;
+
+ adaptor.addChild(root_0, function25.tree);
+ char_literal26=(Token)input.LT(1);
+ match(input,26,FOLLOW_26_in_commands149);
+
+ }
+ break;
+ case 9 :
+ // bst.g:25:4: ENTRY^^ idList0 idList0 idList0
+ {
+ root_0 = (Object)adaptor.nil();
+
+ ENTRY27=(Token)input.LT(1);
+ match(input,ENTRY,FOLLOW_ENTRY_in_commands155);
+ ENTRY27_tree = (Object)adaptor.create(ENTRY27);
+ root_0 = (Object)adaptor.becomeRoot(ENTRY27_tree, root_0);
+
+ pushFollow(FOLLOW_idList0_in_commands158);
+ idList028=idList0();
+ _fsp--;
+
+ adaptor.addChild(root_0, idList028.tree);
+ pushFollow(FOLLOW_idList0_in_commands160);
+ idList029=idList0();
+ _fsp--;
+
+ adaptor.addChild(root_0, idList029.tree);
+ pushFollow(FOLLOW_idList0_in_commands162);
+ idList030=idList0();
+ _fsp--;
+
+ adaptor.addChild(root_0, idList030.tree);
+
+ }
+ break;
+ case 10 :
+ // bst.g:26:4: SORT^^
+ {
+ root_0 = (Object)adaptor.nil();
+
+ SORT31=(Token)input.LT(1);
+ match(input,SORT,FOLLOW_SORT_in_commands167);
+ SORT31_tree = (Object)adaptor.create(SORT31);
+ root_0 = (Object)adaptor.becomeRoot(SORT31_tree, root_0);
+
+
+ }
+ break;
+
+ }
+ }
+ catch (RecognitionException re) {
+ reportError(re);
+ recover(input,re);
+ }
+ finally {
+ retval.stop = input.LT(-1);
+
+ retval.tree = (Object)adaptor.rulePostProcessing(root_0);
+ adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop);
+
+ }
+ return retval;
+ }
+ // $ANTLR end commands
+
+ public static class identifier_return extends ParserRuleReturnScope {
+ Object tree;
+ public Object getTree() { return tree; }
+ };
+
+ // $ANTLR start identifier
+ // bst.g:28:1: identifier : IDENTIFIER ;
+ public identifier_return identifier() throws RecognitionException {
+ identifier_return retval = new identifier_return();
+ retval.start = input.LT(1);
+
+ Object root_0 = null;
+
+ Token IDENTIFIER32=null;
+
+ Object IDENTIFIER32_tree=null;
+
+ try {
+ // bst.g:29:4: ( IDENTIFIER )
+ // bst.g:29:4: IDENTIFIER
+ {
+ root_0 = (Object)adaptor.nil();
+
+ IDENTIFIER32=(Token)input.LT(1);
+ match(input,IDENTIFIER,FOLLOW_IDENTIFIER_in_identifier178);
+ IDENTIFIER32_tree = (Object)adaptor.create(IDENTIFIER32);
+ adaptor.addChild(root_0, IDENTIFIER32_tree);
+
+
+ }
+
+ }
+ catch (RecognitionException re) {
+ reportError(re);
+ recover(input,re);
+ }
+ finally {
+ retval.stop = input.LT(-1);
+
+ retval.tree = (Object)adaptor.rulePostProcessing(root_0);
+ adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop);
+
+ }
+ return retval;
+ }
+ // $ANTLR end identifier
+
+ public static class id_return extends ParserRuleReturnScope {
+ Object tree;
+ public Object getTree() { return tree; }
+ };
+
+ // $ANTLR start id
+ // bst.g:31:1: id : '{'! identifier '}'! ;
+ public id_return id() throws RecognitionException {
+ id_return retval = new id_return();
+ retval.start = input.LT(1);
+
+ Object root_0 = null;
+
+ Token char_literal33=null;
+ Token char_literal35=null;
+ identifier_return identifier34 = null;
+
+
+ Object char_literal33_tree=null;
+ Object char_literal35_tree=null;
+
+ try {
+ // bst.g:32:4: ( '{'! identifier '}'! )
+ // bst.g:32:4: '{'! identifier '}'!
+ {
+ root_0 = (Object)adaptor.nil();
+
+ char_literal33=(Token)input.LT(1);
+ match(input,25,FOLLOW_25_in_id188);
+ pushFollow(FOLLOW_identifier_in_id191);
+ identifier34=identifier();
+ _fsp--;
+
+ adaptor.addChild(root_0, identifier34.tree);
+ char_literal35=(Token)input.LT(1);
+ match(input,26,FOLLOW_26_in_id193);
+
+ }
+
+ }
+ catch (RecognitionException re) {
+ reportError(re);
+ recover(input,re);
+ }
+ finally {
+ retval.stop = input.LT(-1);
+
+ retval.tree = (Object)adaptor.rulePostProcessing(root_0);
+ adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop);
+
+ }
+ return retval;
+ }
+ // $ANTLR end id
+
+ public static class idList_return extends ParserRuleReturnScope {
+ Object tree;
+ public Object getTree() { return tree; }
+ };
+
+ // $ANTLR start idList
+ // bst.g:34:1: idList : '{' ( identifier )+ '}' -> ^( IDLIST ( identifier )+ ) ;
+ public idList_return idList() throws RecognitionException {
+ idList_return retval = new idList_return();
+ retval.start = input.LT(1);
+
+ Object root_0 = null;
+
+ Token char_literal36=null;
+ Token char_literal38=null;
+ identifier_return identifier37 = null;
+
+ List list_identifier=new ArrayList();
+ List list_26=new ArrayList();
+ List list_25=new ArrayList();
+ Object char_literal36_tree=null;
+ Object char_literal38_tree=null;
+
+ try {
+ // bst.g:35:4: ( '{' ( identifier )+ '}' -> ^( IDLIST ( identifier )+ ) )
+ // bst.g:35:4: '{' ( identifier )+ '}'
+ {
+ char_literal36=(Token)input.LT(1);
+ match(input,25,FOLLOW_25_in_idList205);
+ list_25.add(char_literal36);
+
+ // bst.g:35:8: ( identifier )+
+ int cnt3=0;
+ loop3:
+ do {
+ int alt3=2;
+ int LA3_0 = input.LA(1);
+ if ( (LA3_0==IDENTIFIER) ) {
+ alt3=1;
+ }
+
+
+ switch (alt3) {
+ case 1 :
+ // bst.g:35:8: identifier
+ {
+ pushFollow(FOLLOW_identifier_in_idList207);
+ identifier37=identifier();
+ _fsp--;
+
+ list_identifier.add(identifier37.tree);
+
+ }
+ break;
+
+ default :
+ if ( cnt3 >= 1 ) break loop3;
+ EarlyExitException eee =
+ new EarlyExitException(3, input);
+ throw eee;
+ }
+ cnt3++;
+ } while (true);
+
+ char_literal38=(Token)input.LT(1);
+ match(input,26,FOLLOW_26_in_idList210);
+ list_26.add(char_literal38);
+
+
+ // AST REWRITE
+ int i_0 = 0;
+ retval.tree = root_0;
+ root_0 = (Object)adaptor.nil();
+ // 35:24: -> ^( IDLIST ( identifier )+ )
+ {
+ // bst.g:35:27: ^( IDLIST ( identifier )+ )
+ {
+ Object root_1 = (Object)adaptor.nil();
+ root_1 = (Object)adaptor.becomeRoot(adaptor.create(IDLIST, "IDLIST"), root_1);
+
+ // bst.g:35:36: ( identifier )+
+ {
+ int n_1 = list_identifier == null ? 0 : list_identifier.size();
+
+
+
+ if ( n_1==0 ) throw new RuntimeException("Must have more than one element for (...)+ loops");
+ for (int i_1=0; i_1<n_1; i_1++) {
+ adaptor.addChild(root_1, list_identifier.get(i_1));
+
+ }
+ }
+
+ adaptor.addChild(root_0, root_1);
+ }
+
+ }
+
+
+
+ }
+
+ }
+ catch (RecognitionException re) {
+ reportError(re);
+ recover(input,re);
+ }
+ finally {
+ retval.stop = input.LT(-1);
+
+ retval.tree = (Object)adaptor.rulePostProcessing(root_0);
+ adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop);
+
+ }
+ return retval;
+ }
+ // $ANTLR end idList
+
+ public static class idList0_return extends ParserRuleReturnScope {
+ Object tree;
+ public Object getTree() { return tree; }
+ };
+
+ // $ANTLR start idList0
+ // bst.g:37:1: idList0 : '{' ( identifier )* '}' -> ^( IDLIST ( identifier )* ) ;
+ public idList0_return idList0() throws RecognitionException {
+ idList0_return retval = new idList0_return();
+ retval.start = input.LT(1);
+
+ Object root_0 = null;
+
+ Token char_literal39=null;
+ Token char_literal41=null;
+ identifier_return identifier40 = null;
+
+ List list_identifier=new ArrayList();
+ List list_26=new ArrayList();
+ List list_25=new ArrayList();
+ Object char_literal39_tree=null;
+ Object char_literal41_tree=null;
+
+ try {
+ // bst.g:38:4: ( '{' ( identifier )* '}' -> ^( IDLIST ( identifier )* ) )
+ // bst.g:38:4: '{' ( identifier )* '}'
+ {
+ char_literal39=(Token)input.LT(1);
+ match(input,25,FOLLOW_25_in_idList0230);
+ list_25.add(char_literal39);
+
+ // bst.g:38:8: ( identifier )*
+ loop4:
+ do {
+ int alt4=2;
+ int LA4_0 = input.LA(1);
+ if ( (LA4_0==IDENTIFIER) ) {
+ alt4=1;
+ }
+
+
+ switch (alt4) {
+ case 1 :
+ // bst.g:38:8: identifier
+ {
+ pushFollow(FOLLOW_identifier_in_idList0232);
+ identifier40=identifier();
+ _fsp--;
+
+ list_identifier.add(identifier40.tree);
+
+ }
+ break;
+
+ default :
+ break loop4;
+ }
+ } while (true);
+
+ char_literal41=(Token)input.LT(1);
+ match(input,26,FOLLOW_26_in_idList0235);
+ list_26.add(char_literal41);
+
+
+ // AST REWRITE
+ int i_0 = 0;
+ retval.tree = root_0;
+ root_0 = (Object)adaptor.nil();
+ // 38:24: -> ^( IDLIST ( identifier )* )
+ {
+ // bst.g:38:27: ^( IDLIST ( identifier )* )
+ {
+ Object root_1 = (Object)adaptor.nil();
+ root_1 = (Object)adaptor.becomeRoot(adaptor.create(IDLIST, "IDLIST"), root_1);
+
+ // bst.g:38:36: ( identifier )*
+ {
+ int n_1 = list_identifier == null ? 0 : list_identifier.size();
+
+
+
+ for (int i_1=0; i_1<n_1; i_1++) {
+ adaptor.addChild(root_1, list_identifier.get(i_1));
+
+ }
+ }
+
+ adaptor.addChild(root_0, root_1);
+ }
+
+ }
+
+
+
+ }
+
+ }
+ catch (RecognitionException re) {
+ reportError(re);
+ recover(input,re);
+ }
+ finally {
+ retval.stop = input.LT(-1);
+
+ retval.tree = (Object)adaptor.rulePostProcessing(root_0);
+ adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop);
+
+ }
+ return retval;
+ }
+ // $ANTLR end idList0
+
+ public static class function_return extends ParserRuleReturnScope {
+ Object tree;
+ public Object getTree() { return tree; }
+ };
+
+ // $ANTLR start function
+ // bst.g:40:1: function : ( '<' | '>' | '=' | '+' | '-' | ':=' | '*' | 'add.period$' | 'call.type$' | 'change.case$' | 'chr.to.int$' | 'cite$' | 'duplicat$' | 'empty$' | 'format.name$' | 'if$' | 'int.to.chr$' | 'int.to.str$' | 'missing$' | 'newline$' | 'num.names$' | 'pop$' | 'preamble$' | 'purify$' | 'quote$' | 'skip$' | 'stack$' | 'substring$' | 'swap$' | 'text.length$' | 'text.prefix$' | 'top$' | 'type$' | 'warning$' | 'while$' | 'width$' | 'write$' | identifier );
+ public function_return function() throws RecognitionException {
+ function_return retval = new function_return();
+ retval.start = input.LT(1);
+
+ Object root_0 = null;
+
+ Token char_literal42=null;
+ Token char_literal43=null;
+ Token char_literal44=null;
+ Token char_literal45=null;
+ Token char_literal46=null;
+ Token string_literal47=null;
+ Token char_literal48=null;
+ Token string_literal49=null;
+ Token string_literal50=null;
+ Token string_literal51=null;
+ Token string_literal52=null;
+ Token string_literal53=null;
+ Token string_literal54=null;
+ Token string_literal55=null;
+ Token string_literal56=null;
+ Token string_literal57=null;
+ Token string_literal58=null;
+ Token string_literal59=null;
+ Token string_literal60=null;
+ Token string_literal61=null;
+ Token string_literal62=null;
+ Token string_literal63=null;
+ Token string_literal64=null;
+ Token string_literal65=null;
+ Token string_literal66=null;
+ Token string_literal67=null;
+ Token string_literal68=null;
+ Token string_literal69=null;
+ Token string_literal70=null;
+ Token string_literal71=null;
+ Token string_literal72=null;
+ Token string_literal73=null;
+ Token string_literal74=null;
+ Token string_literal75=null;
+ Token string_literal76=null;
+ Token string_literal77=null;
+ Token string_literal78=null;
+ identifier_return identifier79 = null;
+
+
+ Object char_literal42_tree=null;
+ Object char_literal43_tree=null;
+ Object char_literal44_tree=null;
+ Object char_literal45_tree=null;
+ Object char_literal46_tree=null;
+ Object string_literal47_tree=null;
+ Object char_literal48_tree=null;
+ Object string_literal49_tree=null;
+ Object string_literal50_tree=null;
+ Object string_literal51_tree=null;
+ Object string_literal52_tree=null;
+ Object string_literal53_tree=null;
+ Object string_literal54_tree=null;
+ Object string_literal55_tree=null;
+ Object string_literal56_tree=null;
+ Object string_literal57_tree=null;
+ Object string_literal58_tree=null;
+ Object string_literal59_tree=null;
+ Object string_literal60_tree=null;
+ Object string_literal61_tree=null;
+ Object string_literal62_tree=null;
+ Object string_literal63_tree=null;
+ Object string_literal64_tree=null;
+ Object string_literal65_tree=null;
+ Object string_literal66_tree=null;
+ Object string_literal67_tree=null;
+ Object string_literal68_tree=null;
+ Object string_literal69_tree=null;
+ Object string_literal70_tree=null;
+ Object string_literal71_tree=null;
+ Object string_literal72_tree=null;
+ Object string_literal73_tree=null;
+ Object string_literal74_tree=null;
+ Object string_literal75_tree=null;
+ Object string_literal76_tree=null;
+ Object string_literal77_tree=null;
+ Object string_literal78_tree=null;
+
+ try {
+ // bst.g:41:4: ( '<' | '>' | '=' | '+' | '-' | ':=' | '*' | 'add.period$' | 'call.type$' | 'change.case$' | 'chr.to.int$' | 'cite$' | 'duplicat$' | 'empty$' | 'format.name$' | 'if$' | 'int.to.chr$' | 'int.to.str$' | 'missing$' | 'newline$' | 'num.names$' | 'pop$' | 'preamble$' | 'purify$' | 'quote$' | 'skip$' | 'stack$' | 'substring$' | 'swap$' | 'text.length$' | 'text.prefix$' | 'top$' | 'type$' | 'warning$' | 'while$' | 'width$' | 'write$' | identifier )
+ int alt5=38;
+ switch ( input.LA(1) ) {
+ case 27:
+ alt5=1;
+ break;
+ case 28:
+ alt5=2;
+ break;
+ case 29:
+ alt5=3;
+ break;
+ case 30:
+ alt5=4;
+ break;
+ case 31:
+ alt5=5;
+ break;
+ case 32:
+ alt5=6;
+ break;
+ case 33:
+ alt5=7;
+ break;
+ case 34:
+ alt5=8;
+ break;
+ case 35:
+ alt5=9;
+ break;
+ case 36:
+ alt5=10;
+ break;
+ case 37:
+ alt5=11;
+ break;
+ case 38:
+ alt5=12;
+ break;
+ case 39:
+ alt5=13;
+ break;
+ case 40:
+ alt5=14;
+ break;
+ case 41:
+ alt5=15;
+ break;
+ case 42:
+ alt5=16;
+ break;
+ case 43:
+ alt5=17;
+ break;
+ case 44:
+ alt5=18;
+ break;
+ case 45:
+ alt5=19;
+ break;
+ case 46:
+ alt5=20;
+ break;
+ case 47:
+ alt5=21;
+ break;
+ case 48:
+ alt5=22;
+ break;
+ case 49:
+ alt5=23;
+ break;
+ case 50:
+ alt5=24;
+ break;
+ case 51:
+ alt5=25;
+ break;
+ case 52:
+ alt5=26;
+ break;
+ case 53:
+ alt5=27;
+ break;
+ case 54:
+ alt5=28;
+ break;
+ case 55:
+ alt5=29;
+ break;
+ case 56:
+ alt5=30;
+ break;
+ case 57:
+ alt5=31;
+ break;
+ case 58:
+ alt5=32;
+ break;
+ case 59:
+ alt5=33;
+ break;
+ case 60:
+ alt5=34;
+ break;
+ case 61:
+ alt5=35;
+ break;
+ case 62:
+ alt5=36;
+ break;
+ case 63:
+ alt5=37;
+ break;
+ case IDENTIFIER:
+ alt5=38;
+ break;
+ default:
+ NoViableAltException nvae =
+ new NoViableAltException("40:1: function : ( '<' | '>' | '=' | '+' | '-' | ':=' | '*' | 'add.period$' | 'call.type$' | 'change.case$' | 'chr.to.int$' | 'cite$' | 'duplicat$' | 'empty$' | 'format.name$' | 'if$' | 'int.to.chr$' | 'int.to.str$' | 'missing$' | 'newline$' | 'num.names$' | 'pop$' | 'preamble$' | 'purify$' | 'quote$' | 'skip$' | 'stack$' | 'substring$' | 'swap$' | 'text.length$' | 'text.prefix$' | 'top$' | 'type$' | 'warning$' | 'while$' | 'width$' | 'write$ [...]
+
+ throw nvae;
+ }
+
+ switch (alt5) {
+ case 1 :
+ // bst.g:41:4: '<'
+ {
+ root_0 = (Object)adaptor.nil();
+
+ char_literal42=(Token)input.LT(1);
+ match(input,27,FOLLOW_27_in_function254);
+ char_literal42_tree = (Object)adaptor.create(char_literal42);
+ adaptor.addChild(root_0, char_literal42_tree);
+
+
+ }
+ break;
+ case 2 :
+ // bst.g:41:10: '>'
+ {
+ root_0 = (Object)adaptor.nil();
+
+ char_literal43=(Token)input.LT(1);
+ match(input,28,FOLLOW_28_in_function258);
+ char_literal43_tree = (Object)adaptor.create(char_literal43);
+ adaptor.addChild(root_0, char_literal43_tree);
+
+
+ }
+ break;
+ case 3 :
+ // bst.g:41:16: '='
+ {
+ root_0 = (Object)adaptor.nil();
+
+ char_literal44=(Token)input.LT(1);
+ match(input,29,FOLLOW_29_in_function262);
+ char_literal44_tree = (Object)adaptor.create(char_literal44);
+ adaptor.addChild(root_0, char_literal44_tree);
+
+
+ }
+ break;
+ case 4 :
+ // bst.g:41:22: '+'
+ {
+ root_0 = (Object)adaptor.nil();
+
+ char_literal45=(Token)input.LT(1);
+ match(input,30,FOLLOW_30_in_function266);
+ char_literal45_tree = (Object)adaptor.create(char_literal45);
+ adaptor.addChild(root_0, char_literal45_tree);
+
+
+ }
+ break;
+ case 5 :
+ // bst.g:41:28: '-'
+ {
+ root_0 = (Object)adaptor.nil();
+
+ char_literal46=(Token)input.LT(1);
+ match(input,31,FOLLOW_31_in_function270);
+ char_literal46_tree = (Object)adaptor.create(char_literal46);
+ adaptor.addChild(root_0, char_literal46_tree);
+
+
+ }
+ break;
+ case 6 :
+ // bst.g:41:34: ':='
+ {
+ root_0 = (Object)adaptor.nil();
+
+ string_literal47=(Token)input.LT(1);
+ match(input,32,FOLLOW_32_in_function274);
+ string_literal47_tree = (Object)adaptor.create(string_literal47);
+ adaptor.addChild(root_0, string_literal47_tree);
+
+
+ }
+ break;
+ case 7 :
+ // bst.g:41:41: '*'
+ {
+ root_0 = (Object)adaptor.nil();
+
+ char_literal48=(Token)input.LT(1);
+ match(input,33,FOLLOW_33_in_function278);
+ char_literal48_tree = (Object)adaptor.create(char_literal48);
+ adaptor.addChild(root_0, char_literal48_tree);
+
+
+ }
+ break;
+ case 8 :
+ // bst.g:41:47: 'add.period$'
+ {
+ root_0 = (Object)adaptor.nil();
+
+ string_literal49=(Token)input.LT(1);
+ match(input,34,FOLLOW_34_in_function282);
+ string_literal49_tree = (Object)adaptor.create(string_literal49);
+ adaptor.addChild(root_0, string_literal49_tree);
+
+
+ }
+ break;
+ case 9 :
+ // bst.g:41:63: 'call.type$'
+ {
+ root_0 = (Object)adaptor.nil();
+
+ string_literal50=(Token)input.LT(1);
+ match(input,35,FOLLOW_35_in_function286);
+ string_literal50_tree = (Object)adaptor.create(string_literal50);
+ adaptor.addChild(root_0, string_literal50_tree);
+
+
+ }
+ break;
+ case 10 :
+ // bst.g:41:78: 'change.case$'
+ {
+ root_0 = (Object)adaptor.nil();
+
+ string_literal51=(Token)input.LT(1);
+ match(input,36,FOLLOW_36_in_function290);
+ string_literal51_tree = (Object)adaptor.create(string_literal51);
+ adaptor.addChild(root_0, string_literal51_tree);
+
+
+ }
+ break;
+ case 11 :
+ // bst.g:41:95: 'chr.to.int$'
+ {
+ root_0 = (Object)adaptor.nil();
+
+ string_literal52=(Token)input.LT(1);
+ match(input,37,FOLLOW_37_in_function294);
+ string_literal52_tree = (Object)adaptor.create(string_literal52);
+ adaptor.addChild(root_0, string_literal52_tree);
+
+
+ }
+ break;
+ case 12 :
+ // bst.g:42:4: 'cite$'
+ {
+ root_0 = (Object)adaptor.nil();
+
+ string_literal53=(Token)input.LT(1);
+ match(input,38,FOLLOW_38_in_function299);
+ string_literal53_tree = (Object)adaptor.create(string_literal53);
+ adaptor.addChild(root_0, string_literal53_tree);
+
+
+ }
+ break;
+ case 13 :
+ // bst.g:42:14: 'duplicat$'
+ {
+ root_0 = (Object)adaptor.nil();
+
+ string_literal54=(Token)input.LT(1);
+ match(input,39,FOLLOW_39_in_function303);
+ string_literal54_tree = (Object)adaptor.create(string_literal54);
+ adaptor.addChild(root_0, string_literal54_tree);
+
+
+ }
+ break;
+ case 14 :
+ // bst.g:42:28: 'empty$'
+ {
+ root_0 = (Object)adaptor.nil();
+
+ string_literal55=(Token)input.LT(1);
+ match(input,40,FOLLOW_40_in_function307);
+ string_literal55_tree = (Object)adaptor.create(string_literal55);
+ adaptor.addChild(root_0, string_literal55_tree);
+
+
+ }
+ break;
+ case 15 :
+ // bst.g:42:39: 'format.name$'
+ {
+ root_0 = (Object)adaptor.nil();
+
+ string_literal56=(Token)input.LT(1);
+ match(input,41,FOLLOW_41_in_function311);
+ string_literal56_tree = (Object)adaptor.create(string_literal56);
+ adaptor.addChild(root_0, string_literal56_tree);
+
+
+ }
+ break;
+ case 16 :
+ // bst.g:42:56: 'if$'
+ {
+ root_0 = (Object)adaptor.nil();
+
+ string_literal57=(Token)input.LT(1);
+ match(input,42,FOLLOW_42_in_function315);
+ string_literal57_tree = (Object)adaptor.create(string_literal57);
+ adaptor.addChild(root_0, string_literal57_tree);
+
+
+ }
+ break;
+ case 17 :
+ // bst.g:42:64: 'int.to.chr$'
+ {
+ root_0 = (Object)adaptor.nil();
+
+ string_literal58=(Token)input.LT(1);
+ match(input,43,FOLLOW_43_in_function319);
+ string_literal58_tree = (Object)adaptor.create(string_literal58);
+ adaptor.addChild(root_0, string_literal58_tree);
+
+
+ }
+ break;
+ case 18 :
+ // bst.g:42:80: 'int.to.str$'
+ {
+ root_0 = (Object)adaptor.nil();
+
+ string_literal59=(Token)input.LT(1);
+ match(input,44,FOLLOW_44_in_function323);
+ string_literal59_tree = (Object)adaptor.create(string_literal59);
+ adaptor.addChild(root_0, string_literal59_tree);
+
+
+ }
+ break;
+ case 19 :
+ // bst.g:42:96: 'missing$'
+ {
+ root_0 = (Object)adaptor.nil();
+
+ string_literal60=(Token)input.LT(1);
+ match(input,45,FOLLOW_45_in_function327);
+ string_literal60_tree = (Object)adaptor.create(string_literal60);
+ adaptor.addChild(root_0, string_literal60_tree);
+
+
+ }
+ break;
+ case 20 :
+ // bst.g:43:4: 'newline$'
+ {
+ root_0 = (Object)adaptor.nil();
+
+ string_literal61=(Token)input.LT(1);
+ match(input,46,FOLLOW_46_in_function332);
+ string_literal61_tree = (Object)adaptor.create(string_literal61);
+ adaptor.addChild(root_0, string_literal61_tree);
+
+
+ }
+ break;
+ case 21 :
+ // bst.g:43:17: 'num.names$'
+ {
+ root_0 = (Object)adaptor.nil();
+
+ string_literal62=(Token)input.LT(1);
+ match(input,47,FOLLOW_47_in_function336);
+ string_literal62_tree = (Object)adaptor.create(string_literal62);
+ adaptor.addChild(root_0, string_literal62_tree);
+
+
+ }
+ break;
+ case 22 :
+ // bst.g:43:32: 'pop$'
+ {
+ root_0 = (Object)adaptor.nil();
+
+ string_literal63=(Token)input.LT(1);
+ match(input,48,FOLLOW_48_in_function340);
+ string_literal63_tree = (Object)adaptor.create(string_literal63);
+ adaptor.addChild(root_0, string_literal63_tree);
+
+
+ }
+ break;
+ case 23 :
+ // bst.g:43:41: 'preamble$'
+ {
+ root_0 = (Object)adaptor.nil();
+
+ string_literal64=(Token)input.LT(1);
+ match(input,49,FOLLOW_49_in_function344);
+ string_literal64_tree = (Object)adaptor.create(string_literal64);
+ adaptor.addChild(root_0, string_literal64_tree);
+
+
+ }
+ break;
+ case 24 :
+ // bst.g:43:55: 'purify$'
+ {
+ root_0 = (Object)adaptor.nil();
+
+ string_literal65=(Token)input.LT(1);
+ match(input,50,FOLLOW_50_in_function348);
+ string_literal65_tree = (Object)adaptor.create(string_literal65);
+ adaptor.addChild(root_0, string_literal65_tree);
+
+
+ }
+ break;
+ case 25 :
+ // bst.g:43:67: 'quote$'
+ {
+ root_0 = (Object)adaptor.nil();
+
+ string_literal66=(Token)input.LT(1);
+ match(input,51,FOLLOW_51_in_function352);
+ string_literal66_tree = (Object)adaptor.create(string_literal66);
+ adaptor.addChild(root_0, string_literal66_tree);
+
+
+ }
+ break;
+ case 26 :
+ // bst.g:43:78: 'skip$'
+ {
+ root_0 = (Object)adaptor.nil();
+
+ string_literal67=(Token)input.LT(1);
+ match(input,52,FOLLOW_52_in_function356);
+ string_literal67_tree = (Object)adaptor.create(string_literal67);
+ adaptor.addChild(root_0, string_literal67_tree);
+
+
+ }
+ break;
+ case 27 :
+ // bst.g:43:88: 'stack$'
+ {
+ root_0 = (Object)adaptor.nil();
+
+ string_literal68=(Token)input.LT(1);
+ match(input,53,FOLLOW_53_in_function360);
+ string_literal68_tree = (Object)adaptor.create(string_literal68);
+ adaptor.addChild(root_0, string_literal68_tree);
+
+
+ }
+ break;
+ case 28 :
+ // bst.g:43:99: 'substring$'
+ {
+ root_0 = (Object)adaptor.nil();
+
+ string_literal69=(Token)input.LT(1);
+ match(input,54,FOLLOW_54_in_function364);
+ string_literal69_tree = (Object)adaptor.create(string_literal69);
+ adaptor.addChild(root_0, string_literal69_tree);
+
+
+ }
+ break;
+ case 29 :
+ // bst.g:44:4: 'swap$'
+ {
+ root_0 = (Object)adaptor.nil();
+
+ string_literal70=(Token)input.LT(1);
+ match(input,55,FOLLOW_55_in_function369);
+ string_literal70_tree = (Object)adaptor.create(string_literal70);
+ adaptor.addChild(root_0, string_literal70_tree);
+
+
+ }
+ break;
+ case 30 :
+ // bst.g:44:14: 'text.length$'
+ {
+ root_0 = (Object)adaptor.nil();
+
+ string_literal71=(Token)input.LT(1);
+ match(input,56,FOLLOW_56_in_function373);
+ string_literal71_tree = (Object)adaptor.create(string_literal71);
+ adaptor.addChild(root_0, string_literal71_tree);
+
+
+ }
+ break;
+ case 31 :
+ // bst.g:44:31: 'text.prefix$'
+ {
+ root_0 = (Object)adaptor.nil();
+
+ string_literal72=(Token)input.LT(1);
+ match(input,57,FOLLOW_57_in_function377);
+ string_literal72_tree = (Object)adaptor.create(string_literal72);
+ adaptor.addChild(root_0, string_literal72_tree);
+
+
+ }
+ break;
+ case 32 :
+ // bst.g:44:48: 'top$'
+ {
+ root_0 = (Object)adaptor.nil();
+
+ string_literal73=(Token)input.LT(1);
+ match(input,58,FOLLOW_58_in_function381);
+ string_literal73_tree = (Object)adaptor.create(string_literal73);
+ adaptor.addChild(root_0, string_literal73_tree);
+
+
+ }
+ break;
+ case 33 :
+ // bst.g:44:57: 'type$'
+ {
+ root_0 = (Object)adaptor.nil();
+
+ string_literal74=(Token)input.LT(1);
+ match(input,59,FOLLOW_59_in_function385);
+ string_literal74_tree = (Object)adaptor.create(string_literal74);
+ adaptor.addChild(root_0, string_literal74_tree);
+
+
+ }
+ break;
+ case 34 :
+ // bst.g:44:67: 'warning$'
+ {
+ root_0 = (Object)adaptor.nil();
+
+ string_literal75=(Token)input.LT(1);
+ match(input,60,FOLLOW_60_in_function389);
+ string_literal75_tree = (Object)adaptor.create(string_literal75);
+ adaptor.addChild(root_0, string_literal75_tree);
+
+
+ }
+ break;
+ case 35 :
+ // bst.g:44:80: 'while$'
+ {
+ root_0 = (Object)adaptor.nil();
+
+ string_literal76=(Token)input.LT(1);
+ match(input,61,FOLLOW_61_in_function393);
+ string_literal76_tree = (Object)adaptor.create(string_literal76);
+ adaptor.addChild(root_0, string_literal76_tree);
+
+
+ }
+ break;
+ case 36 :
+ // bst.g:44:91: 'width$'
+ {
+ root_0 = (Object)adaptor.nil();
+
+ string_literal77=(Token)input.LT(1);
+ match(input,62,FOLLOW_62_in_function397);
+ string_literal77_tree = (Object)adaptor.create(string_literal77);
+ adaptor.addChild(root_0, string_literal77_tree);
+
+
+ }
+ break;
+ case 37 :
+ // bst.g:45:4: 'write$'
+ {
+ root_0 = (Object)adaptor.nil();
+
+ string_literal78=(Token)input.LT(1);
+ match(input,63,FOLLOW_63_in_function402);
+ string_literal78_tree = (Object)adaptor.create(string_literal78);
+ adaptor.addChild(root_0, string_literal78_tree);
+
+
+ }
+ break;
+ case 38 :
+ // bst.g:45:15: identifier
+ {
+ root_0 = (Object)adaptor.nil();
+
+ pushFollow(FOLLOW_identifier_in_function406);
+ identifier79=identifier();
+ _fsp--;
+
+ adaptor.addChild(root_0, identifier79.tree);
+
+ }
+ break;
+
+ }
+ }
+ catch (RecognitionException re) {
+ reportError(re);
+ recover(input,re);
+ }
+ finally {
+ retval.stop = input.LT(-1);
+
+ retval.tree = (Object)adaptor.rulePostProcessing(root_0);
+ adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop);
+
+ }
+ return retval;
+ }
+ // $ANTLR end function
+
+ public static class stack_return extends ParserRuleReturnScope {
+ Object tree;
+ public Object getTree() { return tree; }
+ };
+
+ // $ANTLR start stack
+ // bst.g:47:1: stack : '{' ( stackitem )+ '}' -> ^( STACK ( stackitem )+ ) ;
+ public stack_return stack() throws RecognitionException {
+ stack_return retval = new stack_return();
+ retval.start = input.LT(1);
+
+ Object root_0 = null;
+
+ Token char_literal80=null;
+ Token char_literal82=null;
+ stackitem_return stackitem81 = null;
+
+ List list_stackitem=new ArrayList();
+ List list_26=new ArrayList();
+ List list_25=new ArrayList();
+ Object char_literal80_tree=null;
+ Object char_literal82_tree=null;
+
+ try {
+ // bst.g:48:4: ( '{' ( stackitem )+ '}' -> ^( STACK ( stackitem )+ ) )
+ // bst.g:48:4: '{' ( stackitem )+ '}'
+ {
+ char_literal80=(Token)input.LT(1);
+ match(input,25,FOLLOW_25_in_stack417);
+ list_25.add(char_literal80);
+
+ // bst.g:48:8: ( stackitem )+
+ int cnt6=0;
+ loop6:
+ do {
+ int alt6=2;
+ int LA6_0 = input.LA(1);
+ if ( (LA6_0==STRING||(LA6_0>=IDENTIFIER && LA6_0<=QUOTED)||LA6_0==25||(LA6_0>=27 && LA6_0<=63)) ) {
+ alt6=1;
+ }
+
+
+ switch (alt6) {
+ case 1 :
+ // bst.g:48:8: stackitem
+ {
+ pushFollow(FOLLOW_stackitem_in_stack419);
+ stackitem81=stackitem();
+ _fsp--;
+
+ list_stackitem.add(stackitem81.tree);
+
+ }
+ break;
+
+ default :
+ if ( cnt6 >= 1 ) break loop6;
+ EarlyExitException eee =
+ new EarlyExitException(6, input);
+ throw eee;
+ }
+ cnt6++;
+ } while (true);
+
+ char_literal82=(Token)input.LT(1);
+ match(input,26,FOLLOW_26_in_stack422);
+ list_26.add(char_literal82);
+
+
+ // AST REWRITE
+ int i_0 = 0;
+ retval.tree = root_0;
+ root_0 = (Object)adaptor.nil();
+ // 48:23: -> ^( STACK ( stackitem )+ )
+ {
+ // bst.g:48:26: ^( STACK ( stackitem )+ )
+ {
+ Object root_1 = (Object)adaptor.nil();
+ root_1 = (Object)adaptor.becomeRoot(adaptor.create(STACK, "STACK"), root_1);
+
+ // bst.g:48:34: ( stackitem )+
+ {
+ int n_1 = list_stackitem == null ? 0 : list_stackitem.size();
+
+
+
+ if ( n_1==0 ) throw new RuntimeException("Must have more than one element for (...)+ loops");
+ for (int i_1=0; i_1<n_1; i_1++) {
+ adaptor.addChild(root_1, list_stackitem.get(i_1));
+
+ }
+ }
+
+ adaptor.addChild(root_0, root_1);
+ }
+
+ }
+
+
+
+ }
+
+ }
+ catch (RecognitionException re) {
+ reportError(re);
+ recover(input,re);
+ }
+ finally {
+ retval.stop = input.LT(-1);
+
+ retval.tree = (Object)adaptor.rulePostProcessing(root_0);
+ adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop);
+
+ }
+ return retval;
+ }
+ // $ANTLR end stack
+
+ public static class stackitem_return extends ParserRuleReturnScope {
+ Object tree;
+ public Object getTree() { return tree; }
+ };
+
+ // $ANTLR start stackitem
+ // bst.g:50:1: stackitem : ( function | STRING | INTEGER | QUOTED | stack );
+ public stackitem_return stackitem() throws RecognitionException {
+ stackitem_return retval = new stackitem_return();
+ retval.start = input.LT(1);
+
+ Object root_0 = null;
+
+ Token STRING84=null;
+ Token INTEGER85=null;
+ Token QUOTED86=null;
+ function_return function83 = null;
+
+ stack_return stack87 = null;
+
+
+ Object STRING84_tree=null;
+ Object INTEGER85_tree=null;
+ Object QUOTED86_tree=null;
+
+ try {
+ // bst.g:51:4: ( function | STRING | INTEGER | QUOTED | stack )
+ int alt7=5;
+ switch ( input.LA(1) ) {
+ case IDENTIFIER:
+ case 27:
+ case 28:
+ case 29:
+ case 30:
+ case 31:
+ case 32:
+ case 33:
+ case 34:
+ case 35:
+ case 36:
+ case 37:
+ case 38:
+ case 39:
+ case 40:
+ case 41:
+ case 42:
+ case 43:
+ case 44:
+ case 45:
+ case 46:
+ case 47:
+ case 48:
+ case 49:
+ case 50:
+ case 51:
+ case 52:
+ case 53:
+ case 54:
+ case 55:
+ case 56:
+ case 57:
+ case 58:
+ case 59:
+ case 60:
+ case 61:
+ case 62:
+ case 63:
+ alt7=1;
+ break;
+ case STRING:
+ alt7=2;
+ break;
+ case INTEGER:
+ alt7=3;
+ break;
+ case QUOTED:
+ alt7=4;
+ break;
+ case 25:
+ alt7=5;
+ break;
+ default:
+ NoViableAltException nvae =
+ new NoViableAltException("50:1: stackitem : ( function | STRING | INTEGER | QUOTED | stack );", 7, 0, input);
+
+ throw nvae;
+ }
+
+ switch (alt7) {
+ case 1 :
+ // bst.g:51:4: function
+ {
+ root_0 = (Object)adaptor.nil();
+
+ pushFollow(FOLLOW_function_in_stackitem441);
+ function83=function();
+ _fsp--;
+
+ adaptor.addChild(root_0, function83.tree);
+
+ }
+ break;
+ case 2 :
+ // bst.g:52:4: STRING
+ {
+ root_0 = (Object)adaptor.nil();
+
+ STRING84=(Token)input.LT(1);
+ match(input,STRING,FOLLOW_STRING_in_stackitem446);
+ STRING84_tree = (Object)adaptor.create(STRING84);
+ adaptor.addChild(root_0, STRING84_tree);
+
+
+ }
+ break;
+ case 3 :
+ // bst.g:53:4: INTEGER
+ {
+ root_0 = (Object)adaptor.nil();
+
+ INTEGER85=(Token)input.LT(1);
+ match(input,INTEGER,FOLLOW_INTEGER_in_stackitem452);
+ INTEGER85_tree = (Object)adaptor.create(INTEGER85);
+ adaptor.addChild(root_0, INTEGER85_tree);
+
+
+ }
+ break;
+ case 4 :
+ // bst.g:54:4: QUOTED
+ {
+ root_0 = (Object)adaptor.nil();
+
+ QUOTED86=(Token)input.LT(1);
+ match(input,QUOTED,FOLLOW_QUOTED_in_stackitem458);
+ QUOTED86_tree = (Object)adaptor.create(QUOTED86);
+ adaptor.addChild(root_0, QUOTED86_tree);
+
+
+ }
+ break;
+ case 5 :
+ // bst.g:55:4: stack
+ {
+ root_0 = (Object)adaptor.nil();
+
+ pushFollow(FOLLOW_stack_in_stackitem463);
+ stack87=stack();
+ _fsp--;
+
+ adaptor.addChild(root_0, stack87.tree);
+
+ }
+ break;
+
+ }
+ }
+ catch (RecognitionException re) {
+ reportError(re);
+ recover(input,re);
+ }
+ finally {
+ retval.stop = input.LT(-1);
+
+ retval.tree = (Object)adaptor.rulePostProcessing(root_0);
+ adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop);
+
+ }
+ return retval;
+ }
+ // $ANTLR end stackitem
+
+
+
+
+ public static final BitSet FOLLOW_commands_in_program45 = new BitSet(new long[]{0x000000000003EF42L});
+ public static final BitSet FOLLOW_STRINGS_in_commands65 = new BitSet(new long[]{0x0000000002000000L});
+ public static final BitSet FOLLOW_idList_in_commands68 = new BitSet(new long[]{0x0000000000000002L});
+ public static final BitSet FOLLOW_INTEGERS_in_commands73 = new BitSet(new long[]{0x0000000002000000L});
+ public static final BitSet FOLLOW_idList_in_commands76 = new BitSet(new long[]{0x0000000000000002L});
+ public static final BitSet FOLLOW_FUNCTION_in_commands81 = new BitSet(new long[]{0x0000000002000000L});
+ public static final BitSet FOLLOW_id_in_commands84 = new BitSet(new long[]{0x0000000002000000L});
+ public static final BitSet FOLLOW_stack_in_commands86 = new BitSet(new long[]{0x0000000000000002L});
+ public static final BitSet FOLLOW_MACRO_in_commands91 = new BitSet(new long[]{0x0000000002000000L});
+ public static final BitSet FOLLOW_id_in_commands94 = new BitSet(new long[]{0x0000000002000000L});
+ public static final BitSet FOLLOW_25_in_commands96 = new BitSet(new long[]{0x0000000000001000L});
+ public static final BitSet FOLLOW_STRING_in_commands99 = new BitSet(new long[]{0x0000000004000000L});
+ public static final BitSet FOLLOW_26_in_commands101 = new BitSet(new long[]{0x0000000000000002L});
+ public static final BitSet FOLLOW_READ_in_commands107 = new BitSet(new long[]{0x0000000000000002L});
+ public static final BitSet FOLLOW_EXECUTE_in_commands113 = new BitSet(new long[]{0x0000000002000000L});
+ public static final BitSet FOLLOW_25_in_commands116 = new BitSet(new long[]{0xFFFFFFFFF8040000L});
+ public static final BitSet FOLLOW_function_in_commands119 = new BitSet(new long[]{0x0000000004000000L});
+ public static final BitSet FOLLOW_26_in_commands121 = new BitSet(new long[]{0x0000000000000002L});
+ public static final BitSet FOLLOW_ITERATE_in_commands127 = new BitSet(new long[]{0x0000000002000000L});
+ public static final BitSet FOLLOW_25_in_commands130 = new BitSet(new long[]{0xFFFFFFFFF8040000L});
+ public static final BitSet FOLLOW_function_in_commands133 = new BitSet(new long[]{0x0000000004000000L});
+ public static final BitSet FOLLOW_26_in_commands135 = new BitSet(new long[]{0x0000000000000002L});
+ public static final BitSet FOLLOW_REVERSE_in_commands141 = new BitSet(new long[]{0x0000000002000000L});
+ public static final BitSet FOLLOW_25_in_commands144 = new BitSet(new long[]{0xFFFFFFFFF8040000L});
+ public static final BitSet FOLLOW_function_in_commands147 = new BitSet(new long[]{0x0000000004000000L});
+ public static final BitSet FOLLOW_26_in_commands149 = new BitSet(new long[]{0x0000000000000002L});
+ public static final BitSet FOLLOW_ENTRY_in_commands155 = new BitSet(new long[]{0x0000000002000000L});
+ public static final BitSet FOLLOW_idList0_in_commands158 = new BitSet(new long[]{0x0000000002000000L});
+ public static final BitSet FOLLOW_idList0_in_commands160 = new BitSet(new long[]{0x0000000002000000L});
+ public static final BitSet FOLLOW_idList0_in_commands162 = new BitSet(new long[]{0x0000000000000002L});
+ public static final BitSet FOLLOW_SORT_in_commands167 = new BitSet(new long[]{0x0000000000000002L});
+ public static final BitSet FOLLOW_IDENTIFIER_in_identifier178 = new BitSet(new long[]{0x0000000000000002L});
+ public static final BitSet FOLLOW_25_in_id188 = new BitSet(new long[]{0x0000000000040000L});
+ public static final BitSet FOLLOW_identifier_in_id191 = new BitSet(new long[]{0x0000000004000000L});
+ public static final BitSet FOLLOW_26_in_id193 = new BitSet(new long[]{0x0000000000000002L});
+ public static final BitSet FOLLOW_25_in_idList205 = new BitSet(new long[]{0x0000000000040000L});
+ public static final BitSet FOLLOW_identifier_in_idList207 = new BitSet(new long[]{0x0000000004040000L});
+ public static final BitSet FOLLOW_26_in_idList210 = new BitSet(new long[]{0x0000000000000002L});
+ public static final BitSet FOLLOW_25_in_idList0230 = new BitSet(new long[]{0x0000000004040000L});
+ public static final BitSet FOLLOW_identifier_in_idList0232 = new BitSet(new long[]{0x0000000004040000L});
+ public static final BitSet FOLLOW_26_in_idList0235 = new BitSet(new long[]{0x0000000000000002L});
+ public static final BitSet FOLLOW_27_in_function254 = new BitSet(new long[]{0x0000000000000002L});
+ public static final BitSet FOLLOW_28_in_function258 = new BitSet(new long[]{0x0000000000000002L});
+ public static final BitSet FOLLOW_29_in_function262 = new BitSet(new long[]{0x0000000000000002L});
+ public static final BitSet FOLLOW_30_in_function266 = new BitSet(new long[]{0x0000000000000002L});
+ public static final BitSet FOLLOW_31_in_function270 = new BitSet(new long[]{0x0000000000000002L});
+ public static final BitSet FOLLOW_32_in_function274 = new BitSet(new long[]{0x0000000000000002L});
+ public static final BitSet FOLLOW_33_in_function278 = new BitSet(new long[]{0x0000000000000002L});
+ public static final BitSet FOLLOW_34_in_function282 = new BitSet(new long[]{0x0000000000000002L});
+ public static final BitSet FOLLOW_35_in_function286 = new BitSet(new long[]{0x0000000000000002L});
+ public static final BitSet FOLLOW_36_in_function290 = new BitSet(new long[]{0x0000000000000002L});
+ public static final BitSet FOLLOW_37_in_function294 = new BitSet(new long[]{0x0000000000000002L});
+ public static final BitSet FOLLOW_38_in_function299 = new BitSet(new long[]{0x0000000000000002L});
+ public static final BitSet FOLLOW_39_in_function303 = new BitSet(new long[]{0x0000000000000002L});
+ public static final BitSet FOLLOW_40_in_function307 = new BitSet(new long[]{0x0000000000000002L});
+ public static final BitSet FOLLOW_41_in_function311 = new BitSet(new long[]{0x0000000000000002L});
+ public static final BitSet FOLLOW_42_in_function315 = new BitSet(new long[]{0x0000000000000002L});
+ public static final BitSet FOLLOW_43_in_function319 = new BitSet(new long[]{0x0000000000000002L});
+ public static final BitSet FOLLOW_44_in_function323 = new BitSet(new long[]{0x0000000000000002L});
+ public static final BitSet FOLLOW_45_in_function327 = new BitSet(new long[]{0x0000000000000002L});
+ public static final BitSet FOLLOW_46_in_function332 = new BitSet(new long[]{0x0000000000000002L});
+ public static final BitSet FOLLOW_47_in_function336 = new BitSet(new long[]{0x0000000000000002L});
+ public static final BitSet FOLLOW_48_in_function340 = new BitSet(new long[]{0x0000000000000002L});
+ public static final BitSet FOLLOW_49_in_function344 = new BitSet(new long[]{0x0000000000000002L});
+ public static final BitSet FOLLOW_50_in_function348 = new BitSet(new long[]{0x0000000000000002L});
+ public static final BitSet FOLLOW_51_in_function352 = new BitSet(new long[]{0x0000000000000002L});
+ public static final BitSet FOLLOW_52_in_function356 = new BitSet(new long[]{0x0000000000000002L});
+ public static final BitSet FOLLOW_53_in_function360 = new BitSet(new long[]{0x0000000000000002L});
+ public static final BitSet FOLLOW_54_in_function364 = new BitSet(new long[]{0x0000000000000002L});
+ public static final BitSet FOLLOW_55_in_function369 = new BitSet(new long[]{0x0000000000000002L});
+ public static final BitSet FOLLOW_56_in_function373 = new BitSet(new long[]{0x0000000000000002L});
+ public static final BitSet FOLLOW_57_in_function377 = new BitSet(new long[]{0x0000000000000002L});
+ public static final BitSet FOLLOW_58_in_function381 = new BitSet(new long[]{0x0000000000000002L});
+ public static final BitSet FOLLOW_59_in_function385 = new BitSet(new long[]{0x0000000000000002L});
+ public static final BitSet FOLLOW_60_in_function389 = new BitSet(new long[]{0x0000000000000002L});
+ public static final BitSet FOLLOW_61_in_function393 = new BitSet(new long[]{0x0000000000000002L});
+ public static final BitSet FOLLOW_62_in_function397 = new BitSet(new long[]{0x0000000000000002L});
+ public static final BitSet FOLLOW_63_in_function402 = new BitSet(new long[]{0x0000000000000002L});
+ public static final BitSet FOLLOW_identifier_in_function406 = new BitSet(new long[]{0x0000000000000002L});
+ public static final BitSet FOLLOW_25_in_stack417 = new BitSet(new long[]{0xFFFFFFFFFA1C1000L});
+ public static final BitSet FOLLOW_stackitem_in_stack419 = new BitSet(new long[]{0xFFFFFFFFFE1C1000L});
+ public static final BitSet FOLLOW_26_in_stack422 = new BitSet(new long[]{0x0000000000000002L});
+ public static final BitSet FOLLOW_function_in_stackitem441 = new BitSet(new long[]{0x0000000000000002L});
+ public static final BitSet FOLLOW_STRING_in_stackitem446 = new BitSet(new long[]{0x0000000000000002L});
+ public static final BitSet FOLLOW_INTEGER_in_stackitem452 = new BitSet(new long[]{0x0000000000000002L});
+ public static final BitSet FOLLOW_QUOTED_in_stackitem458 = new BitSet(new long[]{0x0000000000000002L});
+ public static final BitSet FOLLOW_stack_in_stackitem463 = new BitSet(new long[]{0x0000000000000002L});
+
+}
\ No newline at end of file
diff --git a/src/java/net/sf/jabref/bst/BstLexer.java b/src/java/net/sf/jabref/bst/BstLexer.java
new file mode 100644
index 0000000..9d81e3e
--- /dev/null
+++ b/src/java/net/sf/jabref/bst/BstLexer.java
@@ -0,0 +1,1659 @@
+package net.sf.jabref.bst;
+
+// $ANTLR 3.0b5 Bst.g 2006-11-23 23:20:24
+
+import org.antlr.runtime.*;
+import java.util.Stack;
+import java.util.List;
+import java.util.ArrayList;
+
+public class BstLexer extends Lexer {
+ public static final int LETTER=21;
+ public static final int T29=29;
+ public static final int T33=33;
+ public static final int INTEGERS=9;
+ public static final int ENTRY=6;
+ public static final int WS=23;
+ public static final int COMMANDS=7;
+ public static final int STRING=12;
+ public static final int T28=28;
+ public static final int EXECUTE=14;
+ public static final int LINE_COMMENT=24;
+ public static final int SORT=17;
+ public static final int STACK=5;
+ public static final int REVERSE=16;
+ public static final int QUOTED=20;
+ public static final int T25=25;
+ public static final int INTEGER=19;
+ public static final int ITERATE=15;
+ public static final int FUNCTION=10;
+ public static final int T26=26;
+ public static final int EOF=-1;
+ public static final int T32=32;
+ public static final int Tokens=34;
+ public static final int STRINGS=8;
+ public static final int T31=31;
+ public static final int T27=27;
+ public static final int IDENTIFIER=18;
+ public static final int MACRO=11;
+ public static final int T30=30;
+ public static final int IDLIST=4;
+ public static final int NUMERAL=22;
+ public static final int READ=13;
+ public BstLexer() {;}
+ public BstLexer(CharStream input) {
+ super(input);
+ }
+ public String getGrammarFileName() { return "Bst.g"; }
+
+ // $ANTLR start T25
+ public void mT25() throws RecognitionException {
+ try {
+ ruleNestingLevel++;
+ int _type = T25;
+ int _start = getCharIndex();
+ int _line = getLine();
+ int _charPosition = getCharPositionInLine();
+ int _channel = Token.DEFAULT_CHANNEL;
+ // Bst.g:3:7: ( '{' )
+ // Bst.g:3:7: '{'
+ {
+ match('{');
+
+ }
+
+
+
+ if ( token==null && ruleNestingLevel==1 ) {
+ emit(_type,_line,_charPosition,_channel,_start,getCharIndex()-1);
+ }
+
+ }
+ finally {
+ ruleNestingLevel--;
+ }
+ }
+ // $ANTLR end T25
+
+ // $ANTLR start T26
+ public void mT26() throws RecognitionException {
+ try {
+ ruleNestingLevel++;
+ int _type = T26;
+ int _start = getCharIndex();
+ int _line = getLine();
+ int _charPosition = getCharPositionInLine();
+ int _channel = Token.DEFAULT_CHANNEL;
+ // Bst.g:4:7: ( '}' )
+ // Bst.g:4:7: '}'
+ {
+ match('}');
+
+ }
+
+
+
+ if ( token==null && ruleNestingLevel==1 ) {
+ emit(_type,_line,_charPosition,_channel,_start,getCharIndex()-1);
+ }
+
+ }
+ finally {
+ ruleNestingLevel--;
+ }
+ }
+ // $ANTLR end T26
+
+ // $ANTLR start T27
+ public void mT27() throws RecognitionException {
+ try {
+ ruleNestingLevel++;
+ int _type = T27;
+ int _start = getCharIndex();
+ int _line = getLine();
+ int _charPosition = getCharPositionInLine();
+ int _channel = Token.DEFAULT_CHANNEL;
+ // Bst.g:5:7: ( '<' )
+ // Bst.g:5:7: '<'
+ {
+ match('<');
+
+ }
+
+
+
+ if ( token==null && ruleNestingLevel==1 ) {
+ emit(_type,_line,_charPosition,_channel,_start,getCharIndex()-1);
+ }
+
+ }
+ finally {
+ ruleNestingLevel--;
+ }
+ }
+ // $ANTLR end T27
+
+ // $ANTLR start T28
+ public void mT28() throws RecognitionException {
+ try {
+ ruleNestingLevel++;
+ int _type = T28;
+ int _start = getCharIndex();
+ int _line = getLine();
+ int _charPosition = getCharPositionInLine();
+ int _channel = Token.DEFAULT_CHANNEL;
+ // Bst.g:6:7: ( '>' )
+ // Bst.g:6:7: '>'
+ {
+ match('>');
+
+ }
+
+
+
+ if ( token==null && ruleNestingLevel==1 ) {
+ emit(_type,_line,_charPosition,_channel,_start,getCharIndex()-1);
+ }
+
+ }
+ finally {
+ ruleNestingLevel--;
+ }
+ }
+ // $ANTLR end T28
+
+ // $ANTLR start T29
+ public void mT29() throws RecognitionException {
+ try {
+ ruleNestingLevel++;
+ int _type = T29;
+ int _start = getCharIndex();
+ int _line = getLine();
+ int _charPosition = getCharPositionInLine();
+ int _channel = Token.DEFAULT_CHANNEL;
+ // Bst.g:7:7: ( '=' )
+ // Bst.g:7:7: '='
+ {
+ match('=');
+
+ }
+
+
+
+ if ( token==null && ruleNestingLevel==1 ) {
+ emit(_type,_line,_charPosition,_channel,_start,getCharIndex()-1);
+ }
+
+ }
+ finally {
+ ruleNestingLevel--;
+ }
+ }
+ // $ANTLR end T29
+
+ // $ANTLR start T30
+ public void mT30() throws RecognitionException {
+ try {
+ ruleNestingLevel++;
+ int _type = T30;
+ int _start = getCharIndex();
+ int _line = getLine();
+ int _charPosition = getCharPositionInLine();
+ int _channel = Token.DEFAULT_CHANNEL;
+ // Bst.g:8:7: ( '+' )
+ // Bst.g:8:7: '+'
+ {
+ match('+');
+
+ }
+
+
+
+ if ( token==null && ruleNestingLevel==1 ) {
+ emit(_type,_line,_charPosition,_channel,_start,getCharIndex()-1);
+ }
+
+ }
+ finally {
+ ruleNestingLevel--;
+ }
+ }
+ // $ANTLR end T30
+
+ // $ANTLR start T31
+ public void mT31() throws RecognitionException {
+ try {
+ ruleNestingLevel++;
+ int _type = T31;
+ int _start = getCharIndex();
+ int _line = getLine();
+ int _charPosition = getCharPositionInLine();
+ int _channel = Token.DEFAULT_CHANNEL;
+ // Bst.g:9:7: ( '-' )
+ // Bst.g:9:7: '-'
+ {
+ match('-');
+
+ }
+
+
+
+ if ( token==null && ruleNestingLevel==1 ) {
+ emit(_type,_line,_charPosition,_channel,_start,getCharIndex()-1);
+ }
+
+ }
+ finally {
+ ruleNestingLevel--;
+ }
+ }
+ // $ANTLR end T31
+
+ // $ANTLR start T32
+ public void mT32() throws RecognitionException {
+ try {
+ ruleNestingLevel++;
+ int _type = T32;
+ int _start = getCharIndex();
+ int _line = getLine();
+ int _charPosition = getCharPositionInLine();
+ int _channel = Token.DEFAULT_CHANNEL;
+ // Bst.g:10:7: ( ':=' )
+ // Bst.g:10:7: ':='
+ {
+ match(":=");
+
+
+ }
+
+
+
+ if ( token==null && ruleNestingLevel==1 ) {
+ emit(_type,_line,_charPosition,_channel,_start,getCharIndex()-1);
+ }
+
+ }
+ finally {
+ ruleNestingLevel--;
+ }
+ }
+ // $ANTLR end T32
+
+ // $ANTLR start T33
+ public void mT33() throws RecognitionException {
+ try {
+ ruleNestingLevel++;
+ int _type = T33;
+ int _start = getCharIndex();
+ int _line = getLine();
+ int _charPosition = getCharPositionInLine();
+ int _channel = Token.DEFAULT_CHANNEL;
+ // Bst.g:11:7: ( '*' )
+ // Bst.g:11:7: '*'
+ {
+ match('*');
+
+ }
+
+
+
+ if ( token==null && ruleNestingLevel==1 ) {
+ emit(_type,_line,_charPosition,_channel,_start,getCharIndex()-1);
+ }
+
+ }
+ finally {
+ ruleNestingLevel--;
+ }
+ }
+ // $ANTLR end T33
+
+ // $ANTLR start STRINGS
+ public void mSTRINGS() throws RecognitionException {
+ try {
+ ruleNestingLevel++;
+ int _type = STRINGS;
+ int _start = getCharIndex();
+ int _line = getLine();
+ int _charPosition = getCharPositionInLine();
+ int _channel = Token.DEFAULT_CHANNEL;
+ // Bst.g:53:11: ( 'STRINGS' )
+ // Bst.g:53:11: 'STRINGS'
+ {
+ match("STRINGS");
+
+
+ }
+
+
+
+ if ( token==null && ruleNestingLevel==1 ) {
+ emit(_type,_line,_charPosition,_channel,_start,getCharIndex()-1);
+ }
+
+ }
+ finally {
+ ruleNestingLevel--;
+ }
+ }
+ // $ANTLR end STRINGS
+
+ // $ANTLR start INTEGERS
+ public void mINTEGERS() throws RecognitionException {
+ try {
+ ruleNestingLevel++;
+ int _type = INTEGERS;
+ int _start = getCharIndex();
+ int _line = getLine();
+ int _charPosition = getCharPositionInLine();
+ int _channel = Token.DEFAULT_CHANNEL;
+ // Bst.g:54:12: ( 'INTEGERS' )
+ // Bst.g:54:12: 'INTEGERS'
+ {
+ match("INTEGERS");
+
+
+ }
+
+
+
+ if ( token==null && ruleNestingLevel==1 ) {
+ emit(_type,_line,_charPosition,_channel,_start,getCharIndex()-1);
+ }
+
+ }
+ finally {
+ ruleNestingLevel--;
+ }
+ }
+ // $ANTLR end INTEGERS
+
+ // $ANTLR start FUNCTION
+ public void mFUNCTION() throws RecognitionException {
+ try {
+ ruleNestingLevel++;
+ int _type = FUNCTION;
+ int _start = getCharIndex();
+ int _line = getLine();
+ int _charPosition = getCharPositionInLine();
+ int _channel = Token.DEFAULT_CHANNEL;
+ // Bst.g:55:12: ( 'FUNCTION' )
+ // Bst.g:55:12: 'FUNCTION'
+ {
+ match("FUNCTION");
+
+
+ }
+
+
+
+ if ( token==null && ruleNestingLevel==1 ) {
+ emit(_type,_line,_charPosition,_channel,_start,getCharIndex()-1);
+ }
+
+ }
+ finally {
+ ruleNestingLevel--;
+ }
+ }
+ // $ANTLR end FUNCTION
+
+ // $ANTLR start EXECUTE
+ public void mEXECUTE() throws RecognitionException {
+ try {
+ ruleNestingLevel++;
+ int _type = EXECUTE;
+ int _start = getCharIndex();
+ int _line = getLine();
+ int _charPosition = getCharPositionInLine();
+ int _channel = Token.DEFAULT_CHANNEL;
+ // Bst.g:56:11: ( 'EXECUTE' )
+ // Bst.g:56:11: 'EXECUTE'
+ {
+ match("EXECUTE");
+
+
+ }
+
+
+
+ if ( token==null && ruleNestingLevel==1 ) {
+ emit(_type,_line,_charPosition,_channel,_start,getCharIndex()-1);
+ }
+
+ }
+ finally {
+ ruleNestingLevel--;
+ }
+ }
+ // $ANTLR end EXECUTE
+
+ // $ANTLR start SORT
+ public void mSORT() throws RecognitionException {
+ try {
+ ruleNestingLevel++;
+ int _type = SORT;
+ int _start = getCharIndex();
+ int _line = getLine();
+ int _charPosition = getCharPositionInLine();
+ int _channel = Token.DEFAULT_CHANNEL;
+ // Bst.g:57:8: ( 'SORT' )
+ // Bst.g:57:8: 'SORT'
+ {
+ match("SORT");
+
+
+ }
+
+
+
+ if ( token==null && ruleNestingLevel==1 ) {
+ emit(_type,_line,_charPosition,_channel,_start,getCharIndex()-1);
+ }
+
+ }
+ finally {
+ ruleNestingLevel--;
+ }
+ }
+ // $ANTLR end SORT
+
+ // $ANTLR start ITERATE
+ public void mITERATE() throws RecognitionException {
+ try {
+ ruleNestingLevel++;
+ int _type = ITERATE;
+ int _start = getCharIndex();
+ int _line = getLine();
+ int _charPosition = getCharPositionInLine();
+ int _channel = Token.DEFAULT_CHANNEL;
+ // Bst.g:58:11: ( 'ITERATE' )
+ // Bst.g:58:11: 'ITERATE'
+ {
+ match("ITERATE");
+
+
+ }
+
+
+
+ if ( token==null && ruleNestingLevel==1 ) {
+ emit(_type,_line,_charPosition,_channel,_start,getCharIndex()-1);
+ }
+
+ }
+ finally {
+ ruleNestingLevel--;
+ }
+ }
+ // $ANTLR end ITERATE
+
+ // $ANTLR start REVERSE
+ public void mREVERSE() throws RecognitionException {
+ try {
+ ruleNestingLevel++;
+ int _type = REVERSE;
+ int _start = getCharIndex();
+ int _line = getLine();
+ int _charPosition = getCharPositionInLine();
+ int _channel = Token.DEFAULT_CHANNEL;
+ // Bst.g:59:11: ( 'REVERSE' )
+ // Bst.g:59:11: 'REVERSE'
+ {
+ match("REVERSE");
+
+
+ }
+
+
+
+ if ( token==null && ruleNestingLevel==1 ) {
+ emit(_type,_line,_charPosition,_channel,_start,getCharIndex()-1);
+ }
+
+ }
+ finally {
+ ruleNestingLevel--;
+ }
+ }
+ // $ANTLR end REVERSE
+
+ // $ANTLR start ENTRY
+ public void mENTRY() throws RecognitionException {
+ try {
+ ruleNestingLevel++;
+ int _type = ENTRY;
+ int _start = getCharIndex();
+ int _line = getLine();
+ int _charPosition = getCharPositionInLine();
+ int _channel = Token.DEFAULT_CHANNEL;
+ // Bst.g:60:9: ( 'ENTRY' )
+ // Bst.g:60:9: 'ENTRY'
+ {
+ match("ENTRY");
+
+
+ }
+
+
+
+ if ( token==null && ruleNestingLevel==1 ) {
+ emit(_type,_line,_charPosition,_channel,_start,getCharIndex()-1);
+ }
+
+ }
+ finally {
+ ruleNestingLevel--;
+ }
+ }
+ // $ANTLR end ENTRY
+
+ // $ANTLR start READ
+ public void mREAD() throws RecognitionException {
+ try {
+ ruleNestingLevel++;
+ int _type = READ;
+ int _start = getCharIndex();
+ int _line = getLine();
+ int _charPosition = getCharPositionInLine();
+ int _channel = Token.DEFAULT_CHANNEL;
+ // Bst.g:61:8: ( 'READ' )
+ // Bst.g:61:8: 'READ'
+ {
+ match("READ");
+
+
+ }
+
+
+
+ if ( token==null && ruleNestingLevel==1 ) {
+ emit(_type,_line,_charPosition,_channel,_start,getCharIndex()-1);
+ }
+
+ }
+ finally {
+ ruleNestingLevel--;
+ }
+ }
+ // $ANTLR end READ
+
+ // $ANTLR start MACRO
+ public void mMACRO() throws RecognitionException {
+ try {
+ ruleNestingLevel++;
+ int _type = MACRO;
+ int _start = getCharIndex();
+ int _line = getLine();
+ int _charPosition = getCharPositionInLine();
+ int _channel = Token.DEFAULT_CHANNEL;
+ // Bst.g:62:9: ( 'MACRO' )
+ // Bst.g:62:9: 'MACRO'
+ {
+ match("MACRO");
+
+
+ }
+
+
+
+ if ( token==null && ruleNestingLevel==1 ) {
+ emit(_type,_line,_charPosition,_channel,_start,getCharIndex()-1);
+ }
+
+ }
+ finally {
+ ruleNestingLevel--;
+ }
+ }
+ // $ANTLR end MACRO
+
+ // $ANTLR start QUOTED
+ public void mQUOTED() throws RecognitionException {
+ try {
+ ruleNestingLevel++;
+ int _type = QUOTED;
+ int _start = getCharIndex();
+ int _line = getLine();
+ int _charPosition = getCharPositionInLine();
+ int _channel = Token.DEFAULT_CHANNEL;
+ // Bst.g:65:4: ( '\\'' IDENTIFIER )
+ // Bst.g:65:4: '\\'' IDENTIFIER
+ {
+ match('\'');
+ mIDENTIFIER();
+
+ }
+
+
+
+ if ( token==null && ruleNestingLevel==1 ) {
+ emit(_type,_line,_charPosition,_channel,_start,getCharIndex()-1);
+ }
+
+ }
+ finally {
+ ruleNestingLevel--;
+ }
+ }
+ // $ANTLR end QUOTED
+
+ // $ANTLR start IDENTIFIER
+ public void mIDENTIFIER() throws RecognitionException {
+ try {
+ ruleNestingLevel++;
+ int _type = IDENTIFIER;
+ int _start = getCharIndex();
+ int _line = getLine();
+ int _charPosition = getCharPositionInLine();
+ int _channel = Token.DEFAULT_CHANNEL;
+ // Bst.g:68:4: ( LETTER ( LETTER | NUMERAL )* )
+ // Bst.g:68:4: LETTER ( LETTER | NUMERAL )*
+ {
+ mLETTER();
+ // Bst.g:68:11: ( LETTER | NUMERAL )*
+ loop1:
+ do {
+ int alt1=3;
+ int LA1_0 = input.LA(1);
+ if ( (LA1_0=='$'||LA1_0=='.'||(LA1_0>='A' && LA1_0<='Z')||(LA1_0>='a' && LA1_0<='z')) ) {
+ alt1=1;
+ }
+ else if ( ((LA1_0>='0' && LA1_0<='9')) ) {
+ alt1=2;
+ }
+
+
+ switch (alt1) {
+ case 1 :
+ // Bst.g:68:12: LETTER
+ {
+ mLETTER();
+
+ }
+ break;
+ case 2 :
+ // Bst.g:68:19: NUMERAL
+ {
+ mNUMERAL();
+
+ }
+ break;
+
+ default :
+ break loop1;
+ }
+ } while (true);
+
+
+ }
+
+
+
+ if ( token==null && ruleNestingLevel==1 ) {
+ emit(_type,_line,_charPosition,_channel,_start,getCharIndex()-1);
+ }
+
+ }
+ finally {
+ ruleNestingLevel--;
+ }
+ }
+ // $ANTLR end IDENTIFIER
+
+ // $ANTLR start LETTER
+ public void mLETTER() throws RecognitionException {
+ try {
+ ruleNestingLevel++;
+ // Bst.g:71:4: ( ('a'..'z'|'A'..'Z'|'.'|'$'))
+ // Bst.g:71:4: ('a'..'z'|'A'..'Z'|'.'|'$')
+ {
+ if ( input.LA(1)=='$'||input.LA(1)=='.'||(input.LA(1)>='A' && input.LA(1)<='Z')||(input.LA(1)>='a' && input.LA(1)<='z') ) {
+ input.consume();
+
+ }
+ else {
+ MismatchedSetException mse =
+ new MismatchedSetException(null,input);
+ recover(mse); throw mse;
+ }
+
+
+ }
+
+ }
+ finally {
+ ruleNestingLevel--;
+ }
+ }
+ // $ANTLR end LETTER
+
+ // $ANTLR start STRING
+ public void mSTRING() throws RecognitionException {
+ try {
+ ruleNestingLevel++;
+ int _type = STRING;
+ int _start = getCharIndex();
+ int _line = getLine();
+ int _charPosition = getCharPositionInLine();
+ int _channel = Token.DEFAULT_CHANNEL;
+ // Bst.g:74:4: ( '\"' (~ '\"' )* '\"' )
+ // Bst.g:74:4: '\"' (~ '\"' )* '\"'
+ {
+ match('\"');
+ // Bst.g:74:8: (~ '\"' )*
+ loop2:
+ do {
+ int alt2=2;
+ int LA2_0 = input.LA(1);
+ if ( ((LA2_0>='\u0000' && LA2_0<='!')||(LA2_0>='#' && LA2_0<='\uFFFE')) ) {
+ alt2=1;
+ }
+
+
+ switch (alt2) {
+ case 1 :
+ // Bst.g:74:9: ~ '\"'
+ {
+ if ( (input.LA(1)>='\u0000' && input.LA(1)<='!')||(input.LA(1)>='#' && input.LA(1)<='\uFFFE') ) {
+ input.consume();
+
+ }
+ else {
+ MismatchedSetException mse =
+ new MismatchedSetException(null,input);
+ recover(mse); throw mse;
+ }
+
+
+ }
+ break;
+
+ default :
+ break loop2;
+ }
+ } while (true);
+
+ match('\"');
+
+ }
+
+
+
+ if ( token==null && ruleNestingLevel==1 ) {
+ emit(_type,_line,_charPosition,_channel,_start,getCharIndex()-1);
+ }
+
+ }
+ finally {
+ ruleNestingLevel--;
+ }
+ }
+ // $ANTLR end STRING
+
+ // $ANTLR start INTEGER
+ public void mINTEGER() throws RecognitionException {
+ try {
+ ruleNestingLevel++;
+ int _type = INTEGER;
+ int _start = getCharIndex();
+ int _line = getLine();
+ int _charPosition = getCharPositionInLine();
+ int _channel = Token.DEFAULT_CHANNEL;
+ // Bst.g:77:4: ( '#' ( ('+'|'-'))? ( NUMERAL )+ )
+ // Bst.g:77:4: '#' ( ('+'|'-'))? ( NUMERAL )+
+ {
+ match('#');
+ // Bst.g:77:8: ( ('+'|'-'))?
+ int alt3=2;
+ int LA3_0 = input.LA(1);
+ if ( (LA3_0=='+'||LA3_0=='-') ) {
+ alt3=1;
+ }
+ switch (alt3) {
+ case 1 :
+ // Bst.g:77:9: ('+'|'-')
+ {
+ if ( input.LA(1)=='+'||input.LA(1)=='-' ) {
+ input.consume();
+
+ }
+ else {
+ MismatchedSetException mse =
+ new MismatchedSetException(null,input);
+ recover(mse); throw mse;
+ }
+
+
+ }
+ break;
+
+ }
+
+ // Bst.g:77:19: ( NUMERAL )+
+ int cnt4=0;
+ loop4:
+ do {
+ int alt4=2;
+ int LA4_0 = input.LA(1);
+ if ( ((LA4_0>='0' && LA4_0<='9')) ) {
+ alt4=1;
+ }
+
+
+ switch (alt4) {
+ case 1 :
+ // Bst.g:77:19: NUMERAL
+ {
+ mNUMERAL();
+
+ }
+ break;
+
+ default :
+ if ( cnt4 >= 1 ) break loop4;
+ EarlyExitException eee =
+ new EarlyExitException(4, input);
+ throw eee;
+ }
+ cnt4++;
+ } while (true);
+
+
+ }
+
+
+
+ if ( token==null && ruleNestingLevel==1 ) {
+ emit(_type,_line,_charPosition,_channel,_start,getCharIndex()-1);
+ }
+
+ }
+ finally {
+ ruleNestingLevel--;
+ }
+ }
+ // $ANTLR end INTEGER
+
+ // $ANTLR start NUMERAL
+ public void mNUMERAL() throws RecognitionException {
+ try {
+ ruleNestingLevel++;
+ // Bst.g:80:4: ( ( '0' .. '9' ) )
+ // Bst.g:80:4: ( '0' .. '9' )
+ {
+ // Bst.g:80:4: ( '0' .. '9' )
+ // Bst.g:80:5: '0' .. '9'
+ {
+ matchRange('0','9');
+
+ }
+
+
+ }
+
+ }
+ finally {
+ ruleNestingLevel--;
+ }
+ }
+ // $ANTLR end NUMERAL
+
+ // $ANTLR start WS
+ public void mWS() throws RecognitionException {
+ try {
+ ruleNestingLevel++;
+ int _type = WS;
+ int _start = getCharIndex();
+ int _line = getLine();
+ int _charPosition = getCharPositionInLine();
+ int _channel = Token.DEFAULT_CHANNEL;
+ // Bst.g:82:9: ( ( (' '|'\\t'|'\\r'|'\\n'))+ )
+ // Bst.g:82:9: ( (' '|'\\t'|'\\r'|'\\n'))+
+ {
+ // Bst.g:82:9: ( (' '|'\\t'|'\\r'|'\\n'))+
+ int cnt5=0;
+ loop5:
+ do {
+ int alt5=2;
+ int LA5_0 = input.LA(1);
+ if ( ((LA5_0>='\t' && LA5_0<='\n')||LA5_0=='\r'||LA5_0==' ') ) {
+ alt5=1;
+ }
+
+
+ switch (alt5) {
+ case 1 :
+ // Bst.g:82:13: (' '|'\\t'|'\\r'|'\\n')
+ {
+ if ( (input.LA(1)>='\t' && input.LA(1)<='\n')||input.LA(1)=='\r'||input.LA(1)==' ' ) {
+ input.consume();
+
+ }
+ else {
+ MismatchedSetException mse =
+ new MismatchedSetException(null,input);
+ recover(mse); throw mse;
+ }
+
+
+ }
+ break;
+
+ default :
+ if ( cnt5 >= 1 ) break loop5;
+ EarlyExitException eee =
+ new EarlyExitException(5, input);
+ throw eee;
+ }
+ cnt5++;
+ } while (true);
+
+ _channel=HIDDEN;
+
+ }
+
+
+
+ if ( token==null && ruleNestingLevel==1 ) {
+ emit(_type,_line,_charPosition,_channel,_start,getCharIndex()-1);
+ }
+
+ }
+ finally {
+ ruleNestingLevel--;
+ }
+ }
+ // $ANTLR end WS
+
+ // $ANTLR start LINE_COMMENT
+ public void mLINE_COMMENT() throws RecognitionException {
+ try {
+ ruleNestingLevel++;
+ int _type = LINE_COMMENT;
+ int _start = getCharIndex();
+ int _line = getLine();
+ int _charPosition = getCharPositionInLine();
+ int _channel = Token.DEFAULT_CHANNEL;
+ // Bst.g:90:7: ( '%' (~ ('\\n'|'\\r'))* ( '\\r' )? '\\n' )
+ // Bst.g:90:7: '%' (~ ('\\n'|'\\r'))* ( '\\r' )? '\\n'
+ {
+ match('%');
+ // Bst.g:90:11: (~ ('\\n'|'\\r'))*
+ loop6:
+ do {
+ int alt6=2;
+ int LA6_0 = input.LA(1);
+ if ( ((LA6_0>='\u0000' && LA6_0<='\t')||(LA6_0>='\u000B' && LA6_0<='\f')||(LA6_0>='\u000E' && LA6_0<='\uFFFE')) ) {
+ alt6=1;
+ }
+
+
+ switch (alt6) {
+ case 1 :
+ // Bst.g:90:11: ~ ('\\n'|'\\r')
+ {
+ if ( (input.LA(1)>='\u0000' && input.LA(1)<='\t')||(input.LA(1)>='\u000B' && input.LA(1)<='\f')||(input.LA(1)>='\u000E' && input.LA(1)<='\uFFFE') ) {
+ input.consume();
+
+ }
+ else {
+ MismatchedSetException mse =
+ new MismatchedSetException(null,input);
+ recover(mse); throw mse;
+ }
+
+
+ }
+ break;
+
+ default :
+ break loop6;
+ }
+ } while (true);
+
+ // Bst.g:90:25: ( '\\r' )?
+ int alt7=2;
+ int LA7_0 = input.LA(1);
+ if ( (LA7_0=='\r') ) {
+ alt7=1;
+ }
+ switch (alt7) {
+ case 1 :
+ // Bst.g:90:25: '\\r'
+ {
+ match('\r');
+
+ }
+ break;
+
+ }
+
+ match('\n');
+ _channel=HIDDEN;
+
+ }
+
+
+
+ if ( token==null && ruleNestingLevel==1 ) {
+ emit(_type,_line,_charPosition,_channel,_start,getCharIndex()-1);
+ }
+
+ }
+ finally {
+ ruleNestingLevel--;
+ }
+ }
+ // $ANTLR end LINE_COMMENT
+
+ public void mTokens() throws RecognitionException {
+ // Bst.g:1:10: ( T25 | T26 | T27 | T28 | T29 | T30 | T31 | T32 | T33 | STRINGS | INTEGERS | FUNCTION | EXECUTE | SORT | ITERATE | REVERSE | ENTRY | READ | MACRO | QUOTED | IDENTIFIER | STRING | INTEGER | WS | LINE_COMMENT )
+ int alt8=25;
+ switch ( input.LA(1) ) {
+ case '{':
+ alt8=1;
+ break;
+ case '}':
+ alt8=2;
+ break;
+ case '<':
+ alt8=3;
+ break;
+ case '>':
+ alt8=4;
+ break;
+ case '=':
+ alt8=5;
+ break;
+ case '+':
+ alt8=6;
+ break;
+ case '-':
+ alt8=7;
+ break;
+ case ':':
+ alt8=8;
+ break;
+ case '*':
+ alt8=9;
+ break;
+ case 'S':
+ switch ( input.LA(2) ) {
+ case 'T':
+ int LA8_22 = input.LA(3);
+ if ( (LA8_22=='R') ) {
+ int LA8_31 = input.LA(4);
+ if ( (LA8_31=='I') ) {
+ int LA8_41 = input.LA(5);
+ if ( (LA8_41=='N') ) {
+ int LA8_51 = input.LA(6);
+ if ( (LA8_51=='G') ) {
+ int LA8_61 = input.LA(7);
+ if ( (LA8_61=='S') ) {
+ int LA8_69 = input.LA(8);
+ if ( (LA8_69=='$'||LA8_69=='.'||(LA8_69>='0' && LA8_69<='9')||(LA8_69>='A' && LA8_69<='Z')||(LA8_69>='a' && LA8_69<='z')) ) {
+ alt8=21;
+ }
+ else {
+ alt8=10;}
+ }
+ else {
+ alt8=21;}
+ }
+ else {
+ alt8=21;}
+ }
+ else {
+ alt8=21;}
+ }
+ else {
+ alt8=21;}
+ }
+ else {
+ alt8=21;}
+ break;
+ case 'O':
+ int LA8_23 = input.LA(3);
+ if ( (LA8_23=='R') ) {
+ int LA8_32 = input.LA(4);
+ if ( (LA8_32=='T') ) {
+ int LA8_42 = input.LA(5);
+ if ( (LA8_42=='$'||LA8_42=='.'||(LA8_42>='0' && LA8_42<='9')||(LA8_42>='A' && LA8_42<='Z')||(LA8_42>='a' && LA8_42<='z')) ) {
+ alt8=21;
+ }
+ else {
+ alt8=14;}
+ }
+ else {
+ alt8=21;}
+ }
+ else {
+ alt8=21;}
+ break;
+ default:
+ alt8=21;}
+
+ break;
+ case 'I':
+ switch ( input.LA(2) ) {
+ case 'T':
+ int LA8_24 = input.LA(3);
+ if ( (LA8_24=='E') ) {
+ int LA8_33 = input.LA(4);
+ if ( (LA8_33=='R') ) {
+ int LA8_43 = input.LA(5);
+ if ( (LA8_43=='A') ) {
+ int LA8_53 = input.LA(6);
+ if ( (LA8_53=='T') ) {
+ int LA8_62 = input.LA(7);
+ if ( (LA8_62=='E') ) {
+ int LA8_70 = input.LA(8);
+ if ( (LA8_70=='$'||LA8_70=='.'||(LA8_70>='0' && LA8_70<='9')||(LA8_70>='A' && LA8_70<='Z')||(LA8_70>='a' && LA8_70<='z')) ) {
+ alt8=21;
+ }
+ else {
+ alt8=15;}
+ }
+ else {
+ alt8=21;}
+ }
+ else {
+ alt8=21;}
+ }
+ else {
+ alt8=21;}
+ }
+ else {
+ alt8=21;}
+ }
+ else {
+ alt8=21;}
+ break;
+ case 'N':
+ int LA8_25 = input.LA(3);
+ if ( (LA8_25=='T') ) {
+ int LA8_34 = input.LA(4);
+ if ( (LA8_34=='E') ) {
+ int LA8_44 = input.LA(5);
+ if ( (LA8_44=='G') ) {
+ int LA8_54 = input.LA(6);
+ if ( (LA8_54=='E') ) {
+ int LA8_63 = input.LA(7);
+ if ( (LA8_63=='R') ) {
+ int LA8_71 = input.LA(8);
+ if ( (LA8_71=='S') ) {
+ int LA8_77 = input.LA(9);
+ if ( (LA8_77=='$'||LA8_77=='.'||(LA8_77>='0' && LA8_77<='9')||(LA8_77>='A' && LA8_77<='Z')||(LA8_77>='a' && LA8_77<='z')) ) {
+ alt8=21;
+ }
+ else {
+ alt8=11;}
+ }
+ else {
+ alt8=21;}
+ }
+ else {
+ alt8=21;}
+ }
+ else {
+ alt8=21;}
+ }
+ else {
+ alt8=21;}
+ }
+ else {
+ alt8=21;}
+ }
+ else {
+ alt8=21;}
+ break;
+ default:
+ alt8=21;}
+
+ break;
+ case 'F':
+ int LA8_12 = input.LA(2);
+ if ( (LA8_12=='U') ) {
+ int LA8_26 = input.LA(3);
+ if ( (LA8_26=='N') ) {
+ int LA8_35 = input.LA(4);
+ if ( (LA8_35=='C') ) {
+ int LA8_45 = input.LA(5);
+ if ( (LA8_45=='T') ) {
+ int LA8_55 = input.LA(6);
+ if ( (LA8_55=='I') ) {
+ int LA8_64 = input.LA(7);
+ if ( (LA8_64=='O') ) {
+ int LA8_72 = input.LA(8);
+ if ( (LA8_72=='N') ) {
+ int LA8_78 = input.LA(9);
+ if ( (LA8_78=='$'||LA8_78=='.'||(LA8_78>='0' && LA8_78<='9')||(LA8_78>='A' && LA8_78<='Z')||(LA8_78>='a' && LA8_78<='z')) ) {
+ alt8=21;
+ }
+ else {
+ alt8=12;}
+ }
+ else {
+ alt8=21;}
+ }
+ else {
+ alt8=21;}
+ }
+ else {
+ alt8=21;}
+ }
+ else {
+ alt8=21;}
+ }
+ else {
+ alt8=21;}
+ }
+ else {
+ alt8=21;}
+ }
+ else {
+ alt8=21;}
+ break;
+ case 'E':
+ switch ( input.LA(2) ) {
+ case 'N':
+ int LA8_27 = input.LA(3);
+ if ( (LA8_27=='T') ) {
+ int LA8_36 = input.LA(4);
+ if ( (LA8_36=='R') ) {
+ int LA8_46 = input.LA(5);
+ if ( (LA8_46=='Y') ) {
+ int LA8_56 = input.LA(6);
+ if ( (LA8_56=='$'||LA8_56=='.'||(LA8_56>='0' && LA8_56<='9')||(LA8_56>='A' && LA8_56<='Z')||(LA8_56>='a' && LA8_56<='z')) ) {
+ alt8=21;
+ }
+ else {
+ alt8=17;}
+ }
+ else {
+ alt8=21;}
+ }
+ else {
+ alt8=21;}
+ }
+ else {
+ alt8=21;}
+ break;
+ case 'X':
+ int LA8_28 = input.LA(3);
+ if ( (LA8_28=='E') ) {
+ int LA8_37 = input.LA(4);
+ if ( (LA8_37=='C') ) {
+ int LA8_47 = input.LA(5);
+ if ( (LA8_47=='U') ) {
+ int LA8_57 = input.LA(6);
+ if ( (LA8_57=='T') ) {
+ int LA8_66 = input.LA(7);
+ if ( (LA8_66=='E') ) {
+ int LA8_73 = input.LA(8);
+ if ( (LA8_73=='$'||LA8_73=='.'||(LA8_73>='0' && LA8_73<='9')||(LA8_73>='A' && LA8_73<='Z')||(LA8_73>='a' && LA8_73<='z')) ) {
+ alt8=21;
+ }
+ else {
+ alt8=13;}
+ }
+ else {
+ alt8=21;}
+ }
+ else {
+ alt8=21;}
+ }
+ else {
+ alt8=21;}
+ }
+ else {
+ alt8=21;}
+ }
+ else {
+ alt8=21;}
+ break;
+ default:
+ alt8=21;}
+
+ break;
+ case 'R':
+ int LA8_14 = input.LA(2);
+ if ( (LA8_14=='E') ) {
+ switch ( input.LA(3) ) {
+ case 'A':
+ int LA8_38 = input.LA(4);
+ if ( (LA8_38=='D') ) {
+ int LA8_48 = input.LA(5);
+ if ( (LA8_48=='$'||LA8_48=='.'||(LA8_48>='0' && LA8_48<='9')||(LA8_48>='A' && LA8_48<='Z')||(LA8_48>='a' && LA8_48<='z')) ) {
+ alt8=21;
+ }
+ else {
+ alt8=18;}
+ }
+ else {
+ alt8=21;}
+ break;
+ case 'V':
+ int LA8_39 = input.LA(4);
+ if ( (LA8_39=='E') ) {
+ int LA8_49 = input.LA(5);
+ if ( (LA8_49=='R') ) {
+ int LA8_59 = input.LA(6);
+ if ( (LA8_59=='S') ) {
+ int LA8_67 = input.LA(7);
+ if ( (LA8_67=='E') ) {
+ int LA8_74 = input.LA(8);
+ if ( (LA8_74=='$'||LA8_74=='.'||(LA8_74>='0' && LA8_74<='9')||(LA8_74>='A' && LA8_74<='Z')||(LA8_74>='a' && LA8_74<='z')) ) {
+ alt8=21;
+ }
+ else {
+ alt8=16;}
+ }
+ else {
+ alt8=21;}
+ }
+ else {
+ alt8=21;}
+ }
+ else {
+ alt8=21;}
+ }
+ else {
+ alt8=21;}
+ break;
+ default:
+ alt8=21;}
+
+ }
+ else {
+ alt8=21;}
+ break;
+ case 'M':
+ int LA8_15 = input.LA(2);
+ if ( (LA8_15=='A') ) {
+ int LA8_30 = input.LA(3);
+ if ( (LA8_30=='C') ) {
+ int LA8_40 = input.LA(4);
+ if ( (LA8_40=='R') ) {
+ int LA8_50 = input.LA(5);
+ if ( (LA8_50=='O') ) {
+ int LA8_60 = input.LA(6);
+ if ( (LA8_60=='$'||LA8_60=='.'||(LA8_60>='0' && LA8_60<='9')||(LA8_60>='A' && LA8_60<='Z')||(LA8_60>='a' && LA8_60<='z')) ) {
+ alt8=21;
+ }
+ else {
+ alt8=19;}
+ }
+ else {
+ alt8=21;}
+ }
+ else {
+ alt8=21;}
+ }
+ else {
+ alt8=21;}
+ }
+ else {
+ alt8=21;}
+ break;
+ case '\'':
+ alt8=20;
+ break;
+ case '$':
+ case '.':
+ case 'A':
+ case 'B':
+ case 'C':
+ case 'D':
+ case 'G':
+ case 'H':
+ case 'J':
+ case 'K':
+ case 'L':
+ case 'N':
+ case 'O':
+ case 'P':
+ case 'Q':
+ case 'T':
+ case 'U':
+ case 'V':
+ case 'W':
+ case 'X':
+ case 'Y':
+ case 'Z':
+ case 'a':
+ case 'b':
+ case 'c':
+ case 'd':
+ case 'e':
+ case 'f':
+ case 'g':
+ case 'h':
+ case 'i':
+ case 'j':
+ case 'k':
+ case 'l':
+ case 'm':
+ case 'n':
+ case 'o':
+ case 'p':
+ case 'q':
+ case 'r':
+ case 's':
+ case 't':
+ case 'u':
+ case 'v':
+ case 'w':
+ case 'x':
+ case 'y':
+ case 'z':
+ alt8=21;
+ break;
+ case '\"':
+ alt8=22;
+ break;
+ case '#':
+ alt8=23;
+ break;
+ case '\t':
+ case '\n':
+ case '\r':
+ case ' ':
+ alt8=24;
+ break;
+ case '%':
+ alt8=25;
+ break;
+ default:
+ NoViableAltException nvae =
+ new NoViableAltException("1:1: Tokens : ( T25 | T26 | T27 | T28 | T29 | T30 | T31 | T32 | T33 | STRINGS | INTEGERS | FUNCTION | EXECUTE | SORT | ITERATE | REVERSE | ENTRY | READ | MACRO | QUOTED | IDENTIFIER | STRING | INTEGER | WS | LINE_COMMENT );", 8, 0, input);
+
+ throw nvae;
+ }
+
+ switch (alt8) {
+ case 1 :
+ // Bst.g:1:10: T25
+ {
+ mT25();
+
+ }
+ break;
+ case 2 :
+ // Bst.g:1:14: T26
+ {
+ mT26();
+
+ }
+ break;
+ case 3 :
+ // Bst.g:1:18: T27
+ {
+ mT27();
+
+ }
+ break;
+ case 4 :
+ // Bst.g:1:22: T28
+ {
+ mT28();
+
+ }
+ break;
+ case 5 :
+ // Bst.g:1:26: T29
+ {
+ mT29();
+
+ }
+ break;
+ case 6 :
+ // Bst.g:1:30: T30
+ {
+ mT30();
+
+ }
+ break;
+ case 7 :
+ // Bst.g:1:34: T31
+ {
+ mT31();
+
+ }
+ break;
+ case 8 :
+ // Bst.g:1:38: T32
+ {
+ mT32();
+
+ }
+ break;
+ case 9 :
+ // Bst.g:1:42: T33
+ {
+ mT33();
+
+ }
+ break;
+ case 10 :
+ // Bst.g:1:46: STRINGS
+ {
+ mSTRINGS();
+
+ }
+ break;
+ case 11 :
+ // Bst.g:1:54: INTEGERS
+ {
+ mINTEGERS();
+
+ }
+ break;
+ case 12 :
+ // Bst.g:1:63: FUNCTION
+ {
+ mFUNCTION();
+
+ }
+ break;
+ case 13 :
+ // Bst.g:1:72: EXECUTE
+ {
+ mEXECUTE();
+
+ }
+ break;
+ case 14 :
+ // Bst.g:1:80: SORT
+ {
+ mSORT();
+
+ }
+ break;
+ case 15 :
+ // Bst.g:1:85: ITERATE
+ {
+ mITERATE();
+
+ }
+ break;
+ case 16 :
+ // Bst.g:1:93: REVERSE
+ {
+ mREVERSE();
+
+ }
+ break;
+ case 17 :
+ // Bst.g:1:101: ENTRY
+ {
+ mENTRY();
+
+ }
+ break;
+ case 18 :
+ // Bst.g:1:107: READ
+ {
+ mREAD();
+
+ }
+ break;
+ case 19 :
+ // Bst.g:1:112: MACRO
+ {
+ mMACRO();
+
+ }
+ break;
+ case 20 :
+ // Bst.g:1:118: QUOTED
+ {
+ mQUOTED();
+
+ }
+ break;
+ case 21 :
+ // Bst.g:1:125: IDENTIFIER
+ {
+ mIDENTIFIER();
+
+ }
+ break;
+ case 22 :
+ // Bst.g:1:136: STRING
+ {
+ mSTRING();
+
+ }
+ break;
+ case 23 :
+ // Bst.g:1:143: INTEGER
+ {
+ mINTEGER();
+
+ }
+ break;
+ case 24 :
+ // Bst.g:1:151: WS
+ {
+ mWS();
+
+ }
+ break;
+ case 25 :
+ // Bst.g:1:154: LINE_COMMENT
+ {
+ mLINE_COMMENT();
+
+ }
+ break;
+
+ }
+
+ }
+
+
+
+
+}
\ No newline at end of file
diff --git a/src/java/net/sf/jabref/bst/BstParser.java b/src/java/net/sf/jabref/bst/BstParser.java
new file mode 100644
index 0000000..516e240
--- /dev/null
+++ b/src/java/net/sf/jabref/bst/BstParser.java
@@ -0,0 +1,1344 @@
+package net.sf.jabref.bst;
+
+// $ANTLR 3.0b5 Bst.g 2006-11-23 23:20:24
+
+import org.antlr.runtime.*;
+import java.util.Stack;
+import java.util.List;
+import java.util.ArrayList;
+
+
+import org.antlr.runtime.tree.*;
+
+public class BstParser extends Parser {
+ public static final String[] tokenNames = new String[] {
+ "<invalid>", "<EOR>", "<DOWN>", "<UP>", "IDLIST", "STACK", "ENTRY", "COMMANDS", "STRINGS", "INTEGERS", "FUNCTION", "MACRO", "STRING", "READ", "EXECUTE", "ITERATE", "REVERSE", "SORT", "IDENTIFIER", "INTEGER", "QUOTED", "LETTER", "NUMERAL", "WS", "LINE_COMMENT", "'{'", "'}'", "'<'", "'>'", "'='", "'+'", "'-'", "':='", "'*'"
+ };
+ public static final int LETTER=21;
+ public static final int ENTRY=6;
+ public static final int INTEGERS=9;
+ public static final int WS=23;
+ public static final int COMMANDS=7;
+ public static final int STRING=12;
+ public static final int EXECUTE=14;
+ public static final int LINE_COMMENT=24;
+ public static final int SORT=17;
+ public static final int STACK=5;
+ public static final int REVERSE=16;
+ public static final int QUOTED=20;
+ public static final int INTEGER=19;
+ public static final int ITERATE=15;
+ public static final int FUNCTION=10;
+ public static final int EOF=-1;
+ public static final int STRINGS=8;
+ public static final int IDENTIFIER=18;
+ public static final int MACRO=11;
+ public static final int IDLIST=4;
+ public static final int NUMERAL=22;
+ public static final int READ=13;
+
+ public BstParser(TokenStream input) {
+ super(input);
+ }
+
+ protected TreeAdaptor adaptor = new CommonTreeAdaptor();
+
+ public void setTreeAdaptor(TreeAdaptor adaptor) {
+ this.adaptor = adaptor;
+ }
+ public TreeAdaptor getTreeAdaptor() {
+ return adaptor;
+ }
+
+ public String[] getTokenNames() { return tokenNames; }
+ public String getGrammarFileName() { return "Bst.g"; }
+
+
+ public static class program_return extends ParserRuleReturnScope {
+ Object tree;
+ public Object getTree() { return tree; }
+ };
+
+ // $ANTLR start program
+ // Bst.g:14:1: program : ( commands )+ -> ^( COMMANDS ( commands )+ ) ;
+ public program_return program() throws RecognitionException {
+ program_return retval = new program_return();
+ retval.start = input.LT(1);
+
+ Object root_0 = null;
+
+ commands_return commands1 = null;
+
+ List list_commands=new ArrayList();
+
+ try {
+ // Bst.g:14:11: ( ( commands )+ -> ^( COMMANDS ( commands )+ ) )
+ // Bst.g:14:11: ( commands )+
+ {
+ // Bst.g:14:11: ( commands )+
+ int cnt1=0;
+ loop1:
+ do {
+ int alt1=2;
+ int LA1_0 = input.LA(1);
+ if ( (LA1_0==ENTRY||(LA1_0>=STRINGS && LA1_0<=MACRO)||(LA1_0>=READ && LA1_0<=SORT)) ) {
+ alt1=1;
+ }
+
+
+ switch (alt1) {
+ case 1 :
+ // Bst.g:14:11: commands
+ {
+ pushFollow(FOLLOW_commands_in_program45);
+ commands1=commands();
+ _fsp--;
+
+ list_commands.add(commands1.tree);
+
+ }
+ break;
+
+ default :
+ if ( cnt1 >= 1 ) break loop1;
+ EarlyExitException eee =
+ new EarlyExitException(1, input);
+ throw eee;
+ }
+ cnt1++;
+ } while (true);
+
+
+ // AST REWRITE
+ int i_0 = 0;
+ retval.tree = root_0;
+ root_0 = (Object)adaptor.nil();
+ // 14:21: -> ^( COMMANDS ( commands )+ )
+ {
+ // Bst.g:14:24: ^( COMMANDS ( commands )+ )
+ {
+ Object root_1 = (Object)adaptor.nil();
+ root_1 = (Object)adaptor.becomeRoot(adaptor.create(COMMANDS, "COMMANDS"), root_1);
+
+ // Bst.g:14:35: ( commands )+
+ {
+ int n_1 = list_commands == null ? 0 : list_commands.size();
+
+
+
+ if ( n_1==0 ) throw new RuntimeException("Must have more than one element for (...)+ loops");
+ for (int i_1=0; i_1<n_1; i_1++) {
+ adaptor.addChild(root_1, list_commands.get(i_1));
+
+ }
+ }
+
+ adaptor.addChild(root_0, root_1);
+ }
+
+ }
+
+
+
+ }
+
+ }
+ catch (RecognitionException re) {
+ reportError(re);
+ recover(input,re);
+ }
+ finally {
+ retval.stop = input.LT(-1);
+
+ retval.tree = (Object)adaptor.rulePostProcessing(root_0);
+ adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop);
+
+ }
+ return retval;
+ }
+ // $ANTLR end program
+
+ public static class commands_return extends ParserRuleReturnScope {
+ Object tree;
+ public Object getTree() { return tree; }
+ };
+
+ // $ANTLR start commands
+ // Bst.g:16:1: commands : ( STRINGS^^ idList | INTEGERS^^ idList | FUNCTION^^ id stack | MACRO^^ id '{'! STRING '}'! | READ^^ | EXECUTE^^ '{'! function '}'! | ITERATE^^ '{'! function '}'! | REVERSE^^ '{'! function '}'! | ENTRY^^ idList0 idList0 idList0 | SORT^^ );
+ public commands_return commands() throws RecognitionException {
+ commands_return retval = new commands_return();
+ retval.start = input.LT(1);
+
+ Object root_0 = null;
+
+ Token STRINGS2=null;
+ Token INTEGERS4=null;
+ Token FUNCTION6=null;
+ Token MACRO9=null;
+ Token char_literal11=null;
+ Token STRING12=null;
+ Token char_literal13=null;
+ Token READ14=null;
+ Token EXECUTE15=null;
+ Token char_literal16=null;
+ Token char_literal18=null;
+ Token ITERATE19=null;
+ Token char_literal20=null;
+ Token char_literal22=null;
+ Token REVERSE23=null;
+ Token char_literal24=null;
+ Token char_literal26=null;
+ Token ENTRY27=null;
+ Token SORT31=null;
+ idList_return idList3 = null;
+
+ idList_return idList5 = null;
+
+ id_return id7 = null;
+
+ stack_return stack8 = null;
+
+ id_return id10 = null;
+
+ function_return function17 = null;
+
+ function_return function21 = null;
+
+ function_return function25 = null;
+
+ idList0_return idList028 = null;
+
+ idList0_return idList029 = null;
+
+ idList0_return idList030 = null;
+
+
+ Object STRINGS2_tree=null;
+ Object INTEGERS4_tree=null;
+ Object FUNCTION6_tree=null;
+ Object MACRO9_tree=null;
+ Object char_literal11_tree=null;
+ Object STRING12_tree=null;
+ Object char_literal13_tree=null;
+ Object READ14_tree=null;
+ Object EXECUTE15_tree=null;
+ Object char_literal16_tree=null;
+ Object char_literal18_tree=null;
+ Object ITERATE19_tree=null;
+ Object char_literal20_tree=null;
+ Object char_literal22_tree=null;
+ Object REVERSE23_tree=null;
+ Object char_literal24_tree=null;
+ Object char_literal26_tree=null;
+ Object ENTRY27_tree=null;
+ Object SORT31_tree=null;
+
+ try {
+ // Bst.g:17:4: ( STRINGS^^ idList | INTEGERS^^ idList | FUNCTION^^ id stack | MACRO^^ id '{'! STRING '}'! | READ^^ | EXECUTE^^ '{'! function '}'! | ITERATE^^ '{'! function '}'! | REVERSE^^ '{'! function '}'! | ENTRY^^ idList0 idList0 idList0 | SORT^^ )
+ int alt2=10;
+ switch ( input.LA(1) ) {
+ case STRINGS:
+ alt2=1;
+ break;
+ case INTEGERS:
+ alt2=2;
+ break;
+ case FUNCTION:
+ alt2=3;
+ break;
+ case MACRO:
+ alt2=4;
+ break;
+ case READ:
+ alt2=5;
+ break;
+ case EXECUTE:
+ alt2=6;
+ break;
+ case ITERATE:
+ alt2=7;
+ break;
+ case REVERSE:
+ alt2=8;
+ break;
+ case ENTRY:
+ alt2=9;
+ break;
+ case SORT:
+ alt2=10;
+ break;
+ default:
+ NoViableAltException nvae =
+ new NoViableAltException("16:1: commands : ( STRINGS^^ idList | INTEGERS^^ idList | FUNCTION^^ id stack | MACRO^^ id '{'! STRING '}'! | READ^^ | EXECUTE^^ '{'! function '}'! | ITERATE^^ '{'! function '}'! | REVERSE^^ '{'! function '}'! | ENTRY^^ idList0 idList0 idList0 | SORT^^ );", 2, 0, input);
+
+ throw nvae;
+ }
+
+ switch (alt2) {
+ case 1 :
+ // Bst.g:17:4: STRINGS^^ idList
+ {
+ root_0 = (Object)adaptor.nil();
+
+ STRINGS2=(Token)input.LT(1);
+ match(input,STRINGS,FOLLOW_STRINGS_in_commands65);
+ STRINGS2_tree = (Object)adaptor.create(STRINGS2);
+ root_0 = (Object)adaptor.becomeRoot(STRINGS2_tree, root_0);
+
+ pushFollow(FOLLOW_idList_in_commands68);
+ idList3=idList();
+ _fsp--;
+
+ adaptor.addChild(root_0, idList3.tree);
+
+ }
+ break;
+ case 2 :
+ // Bst.g:18:4: INTEGERS^^ idList
+ {
+ root_0 = (Object)adaptor.nil();
+
+ INTEGERS4=(Token)input.LT(1);
+ match(input,INTEGERS,FOLLOW_INTEGERS_in_commands73);
+ INTEGERS4_tree = (Object)adaptor.create(INTEGERS4);
+ root_0 = (Object)adaptor.becomeRoot(INTEGERS4_tree, root_0);
+
+ pushFollow(FOLLOW_idList_in_commands76);
+ idList5=idList();
+ _fsp--;
+
+ adaptor.addChild(root_0, idList5.tree);
+
+ }
+ break;
+ case 3 :
+ // Bst.g:19:4: FUNCTION^^ id stack
+ {
+ root_0 = (Object)adaptor.nil();
+
+ FUNCTION6=(Token)input.LT(1);
+ match(input,FUNCTION,FOLLOW_FUNCTION_in_commands81);
+ FUNCTION6_tree = (Object)adaptor.create(FUNCTION6);
+ root_0 = (Object)adaptor.becomeRoot(FUNCTION6_tree, root_0);
+
+ pushFollow(FOLLOW_id_in_commands84);
+ id7=id();
+ _fsp--;
+
+ adaptor.addChild(root_0, id7.tree);
+ pushFollow(FOLLOW_stack_in_commands86);
+ stack8=stack();
+ _fsp--;
+
+ adaptor.addChild(root_0, stack8.tree);
+
+ }
+ break;
+ case 4 :
+ // Bst.g:20:4: MACRO^^ id '{'! STRING '}'!
+ {
+ root_0 = (Object)adaptor.nil();
+
+ MACRO9=(Token)input.LT(1);
+ match(input,MACRO,FOLLOW_MACRO_in_commands91);
+ MACRO9_tree = (Object)adaptor.create(MACRO9);
+ root_0 = (Object)adaptor.becomeRoot(MACRO9_tree, root_0);
+
+ pushFollow(FOLLOW_id_in_commands94);
+ id10=id();
+ _fsp--;
+
+ adaptor.addChild(root_0, id10.tree);
+ char_literal11=(Token)input.LT(1);
+ match(input,25,FOLLOW_25_in_commands96);
+ STRING12=(Token)input.LT(1);
+ match(input,STRING,FOLLOW_STRING_in_commands99);
+ STRING12_tree = (Object)adaptor.create(STRING12);
+ adaptor.addChild(root_0, STRING12_tree);
+
+ char_literal13=(Token)input.LT(1);
+ match(input,26,FOLLOW_26_in_commands101);
+
+ }
+ break;
+ case 5 :
+ // Bst.g:21:4: READ^^
+ {
+ root_0 = (Object)adaptor.nil();
+
+ READ14=(Token)input.LT(1);
+ match(input,READ,FOLLOW_READ_in_commands107);
+ READ14_tree = (Object)adaptor.create(READ14);
+ root_0 = (Object)adaptor.becomeRoot(READ14_tree, root_0);
+
+
+ }
+ break;
+ case 6 :
+ // Bst.g:22:4: EXECUTE^^ '{'! function '}'!
+ {
+ root_0 = (Object)adaptor.nil();
+
+ EXECUTE15=(Token)input.LT(1);
+ match(input,EXECUTE,FOLLOW_EXECUTE_in_commands113);
+ EXECUTE15_tree = (Object)adaptor.create(EXECUTE15);
+ root_0 = (Object)adaptor.becomeRoot(EXECUTE15_tree, root_0);
+
+ char_literal16=(Token)input.LT(1);
+ match(input,25,FOLLOW_25_in_commands116);
+ pushFollow(FOLLOW_function_in_commands119);
+ function17=function();
+ _fsp--;
+
+ adaptor.addChild(root_0, function17.tree);
+ char_literal18=(Token)input.LT(1);
+ match(input,26,FOLLOW_26_in_commands121);
+
+ }
+ break;
+ case 7 :
+ // Bst.g:23:4: ITERATE^^ '{'! function '}'!
+ {
+ root_0 = (Object)adaptor.nil();
+
+ ITERATE19=(Token)input.LT(1);
+ match(input,ITERATE,FOLLOW_ITERATE_in_commands127);
+ ITERATE19_tree = (Object)adaptor.create(ITERATE19);
+ root_0 = (Object)adaptor.becomeRoot(ITERATE19_tree, root_0);
+
+ char_literal20=(Token)input.LT(1);
+ match(input,25,FOLLOW_25_in_commands130);
+ pushFollow(FOLLOW_function_in_commands133);
+ function21=function();
+ _fsp--;
+
+ adaptor.addChild(root_0, function21.tree);
+ char_literal22=(Token)input.LT(1);
+ match(input,26,FOLLOW_26_in_commands135);
+
+ }
+ break;
+ case 8 :
+ // Bst.g:24:4: REVERSE^^ '{'! function '}'!
+ {
+ root_0 = (Object)adaptor.nil();
+
+ REVERSE23=(Token)input.LT(1);
+ match(input,REVERSE,FOLLOW_REVERSE_in_commands141);
+ REVERSE23_tree = (Object)adaptor.create(REVERSE23);
+ root_0 = (Object)adaptor.becomeRoot(REVERSE23_tree, root_0);
+
+ char_literal24=(Token)input.LT(1);
+ match(input,25,FOLLOW_25_in_commands144);
+ pushFollow(FOLLOW_function_in_commands147);
+ function25=function();
+ _fsp--;
+
+ adaptor.addChild(root_0, function25.tree);
+ char_literal26=(Token)input.LT(1);
+ match(input,26,FOLLOW_26_in_commands149);
+
+ }
+ break;
+ case 9 :
+ // Bst.g:25:4: ENTRY^^ idList0 idList0 idList0
+ {
+ root_0 = (Object)adaptor.nil();
+
+ ENTRY27=(Token)input.LT(1);
+ match(input,ENTRY,FOLLOW_ENTRY_in_commands155);
+ ENTRY27_tree = (Object)adaptor.create(ENTRY27);
+ root_0 = (Object)adaptor.becomeRoot(ENTRY27_tree, root_0);
+
+ pushFollow(FOLLOW_idList0_in_commands158);
+ idList028=idList0();
+ _fsp--;
+
+ adaptor.addChild(root_0, idList028.tree);
+ pushFollow(FOLLOW_idList0_in_commands160);
+ idList029=idList0();
+ _fsp--;
+
+ adaptor.addChild(root_0, idList029.tree);
+ pushFollow(FOLLOW_idList0_in_commands162);
+ idList030=idList0();
+ _fsp--;
+
+ adaptor.addChild(root_0, idList030.tree);
+
+ }
+ break;
+ case 10 :
+ // Bst.g:26:4: SORT^^
+ {
+ root_0 = (Object)adaptor.nil();
+
+ SORT31=(Token)input.LT(1);
+ match(input,SORT,FOLLOW_SORT_in_commands167);
+ SORT31_tree = (Object)adaptor.create(SORT31);
+ root_0 = (Object)adaptor.becomeRoot(SORT31_tree, root_0);
+
+
+ }
+ break;
+
+ }
+ }
+ catch (RecognitionException re) {
+ reportError(re);
+ recover(input,re);
+ }
+ finally {
+ retval.stop = input.LT(-1);
+
+ retval.tree = (Object)adaptor.rulePostProcessing(root_0);
+ adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop);
+
+ }
+ return retval;
+ }
+ // $ANTLR end commands
+
+ public static class identifier_return extends ParserRuleReturnScope {
+ Object tree;
+ public Object getTree() { return tree; }
+ };
+
+ // $ANTLR start identifier
+ // Bst.g:28:1: identifier : IDENTIFIER ;
+ public identifier_return identifier() throws RecognitionException {
+ identifier_return retval = new identifier_return();
+ retval.start = input.LT(1);
+
+ Object root_0 = null;
+
+ Token IDENTIFIER32=null;
+
+ Object IDENTIFIER32_tree=null;
+
+ try {
+ // Bst.g:29:4: ( IDENTIFIER )
+ // Bst.g:29:4: IDENTIFIER
+ {
+ root_0 = (Object)adaptor.nil();
+
+ IDENTIFIER32=(Token)input.LT(1);
+ match(input,IDENTIFIER,FOLLOW_IDENTIFIER_in_identifier178);
+ IDENTIFIER32_tree = (Object)adaptor.create(IDENTIFIER32);
+ adaptor.addChild(root_0, IDENTIFIER32_tree);
+
+
+ }
+
+ }
+ catch (RecognitionException re) {
+ reportError(re);
+ recover(input,re);
+ }
+ finally {
+ retval.stop = input.LT(-1);
+
+ retval.tree = (Object)adaptor.rulePostProcessing(root_0);
+ adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop);
+
+ }
+ return retval;
+ }
+ // $ANTLR end identifier
+
+ public static class id_return extends ParserRuleReturnScope {
+ Object tree;
+ public Object getTree() { return tree; }
+ };
+
+ // $ANTLR start id
+ // Bst.g:31:1: id : '{'! identifier '}'! ;
+ public id_return id() throws RecognitionException {
+ id_return retval = new id_return();
+ retval.start = input.LT(1);
+
+ Object root_0 = null;
+
+ Token char_literal33=null;
+ Token char_literal35=null;
+ identifier_return identifier34 = null;
+
+
+ Object char_literal33_tree=null;
+ Object char_literal35_tree=null;
+
+ try {
+ // Bst.g:32:4: ( '{'! identifier '}'! )
+ // Bst.g:32:4: '{'! identifier '}'!
+ {
+ root_0 = (Object)adaptor.nil();
+
+ char_literal33=(Token)input.LT(1);
+ match(input,25,FOLLOW_25_in_id188);
+ pushFollow(FOLLOW_identifier_in_id191);
+ identifier34=identifier();
+ _fsp--;
+
+ adaptor.addChild(root_0, identifier34.tree);
+ char_literal35=(Token)input.LT(1);
+ match(input,26,FOLLOW_26_in_id193);
+
+ }
+
+ }
+ catch (RecognitionException re) {
+ reportError(re);
+ recover(input,re);
+ }
+ finally {
+ retval.stop = input.LT(-1);
+
+ retval.tree = (Object)adaptor.rulePostProcessing(root_0);
+ adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop);
+
+ }
+ return retval;
+ }
+ // $ANTLR end id
+
+ public static class idList_return extends ParserRuleReturnScope {
+ Object tree;
+ public Object getTree() { return tree; }
+ };
+
+ // $ANTLR start idList
+ // Bst.g:34:1: idList : '{' ( identifier )+ '}' -> ^( IDLIST ( identifier )+ ) ;
+ public idList_return idList() throws RecognitionException {
+ idList_return retval = new idList_return();
+ retval.start = input.LT(1);
+
+ Object root_0 = null;
+
+ Token char_literal36=null;
+ Token char_literal38=null;
+ identifier_return identifier37 = null;
+
+ List list_identifier=new ArrayList();
+ List list_26=new ArrayList();
+ List list_25=new ArrayList();
+ Object char_literal36_tree=null;
+ Object char_literal38_tree=null;
+
+ try {
+ // Bst.g:35:4: ( '{' ( identifier )+ '}' -> ^( IDLIST ( identifier )+ ) )
+ // Bst.g:35:4: '{' ( identifier )+ '}'
+ {
+ char_literal36=(Token)input.LT(1);
+ match(input,25,FOLLOW_25_in_idList205);
+ list_25.add(char_literal36);
+
+ // Bst.g:35:8: ( identifier )+
+ int cnt3=0;
+ loop3:
+ do {
+ int alt3=2;
+ int LA3_0 = input.LA(1);
+ if ( (LA3_0==IDENTIFIER) ) {
+ alt3=1;
+ }
+
+
+ switch (alt3) {
+ case 1 :
+ // Bst.g:35:8: identifier
+ {
+ pushFollow(FOLLOW_identifier_in_idList207);
+ identifier37=identifier();
+ _fsp--;
+
+ list_identifier.add(identifier37.tree);
+
+ }
+ break;
+
+ default :
+ if ( cnt3 >= 1 ) break loop3;
+ EarlyExitException eee =
+ new EarlyExitException(3, input);
+ throw eee;
+ }
+ cnt3++;
+ } while (true);
+
+ char_literal38=(Token)input.LT(1);
+ match(input,26,FOLLOW_26_in_idList210);
+ list_26.add(char_literal38);
+
+
+ // AST REWRITE
+ int i_0 = 0;
+ retval.tree = root_0;
+ root_0 = (Object)adaptor.nil();
+ // 35:24: -> ^( IDLIST ( identifier )+ )
+ {
+ // Bst.g:35:27: ^( IDLIST ( identifier )+ )
+ {
+ Object root_1 = (Object)adaptor.nil();
+ root_1 = (Object)adaptor.becomeRoot(adaptor.create(IDLIST, "IDLIST"), root_1);
+
+ // Bst.g:35:36: ( identifier )+
+ {
+ int n_1 = list_identifier == null ? 0 : list_identifier.size();
+
+
+
+ if ( n_1==0 ) throw new RuntimeException("Must have more than one element for (...)+ loops");
+ for (int i_1=0; i_1<n_1; i_1++) {
+ adaptor.addChild(root_1, list_identifier.get(i_1));
+
+ }
+ }
+
+ adaptor.addChild(root_0, root_1);
+ }
+
+ }
+
+
+
+ }
+
+ }
+ catch (RecognitionException re) {
+ reportError(re);
+ recover(input,re);
+ }
+ finally {
+ retval.stop = input.LT(-1);
+
+ retval.tree = (Object)adaptor.rulePostProcessing(root_0);
+ adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop);
+
+ }
+ return retval;
+ }
+ // $ANTLR end idList
+
+ public static class idList0_return extends ParserRuleReturnScope {
+ Object tree;
+ public Object getTree() { return tree; }
+ };
+
+ // $ANTLR start idList0
+ // Bst.g:37:1: idList0 : '{' ( identifier )* '}' -> ^( IDLIST ( identifier )* ) ;
+ public idList0_return idList0() throws RecognitionException {
+ idList0_return retval = new idList0_return();
+ retval.start = input.LT(1);
+
+ Object root_0 = null;
+
+ Token char_literal39=null;
+ Token char_literal41=null;
+ identifier_return identifier40 = null;
+
+ List list_identifier=new ArrayList();
+ List list_26=new ArrayList();
+ List list_25=new ArrayList();
+ Object char_literal39_tree=null;
+ Object char_literal41_tree=null;
+
+ try {
+ // Bst.g:38:4: ( '{' ( identifier )* '}' -> ^( IDLIST ( identifier )* ) )
+ // Bst.g:38:4: '{' ( identifier )* '}'
+ {
+ char_literal39=(Token)input.LT(1);
+ match(input,25,FOLLOW_25_in_idList0230);
+ list_25.add(char_literal39);
+
+ // Bst.g:38:8: ( identifier )*
+ loop4:
+ do {
+ int alt4=2;
+ int LA4_0 = input.LA(1);
+ if ( (LA4_0==IDENTIFIER) ) {
+ alt4=1;
+ }
+
+
+ switch (alt4) {
+ case 1 :
+ // Bst.g:38:8: identifier
+ {
+ pushFollow(FOLLOW_identifier_in_idList0232);
+ identifier40=identifier();
+ _fsp--;
+
+ list_identifier.add(identifier40.tree);
+
+ }
+ break;
+
+ default :
+ break loop4;
+ }
+ } while (true);
+
+ char_literal41=(Token)input.LT(1);
+ match(input,26,FOLLOW_26_in_idList0235);
+ list_26.add(char_literal41);
+
+
+ // AST REWRITE
+ int i_0 = 0;
+ retval.tree = root_0;
+ root_0 = (Object)adaptor.nil();
+ // 38:24: -> ^( IDLIST ( identifier )* )
+ {
+ // Bst.g:38:27: ^( IDLIST ( identifier )* )
+ {
+ Object root_1 = (Object)adaptor.nil();
+ root_1 = (Object)adaptor.becomeRoot(adaptor.create(IDLIST, "IDLIST"), root_1);
+
+ // Bst.g:38:36: ( identifier )*
+ {
+ int n_1 = list_identifier == null ? 0 : list_identifier.size();
+
+
+
+ for (int i_1=0; i_1<n_1; i_1++) {
+ adaptor.addChild(root_1, list_identifier.get(i_1));
+
+ }
+ }
+
+ adaptor.addChild(root_0, root_1);
+ }
+
+ }
+
+
+
+ }
+
+ }
+ catch (RecognitionException re) {
+ reportError(re);
+ recover(input,re);
+ }
+ finally {
+ retval.stop = input.LT(-1);
+
+ retval.tree = (Object)adaptor.rulePostProcessing(root_0);
+ adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop);
+
+ }
+ return retval;
+ }
+ // $ANTLR end idList0
+
+ public static class function_return extends ParserRuleReturnScope {
+ Object tree;
+ public Object getTree() { return tree; }
+ };
+
+ // $ANTLR start function
+ // Bst.g:40:1: function : ( '<' | '>' | '=' | '+' | '-' | ':=' | '*' | identifier );
+ public function_return function() throws RecognitionException {
+ function_return retval = new function_return();
+ retval.start = input.LT(1);
+
+ Object root_0 = null;
+
+ Token char_literal42=null;
+ Token char_literal43=null;
+ Token char_literal44=null;
+ Token char_literal45=null;
+ Token char_literal46=null;
+ Token string_literal47=null;
+ Token char_literal48=null;
+ identifier_return identifier49 = null;
+
+
+ Object char_literal42_tree=null;
+ Object char_literal43_tree=null;
+ Object char_literal44_tree=null;
+ Object char_literal45_tree=null;
+ Object char_literal46_tree=null;
+ Object string_literal47_tree=null;
+ Object char_literal48_tree=null;
+
+ try {
+ // Bst.g:41:4: ( '<' | '>' | '=' | '+' | '-' | ':=' | '*' | identifier )
+ int alt5=8;
+ switch ( input.LA(1) ) {
+ case 27:
+ alt5=1;
+ break;
+ case 28:
+ alt5=2;
+ break;
+ case 29:
+ alt5=3;
+ break;
+ case 30:
+ alt5=4;
+ break;
+ case 31:
+ alt5=5;
+ break;
+ case 32:
+ alt5=6;
+ break;
+ case 33:
+ alt5=7;
+ break;
+ case IDENTIFIER:
+ alt5=8;
+ break;
+ default:
+ NoViableAltException nvae =
+ new NoViableAltException("40:1: function : ( '<' | '>' | '=' | '+' | '-' | ':=' | '*' | identifier );", 5, 0, input);
+
+ throw nvae;
+ }
+
+ switch (alt5) {
+ case 1 :
+ // Bst.g:41:4: '<'
+ {
+ root_0 = (Object)adaptor.nil();
+
+ char_literal42=(Token)input.LT(1);
+ match(input,27,FOLLOW_27_in_function254);
+ char_literal42_tree = (Object)adaptor.create(char_literal42);
+ adaptor.addChild(root_0, char_literal42_tree);
+
+
+ }
+ break;
+ case 2 :
+ // Bst.g:41:10: '>'
+ {
+ root_0 = (Object)adaptor.nil();
+
+ char_literal43=(Token)input.LT(1);
+ match(input,28,FOLLOW_28_in_function258);
+ char_literal43_tree = (Object)adaptor.create(char_literal43);
+ adaptor.addChild(root_0, char_literal43_tree);
+
+
+ }
+ break;
+ case 3 :
+ // Bst.g:41:16: '='
+ {
+ root_0 = (Object)adaptor.nil();
+
+ char_literal44=(Token)input.LT(1);
+ match(input,29,FOLLOW_29_in_function262);
+ char_literal44_tree = (Object)adaptor.create(char_literal44);
+ adaptor.addChild(root_0, char_literal44_tree);
+
+
+ }
+ break;
+ case 4 :
+ // Bst.g:41:22: '+'
+ {
+ root_0 = (Object)adaptor.nil();
+
+ char_literal45=(Token)input.LT(1);
+ match(input,30,FOLLOW_30_in_function266);
+ char_literal45_tree = (Object)adaptor.create(char_literal45);
+ adaptor.addChild(root_0, char_literal45_tree);
+
+
+ }
+ break;
+ case 5 :
+ // Bst.g:41:28: '-'
+ {
+ root_0 = (Object)adaptor.nil();
+
+ char_literal46=(Token)input.LT(1);
+ match(input,31,FOLLOW_31_in_function270);
+ char_literal46_tree = (Object)adaptor.create(char_literal46);
+ adaptor.addChild(root_0, char_literal46_tree);
+
+
+ }
+ break;
+ case 6 :
+ // Bst.g:41:34: ':='
+ {
+ root_0 = (Object)adaptor.nil();
+
+ string_literal47=(Token)input.LT(1);
+ match(input,32,FOLLOW_32_in_function274);
+ string_literal47_tree = (Object)adaptor.create(string_literal47);
+ adaptor.addChild(root_0, string_literal47_tree);
+
+
+ }
+ break;
+ case 7 :
+ // Bst.g:41:41: '*'
+ {
+ root_0 = (Object)adaptor.nil();
+
+ char_literal48=(Token)input.LT(1);
+ match(input,33,FOLLOW_33_in_function278);
+ char_literal48_tree = (Object)adaptor.create(char_literal48);
+ adaptor.addChild(root_0, char_literal48_tree);
+
+
+ }
+ break;
+ case 8 :
+ // Bst.g:41:47: identifier
+ {
+ root_0 = (Object)adaptor.nil();
+
+ pushFollow(FOLLOW_identifier_in_function282);
+ identifier49=identifier();
+ _fsp--;
+
+ adaptor.addChild(root_0, identifier49.tree);
+
+ }
+ break;
+
+ }
+ }
+ catch (RecognitionException re) {
+ reportError(re);
+ recover(input,re);
+ }
+ finally {
+ retval.stop = input.LT(-1);
+
+ retval.tree = (Object)adaptor.rulePostProcessing(root_0);
+ adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop);
+
+ }
+ return retval;
+ }
+ // $ANTLR end function
+
+ public static class stack_return extends ParserRuleReturnScope {
+ Object tree;
+ public Object getTree() { return tree; }
+ };
+
+ // $ANTLR start stack
+ // Bst.g:43:1: stack : '{' ( stackitem )+ '}' -> ^( STACK ( stackitem )+ ) ;
+ public stack_return stack() throws RecognitionException {
+ stack_return retval = new stack_return();
+ retval.start = input.LT(1);
+
+ Object root_0 = null;
+
+ Token char_literal50=null;
+ Token char_literal52=null;
+ stackitem_return stackitem51 = null;
+
+ List list_stackitem=new ArrayList();
+ List list_26=new ArrayList();
+ List list_25=new ArrayList();
+ Object char_literal50_tree=null;
+ Object char_literal52_tree=null;
+
+ try {
+ // Bst.g:44:4: ( '{' ( stackitem )+ '}' -> ^( STACK ( stackitem )+ ) )
+ // Bst.g:44:4: '{' ( stackitem )+ '}'
+ {
+ char_literal50=(Token)input.LT(1);
+ match(input,25,FOLLOW_25_in_stack293);
+ list_25.add(char_literal50);
+
+ // Bst.g:44:8: ( stackitem )+
+ int cnt6=0;
+ loop6:
+ do {
+ int alt6=2;
+ int LA6_0 = input.LA(1);
+ if ( (LA6_0==STRING||(LA6_0>=IDENTIFIER && LA6_0<=QUOTED)||LA6_0==25||(LA6_0>=27 && LA6_0<=33)) ) {
+ alt6=1;
+ }
+
+
+ switch (alt6) {
+ case 1 :
+ // Bst.g:44:8: stackitem
+ {
+ pushFollow(FOLLOW_stackitem_in_stack295);
+ stackitem51=stackitem();
+ _fsp--;
+
+ list_stackitem.add(stackitem51.tree);
+
+ }
+ break;
+
+ default :
+ if ( cnt6 >= 1 ) break loop6;
+ EarlyExitException eee =
+ new EarlyExitException(6, input);
+ throw eee;
+ }
+ cnt6++;
+ } while (true);
+
+ char_literal52=(Token)input.LT(1);
+ match(input,26,FOLLOW_26_in_stack298);
+ list_26.add(char_literal52);
+
+
+ // AST REWRITE
+ int i_0 = 0;
+ retval.tree = root_0;
+ root_0 = (Object)adaptor.nil();
+ // 44:23: -> ^( STACK ( stackitem )+ )
+ {
+ // Bst.g:44:26: ^( STACK ( stackitem )+ )
+ {
+ Object root_1 = (Object)adaptor.nil();
+ root_1 = (Object)adaptor.becomeRoot(adaptor.create(STACK, "STACK"), root_1);
+
+ // Bst.g:44:34: ( stackitem )+
+ {
+ int n_1 = list_stackitem == null ? 0 : list_stackitem.size();
+
+
+
+ if ( n_1==0 ) throw new RuntimeException("Must have more than one element for (...)+ loops");
+ for (int i_1=0; i_1<n_1; i_1++) {
+ adaptor.addChild(root_1, list_stackitem.get(i_1));
+
+ }
+ }
+
+ adaptor.addChild(root_0, root_1);
+ }
+
+ }
+
+
+
+ }
+
+ }
+ catch (RecognitionException re) {
+ reportError(re);
+ recover(input,re);
+ }
+ finally {
+ retval.stop = input.LT(-1);
+
+ retval.tree = (Object)adaptor.rulePostProcessing(root_0);
+ adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop);
+
+ }
+ return retval;
+ }
+ // $ANTLR end stack
+
+ public static class stackitem_return extends ParserRuleReturnScope {
+ Object tree;
+ public Object getTree() { return tree; }
+ };
+
+ // $ANTLR start stackitem
+ // Bst.g:46:1: stackitem : ( function | STRING | INTEGER | QUOTED | stack );
+ public stackitem_return stackitem() throws RecognitionException {
+ stackitem_return retval = new stackitem_return();
+ retval.start = input.LT(1);
+
+ Object root_0 = null;
+
+ Token STRING54=null;
+ Token INTEGER55=null;
+ Token QUOTED56=null;
+ function_return function53 = null;
+
+ stack_return stack57 = null;
+
+
+ Object STRING54_tree=null;
+ Object INTEGER55_tree=null;
+ Object QUOTED56_tree=null;
+
+ try {
+ // Bst.g:47:4: ( function | STRING | INTEGER | QUOTED | stack )
+ int alt7=5;
+ switch ( input.LA(1) ) {
+ case IDENTIFIER:
+ case 27:
+ case 28:
+ case 29:
+ case 30:
+ case 31:
+ case 32:
+ case 33:
+ alt7=1;
+ break;
+ case STRING:
+ alt7=2;
+ break;
+ case INTEGER:
+ alt7=3;
+ break;
+ case QUOTED:
+ alt7=4;
+ break;
+ case 25:
+ alt7=5;
+ break;
+ default:
+ NoViableAltException nvae =
+ new NoViableAltException("46:1: stackitem : ( function | STRING | INTEGER | QUOTED | stack );", 7, 0, input);
+
+ throw nvae;
+ }
+
+ switch (alt7) {
+ case 1 :
+ // Bst.g:47:4: function
+ {
+ root_0 = (Object)adaptor.nil();
+
+ pushFollow(FOLLOW_function_in_stackitem317);
+ function53=function();
+ _fsp--;
+
+ adaptor.addChild(root_0, function53.tree);
+
+ }
+ break;
+ case 2 :
+ // Bst.g:48:4: STRING
+ {
+ root_0 = (Object)adaptor.nil();
+
+ STRING54=(Token)input.LT(1);
+ match(input,STRING,FOLLOW_STRING_in_stackitem322);
+ STRING54_tree = (Object)adaptor.create(STRING54);
+ adaptor.addChild(root_0, STRING54_tree);
+
+
+ }
+ break;
+ case 3 :
+ // Bst.g:49:4: INTEGER
+ {
+ root_0 = (Object)adaptor.nil();
+
+ INTEGER55=(Token)input.LT(1);
+ match(input,INTEGER,FOLLOW_INTEGER_in_stackitem328);
+ INTEGER55_tree = (Object)adaptor.create(INTEGER55);
+ adaptor.addChild(root_0, INTEGER55_tree);
+
+
+ }
+ break;
+ case 4 :
+ // Bst.g:50:4: QUOTED
+ {
+ root_0 = (Object)adaptor.nil();
+
+ QUOTED56=(Token)input.LT(1);
+ match(input,QUOTED,FOLLOW_QUOTED_in_stackitem334);
+ QUOTED56_tree = (Object)adaptor.create(QUOTED56);
+ adaptor.addChild(root_0, QUOTED56_tree);
+
+
+ }
+ break;
+ case 5 :
+ // Bst.g:51:4: stack
+ {
+ root_0 = (Object)adaptor.nil();
+
+ pushFollow(FOLLOW_stack_in_stackitem339);
+ stack57=stack();
+ _fsp--;
+
+ adaptor.addChild(root_0, stack57.tree);
+
+ }
+ break;
+
+ }
+ }
+ catch (RecognitionException re) {
+ reportError(re);
+ recover(input,re);
+ }
+ finally {
+ retval.stop = input.LT(-1);
+
+ retval.tree = (Object)adaptor.rulePostProcessing(root_0);
+ adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop);
+
+ }
+ return retval;
+ }
+ // $ANTLR end stackitem
+
+
+
+
+ public static final BitSet FOLLOW_commands_in_program45 = new BitSet(new long[]{0x000000000003EF42L});
+ public static final BitSet FOLLOW_STRINGS_in_commands65 = new BitSet(new long[]{0x0000000002000000L});
+ public static final BitSet FOLLOW_idList_in_commands68 = new BitSet(new long[]{0x0000000000000002L});
+ public static final BitSet FOLLOW_INTEGERS_in_commands73 = new BitSet(new long[]{0x0000000002000000L});
+ public static final BitSet FOLLOW_idList_in_commands76 = new BitSet(new long[]{0x0000000000000002L});
+ public static final BitSet FOLLOW_FUNCTION_in_commands81 = new BitSet(new long[]{0x0000000002000000L});
+ public static final BitSet FOLLOW_id_in_commands84 = new BitSet(new long[]{0x0000000002000000L});
+ public static final BitSet FOLLOW_stack_in_commands86 = new BitSet(new long[]{0x0000000000000002L});
+ public static final BitSet FOLLOW_MACRO_in_commands91 = new BitSet(new long[]{0x0000000002000000L});
+ public static final BitSet FOLLOW_id_in_commands94 = new BitSet(new long[]{0x0000000002000000L});
+ public static final BitSet FOLLOW_25_in_commands96 = new BitSet(new long[]{0x0000000000001000L});
+ public static final BitSet FOLLOW_STRING_in_commands99 = new BitSet(new long[]{0x0000000004000000L});
+ public static final BitSet FOLLOW_26_in_commands101 = new BitSet(new long[]{0x0000000000000002L});
+ public static final BitSet FOLLOW_READ_in_commands107 = new BitSet(new long[]{0x0000000000000002L});
+ public static final BitSet FOLLOW_EXECUTE_in_commands113 = new BitSet(new long[]{0x0000000002000000L});
+ public static final BitSet FOLLOW_25_in_commands116 = new BitSet(new long[]{0x00000003F8040000L});
+ public static final BitSet FOLLOW_function_in_commands119 = new BitSet(new long[]{0x0000000004000000L});
+ public static final BitSet FOLLOW_26_in_commands121 = new BitSet(new long[]{0x0000000000000002L});
+ public static final BitSet FOLLOW_ITERATE_in_commands127 = new BitSet(new long[]{0x0000000002000000L});
+ public static final BitSet FOLLOW_25_in_commands130 = new BitSet(new long[]{0x00000003F8040000L});
+ public static final BitSet FOLLOW_function_in_commands133 = new BitSet(new long[]{0x0000000004000000L});
+ public static final BitSet FOLLOW_26_in_commands135 = new BitSet(new long[]{0x0000000000000002L});
+ public static final BitSet FOLLOW_REVERSE_in_commands141 = new BitSet(new long[]{0x0000000002000000L});
+ public static final BitSet FOLLOW_25_in_commands144 = new BitSet(new long[]{0x00000003F8040000L});
+ public static final BitSet FOLLOW_function_in_commands147 = new BitSet(new long[]{0x0000000004000000L});
+ public static final BitSet FOLLOW_26_in_commands149 = new BitSet(new long[]{0x0000000000000002L});
+ public static final BitSet FOLLOW_ENTRY_in_commands155 = new BitSet(new long[]{0x0000000002000000L});
+ public static final BitSet FOLLOW_idList0_in_commands158 = new BitSet(new long[]{0x0000000002000000L});
+ public static final BitSet FOLLOW_idList0_in_commands160 = new BitSet(new long[]{0x0000000002000000L});
+ public static final BitSet FOLLOW_idList0_in_commands162 = new BitSet(new long[]{0x0000000000000002L});
+ public static final BitSet FOLLOW_SORT_in_commands167 = new BitSet(new long[]{0x0000000000000002L});
+ public static final BitSet FOLLOW_IDENTIFIER_in_identifier178 = new BitSet(new long[]{0x0000000000000002L});
+ public static final BitSet FOLLOW_25_in_id188 = new BitSet(new long[]{0x0000000000040000L});
+ public static final BitSet FOLLOW_identifier_in_id191 = new BitSet(new long[]{0x0000000004000000L});
+ public static final BitSet FOLLOW_26_in_id193 = new BitSet(new long[]{0x0000000000000002L});
+ public static final BitSet FOLLOW_25_in_idList205 = new BitSet(new long[]{0x0000000000040000L});
+ public static final BitSet FOLLOW_identifier_in_idList207 = new BitSet(new long[]{0x0000000004040000L});
+ public static final BitSet FOLLOW_26_in_idList210 = new BitSet(new long[]{0x0000000000000002L});
+ public static final BitSet FOLLOW_25_in_idList0230 = new BitSet(new long[]{0x0000000004040000L});
+ public static final BitSet FOLLOW_identifier_in_idList0232 = new BitSet(new long[]{0x0000000004040000L});
+ public static final BitSet FOLLOW_26_in_idList0235 = new BitSet(new long[]{0x0000000000000002L});
+ public static final BitSet FOLLOW_27_in_function254 = new BitSet(new long[]{0x0000000000000002L});
+ public static final BitSet FOLLOW_28_in_function258 = new BitSet(new long[]{0x0000000000000002L});
+ public static final BitSet FOLLOW_29_in_function262 = new BitSet(new long[]{0x0000000000000002L});
+ public static final BitSet FOLLOW_30_in_function266 = new BitSet(new long[]{0x0000000000000002L});
+ public static final BitSet FOLLOW_31_in_function270 = new BitSet(new long[]{0x0000000000000002L});
+ public static final BitSet FOLLOW_32_in_function274 = new BitSet(new long[]{0x0000000000000002L});
+ public static final BitSet FOLLOW_33_in_function278 = new BitSet(new long[]{0x0000000000000002L});
+ public static final BitSet FOLLOW_identifier_in_function282 = new BitSet(new long[]{0x0000000000000002L});
+ public static final BitSet FOLLOW_25_in_stack293 = new BitSet(new long[]{0x00000003FA1C1000L});
+ public static final BitSet FOLLOW_stackitem_in_stack295 = new BitSet(new long[]{0x00000003FE1C1000L});
+ public static final BitSet FOLLOW_26_in_stack298 = new BitSet(new long[]{0x0000000000000002L});
+ public static final BitSet FOLLOW_function_in_stackitem317 = new BitSet(new long[]{0x0000000000000002L});
+ public static final BitSet FOLLOW_STRING_in_stackitem322 = new BitSet(new long[]{0x0000000000000002L});
+ public static final BitSet FOLLOW_INTEGER_in_stackitem328 = new BitSet(new long[]{0x0000000000000002L});
+ public static final BitSet FOLLOW_QUOTED_in_stackitem334 = new BitSet(new long[]{0x0000000000000002L});
+ public static final BitSet FOLLOW_stack_in_stackitem339 = new BitSet(new long[]{0x0000000000000002L});
+
+}
\ No newline at end of file
diff --git a/src/java/net/sf/jabref/bst/ChangeCaseFunction.java b/src/java/net/sf/jabref/bst/ChangeCaseFunction.java
new file mode 100644
index 0000000..da32600
--- /dev/null
+++ b/src/java/net/sf/jabref/bst/ChangeCaseFunction.java
@@ -0,0 +1,65 @@
+package net.sf.jabref.bst;
+
+import java.util.Stack;
+
+import net.sf.jabref.bst.VM.BstEntry;
+import net.sf.jabref.bst.VM.BstFunction;
+
+
+
+/**
+ * From the Bibtex manual:
+ *
+ * Pops the top two (string) literals; it changes the case of the second
+ * according to the specifications of the first, as follows. (Note: The word
+ * `letters' in the next sentence refers only to those at brace-level 0, the
+ * top-most brace level; no other characters are changed, except perhaps for
+ * \special characters", described in Section 4.) If the first literal is the
+ * string `t', it converts to lower case all letters except the very first
+ * character in the string, which it leaves alone, and except the first
+ * character following any colon and then nonnull white space, which it also
+ * leaves alone; if it's the string `l', it converts all letters to lower case;
+ * and if it's the string `u', it converts all letters to upper case. It then
+ * pushes this resulting string. If either type is incorrect, it complains and
+ * pushes the null string; however, if both types are correct but the
+ * specification string (i.e., the first string) isn't one of the legal ones, it
+ * merely pushes the second back onto the stack, after complaining. (Another
+ * note: It ignores case differences in the specification string; for example,
+ * the strings t and T are equivalent for the purposes of this built-in
+ * function.)
+ *
+ * Christopher: I think this should be another grammar! This parser is horrible.
+ *
+ */
+public class ChangeCaseFunction implements BstFunction {
+
+ VM vm;
+
+ public ChangeCaseFunction(VM vm) {
+ this.vm = vm;
+ }
+
+ public void execute(BstEntry context) {
+ Stack stack = vm.getStack();
+
+ if (stack.size() < 2) {
+ throw new VMException("Not enough operands on stack for operation change.case$");
+ }
+ Object o1 = stack.pop();
+ Object o2 = stack.pop();
+
+ if (!(o1 instanceof String && ((String) o1).length() == 1)) {
+ throw new VMException("A format string of length 1 is needed for change.case$");
+ }
+
+ if (!(o2 instanceof String)) {
+ throw new VMException("A string is needed as second parameter for change.case$");
+ }
+
+ char format = (((String) o1).toLowerCase().charAt(0));
+ String s = (String) o2;
+
+ stack.push(BibtexCaseChanger.changeCase(s, format, vm));
+ }
+
+}
diff --git a/src/java/net/sf/jabref/bst/FormatNameFunction.java b/src/java/net/sf/jabref/bst/FormatNameFunction.java
new file mode 100644
index 0000000..726f863
--- /dev/null
+++ b/src/java/net/sf/jabref/bst/FormatNameFunction.java
@@ -0,0 +1,67 @@
+package net.sf.jabref.bst;
+
+import java.util.Stack;
+
+import net.sf.jabref.AuthorList;
+import net.sf.jabref.AuthorList.Author;
+import net.sf.jabref.bst.VM.BstEntry;
+import net.sf.jabref.bst.VM.BstFunction;
+
+
+/**
+ * From Bibtex:
+ *
+ * "The |built_in| function {\.{format.name\$}} pops the
+ * top three literals (they are a string, an integer, and a string
+ * literal, in that order). The last string literal represents a
+ * name list (each name corresponding to a person), the integer
+ * literal specifies which name to pick from this list, and the
+ * first string literal specifies how to format this name, as
+ * described in the \BibTeX\ documentation. Finally, this function
+ * pushes the formatted name. If any of the types is incorrect, it
+ * complains and pushes the null string."
+ *
+ * All the pain is encapsulated in BibtexNameFormatter. :-)
+ *
+ */
+public class FormatNameFunction implements BstFunction {
+
+ VM vm;
+
+ public FormatNameFunction(VM vm) {
+ this.vm = vm;
+ }
+
+ public void execute(BstEntry context) {
+ Stack stack = vm.getStack();
+
+ if (stack.size() < 3) {
+ throw new VMException("Not enough operands on stack for operation format.name$");
+ }
+ Object o1 = stack.pop();
+ Object o2 = stack.pop();
+ Object o3 = stack.pop();
+
+ if (!(o1 instanceof String) && !(o2 instanceof Integer) && !(o3 instanceof String)) {
+ // warning("A string is needed for change.case$");
+ stack.push("");
+ return;
+ }
+
+ String format = (String) o1;
+ Integer name = (Integer) o2;
+ String names = (String) o3;
+
+ if (names != null){
+ AuthorList a = AuthorList.getAuthorList(names);
+ if (name.intValue() > a.size()){
+ throw new VMException("Author Out of Bounds. Number " + name + " invalid for " + names);
+ }
+ Author author = a.getAuthor(name.intValue() - 1);
+
+ stack.push(BibtexNameFormatter.formatName(author, format, vm));
+ } else {
+ stack.push("");
+ }
+ }
+}
diff --git a/src/java/net/sf/jabref/bst/PurifyFunction.java b/src/java/net/sf/jabref/bst/PurifyFunction.java
new file mode 100644
index 0000000..1fb25a8
--- /dev/null
+++ b/src/java/net/sf/jabref/bst/PurifyFunction.java
@@ -0,0 +1,47 @@
+package net.sf.jabref.bst;
+
+import java.util.Stack;
+
+import net.sf.jabref.bst.VM.BstEntry;
+import net.sf.jabref.bst.VM.BstFunction;
+
+
+
+/**
+ *
+ * The |built_in| function {\.{purify\$}} pops the top (string) literal, removes
+ * nonalphanumeric characters except for |white_space| and |sep_char| characters
+ * (these get converted to a |space|) and removes certain alphabetic characters
+ * contained in the control sequences associated with a special character, and
+ * pushes the resulting string. If the literal isn't a string, it complains and
+ * pushes the null string.
+ *
+ * @author $Author: coezbek $
+ * @version $Revision: 1.1 $ ($Date: 2006/11/11 17:11:39 $)
+ *
+ */
+public class PurifyFunction implements BstFunction {
+
+ VM vm;
+
+ public PurifyFunction(VM vm) {
+ this.vm = vm;
+ }
+
+ public void execute(BstEntry context) {
+ Stack stack = vm.getStack();
+
+ if (stack.size() < 1) {
+ throw new VMException("Not enough operands on stack for operation purify$");
+ }
+ Object o1 = stack.pop();
+
+ if (!(o1 instanceof String)) {
+ vm.warn("A string is needed for purify$");
+ stack.push("");
+ return;
+ }
+
+ stack.push(BibtexPurify.purify((String) o1, vm));
+ }
+}
diff --git a/src/java/net/sf/jabref/bst/TextPrefixFunction.java b/src/java/net/sf/jabref/bst/TextPrefixFunction.java
new file mode 100644
index 0000000..acb6e23
--- /dev/null
+++ b/src/java/net/sf/jabref/bst/TextPrefixFunction.java
@@ -0,0 +1,58 @@
+package net.sf.jabref.bst;
+
+import java.util.Stack;
+
+import net.sf.jabref.bst.VM.BstEntry;
+import net.sf.jabref.bst.VM.BstFunction;
+
+
+
+/**
+The |built_in| function {\.{text.prefix\$}} pops the top two literals
+(the integer literal |pop_lit1| and a string literal, in that order).
+It pushes the substring of the (at most) |pop_lit1| consecutive text
+characters starting from the beginning of the string. This function
+is similar to {\.{substring\$}}, but this one considers an accented
+character (or more precisely, a ``special character''$\!$, even if
+it's missing its matching |right_brace|) to be a single text character
+(rather than however many |ASCII_code| characters it actually
+comprises), and this function doesn't consider braces to be text
+characters; furthermore, this function appends any needed matching
+|right_brace|s. If any of the types is incorrect, it complains and
+pushes the null string.
+ *
+ * @author $Author: coezbek $
+ * @version $Revision: 1.1 $ ($Date: 2006/11/11 17:11:39 $)
+ *
+ */
+public class TextPrefixFunction implements BstFunction {
+
+ VM vm;
+
+ public TextPrefixFunction(VM vm) {
+ this.vm = vm;
+ }
+
+ public void execute(BstEntry context) {
+ Stack stack = vm.getStack();
+
+ if (stack.size() < 2) {
+ throw new VMException("Not enough operands on stack for operation text.prefix$");
+ }
+ Object o1 = stack.pop();
+ Object o2 = stack.pop();
+
+ if (!(o1 instanceof Integer)) {
+ vm.warn("An integer is needed as first parameter to text.prefix$");
+ stack.push("");
+ return;
+ }
+ if (!(o1 instanceof String)) {
+ vm.warn("A string is needed as second parameter to text.prefix$");
+ stack.push("");
+ return;
+ }
+
+ stack.push(BibtexTextPrefix.textPrefix(((Integer) o1).intValue(), (String) o2, vm));
+ }
+}
diff --git a/src/java/net/sf/jabref/bst/VM.java b/src/java/net/sf/jabref/bst/VM.java
new file mode 100644
index 0000000..1626248
--- /dev/null
+++ b/src/java/net/sf/jabref/bst/VM.java
@@ -0,0 +1,1377 @@
+package net.sf.jabref.bst;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.ListIterator;
+import java.util.Map;
+import java.util.Stack;
+import java.util.Vector;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import net.sf.jabref.AuthorList;
+import net.sf.jabref.BibtexDatabase;
+import net.sf.jabref.BibtexEntry;
+
+import org.antlr.runtime.ANTLRFileStream;
+import org.antlr.runtime.ANTLRStringStream;
+import org.antlr.runtime.CharStream;
+import org.antlr.runtime.CommonTokenStream;
+import org.antlr.runtime.RecognitionException;
+import org.antlr.runtime.tree.CommonTree;
+import org.antlr.runtime.tree.Tree;
+
+/**
+ *
+ * A Bibtex Virtual machine that can execute .bst files.
+ *
+ * Documentation can be found in the original bibtex distribution:
+ *
+ * http://texcatalogue.sarovar.org/entries/bibtex.html#Download
+ *
+ * @author $Author: coezbek $
+ * @version $Revision: 1.3 $ ($Date: 2006/11/23 22:37:19 $)
+ *
+ */
+
+public class VM implements Warn {
+
+ PrintStream out = System.out;
+
+ public class Identifier {
+ public String name;
+
+ public Identifier(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+ }
+
+ public class Variable {
+ public String name;
+
+ public Variable(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+ }
+
+ public interface BstFunction {
+ public void execute(BstEntry context);
+ }
+
+ public static final Integer FALSE = new Integer(0);
+
+ public static final Integer TRUE = new Integer(1);
+
+ private HashMap buildInFunctions;
+
+ public File file;
+
+ public VM(File f) throws RecognitionException, IOException {
+ this(new ANTLRFileStream(f.getPath()));
+ this.file = f;
+ }
+
+ public VM(String s) throws RecognitionException {
+ this(new ANTLRStringStream(s));
+ }
+
+ public static CommonTree charStream2CommonTree(CharStream bst) throws RecognitionException {
+ BstLexer lex = new BstLexer(bst);
+ CommonTokenStream tokens = new CommonTokenStream(lex);
+ BstParser parser = new BstParser(tokens);
+ BstParser.program_return r = parser.program();
+ return (CommonTree) r.getTree();
+ }
+
+ public VM(CharStream bst) throws RecognitionException {
+ this(charStream2CommonTree(bst));
+ }
+
+ public VM(CommonTree tree) {
+ this.tree = tree;
+
+ this.buildInFunctions = new HashMap(37);
+
+ buildInFunctions.put(">", new BstFunction() {
+ /**
+ * Pops the top two (integer) literals, compares them, and pushes
+ * the integer 1 if the second is greater than the first, 0
+ * otherwise.
+ */
+ public void execute(BstEntry context) {
+ if (stack.size() < 2) {
+ throw new VMException("Not enough operands on stack for operation >");
+ }
+ Object o2 = stack.pop();
+ Object o1 = stack.pop();
+
+ if (!(o1 instanceof Integer && o2 instanceof Integer)) {
+ throw new VMException("Can only compare two integers with >");
+ }
+
+ if (o1 == null ^ o2 == null) {
+ stack.push(VM.FALSE);
+ return;
+ }
+
+ if (o1 == o2) {
+ stack.push(VM.FALSE);
+ return;
+ }
+
+ stack.push(((Integer) o1).compareTo((Integer) o2) > 0 ? VM.TRUE : VM.FALSE);
+ }
+ });
+
+ buildInFunctions.put("<", new BstFunction() {
+ /** Analogous. */
+ public void execute(BstEntry context) {
+ if (stack.size() < 2) {
+ throw new VMException("Not enough operands on stack for operation <");
+ }
+ Object o2 = stack.pop();
+ Object o1 = stack.pop();
+
+ if (!(o1 instanceof Integer && o2 instanceof Integer)) {
+ throw new VMException("Can only compare two integers with <");
+ }
+
+ if (o1 == null ^ o2 == null) {
+ stack.push(VM.FALSE);
+ return;
+ }
+
+ if (o1 == o2) {
+ stack.push(VM.FALSE);
+ return;
+ }
+
+ stack.push(((Integer) o1).compareTo((Integer) o2) < 0 ? VM.TRUE : VM.FALSE);
+
+ }
+ });
+
+ buildInFunctions.put("=", new BstFunction() {
+ /**
+ * Pops the top two (both integer or both string) literals, compares
+ * them, and pushes the integer 1 if they're equal, 0 otherwise.
+ */
+ public void execute(BstEntry context) {
+ if (stack.size() < 2) {
+ throw new VMException("Not enough operands on stack for operation =");
+ }
+ Object o1 = stack.pop();
+ Object o2 = stack.pop();
+
+ if (o1 == null ^ o2 == null) {
+ stack.push(VM.FALSE);
+ return;
+ }
+
+ if (o1 == o2) {
+ stack.push(VM.TRUE);
+ return;
+ }
+
+ stack.push(o1.equals(o2) ? VM.TRUE : VM.FALSE);
+ }
+ });
+
+ buildInFunctions.put("+", new BstFunction() {
+ /** Pops the top two (integer) literals and pushes their sum. */
+ public void execute(BstEntry context) {
+ if (stack.size() < 2) {
+ throw new VMException("Not enough operands on stack for operation +");
+ }
+ Object o2 = stack.pop();
+ Object o1 = stack.pop();
+
+ if (!(o1 instanceof Integer && o2 instanceof Integer)) {
+ throw new VMException("Can only compare two integers with +");
+ }
+
+ stack.push(new Integer(((Integer) o1).intValue() + ((Integer) o2).intValue()));
+ }
+ });
+
+ buildInFunctions.put("-", new BstFunction() {
+ /**
+ * Pops the top two (integer) literals and pushes their difference
+ * (the first subtracted from the second).
+ */
+ public void execute(BstEntry context) {
+ if (stack.size() < 2) {
+ throw new VMException("Not enough operands on stack for operation -");
+ }
+ Object o2 = stack.pop();
+ Object o1 = stack.pop();
+
+ if (!(o1 instanceof Integer && o2 instanceof Integer)) {
+ throw new VMException("Can only subtract two integers with -");
+ }
+
+ stack.push(new Integer(((Integer) o1).intValue() - ((Integer) o2).intValue()));
+ }
+ });
+
+ buildInFunctions.put("*", new BstFunction() {
+ /**
+ * Pops the top two (string) literals, concatenates them (in reverse
+ * order, that is, the order in which pushed), and pushes the
+ * resulting string.
+ */
+ public void execute(BstEntry context) {
+ if (stack.size() < 2) {
+ throw new VMException("Not enough operands on stack for operation *");
+ }
+ Object o2 = stack.pop();
+ Object o1 = stack.pop();
+
+ if (!(o1 instanceof String && o2 instanceof String)) {
+ throw new VMException("Can only concatenate two String with *");
+ }
+
+ stack.push(((String) o1) + ((String) o2));
+ }
+ });
+
+ buildInFunctions.put(":=", new BstFunction() {
+ /**
+ * Pops the top two literals and assigns to the first (which must be
+ * a global or entry variable) the value of the second.
+ */
+ public void execute(BstEntry context) {
+ if (stack.size() < 2) {
+ throw new VMException("Invalid call to operation :=");
+ }
+ Object o1 = stack.pop();
+ Object o2 = stack.pop();
+ assign(context, o1, o2);
+
+ }
+ });
+
+ buildInFunctions.put("add.period$", new BstFunction() {
+
+ Pattern p = Pattern.compile("([^\\.\\?\\!\\}\\s])(\\}|\\s)*$");
+
+ /**
+ * Pops the top (string) literal, adds a `.' to it if the last non
+ * '}' character isn't a `.', `?', or `!', and pushes this resulting
+ * string.
+ */
+ public void execute(BstEntry context) {
+ if (stack.size() < 1) {
+ throw new VMException("Not enough operands on stack for operation add.period$");
+ }
+ Object o1 = stack.pop();
+
+ if (!(o1 instanceof String)) {
+ throw new VMException("Can only add a period to a string for add.period$");
+ }
+
+ String s = (String) o1;
+ Matcher m = p.matcher(s);
+
+ if (m.find()) {
+ StringBuffer sb = new StringBuffer();
+ m.appendReplacement(sb, m.group(1));
+ sb.append('.');
+ String group2 = m.group(2);
+ if (group2 != null)
+ sb.append(m.group(2));
+ stack.push(sb.toString());
+ } else {
+ stack.push(s);
+ }
+ }
+ });
+
+ buildInFunctions.put("call.type$", new BstFunction() {
+ /**
+ * Executes the function whose name is the entry type of an entry.
+ * For example if an entry is of type book, this function executes
+ * the book function. When given as an argument to the ITERATE
+ * command, call.type$ actually produces the output for the entries.
+ * For an entry with an unknown type, it executes the function
+ * default.type. Thus you should define (before the READ command)
+ * one function for each standard entry type as well as a
+ * default.type function.
+ */
+ public void execute(BstEntry context) {
+
+ if (context == null) {
+ throw new VMException(
+ "Call.type$ can only be called from within a context (ITERATE or REVERSE).");
+ }
+ VM.this.execute(context.entry.getType().getName().toLowerCase(), context);
+ }
+ });
+
+ buildInFunctions.put("change.case$", new ChangeCaseFunction(this));
+
+ buildInFunctions.put("chr.to.int$", new BstFunction() {
+ /**
+ * Pops the top (string) literal, makes sure it's a single
+ * character, converts it to the corresponding ASCII integer, and
+ * pushes this integer.
+ */
+ public void execute(BstEntry context) {
+ if (stack.size() < 1) {
+ throw new VMException("Not enough operands on stack for operation chr.to.int$");
+ }
+ Object o1 = stack.pop();
+
+ if (!(o1 instanceof String && ((String) o1).length() == 1)) {
+ throw new VMException("Can only perform chr.to.int$ on string with length 1");
+ }
+
+ String s = (String) o1;
+
+ stack.push(new Integer((int) s.charAt(0)));
+ }
+ });
+
+ buildInFunctions.put("cite$", new BstFunction() {
+ /**
+ * Pushes the string that was the \cite-command argument for this
+ * entry.
+ */
+ public void execute(BstEntry context) {
+ stack.push(context.entry.getCiteKey());
+ }
+ });
+
+ buildInFunctions.put("duplicate$", new BstFunction() {
+ /**
+ * Pops the top literal from the stack and pushes two copies of it.
+ */
+ public void execute(BstEntry context) {
+ if (stack.size() < 1) {
+ throw new VMException("Not enough operands on stack for operation duplicate$");
+ }
+ Object o1 = stack.pop();
+
+ stack.push(o1);
+ stack.push(o1);
+ }
+ });
+
+ buildInFunctions.put("empty$", new BstFunction() {
+ /**
+ * Pops the top literal and pushes the integer 1 if it's a missing
+ * field or a string having no non-white-space characters, 0
+ * otherwise.
+ */
+ public void execute(BstEntry context) {
+ if (stack.size() < 1) {
+ throw new VMException("Not enough operands on stack for operation empty$");
+ }
+ Object o1 = stack.pop();
+
+ if (o1 == null) {
+ stack.push(VM.TRUE);
+ return;
+ }
+
+ if (!(o1 instanceof String)) {
+ throw new VMException("Operand does not match function empty$");
+ }
+
+ String s = (String) o1;
+
+ stack.push(s.trim().equals("") ? VM.TRUE : VM.FALSE);
+ }
+ });
+
+ buildInFunctions.put("format.name$", new FormatNameFunction(this));
+
+ buildInFunctions.put("if$", new BstFunction() {
+ /**
+ * Pops the top three literals (they are two function literals and
+ * an integer literal, in that order); if the integer is greater
+ * than 0, it executes the second literal, else it executes the
+ * first.
+ */
+ public void execute(BstEntry context) {
+ if (stack.size() < 3) {
+ throw new VMException("Not enough operands on stack for operation =");
+ }
+ Object f1 = stack.pop();
+ Object f2 = stack.pop();
+ Object i = stack.pop();
+
+ if (!(f1 instanceof Identifier || f1 instanceof Tree)
+ && (f2 instanceof Identifier || f2 instanceof Tree) && (i instanceof Integer)) {
+ throw new VMException("Expecting two functions and an integer for if$.");
+ }
+
+ Object toExe;
+ if (((Integer) i).intValue() > 0) {
+ toExe = f2;
+ } else {
+ toExe = f1;
+ }
+ VM.this.executeInContext(toExe, context);
+ }
+ });
+
+ buildInFunctions.put("int.to.chr$", new BstFunction() {
+ /**
+ * Pops the top (integer) literal, interpreted as the ASCII integer
+ * value of a single character, converts it to the corresponding
+ * single-character string, and pushes this string.
+ */
+ public void execute(BstEntry context) {
+ if (stack.size() < 1) {
+ throw new VMException("Not enough operands on stack for operation int.to.chr$");
+ }
+ Object o1 = stack.pop();
+
+ if (!(o1 instanceof Integer)) {
+ throw new VMException("Can only perform operation int.to.chr$ on an Integer");
+ }
+
+ Integer i = (Integer) o1;
+
+ stack.push(String.valueOf((char) i.intValue()));
+ }
+ });
+
+ buildInFunctions.put("int.to.str$", new BstFunction() {
+ /**
+ * Pops the top (integer) literal, converts it to its (unique)
+ * string equivalent, and pushes this string.
+ */
+ public void execute(BstEntry context) {
+ if (stack.size() < 1) {
+ throw new VMException("Not enough operands on stack for operation int.to.str$");
+ }
+ Object o1 = stack.pop();
+
+ if (!(o1 instanceof Integer)) {
+ throw new VMException(
+ "Can only transform an integer to an string using int.to.str$");
+ }
+
+ stack.push(((Integer) o1).toString());
+ }
+ });
+
+ buildInFunctions.put("missing$", new BstFunction() {
+ /**
+ * Pops the top literal and pushes the integer 1 if it's a missing
+ * field, 0 otherwise.
+ */
+ public void execute(BstEntry context) {
+ if (stack.size() < 1) {
+ throw new VMException("Not enough operands on stack for operation missing$");
+ }
+ Object o1 = stack.pop();
+
+ if (o1 == null) {
+ stack.push(VM.TRUE);
+ return;
+ }
+
+ if (!(o1 instanceof String)) {
+ warn("Not a string or missing field in operation missing$");
+ stack.push(VM.TRUE);
+ return;
+ }
+
+ stack.push(VM.FALSE);
+ }
+ });
+
+ buildInFunctions.put("newline$", new BstFunction() {
+ /**
+ * Writes onto the bbl file what's accumulated in the output buffer.
+ * It writes a blank line if and only if the output buffer is empty.
+ * Since write$ does reasonable line breaking, you should use this
+ * function only when you want a blank line or an explicit line
+ * break.
+ */
+ public void execute(BstEntry context) {
+ VM.this.bbl.append('\n');
+ }
+ });
+
+ buildInFunctions.put("num.names$", new BstFunction() {
+ /**
+ * Pops the top (string) literal and pushes the number of names the
+ * string represents one plus the number of occurrences of the
+ * substring "and" (ignoring case differences) surrounded by
+ * non-null white-space at the top brace level.
+ */
+ public void execute(BstEntry context) {
+ if (stack.size() < 1) {
+ throw new VMException("Not enough operands on stack for operation num.names$");
+ }
+ Object o1 = stack.pop();
+
+ if (!(o1 instanceof String)) {
+ throw new VMException("Need a string at the top of the stack for num.names$");
+ }
+ String s = (String) o1;
+
+ stack.push(new Integer(AuthorList.getAuthorList(s).size()));
+ }
+ });
+
+ buildInFunctions.put("pop$", new BstFunction() {
+ /**
+ * Pops the top of the stack but doesn't print it; this gets rid of
+ * an unwanted stack literal.
+ */
+ public void execute(BstEntry context) {
+ stack.pop();
+ }
+ });
+
+ buildInFunctions.put("preamble$", new BstFunction() {
+ /**
+ * The |built_in| function {\.{preamble\$}} pushes onto the stack
+ * the concatenation of all the \.{preamble} strings read from the
+ * database files. (or the empty string if there where none)
+ *
+ * @PREAMBLE strings read from the database files.
+ */
+ public void execute(BstEntry context) {
+ if (preamble != null) {
+ stack.push(preamble);
+ } else {
+ stack.push("");
+ }
+
+ }
+ });
+
+ /**
+ * Pops the top (string) literal, removes nonalphanumeric characters
+ * except for white-space characters and hyphens and ties (these all get
+ * converted to a space), removes certain alphabetic characters
+ * contained in the control sequences associated with a \special
+ * character", and pushes the resulting string.
+ */
+ buildInFunctions.put("purify$", new PurifyFunction(this));
+
+ buildInFunctions.put("quote$", new BstFunction() {
+ /**
+ * Pushes the string consisting of the double-quote character.
+ */
+ public void execute(BstEntry context) {
+ stack.push("\"");
+ }
+ });
+
+ buildInFunctions.put("skip$", new BstFunction() {
+ /**
+ * Is a no-op.
+ */
+ public void execute(BstEntry context) {
+ // Nothing to do! Yeah!
+ }
+ });
+
+ buildInFunctions.put("stack$", new BstFunction() {
+ /**
+ * Pops and prints the whole stack; it's meant to be used for style
+ * designers while debugging.
+ */
+ public void execute(BstEntry context) {
+ while (!stack.empty()) {
+ System.out.println(stack.pop());
+ }
+ }
+ });
+
+ buildInFunctions.put("substring$", new BstFunction() {
+ /**
+ * Pops the top three literals (they are the two integers literals
+ * len and start, and a string literal, in that order). It pushes
+ * the substring of the (at most) len consecutive characters
+ * starting at the startth character (assuming 1-based indexing) if
+ * start is positive, and ending at the start-th character
+ * (including) from the end if start is negative (where the first
+ * character from the end is the last character).
+ */
+ public void execute(BstEntry context) {
+ if (stack.size() < 3) {
+ throw new VMException("Not enough operands on stack for operation substring$");
+ }
+ Object o1 = stack.pop();
+ Object o2 = stack.pop();
+ Object o3 = stack.pop();
+
+ if (!((o1 instanceof Integer) && (o2 instanceof Integer) && (o3 instanceof String))) {
+ throw new VMException("Expecting two integers and a string for substring$");
+ }
+
+ Integer len = (Integer) o1;
+ Integer start = (Integer) o2;
+
+ int lenI = len.intValue();
+ int startI = start.intValue();
+
+ if (lenI > Integer.MAX_VALUE / 2)
+ lenI = Integer.MAX_VALUE / 2;
+
+ if (startI > Integer.MAX_VALUE / 2)
+ startI = Integer.MAX_VALUE / 2;
+
+ if (startI < Integer.MIN_VALUE / 2)
+ startI = -Integer.MIN_VALUE / 2;
+
+ String s = (String) o3;
+
+ if (startI < 0) {
+ startI += s.length() + 1;
+ startI = Math.max(1, startI + 1 - lenI);
+ }
+ stack.push(s.substring(startI - 1, Math.min(startI - 1 + lenI, s.length())));
+ }
+ });
+
+ buildInFunctions.put("swap$", new BstFunction() {
+ /**
+ * Swaps the top two literals on the stack. text.length$ Pops the
+ * top (string) literal, and pushes the number of text char- acters
+ * it contains, where an accented character (more precisely, a
+ * \special character", defined in Section 4) counts as a single
+ * text character, even if it's missing its matching right brace,
+ * and where braces don't count as text characters.
+ */
+ public void execute(BstEntry context) {
+ if (stack.size() < 2) {
+ throw new VMException("Not enough operands on stack for operation swap$");
+ }
+ Object f1 = stack.pop();
+ Object f2 = stack.pop();
+
+ stack.push(f1);
+ stack.push(f2);
+ }
+ });
+
+ buildInFunctions.put("text.length$", new BstFunction() {
+ /**
+ * text.length$ Pops the top (string) literal, and pushes the number
+ * of text characters it contains, where an accented character (more
+ * precisely, a "special character", defined in Section 4) counts as
+ * a single text character, even if it's missing its matching right
+ * brace, and where braces don't count as text characters.
+ *
+ * From BibTeXing: For the purposes of counting letters in labels,
+ * BibTEX considers everything contained inside the braces as a
+ * single letter.
+ */
+ public void execute(BstEntry context) {
+ if (stack.size() < 1) {
+ throw new VMException("Not enough operands on stack for operation text.length$");
+ }
+ Object o1 = stack.pop();
+
+ if (!(o1 instanceof String)) {
+ throw new VMException("Can only perform operation on a string text.length$");
+ }
+
+ String s = (String) o1;
+ char[] c = s.toCharArray();
+ int result = 0;
+
+ // Comments from bibtex.web:
+
+ // sp_ptr := str_start[pop_lit1];
+ int i = 0;
+
+ // sp_end := str_start[pop_lit1+1];
+ int n = s.length();
+
+ // sp_brace_level := 0;
+ int braceLevel = 0;
+
+ // while (sp_ptr < sp_end) do begin
+ while (i < n) {
+ // incr(sp_ptr);
+ i++;
+ // if (str_pool[sp_ptr-1] = left_brace) then
+ // begin
+ if (c[i - 1] == '{') {
+ // incr(sp_brace_level);
+ braceLevel++;
+ // if ((sp_brace_level = 1) and (sp_ptr < sp_end)) then
+ if (braceLevel == 1 && i < n)
+ // if (str_pool[sp_ptr] = backslash) then
+ // begin
+ if (c[i] == '\\') {
+ // incr(sp_ptr); {skip over the |backslash|}
+ i++; // skip over backslash
+ // while ((sp_ptr < sp_end) and (sp_brace_level
+ // > 0)) do begin
+ while (i < n && braceLevel > 0) {
+ // if (str_pool[sp_ptr] = right_brace) then
+ if (c[i] == '}')
+ // decr(sp_brace_level)
+ braceLevel--;
+ // else if (str_pool[sp_ptr] = left_brace)
+ // then
+ else if (c[i] == '{')
+
+ // incr(sp_brace_level);
+ braceLevel++;
+ // incr(sp_ptr);
+ i++;
+ // end;
+ }
+ // incr(num_text_chars);
+ result++;
+ // end;
+ }
+ // end
+ }
+ // else if (str_pool[sp_ptr-1] = right_brace) then
+ // begin
+ else if (c[i - 1] == '}') {
+ // if (sp_brace_level > 0) then
+ if (braceLevel > 0)
+ // decr(sp_brace_level);
+ braceLevel--;
+ // end
+ }
+ // else
+ else
+ // incr(num_text_chars);
+ result++;
+ }
+ stack.push(new Integer(result));
+ }
+ });
+
+ /**
+ * Pops the top two literals (the integer literal len and a string
+ * literal, in that order). It pushes the substring of the (at most) len
+ * consecutive text characters starting from the beginning of the
+ * string. This function is similar to substring$, but this one
+ * considers a \special character", even if it's missing its matching
+ * right brace, to be a single text character (rather than however many
+ * ASCII characters it actually comprises), and this function doesn't
+ * consider braces to be text characters; furthermore, this function
+ * appends any needed matching right braces.
+ */
+ buildInFunctions.put("text.prefix$", new TextPrefixFunction(this));
+
+ buildInFunctions.put("top$", new BstFunction() {
+ /**
+ * Pops and prints the top of the stack on the terminal and log
+ * file. It's useful for debugging.
+ */
+ public void execute(BstEntry context) {
+ System.out.println(stack.pop());
+ }
+ });
+
+ buildInFunctions.put("type$", new BstFunction() {
+ /**
+ * Pushes the current entry's type (book, article, etc.), but pushes
+ * the null string if the type is either unknown or undefined.
+ */
+ public void execute(BstEntry context) {
+ stack.push(context.entry.getType().getName());
+ }
+ });
+
+ buildInFunctions.put("warning$", new BstFunction() {
+ /**
+ * Pops the top (string) literal and prints it following a warning
+ * message. This also increments a count of the number of warning
+ * messages issued.
+ */
+ int warning = 1;
+
+ public void execute(BstEntry context) {
+ out.println("Warning (#" + (warning++) + "): " + stack.pop());
+ }
+ });
+
+ buildInFunctions.put("while$", new BstFunction() {
+ /**
+ * Pops the top two (function) literals, and keeps executing the
+ * second as long as the (integer) literal left on the stack by
+ * executing the first is greater than 0.
+ */
+ public void execute(BstEntry context) {
+ if (stack.size() < 2) {
+ throw new VMException("Not enough operands on stack for operation while$");
+ }
+ Object f2 = stack.pop();
+ Object f1 = stack.pop();
+
+ if (!(f1 instanceof Identifier || f1 instanceof Tree)
+ && (f2 instanceof Identifier || f2 instanceof Tree)) {
+ throw new VMException("Expecting two functions for while$.");
+ }
+
+ do {
+ VM.this.executeInContext(f1, context);
+
+ Object i = stack.pop();
+ if (!(i instanceof Integer)) {
+ throw new VMException(
+ "First parameter to while has to return an integer but was " + i);
+ }
+ if (((Integer) i).intValue() <= 0) {
+ break;
+ }
+ VM.this.executeInContext(f2, context);
+ } while (true);
+ }
+ });
+
+ buildInFunctions.put("width$", new WidthFunction(this));
+
+ buildInFunctions.put("write$", new BstFunction() {
+ /**
+ * Pops the top (string) literal and writes it on the output buffer
+ * (which will result in stuff being written onto the bbl file when
+ * the buffer fills up).
+ */
+ public void execute(BstEntry context) {
+ String s = (String) stack.pop();
+ System.out.println(s);
+ VM.this.bbl.append(s);
+ }
+ });
+
+ }
+
+ protected boolean assign(BstEntry context, Object o1, Object o2) {
+
+ if (!(o1 instanceof Identifier) || !(o2 instanceof String || o2 instanceof Integer))
+ throw new VMException("Invalid parameters");
+
+ String name = ((Identifier) o1).getName();
+
+ if (o2 instanceof String) {
+
+ if (context != null && context.strings.containsKey(name)) {
+ context.strings.put(name, (String) o2);
+ return true;
+ }
+
+ if (strings.containsKey(name)) {
+ strings.put(name, (String) o2);
+ return true;
+ }
+ return false;
+
+ }
+ if (o2 instanceof Integer) {
+ if (context != null && context.integers.containsKey(name)) {
+ context.integers.put(name, (Integer) o2);
+ return true;
+ }
+
+ if (integers.containsKey(name)) {
+ integers.put(name, (Integer) o2);
+ return true;
+ }
+ return false;
+ }
+ return false;
+ }
+
+ CommonTree tree;
+
+ private StringBuffer bbl;
+
+ String preamble;
+
+ public String run(BibtexDatabase db) {
+ preamble = db.getPreamble();
+ return run(db.getEntries());
+ }
+
+ public String run(Collection bibtex) {
+
+ reset();
+
+ { // Create entries
+ entries = new Vector(bibtex.size());
+ ListIterator i = entries.listIterator();
+ Iterator j = bibtex.iterator();
+ while (j.hasNext()) {
+ i.add(new BstEntry((BibtexEntry) j.next()));
+ }
+ }
+
+ // assert tree.getType() == Bst.COMMANDS;
+
+ // Go
+ for (int i = 0; i < tree.getChildCount(); i++) {
+ Tree child = tree.getChild(i);
+ switch (child.getType()) {
+ case BstParser.STRINGS:
+ strings(child);
+ break;
+ case BstParser.INTEGERS:
+ integers(child);
+ break;
+ case BstParser.FUNCTION:
+ function(child);
+ break;
+ case BstParser.EXECUTE:
+ execute(child);
+ break;
+ case BstParser.SORT:
+ sort(child);
+ break;
+ case BstParser.ITERATE:
+ iterate(child);
+ break;
+ case BstParser.REVERSE:
+ reverse(child);
+ break;
+ case BstParser.ENTRY:
+ entry(child);
+ break;
+ case BstParser.READ:
+ read();
+ break;
+ case BstParser.MACRO:
+ macro(child);
+ break;
+ }
+ }
+
+ return bbl.toString();
+ }
+
+ private void reset() {
+ bbl = new StringBuffer();
+
+ entries = null;
+
+ strings = new HashMap();
+
+ integers = new HashMap();
+ integers.put("entry.max$", new Integer(Integer.MAX_VALUE));
+ integers.put("global.max$", new Integer(Integer.MAX_VALUE));
+
+ functions = new HashMap();
+ functions.putAll(buildInFunctions);
+
+ stack = new Stack();
+ }
+
+ /**
+ * Dredges up from the database file the field values for each entry in the
+ * list. It has no arguments. If a database entry doesn't have a value for a
+ * field (and probably no database entry will have a value for every field),
+ * that field variable is marked as missing for the entry.
+ *
+ * We use null for the missing entry designator.
+ *
+ * @param child
+ */
+ private void read() {
+
+ Iterator i = entries.iterator();
+ while (i.hasNext()) {
+ BstEntry e = (BstEntry) i.next();
+
+ Iterator j = e.fields.entrySet().iterator();
+ while (j.hasNext()) {
+ Map.Entry mEntry = (Map.Entry) j.next();
+
+ Object fieldValue = e.entry.getField((String) mEntry.getKey());
+
+ mEntry.setValue((fieldValue == null ? null : fieldValue.toString()));
+ }
+ }
+
+ i = entries.iterator();
+ while (i.hasNext()) {
+ BstEntry e = (BstEntry) i.next();
+ if (!e.fields.containsKey("crossref")) {
+ e.fields.put("crossref", null);
+ }
+ }
+ }
+
+ /**
+ * Defines a string macro. It has two arguments; the first is the macro's
+ * name, which is treated like any other variable or function name, and the
+ * second is its definition, which must be double-quote-delimited. You must
+ * have one for each three-letter month abbreviation; in addition, you
+ * should have one for common journal names. The user's database may
+ * override any definition you define using this command. If you want to
+ * define a string the user can't touch, use the FUNCTION command, which has
+ * a compatible syntax.
+ *
+ * @param child
+ */
+ private void macro(Tree child) {
+ String name = child.getChild(0).getText();
+ String replacement = child.getChild(1).getText();
+ functions.put(name, new MacroFunction(replacement));
+ }
+
+ public class MacroFunction implements BstFunction {
+
+ String replacement;
+
+ public MacroFunction(String replacement) {
+ this.replacement = replacement;
+ }
+
+ public void execute(BstEntry context) {
+ VM.this.push(replacement);
+ }
+ }
+
+ /*
+ * Declares the fields and entry variables. It has three arguments, each a
+ * (possibly empty) list of variable names. The three lists are of: fields,
+ * integer entry variables, and string entry variables. There is an
+ * additional field that BibTEX automatically declares, crossref, used for
+ * cross ref- erencing. And there is an additional string entry variable
+ * automatically declared, sort.key$, used by the SORT command. Each of
+ * these variables has a value for each entry on the list.
+ */
+ private void entry(Tree child) {
+
+ { // Fields first
+ Tree t = child.getChild(0);
+ // assert t.getType() == Bst.IDLIST;
+
+ for (int i = 0; i < t.getChildCount(); i++) {
+ String name = t.getChild(i).getText();
+
+ Iterator j = entries.iterator();
+ while (j.hasNext()) {
+ BstEntry entry = (BstEntry) j.next();
+ entry.fields.put(name, null);
+ }
+ }
+ }
+ { // Integers
+ Tree t = child.getChild(1);
+ // assert t.getType() == Bst.IDLIST;
+
+ for (int i = 0; i < t.getChildCount(); i++) {
+ String name = t.getChild(i).getText();
+ Iterator j = entries.iterator();
+ while (j.hasNext()) {
+ BstEntry entry = (BstEntry) j.next();
+ entry.integers.put(name, new Integer(0));
+ }
+ }
+ }
+ { // Strings
+ Tree t = child.getChild(2);
+ // assert t.getType() == Bst.IDLIST;
+
+ for (int i = 0; i < t.getChildCount(); i++) {
+ String name = t.getChild(i).getText();
+ Iterator j = entries.iterator();
+ while (j.hasNext()) {
+ BstEntry entry = (BstEntry) j.next();
+ entry.strings.put(name, null);
+ }
+ }
+ Iterator j = entries.iterator();
+ while (j.hasNext()) {
+ BstEntry entry = (BstEntry) j.next();
+ entry.strings.put("sort.key$", null);
+ }
+ }
+ }
+
+ private void reverse(Tree child) {
+
+ BstFunction f = (BstFunction) functions.get(child.getChild(0).getText());
+
+ ListIterator i = entries.listIterator(entries.size());
+ while (i.hasPrevious()) {
+ f.execute((BstEntry) i.previous());
+ }
+ }
+
+ private void iterate(Tree child) {
+ BstFunction f = (BstFunction) functions.get(child.getChild(0).getText());
+
+ Iterator i = entries.iterator();
+ while (i.hasNext()) {
+ f.execute((BstEntry) i.next());
+ }
+ }
+
+ /**
+ * Sorts the entry list using the values of the string entry variable
+ * sort.key$. It has no arguments.
+ *
+ * @param child
+ */
+ private void sort(Tree child) {
+ Collections.sort(entries, new Comparator() {
+ public int compare(Object x1, Object x2) {
+ BstEntry o1 = (BstEntry) x1;
+ BstEntry o2 = (BstEntry) x2;
+ return ((String) o1.strings.get("sort.key$")).compareTo((String) o2.strings
+ .get("sort.key$"));
+ }
+ });
+ }
+
+ public void executeInContext(Object o, BstEntry context) {
+ if (o instanceof Tree) {
+ Tree t = (Tree) o;
+ new StackFunction(t).execute(context);
+ } else if (o instanceof Identifier) {
+ execute(((Identifier) o).getName(), context);
+ }
+ }
+
+ public void execute(Tree child) {
+ execute(child.getChild(0).getText(), null);
+ }
+
+ public class StackFunction implements BstFunction {
+
+ Tree tree;
+
+ public Tree getTree() {
+ return tree;
+ }
+
+ public StackFunction(Tree stack) {
+ // assert stack.getType() == Bst.STACK;
+ tree = stack;
+ }
+
+ public void execute(BstEntry context) {
+
+ for (int i = 0; i < tree.getChildCount(); i++) {
+
+ Tree c = tree.getChild(i);
+ try {
+
+ switch (c.getType()) {
+ case BstParser.STRING: {
+ String s = c.getText();
+ push(s.substring(1, s.length() - 1));
+ }
+ break;
+ case BstParser.INTEGER:
+ push(new Integer(Integer.parseInt(c.getText().substring(1))));
+ break;
+ case BstParser.QUOTED:
+ push(new Identifier(c.getText().substring(1)));
+ break;
+ case BstParser.STACK:
+ push(c);
+ break;
+ default:
+ VM.this.execute(c.getText(), context);
+ }
+ } catch (VMException e) {
+ if (file != null) {
+ System.err.println("ERROR " + e.getMessage() + " (" + file.getPath() + ":"
+ + c.getLine() + ")");
+ } else {
+ System.err.println("ERROR " + e.getMessage() + " (" + c.getLine() + ")");
+ }
+ throw e;
+ }
+ }
+
+ }
+ }
+
+ private void push(Tree t) {
+ stack.push(t);
+ }
+
+ public void execute(String name, BstEntry context) {
+
+ if (context != null) {
+
+ if (context.fields.containsKey(name)) {
+ stack.push(context.fields.get(name));
+ return;
+ }
+ if (context.strings.containsKey(name)) {
+ stack.push(context.strings.get(name));
+ return;
+ }
+ if (context.integers.containsKey(name)) {
+ stack.push(context.integers.get(name));
+ return;
+ }
+ }
+ if (strings.containsKey(name)) {
+ stack.push(strings.get(name));
+ return;
+ }
+ if (integers.containsKey(name)) {
+ stack.push(integers.get(name));
+ return;
+ }
+
+ if (functions.containsKey(name)) {
+ ((BstFunction) functions.get(name)).execute(context);
+ return;
+ }
+
+ throw new VMException("No matching identifier found: " + name);
+ }
+
+ private void function(Tree child) {
+ String name = child.getChild(0).getText();
+ Tree stack = child.getChild(1);
+ functions.put(name, new StackFunction(stack));
+
+ }
+
+ /**
+ * Declares global integer variables. It has one argument, a list of
+ * variable names. There are two such automatically-declared variables,
+ * entry.max$ and global.max$, used for limiting the lengths of string vari-
+ * ables. You may have any number of these commands, but a variable's
+ * declaration must precede its use.
+ *
+ * @param child
+ */
+ private void integers(Tree child) {
+ Tree t = child.getChild(0);
+ // assert t.getType() == Bst.IDLIST;
+
+ for (int i = 0; i < t.getChildCount(); i++) {
+ String name = t.getChild(i).getText();
+ integers.put(name, new Integer(0));
+ }
+ }
+
+ /**
+ * Declares global string variables. It has one argument, a list of variable
+ * names. You may have any number of these commands, but a variable's
+ * declaration must precede its use.
+ *
+ * @param child
+ */
+ private void strings(Tree child) {
+ Tree t = child.getChild(0);
+ // assert t.getType() == Bst.IDLIST;
+
+ for (int i = 0; i < t.getChildCount(); i++) {
+ String name = t.getChild(i).getText();
+ strings.put(name, null);
+ }
+ }
+
+ public class BstEntry {
+
+ public BstEntry(BibtexEntry e) {
+ this.entry = e;
+ }
+
+ BibtexEntry entry;
+
+ // Map<String, String> strings = new HashMap<String, String>();
+
+ // Map<String, String> fields = new HashMap<String, String>();
+
+ // Map<String, Integer> integers = new HashMap<String, Integer>();
+
+ Map strings = new HashMap();
+
+ Map fields = new HashMap();
+
+ Map integers = new HashMap();
+
+ public Map getFields() {
+ return fields;
+ }
+
+ public BibtexEntry getBibtexEntry() {
+ return entry;
+ }
+ }
+
+ // Vector<BstEntry> entries;
+ Vector entries;
+
+ // Map<String, String> strings = new HashMap<String, String>();
+ Map strings = new HashMap();
+
+ // Map<String, Integer> integers = new HashMap<String, Integer>();
+ Map integers = new HashMap();
+
+ // Map<String, BstFunction> functions = new HashMap<String, BstFunction>();
+ Map functions = new HashMap();
+
+ // Stack<Object> stack = new Stack<Object>();
+ Stack stack = new Stack();
+
+ public void push(Integer integer) {
+ stack.push(integer);
+ }
+
+ public void push(String string) {
+ stack.push(string);
+ }
+
+ public void push(Identifier identifier) {
+ stack.push(identifier);
+ }
+
+ /*
+ * public Map<String, String> getStrings() { return strings; }
+ *
+ * public Map<String, Integer> getIntegers() { return integers; }
+ *
+ * public Vector<BstEntry> getEntries() { return entries; }
+ *
+ * public Map<String, BstFunction> getFunctions() { return functions; }
+ */
+
+ public Map getStrings() {
+ return strings;
+ }
+
+ public Map getIntegers() {
+ return integers;
+ }
+
+ public Vector getEntries() {
+ return entries;
+ }
+
+ public Map getFunctions() {
+ return functions;
+ }
+
+ public Stack getStack() {
+ return stack;
+ }
+
+ public void warn(String string) {
+ System.out.println(string);
+ }
+
+}
diff --git a/src/java/net/sf/jabref/bst/VMException.java b/src/java/net/sf/jabref/bst/VMException.java
new file mode 100644
index 0000000..f866610
--- /dev/null
+++ b/src/java/net/sf/jabref/bst/VMException.java
@@ -0,0 +1,9 @@
+package net.sf.jabref.bst;
+
+public class VMException extends RuntimeException {
+
+ public VMException(String string) {
+ super(string);
+ }
+
+}
diff --git a/src/java/net/sf/jabref/bst/Warn.java b/src/java/net/sf/jabref/bst/Warn.java
new file mode 100644
index 0000000..a9f1e34
--- /dev/null
+++ b/src/java/net/sf/jabref/bst/Warn.java
@@ -0,0 +1,5 @@
+package net.sf.jabref.bst;
+
+public interface Warn {
+ public void warn(String s);
+}
diff --git a/src/java/net/sf/jabref/bst/WidthFunction.java b/src/java/net/sf/jabref/bst/WidthFunction.java
new file mode 100644
index 0000000..7b10662
--- /dev/null
+++ b/src/java/net/sf/jabref/bst/WidthFunction.java
@@ -0,0 +1,48 @@
+package net.sf.jabref.bst;
+
+import java.util.Stack;
+
+import net.sf.jabref.bst.VM.BstEntry;
+import net.sf.jabref.bst.VM.BstFunction;
+
+
+
+/**
+ * The |built_in| function {\.{width\$}} pops the top (string) literal and
+ * pushes the integer that represents its width in units specified by the
+ * |char_width| array. This function takes the literal literally; that is, it
+ * assumes each character in the string is to be printed as is, regardless of
+ * whether the character has a special meaning to \TeX, except that special
+ * characters (even without their |right_brace|s) are handled specially. If the
+ * literal isn't a string, it complains and pushes~0.
+ *
+ *
+ * @author $Author: coezbek $
+ * @version $Revision: 1.1 $ ($Date: 2006/11/11 17:11:39 $)
+ *
+ */
+public class WidthFunction implements BstFunction {
+
+ VM vm;
+
+ public WidthFunction(VM vm) {
+ this.vm = vm;
+ }
+
+ public void execute(BstEntry context) {
+ Stack stack = vm.getStack();
+
+ if (stack.size() < 1) {
+ throw new VMException("Not enough operands on stack for operation width$");
+ }
+ Object o1 = stack.pop();
+
+ if (!(o1 instanceof String)) {
+ vm.warn("A string is needed for change.case$");
+ stack.push(new Integer(0));
+ return;
+ }
+
+ stack.push(new Integer(BibtexWidth.width((String) o1, vm)));
+ }
+}
diff --git a/src/java/net/sf/jabref/bst/bst.g b/src/java/net/sf/jabref/bst/bst.g
new file mode 100644
index 0000000..6ad12b3
--- /dev/null
+++ b/src/java/net/sf/jabref/bst/bst.g
@@ -0,0 +1,88 @@
+grammar Bst;
+
+options {
+ output=AST;
+}
+
+tokens {
+ IDLIST;
+ STACK;
+ ENTRY;
+ COMMANDS;
+}
+
+program : commands+ -> ^(COMMANDS commands+);
+
+commands
+ : STRINGS^^ idList
+ | INTEGERS^^ idList
+ | FUNCTION^^ id stack
+ | MACRO^^ id '{'! STRING '}'!
+ | READ^^
+ | EXECUTE^^ '{'! function '}'!
+ | ITERATE^^ '{'! function '}'!
+ | REVERSE^^ '{'! function '}'!
+ | ENTRY^^ idList0 idList0 idList0
+ | SORT^^;
+
+identifier
+ : IDENTIFIER;
+
+id
+ : '{'! identifier '}'!;
+
+idList
+ : '{' identifier+ '}' -> ^(IDLIST identifier+);
+
+idList0
+ : '{' identifier* '}' -> ^(IDLIST identifier*);
+
+function
+ : '<' | '>' | '=' | '+' | '-' | ':=' | '*' | identifier;
+
+stack
+ : '{' stackitem+ '}' -> ^(STACK stackitem+);
+
+stackitem
+ : function
+ | STRING
+ | INTEGER
+ | QUOTED
+ | stack;
+
+STRINGS : 'STRINGS';
+INTEGERS : 'INTEGERS';
+FUNCTION : 'FUNCTION';
+EXECUTE : 'EXECUTE';
+SORT : 'SORT';
+ITERATE : 'ITERATE';
+REVERSE : 'REVERSE';
+ENTRY : 'ENTRY';
+READ : 'READ';
+MACRO : 'MACRO';
+
+QUOTED
+ : '\'' IDENTIFIER;
+
+IDENTIFIER
+ : LETTER (LETTER|NUMERAL)* ;
+
+fragment LETTER
+ : ('a'..'z'|'A'..'Z'|'.'|'$');
+
+STRING
+ : '"' (~('"'))* '"';
+
+INTEGER
+ : '#' ('+'|'-')? NUMERAL+ ;
+
+fragment NUMERAL
+ : ('0'..'9');
+
+WS
+ : (' '|'\t'|'\n')+ {channel=99;} ;
+
+LINE_COMMENT
+ : '%' ~('\n'|'\r')* '\r'? '\n' {channel=99;}
+ ;
+
\ No newline at end of file
diff --git a/src/java/net/sf/jabref/collab/ChangeScanner.java b/src/java/net/sf/jabref/collab/ChangeScanner.java
index 0b70166..0a99f42 100644
--- a/src/java/net/sf/jabref/collab/ChangeScanner.java
+++ b/src/java/net/sf/jabref/collab/ChangeScanner.java
@@ -54,15 +54,11 @@ public class ChangeScanner extends Thread {
Globals.prefs.get("defaultEncoding"));
BibtexDatabase inTemp = pr.getDatabase();
MetaData mdInTemp = new MetaData(pr.getMetaData(),inTemp);
- //Util.pr(tempFile.getPath()+": "+inMem.getEntryCount());
-
// Parse the modified file.
pr = OpenDatabaseAction.loadDatabase(f, Globals.prefs.get("defaultEncoding"));
BibtexDatabase onDisk = pr.getDatabase();
MetaData mdOnDisk = new MetaData(pr.getMetaData(),onDisk);
- //Util.pr(f.getPath()+": "+onDisk.getEntryCount());
-
// Sort both databases according to a common sort key.
EntryComparator comp = new EntryComparator(false, true, sortBy[2]);
comp = new EntryComparator(false, true, sortBy[1], comp);
@@ -78,12 +74,16 @@ public class ChangeScanner extends Thread {
EntrySorter sInMem = inMem.getSorter(comp);
// Start looking at changes.
+
scanPreamble(inMem, inTemp, onDisk);
scanStrings(inMem, inTemp, onDisk);
+
+
scanEntries(sInMem, sInTemp, sOnDisk);
+
scanGroups(mdInMem, mdInTemp, mdOnDisk);
- //System.out.println("Time used: "+(System.currentTimeMillis()-startTime));
+
} catch (IOException ex) {
ex.printStackTrace();
}
@@ -125,7 +125,6 @@ public class ChangeScanner extends Thread {
// We must finish scanning for exact matches before looking for near matches, to avoid an exact
// match being "stolen" from another entry.
mainLoop: for (piv1=0; piv1<tmp.getEntryCount(); piv1++) {
- //System.out.println(">>> "+piv1+"\t"+tmp.getEntryCount());
// First check if the similarly placed entry in the other base matches exactly.
double comp = -1;
@@ -163,14 +162,12 @@ public class ChangeScanner extends Thread {
// Now we've found all exact matches, look through the remaining entries, looking
// for close matches.
if (notMatched.size() > 0) {
- //Util.pr("Could not find exact match for "+notMatched.size()+" entries.");
fuzzyLoop: for (Iterator it=notMatched.iterator(); it.hasNext();) {
Integer integ = (Integer)it.next();
piv1 = integ.intValue();
- //Util.printEntry(mem.getEntryAt(piv1));
// These two variables will keep track of which entry most closely matches the
// one we're looking at, in case none matches completely.
@@ -180,9 +177,7 @@ public class ChangeScanner extends Thread {
if (piv2 < disk.getEntryCount()-1) {
for (int i = piv2; i < disk.getEntryCount(); i++) {
- //Util.pr("This one? "+i);
if (!used.contains(""+i)) {
- //Util.pr("Fuzzy matching for entry: "+piv1+" - "+i);
comp = Util.compareEntriesStrictly(tmp.getEntryAt(piv1),
disk.getEntryAt(i));
}
@@ -212,9 +207,8 @@ public class ChangeScanner extends Thread {
//changes.add(ce);
//System.out.println("Possible match for entry:");
- //Util.printEntry(mem.getEntryAt(piv1));
//System.out.println("----------------------------------------------");
- //Util.printEntry(disk.getEntryAt(bestMatchI));
+
}
else {
EntryDeleteChange ec = new EntryDeleteChange(bestFit(tmp, mem, piv1), tmp.getEntryAt(piv1));
@@ -356,7 +350,7 @@ public class ChangeScanner extends Thread {
//for (int j = piv2 + 1; j < nDisk; j++)
if (!used.contains(diskId)) {
BibtexString disk = onDisk.getString(diskId);
- //System.out.println("Cand: "+disk.getName());
+
if (disk.getContent().equals(tmp.getContent())) {
// We have found a string with the same content. It cannot have the same
// name, or we would have found it above.
@@ -380,7 +374,7 @@ public class ChangeScanner extends Thread {
tmp.getContent()));
i.remove();
used.add(diskId);
- //System.out.println(onDisk.getString(diskId).getName());
+
}
}
}
@@ -399,7 +393,6 @@ public class ChangeScanner extends Thread {
}
}
- //System.out.println(used.size());
// Finally, see if there are remaining strings in the disk database. They
// must have been added.
diff --git a/src/java/net/sf/jabref/collab/FileUpdatePanel.java b/src/java/net/sf/jabref/collab/FileUpdatePanel.java
index 6fd4c0d..0d7c3b6 100644
--- a/src/java/net/sf/jabref/collab/FileUpdatePanel.java
+++ b/src/java/net/sf/jabref/collab/FileUpdatePanel.java
@@ -10,50 +10,57 @@ import java.io.File;
public class FileUpdatePanel extends SidePaneComponent implements ActionListener {
- JButton test = new JButton(Globals.lang("Review changes"));
- BasePanel panel;
- JabRefFrame frame;
- SidePaneManager manager;
- JLabel message;
- ChangeScanner scanner;
-
- public FileUpdatePanel(JabRefFrame frame, BasePanel panel,
- SidePaneManager manager, File file, ChangeScanner scanner) {
- super(manager, GUIGlobals.getIconUrl("save"), Globals.lang("File changed"));
- this.panel = panel;
- this.frame = frame;
- this.manager = manager;
- this.scanner = scanner;
-
- JPanel main = new JPanel();
- main.setLayout(new BorderLayout());
-
- message = new JLabel("<html><center>"+Globals.lang("The file<BR>'%0'<BR>has been modified<BR>externally!", file.getName())
- +"</center></html>",
- JLabel.CENTER);
-
- main.add(message, BorderLayout.CENTER);
- main.add(test, BorderLayout.SOUTH);
- main.setBorder(BorderFactory.createEmptyBorder(1,1,1,1));
-
- add(main, BorderLayout.CENTER);
- test.addActionListener(this);
- }
-
- /**
- * actionPerformed
- *
- * @param e ActionEvent
- */
- public void actionPerformed(ActionEvent e) {
- manager.hideAway(this);
- //ChangeScanner scanner = new ChangeScanner(frame, panel); //, panel.database(), panel.metaData());
- //try {
- scanner.displayResult();
- //scanner.changeScan(panel.file());
- panel.setUpdatedExternally(false);
- //} catch (IOException ex) {
- // ex.printStackTrace();
- //}
- }
+ JButton test = new JButton(Globals.lang("Review changes"));
+
+ BasePanel panel;
+
+ JabRefFrame frame;
+
+ SidePaneManager manager;
+
+ JLabel message;
+
+ ChangeScanner scanner;
+
+ public FileUpdatePanel(JabRefFrame frame, BasePanel panel, SidePaneManager manager, File file,
+ ChangeScanner scanner) {
+ super(manager, GUIGlobals.getIconUrl("save"), Globals.lang("File changed"));
+ this.panel = panel;
+ this.frame = frame;
+ this.manager = manager;
+ this.scanner = scanner;
+
+ JPanel main = new JPanel();
+ main.setLayout(new BorderLayout());
+
+ message = new JLabel("<html><center>"
+ + Globals.lang("The file<BR>'%0'<BR>has been modified<BR>externally!", file.getName())
+ + "</center></html>", JLabel.CENTER);
+
+ main.add(message, BorderLayout.CENTER);
+ main.add(test, BorderLayout.SOUTH);
+ main.setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1));
+
+ add(main, BorderLayout.CENTER);
+ test.addActionListener(this);
+ }
+
+ /**
+ * actionPerformed
+ *
+ * @param e
+ * ActionEvent
+ */
+ public void actionPerformed(ActionEvent e) {
+ manager.hideComponent(this);
+ // ChangeScanner scanner = new ChangeScanner(frame, panel); //,
+ // panel.database(), panel.metaData());
+ // try {
+ scanner.displayResult();
+ // scanner.changeScan(panel.file());
+ panel.setUpdatedExternally(false);
+ // } catch (IOException ex) {
+ // ex.printStackTrace();
+ // }
+ }
}
diff --git a/src/java/net/sf/jabref/export/CustomExportList.java b/src/java/net/sf/jabref/export/CustomExportList.java
index 193e784..5a1fc76 100644
--- a/src/java/net/sf/jabref/export/CustomExportList.java
+++ b/src/java/net/sf/jabref/export/CustomExportList.java
@@ -2,6 +2,8 @@ package net.sf.jabref.export;
import java.util.TreeSet;
import java.util.Comparator;
+import java.util.TreeMap;
+
import net.sf.jabref.Globals;
import net.sf.jabref.JabRefPreferences;
@@ -14,6 +16,7 @@ import net.sf.jabref.JabRefPreferences;
public class CustomExportList extends TreeSet {
+ private TreeMap formats = new TreeMap();
private Object[] array;
JabRefPreferences prefs;
// ExportComparator comp = new ExportComparator();
@@ -26,27 +29,47 @@ public class CustomExportList extends TreeSet {
sort();
}
+ public TreeMap getCustomExportFormats() {
+ return formats;
+ }
private void readPrefs() {
int i=0;
String[] s = null;
while ((s = prefs.getStringArray("customExportFormat"+i)) != null) {
+ ExportFormat format = createFormat(s);
+ formats.put(format.getConsoleName(), format);
super.add(s);
i++;
}
}
+ private ExportFormat createFormat(String[] s) {
+ String lfFileName;
+ if (s[1].endsWith(".layout"))
+ lfFileName = s[1].substring(0, s[1].length()-7);
+ else
+ lfFileName = s[1];
+ ExportFormat format = new ExportFormat(s[0], s[0], lfFileName, null, s[2]);
+ format.setCustomExport(true);
+ return format;
+ }
+
public String[] getElementAt(int pos) {
return (String[])(array[pos]);
}
public void addFormat(String[] s) {
super.add(s);
+ ExportFormat format = createFormat(s);
+ formats.put(format.getConsoleName(), format);
sort();
}
public void remove(int pos) {
+ String[] toRemove = (String[])array[pos];
+ formats.remove(toRemove[0]);
super.remove(array[pos]);
sort();
}
diff --git a/src/java/net/sf/jabref/export/ExportCustomizationDialog.java b/src/java/net/sf/jabref/export/ExportCustomizationDialog.java
index a8ed403..0125fc1 100644
--- a/src/java/net/sf/jabref/export/ExportCustomizationDialog.java
+++ b/src/java/net/sf/jabref/export/ExportCustomizationDialog.java
@@ -48,7 +48,7 @@ public class ExportCustomizationDialog extends JDialog {
Globals.prefs.customExports.addFormat(newFormat);
table.revalidate();
table.repaint();
- frame.setUpCustomExportMenu();
+ ExportFormats.initAllExports();
}
}
});
@@ -66,7 +66,7 @@ public class ExportCustomizationDialog extends JDialog {
old[2] = ecd.extension();
table.revalidate();
table.repaint();
- frame.setUpCustomExportMenu();
+ ExportFormats.initAllExports();
}
}
});
@@ -78,7 +78,7 @@ public class ExportCustomizationDialog extends JDialog {
Globals.prefs.customExports.remove(row);
table.revalidate();
table.repaint();
- frame.setUpCustomExportMenu();
+ ExportFormats.initAllExports();
}
});
diff --git a/src/java/net/sf/jabref/export/ExportFileFilter.java b/src/java/net/sf/jabref/export/ExportFileFilter.java
new file mode 100644
index 0000000..1a54870
--- /dev/null
+++ b/src/java/net/sf/jabref/export/ExportFileFilter.java
@@ -0,0 +1,38 @@
+package net.sf.jabref.export;
+
+import javax.swing.filechooser.FileFilter;
+import java.io.File;
+
+/**
+ * File filter that lets the user choose export format while choosing file to
+ * export to. Contains a reference to the ExportFormat in question.
+ */
+public class ExportFileFilter extends FileFilter implements Comparable {
+ private ExportFormat format;
+ private String extension, name;
+
+ public ExportFileFilter(ExportFormat format) {
+ this.format = format;
+ this.extension = format.getExtension();
+ this.name = format.getDisplayName()+" (*"+format.getExtension()+")";
+ }
+
+ public ExportFormat getExportFormat() {
+ return format;
+ }
+
+ public boolean accept(File file) {
+ if (file.isDirectory())
+ return true;
+ else
+ return file.getPath().toLowerCase().endsWith(extension);
+ }
+
+ public String getDescription() {
+ return name;
+ }
+
+ public int compareTo(Object o) {
+ return name.compareTo(((ExportFileFilter)o).name);
+ }
+}
diff --git a/src/java/net/sf/jabref/export/ExportFormat.java b/src/java/net/sf/jabref/export/ExportFormat.java
new file mode 100644
index 0000000..dadcc2a
--- /dev/null
+++ b/src/java/net/sf/jabref/export/ExportFormat.java
@@ -0,0 +1,200 @@
+package net.sf.jabref.export;
+
+import net.sf.jabref.Globals;
+import net.sf.jabref.BibtexDatabase;
+import net.sf.jabref.BibtexEntry;
+import net.sf.jabref.export.layout.Layout;
+import net.sf.jabref.export.layout.LayoutHelper;
+
+import javax.swing.filechooser.FileFilter;
+import java.util.List;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Set;
+import java.io.File;
+import java.io.Reader;
+import java.io.IOException;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: alver
+ * Date: Oct 18, 2006
+ * Time: 9:39:53 PM
+ * To change this template use File | Settings | File Templates.
+ */
+public class ExportFormat {
+
+ private String displayName;
+ private String consoleName;
+ private String lfFileName;
+ private String directory;
+ private String extension;
+ private FileFilter fileFilter;
+ private boolean customExport = false;
+
+ public ExportFormat(String displayName, String consoleName, String lfFileName,
+ String directory, String extension) {
+ this.displayName = displayName;
+
+ this.consoleName = consoleName;
+ this.lfFileName = lfFileName;
+ this.directory = directory;
+ this.extension = extension;
+
+ fileFilter = new ExportFileFilter(this);
+ }
+
+ /**
+ * Indicate whether this is a custom export. A custom export looks for its
+ * layout files using a normal file path, while a built-in export looks in
+ * the classpath.
+ * @param custom true to indicate a custom export format.
+ */
+ public void setCustomExport(boolean custom) {
+ this.customExport = custom;
+ }
+
+ public String getConsoleName() {
+ return consoleName;
+ }
+
+ public String getExtension() {
+ return extension;
+ }
+
+ public String getDisplayName() {
+ return displayName;
+ }
+
+ /**
+ * Perform the export.
+ * @param database The database to export from.
+ * @param file The filename to write to.
+ * @param encoding The encoding to use.
+ * @param entries (may be null) A Set containing the IDs of all entries that should be exported.
+ * If null, all entries will be exported.
+ * @throws Exception
+ */
+ public void performExport(final BibtexDatabase database, final String file,
+ final String encoding,
+ Set entries) throws Exception {
+
+ File outFile = new File(file);
+ SaveSession ss = getSaveSession(encoding, outFile);
+ final String dir;
+ // If this is a custom export, just use the given file name:
+ if (customExport)
+ dir = "";
+ else
+ dir = (directory == null ? Globals.LAYOUT_PREFIX :
+ Globals.LAYOUT_PREFIX + directory + "/");
+ VerifyingWriter ps = ss.getWriter();
+ // Print header
+ Layout beginLayout = null;
+ Reader reader;
+ try {
+ reader = FileActions.getReader(dir + lfFileName + ".begin.layout");
+ LayoutHelper layoutHelper = new LayoutHelper(reader);
+ beginLayout = layoutHelper.getLayoutFromText(Globals.FORMATTER_PACKAGE);
+ reader.close();
+ } catch (IOException ex) {
+ // // If an exception was cast, export filter doesn't have a begin file.
+ }
+ // Write the header
+ if (beginLayout != null) {
+ ps.write(beginLayout.doLayout(database));
+ }
+ // changed section - end (arudert)
+
+ // Write database entries; entries will be sorted as they
+ // appear on the screen, or sorted by author, depending on
+ // Preferences.
+ // We also supply the Set entries - if we are to export only certain entries,
+ // it will be non-null, and be used to choose entries. Otherwise, it will be
+ // null, and be ignored.
+ List sorted = FileActions.getSortedEntries(database, entries, false);
+
+
+ // Load default layout
+ reader = FileActions.getReader(dir + lfFileName + ".layout");
+
+
+ LayoutHelper layoutHelper = new LayoutHelper(reader);
+ Layout defLayout = layoutHelper.getLayoutFromText(Globals.FORMATTER_PACKAGE);
+ reader.close();
+ HashMap layouts = new HashMap();
+ Layout layout;
+ Iterator i = sorted.iterator();
+ for (; i.hasNext();) {
+ // Get the entry
+ BibtexEntry entry = (BibtexEntry) (i.next());
+
+ // Get the layout
+ String type = entry.getType().getName().toLowerCase();
+ if (layouts.containsKey(type))
+ layout = (Layout)layouts.get(type);
+ else {
+ try {
+ // We try to get a type-specific layout for this entry.
+ reader = FileActions.getReader(dir + lfFileName + "."+type+".layout");
+ layoutHelper = new LayoutHelper(reader);
+ layout = layoutHelper.getLayoutFromText(Globals.FORMATTER_PACKAGE);
+ layouts.put(type, layout);
+ reader.close();
+ } catch (IOException ex) {
+ // The exception indicates that no type-specific layout exists, so we
+ // go with the default one.
+ layout = defLayout;
+ }
+ }
+
+ // Write the entry
+ ps.write(layout.doLayout(entry, database));
+ }
+
+ // Print footer
+
+ // changed section - begin (arudert)
+ Layout endLayout = null;
+ try {
+ reader = FileActions.getReader(dir + lfFileName + ".end.layout");
+ layoutHelper = new LayoutHelper(reader);
+ endLayout = layoutHelper.getLayoutFromText(Globals.FORMATTER_PACKAGE);
+ reader.close();
+ } catch (IOException ex) {
+ // If an exception was thrown, export filter doesn't have an end file.
+ }
+
+ // Write the header
+ if (endLayout != null) {
+ ps.write(endLayout.doLayout(database));
+ }
+
+ finalizeSaveSession(ss);
+ }
+
+ public SaveSession getSaveSession(final String encoding, final File outFile)
+ throws IOException {
+
+ SaveSession ss = new SaveSession(outFile, encoding, false);
+ return ss;
+ }
+
+ public void finalizeSaveSession(final SaveSession ss) throws Exception, SaveException {
+ ss.getWriter().flush();
+ ss.getWriter().close();
+
+ if (!ss.getWriter().couldEncodeAll()) {
+ System.err.println("Could not encode...");
+ }
+ ss.commit();
+
+ }
+
+ public FileFilter getFileFilter() {
+ return fileFilter;
+ }
+
+}
+
+
diff --git a/src/java/net/sf/jabref/export/ExportFormats.java b/src/java/net/sf/jabref/export/ExportFormats.java
new file mode 100644
index 0000000..c1a5274
--- /dev/null
+++ b/src/java/net/sf/jabref/export/ExportFormats.java
@@ -0,0 +1,211 @@
+package net.sf.jabref.export;
+
+import net.sf.jabref.Globals;
+import net.sf.jabref.JabRefFrame;
+import net.sf.jabref.MnemonicAwareAction;
+import net.sf.jabref.BibtexEntry;
+
+import javax.swing.*;
+import javax.swing.filechooser.FileFilter;
+import java.util.*;
+import java.awt.event.ActionEvent;
+import java.io.File;
+
+/**
+ * User: alver
+ *
+ * Date: Oct 18, 2006
+ *
+ * Time: 9:35:08 PM
+ */
+public class ExportFormats {
+
+ private static Map exportFormats = new TreeMap();
+
+ public static void initAllExports() {
+ exportFormats.clear();
+ initBuiltinExports();
+ TreeMap customExports = Globals.prefs.customExports.getCustomExportFormats();
+ for (Iterator i=customExports.keySet().iterator(); i.hasNext();) {
+ putFormat((ExportFormat)customExports.get(i.next()));
+ }
+ }
+
+ public static void initBuiltinExports() {
+ putFormat(new ExportFormat(
+ Globals.lang("HTML"), "html", "html", null, ".html"));
+ putFormat(new ExportFormat(
+ Globals.lang("Simple HTML"), "simplehtml", "simplehtml", null, ".html"));
+ putFormat(new ExportFormat(Globals.lang("Docbook"), "docbook", "docbook", null, ".xml"));
+ putFormat(new ExportFormat(Globals.lang("BibTeXML"), "bibtexml", "bibtexml", null, ".xml"));
+ putFormat(new ModsExportFormat());
+ putFormat(new ExportFormat(Globals.lang("HTML table"),
+ "tablerefs", "tablerefs", "tablerefs", ".html"));
+ putFormat(new ExportFormat(Globals.lang("HTML table (with Abstract & BibTeX)"),
+ "tablerefsabsbib", "tablerefsabsbib", "tablerefsabsbib", ".html"));
+ putFormat(new ExportFormat(Globals.lang("Harvard RTF"), "harvard", "harvard",
+ "harvard", ".rtf"));
+ putFormat(new ExportFormat(Globals.lang("Endnote"), "endnote", "EndNote",
+ "endnote", ".txt"));
+ putFormat(new OpenOfficeDocumentCreator());
+ putFormat(new OpenDocumentSpreadsheetCreator());
+
+ //openofficeItem = new JMenuItem("OpenOffice Calc"),
+ //odsItem = new JMenuItem("OpenDocument Spreadsheet");
+
+ }
+
+
+
+
+ /**
+ * Build a string listing all available export formats.
+ *
+ * @param maxLineLength
+ * The max line length before a line break must be added.
+ * @param linePrefix
+ * If a line break is added, this prefix will be inserted at the
+ * beginning of the next line.
+ * @return The string describing available formats.
+ */
+ public static String getConsoleExportList(int maxLineLength, int firstLineSubtr,
+ String linePrefix) {
+ StringBuffer sb = new StringBuffer();
+ int lastBreak = -firstLineSubtr;
+
+ for (Iterator i = exportFormats.keySet().iterator(); i.hasNext();) {
+ String name = (String) i.next();
+ if (sb.length() + 2 + name.length() - lastBreak > maxLineLength) {
+ sb.append(",\n");
+ lastBreak = sb.length();
+ sb.append(linePrefix);
+ } else if (sb.length() > 0)
+ sb.append(", ");
+ sb.append(name);
+ }
+
+ return sb.toString();
+ }
+
+ /**
+ * Look up the named export format.
+ *
+ * @param consoleName
+ * The export name given in the JabRef console help information.
+ * @return The ExportFormat, or null if no exportformat with that name is
+ * registered.
+ */
+ public static ExportFormat getExportFormat(String consoleName) {
+ return (ExportFormat) exportFormats.get(consoleName);
+ }
+
+ /**
+ * Create an AbstractAction for performing an export operation.
+ *
+ * @param frame
+ * The JabRefFrame of this JabRef instance.
+ * @param selectedOnly
+ * true indicates that only selected entries should be exported,
+ * false indicates that all entries should be exported.
+ * @return The action.
+ */
+ public static AbstractAction getExportAction(JabRefFrame frame, boolean selectedOnly) {
+
+ class ExportAction extends MnemonicAwareAction {
+ private JabRefFrame frame;
+
+ private boolean selectedOnly;
+
+ public ExportAction(JabRefFrame frame, boolean selectedOnly) {
+ this.frame = frame;
+ this.selectedOnly = selectedOnly;
+ putValue(NAME, selectedOnly ? "Export selected entries" : "Export");
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ ExportFormats.initAllExports();
+ JFileChooser fc = ExportFormats.createExportFileChooser(Globals.prefs
+ .get("exportWorkingDirectory"));
+ fc.showSaveDialog(frame);
+ File file = fc.getSelectedFile();
+ if (file == null)
+ return;
+ FileFilter ff = fc.getFileFilter();
+ if (ff instanceof ExportFileFilter) {
+ try {
+ ExportFileFilter eff = (ExportFileFilter) ff;
+ String path = file.getPath();
+ if (!path.endsWith(eff.getExportFormat().getExtension()))
+ path = path + eff.getExportFormat().getExtension();
+ file = new File(path);
+ if (file.exists()) {
+ // Warn that the file exists:
+ if (JOptionPane.showConfirmDialog(frame, "'" + file.getName() + "' "
+ + Globals.lang("exists. Overwrite file?"), Globals.lang("Export"),
+ JOptionPane.OK_CANCEL_OPTION) != JOptionPane.OK_OPTION)
+ return;
+ }
+ ExportFormat format = eff.getExportFormat();
+ Set entryIds = null;
+ if (selectedOnly) {
+ BibtexEntry[] selected = frame.basePanel().getSelectedEntries();
+ entryIds = new HashSet();
+ for (int i = 0; i < selected.length; i++) {
+ BibtexEntry bibtexEntry = selected[i];
+ entryIds.add(bibtexEntry.getId());
+ }
+ }
+
+ // Make sure we remember which filter was used, to set
+ // the default for next time:
+ Globals.prefs.put("lastUsedExport", format.getConsoleName());
+ Globals.prefs.put("exportWorkingDirectory", file.getParent());
+
+ format.performExport(frame.basePanel().database(), file.getPath(), frame
+ .basePanel().getEncoding(), entryIds);
+
+ } catch (Exception ex) {
+ ex.printStackTrace();
+
+ frame.output(Globals.lang("Could not save file") + " - " + ex.getMessage());
+
+ // Need to warn the user that saving failed!
+ JOptionPane.showMessageDialog(frame, Globals.lang("Could not save file")
+ + ".\n" + ex.getMessage(), Globals.lang("Save database"),
+ JOptionPane.ERROR_MESSAGE);
+ }
+ }
+ }
+ }
+
+ return new ExportAction(frame, selectedOnly);
+ }
+
+
+ public static JFileChooser createExportFileChooser(String currentDir) {
+ String lastUsedFormat = Globals.prefs.get("lastUsedExport");
+ FileFilter defaultFilter = null;
+ JFileChooser fc = new JFileChooser(currentDir);
+ TreeSet filters = new TreeSet();
+ for (Iterator i = exportFormats.keySet().iterator(); i.hasNext();) {
+ String formatName = (String) i.next();
+ ExportFormat format = (ExportFormat) exportFormats.get(formatName);
+ filters.add(format.getFileFilter());
+ if (formatName.equals(lastUsedFormat))
+ defaultFilter = format.getFileFilter();
+ }
+ for (Iterator i = filters.iterator(); i.hasNext();) {
+ fc.addChoosableFileFilter((ExportFileFilter) i.next());
+ }
+ fc.setAcceptAllFileFilterUsed(false);
+ if (defaultFilter != null)
+ fc.setFileFilter(defaultFilter);
+ return fc;
+ }
+
+ private static void putFormat(ExportFormat format) {
+ exportFormats.put(format.getConsoleName(), format);
+ }
+
+
+}
\ No newline at end of file
diff --git a/src/java/net/sf/jabref/export/FieldFormatter.java b/src/java/net/sf/jabref/export/FieldFormatter.java
index e01c14c..bc95d2f 100644
--- a/src/java/net/sf/jabref/export/FieldFormatter.java
+++ b/src/java/net/sf/jabref/export/FieldFormatter.java
@@ -1,43 +1,36 @@
/*
-Copyright (C) 2003 Morten O. Alver
-All programs in this directory and
-subdirectories are published under the GNU General Public License as
-described below.
+ Copyright (C) 2003 Morten O. Alver
+ All programs in this directory and
+ subdirectories are published under the GNU General Public License as
+ described below.
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or (at
-your option) any later version.
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or (at
+ your option) any later version.
-This program is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
-USA
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA
-Further information about the GNU GPL is available at:
-http://www.gnu.org/copyleft/gpl.ja.html
+ Further information about the GNU GPL is available at:
+ http://www.gnu.org/copyleft/gpl.ja.html
-*/
+ */
package net.sf.jabref.export;
/**
- * DOCUMENT ME!
- *
- * @author $author$
- * @version $Revision: 1.4 $
+ *
+ * @author $Author: coezbek $
+ * @version $Revision: 1.5 $ ($Date: 2006/08/12 15:36:45 $)
+ *
*/
-public interface FieldFormatter
-{
- //~ Methods ////////////////////////////////////////////////////////////////
-
- public String format(String s, String fieldName)
- throws IllegalArgumentException;
+public interface FieldFormatter {
+ public String format(String s, String fieldName) throws IllegalArgumentException;
}
-///////////////////////////////////////////////////////////////////////////////
-// END OF FILE.
-///////////////////////////////////////////////////////////////////////////////
diff --git a/src/java/net/sf/jabref/export/FileActions.java b/src/java/net/sf/jabref/export/FileActions.java
index e4ac079..868d549 100644
--- a/src/java/net/sf/jabref/export/FileActions.java
+++ b/src/java/net/sf/jabref/export/FileActions.java
@@ -145,6 +145,7 @@ public class FileActions
try {
session = new SaveSession(file, encoding, backup);
} catch (Throwable e) {
+ System.err.println("Error from encoding: '"+encoding+"' Len: "+encoding.length());
// we must catch all exceptions to be able notify users that
// saving failed, no matter what the reason was
// (and they won't just quit JabRef thinking
@@ -382,222 +383,6 @@ public class FileActions
}
-
- public static void exportCustomDatabase(BibtexDatabase database, String directory, String lfName,
- File outFile, String encoding)
- throws Exception {
-
- exportDatabase(database, directory, lfName, outFile, encoding);
- }
-
-
-
- public static void exportDatabase(BibtexDatabase database, String lfName,
- File outFile, String encoding)
- throws Exception {
-
- exportDatabase(database, Globals.LAYOUT_PREFIX, lfName, outFile, encoding);
-
- }
-
- public static void exportDatabase(BibtexDatabase database, String prefix, String lfName,
- File outFile, String encoding)
- throws Exception {
-
- if (lfName.equals("oocalc")) {
- OpenOfficeDocumentCreator.exportOpenOfficeCalc(outFile, database);
- return;
- } else if (lfName.equals("ods")) {
- OpenDocumentSpreadsheetCreator.exportOpenDocumentSpreadsheet(outFile, database);
- return;
- }
-
- SaveSession ss = new SaveSession(outFile, encoding, false);
-
- VerifyingWriter ps = ss.getWriter();
- //ps = new OutputStreamWriter(new FileOutputStream(outFile), encoding);
- exportDatabase(database, null, prefix, lfName, ps);
- if (!ps.couldEncodeAll()) {
- System.out.println("Could not encode...");
- }
- try {
- ss.commit();
- } catch (SaveException e) {
- e.printStackTrace();
- }
- }
-
- public static void exportDatabase(BibtexDatabase database, Set entries, String prefix, String lfName,
- Writer ps)
- throws Exception {
-
- Object[] keys = database.getKeySet().toArray();
- String key, type;
- Reader reader;
- int c;
-
-
- if (lfName.equals("mods")) {
- MODSDatabase md = new MODSDatabase(database);
- try {
- DOMSource source = new DOMSource(md.getDOMrepresentation());
- StreamResult result = new StreamResult(ps);
- Transformer trans = TransformerFactory.newInstance().newTransformer();
- trans.setOutputProperty(OutputKeys.INDENT, "yes");
- trans.transform(source, result);
- }
- catch (Exception e) {
- throw new Error(e);
- }
- ps.close();
- return;
- }
-
- // Print header
- // changed section - begin (arudert)
- Layout beginLayout = null;
- try {
- reader = getReader(prefix + lfName + ".begin.layout");
- LayoutHelper layoutHelper = new LayoutHelper(reader);
- beginLayout = layoutHelper.getLayoutFromText(Globals.FORMATTER_PACKAGE);
- reader.close();
-/*
- while ((c = reader.read()) != -1) {
- ps.write((char)c);
- }
- reader.close();
-*/
- } catch (IOException ex) {
- // // If an exception was cast, export filter doesn't have a begin file.
- }
- // Write the header
- if (beginLayout != null) {
- ps.write(beginLayout.doLayout(database));
- }
- // changed section - end (arudert)
-
- // Write database entries; entries will be sorted as they
- // appear on the screen, or sorted by author, depending on
- // Preferences.
- // We also supply the Set entries - if we are to export only certain entries,
- // it will be non-null, and be used to choose entries. Otherwise, it will be
- // null, and be ignored.
- List sorted = getSortedEntries(database, entries, false);
-
-
- // Load default layout
- reader = getReader(prefix+lfName+".layout");
- //Util.pr(prefix+lfName+".layout");
-
- LayoutHelper layoutHelper = new LayoutHelper(reader);
- Layout defLayout = layoutHelper.getLayoutFromText(Globals.FORMATTER_PACKAGE);
- reader.close();
- HashMap layouts = new HashMap();
- Layout layout;
- Iterator i = sorted.iterator();
- for (; i.hasNext();) {
- // Get the entry
- BibtexEntry entry = (BibtexEntry) (i.next());
-
- //System.out.println(entry.getType().getName());
-
- // Get the layout
- type = entry.getType().getName().toLowerCase();
- if (layouts.containsKey(type))
- layout = (Layout)layouts.get(type);
- else {
- try {
- // We try to get a type-specific layout for this entry.
- reader = getReader(prefix+lfName+"."+type+".layout");
- layoutHelper = new LayoutHelper(reader);
- layout = layoutHelper.getLayoutFromText(Globals.FORMATTER_PACKAGE);
- layouts.put(type, layout);
- reader.close();
- } catch (IOException ex) {
- // The exception indicates that no type-specific layout exists, so we
- // go with the default one.
- layout = defLayout;
- }
- }
- //Layout layout = layoutHelper.getLayoutFromText();
-
- // Write the entry
- ps.write(layout.doLayout(entry, database));
- }
-
- // Print footer
-
- // changed section - begin (arudert)
- Layout endLayout = null;
- try {
- reader = getReader(prefix + lfName + ".end.layout");
- layoutHelper = new LayoutHelper(reader);
- endLayout = layoutHelper.getLayoutFromText(Globals.FORMATTER_PACKAGE);
- reader.close();
- /*
- while ((c = reader.read()) != -1) {
- ps.write((char)c);
- }
- reader.close();
- */
- } catch (IOException ex) {
- // // If an exception was cast, export filter doesn't have an end file.
- }
- // Write the header
- if (endLayout != null) {
- ps.write(endLayout.doLayout(database));
- }
- // changed section - end (arudert)
-
- ps.flush();
- ps.close();
- }
-
-
- public static void exportEntries(BibtexDatabase database, BibtexEntry[] bes,
- String lfName, boolean custom, String directory, Writer sw)
- throws Exception {
-
- HashSet keys = new HashSet();
- for (int i=0; i<bes.length; i++)
- keys.add(bes[i].getId());
- exportDatabase(database, keys, (custom ? directory : Globals.LAYOUT_PREFIX), lfName, sw);
-
-
- }
-
- public static void performExport(final BibtexDatabase database,
- final String exportName, final String fileName,
- final String encoding) throws Exception {
-
- String lfFileName = exportName, directory = null;
- if (exportName.equals("harvard")) {
- directory = "harvard";
- } else if (exportName.equals("endnote")) {
- lfFileName = "EndNote";
- directory = "endnote";
- }
-
- // We need to find out:
- // 1. The layout definition string to use. Or, rather, we
- // must provide a Reader for the layout definition.
- // 2. The preferred extension for the layout format.
- // 3. The name of the file to use.
- File outFile = new File(fileName);
- final String dir = (directory == null ? Globals.LAYOUT_PREFIX :
- Globals.LAYOUT_PREFIX + directory + "/");
-
- final String lfName = lfFileName;
- final File oFile = outFile;
-
- //System.out.println(oFile.getPath()+"\t "+dir+"\t "+lfName+"\t "+encoding);
-
- FileActions.exportDatabase
- (database, dir, lfName, oFile, encoding);
-
- }
-
-
public static void exportToCSV(BibtexDatabase database,
File outFile, JabRefPreferences prefs)
throws Exception {
@@ -672,7 +457,7 @@ public class FileActions
* loading it as a resource (from within jar), or as a normal file.
* If unsuccessful (e.g. file not found), an IOException is thrown.
*/
- private static Reader getReader(String name) throws IOException {
+ public static Reader getReader(String name) throws IOException {
Reader reader = null;
// Try loading as a resource first. This works for files inside the jar:
URL reso = Globals.class.getResource(name);
@@ -702,7 +487,7 @@ public class FileActions
* (such as the exportDatabase call), we do not wish to use the
* global preference of saving in standard order.
*/
- protected static List getSortedEntries(BibtexDatabase database, Set keySet, boolean isSaveOperation) {
+ public static List getSortedEntries(BibtexDatabase database, Set keySet, boolean isSaveOperation) {
FieldComparatorStack comparatorStack = null;
if (Globals.prefs.getBoolean("saveInOriginalOrder")) {
diff --git a/src/java/net/sf/jabref/export/ModsExportFormat.java b/src/java/net/sf/jabref/export/ModsExportFormat.java
new file mode 100644
index 0000000..4363af6
--- /dev/null
+++ b/src/java/net/sf/jabref/export/ModsExportFormat.java
@@ -0,0 +1,52 @@
+package net.sf.jabref.export;
+
+import net.sf.jabref.Globals;
+import net.sf.jabref.BibtexDatabase;
+import net.sf.jabref.mods.MODSDatabase;
+
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.OutputKeys;
+import java.util.Set;
+import java.io.IOException;
+import java.io.File;
+
+/**
+ * ExportFormat for exporting in MODS XML format.
+ */
+class ModsExportFormat extends ExportFormat {
+ public ModsExportFormat() {
+ super(Globals.lang("MODS"), "mods", null, null, ".xml");
+
+ }
+
+ public void performExport(final BibtexDatabase database, final String file, final String encoding, Set keySet) throws IOException {
+ SaveSession ss = getSaveSession(encoding, new File(file));
+ VerifyingWriter ps = ss.getWriter();
+ MODSDatabase md = new MODSDatabase(database, keySet);
+
+ // PS: DOES NOT SUPPORT EXPORTING ONLY A SET OF ENTRIES
+
+ try {
+ DOMSource source = new DOMSource(md.getDOMrepresentation());
+ StreamResult result = new StreamResult(ps);
+ Transformer trans = TransformerFactory.newInstance().newTransformer();
+ trans.setOutputProperty(OutputKeys.INDENT, "yes");
+ trans.transform(source, result);
+ }
+ catch (Exception e) {
+ throw new Error(e);
+ }
+
+ try {
+ finalizeSaveSession(ss);
+ } catch (SaveException ex) {
+ throw new IOException(ex.getMessage());
+ } catch (Exception e) {
+ throw new IOException(e.getMessage());
+ }
+ return;
+ }
+}
diff --git a/src/java/net/sf/jabref/export/OOCalcDatabase.java b/src/java/net/sf/jabref/export/OOCalcDatabase.java
index 64938cf..507b503 100644
--- a/src/java/net/sf/jabref/export/OOCalcDatabase.java
+++ b/src/java/net/sf/jabref/export/OOCalcDatabase.java
@@ -24,25 +24,7 @@ import ca.odell.glazedlists.SortedList;
public class OOCalcDatabase {
protected Collection entries;
- /*protected final static String TYPE_COL = "BibliographyType";
-
- protected final static Map columns = new LinkedHashMap();
- static {
-
- columns.put(TYPE_COL, "dummy");
- columns.put("ISBN", "isbn");
- coulmns.put("Identifier", "\bibtexkey");
- coulmns.put("", "");
- coulmns.put("", "");
-
- }*/
-
- public OOCalcDatabase() {
- //entries = new HashSet();
- }
-
- public OOCalcDatabase(BibtexDatabase bibtex) {
- this();
+ public OOCalcDatabase(BibtexDatabase bibtex, Set keySet) {
// Make a list of comparators for sorting the entries:
List comparators = new ArrayList();
comparators.add(new FieldComparator("author"));
@@ -50,7 +32,15 @@ public class OOCalcDatabase {
comparators.add(new FieldComparator(BibtexFields.KEY_FIELD));
// Use glazed lists to get a sorted view of the entries:
BasicEventList entryList = new BasicEventList();
- entryList.addAll(bibtex.getEntries());
+ // Set up a list of all entries, if keySet==null, or the entries whose
+ // ids are in keySet, otherwise:
+ if (keySet == null)
+ entryList.addAll(bibtex.getEntries());
+ else {
+ for (Iterator i=keySet.iterator(); i.hasNext();)
+ entryList.add(bibtex.getEntryById((String)i.next()));
+ }
+
entries = new SortedList(entryList, new FieldComparatorStack(comparators));
}
diff --git a/src/java/net/sf/jabref/export/OpenDocumentRepresentation.java b/src/java/net/sf/jabref/export/OpenDocumentRepresentation.java
index 60c6784..80b1553 100644
--- a/src/java/net/sf/jabref/export/OpenDocumentRepresentation.java
+++ b/src/java/net/sf/jabref/export/OpenDocumentRepresentation.java
@@ -25,25 +25,8 @@ import ca.odell.glazedlists.BasicEventList;
public class OpenDocumentRepresentation {
protected Collection entries;
- /*protected final static String TYPE_COL = "BibliographyType";
- protected final static Map columns = new LinkedHashMap();
- static {
-
- columns.put(TYPE_COL, "dummy");
- columns.put("ISBN", "isbn");
- coulmns.put("Identifier", "\bibtexkey");
- coulmns.put("", "");
- coulmns.put("", "");
-
- }*/
-
- public OpenDocumentRepresentation() {
- //entries = new HashSet();
- }
-
- public OpenDocumentRepresentation(BibtexDatabase bibtex) {
- this();
+ public OpenDocumentRepresentation(BibtexDatabase bibtex, Set keySet) {
// Make a list of comparators for sorting the entries:
List comparators = new ArrayList();
comparators.add(new FieldComparator("author"));
@@ -51,7 +34,16 @@ public class OpenDocumentRepresentation {
comparators.add(new FieldComparator(BibtexFields.KEY_FIELD));
// Use glazed lists to get a sorted view of the entries:
BasicEventList entryList = new BasicEventList();
- entryList.addAll(bibtex.getEntries());
+
+ // Set up a list of all entries, if keySet==null, or the entries whose
+ // ids are in keySet, otherwise:
+ if (keySet == null)
+ entryList.addAll(bibtex.getEntries());
+ else {
+ for (Iterator i=keySet.iterator(); i.hasNext();)
+ entryList.add(bibtex.getEntryById((String)i.next()));
+ }
+
entries = new SortedList(entryList, new FieldComparatorStack(comparators));
}
public Document getDOMrepresentation() {
diff --git a/src/java/net/sf/jabref/export/OpenDocumentSpreadsheetCreator.java b/src/java/net/sf/jabref/export/OpenDocumentSpreadsheetCreator.java
index c61b183..1f76455 100644
--- a/src/java/net/sf/jabref/export/OpenDocumentSpreadsheetCreator.java
+++ b/src/java/net/sf/jabref/export/OpenDocumentSpreadsheetCreator.java
@@ -10,6 +10,7 @@ import net.sf.jabref.*;
import java.io.*;
import java.util.zip.*;
+import java.util.Set;
import java.net.URL;
import javax.xml.transform.*;
import javax.xml.transform.dom.*;
@@ -18,12 +19,17 @@ import javax.xml.transform.stream.*;
/**
* @author alver
*/
-public class OpenDocumentSpreadsheetCreator {
+public class OpenDocumentSpreadsheetCreator extends ExportFormat {
/**
* Creates a new instance of OpenOfficeDocumentCreator
*/
- private OpenDocumentSpreadsheetCreator() {
+ public OpenDocumentSpreadsheetCreator() {
+ super(Globals.lang("OpenDocument Spreadsheet"), "ods", null, null, ".ods");
+ }
+
+ public void performExport(final BibtexDatabase database, final String file, final String encoding, Set keySet) throws Exception {
+ exportOpenDocumentSpreadsheet(new File(file), database, keySet);
}
public static void storeOpenDocumentSpreadsheetFile(File file, InputStream source) throws Exception {
@@ -50,11 +56,11 @@ public class OpenDocumentSpreadsheetCreator {
}
}
- public static void exportOpenDocumentSpreadsheet(File file, BibtexDatabase database) throws Exception {
+ public static void exportOpenDocumentSpreadsheet(File file, BibtexDatabase database, Set keySet) throws Exception {
// First store the xml formatted content to a temporary file.
File tmpFile = File.createTempFile("opendocument", null);
- exportOpenDocumentSpreadsheetXML(tmpFile, database);
+ exportOpenDocumentSpreadsheetXML(tmpFile, database, keySet);
// Then add the content to the zip file:
BufferedInputStream in = new BufferedInputStream(new FileInputStream(tmpFile));
@@ -64,8 +70,8 @@ public class OpenDocumentSpreadsheetCreator {
tmpFile.delete();
}
- public static void exportOpenDocumentSpreadsheetXML(File tmpFile, BibtexDatabase database) {
- OpenDocumentRepresentation od = new OpenDocumentRepresentation(database);
+ public static void exportOpenDocumentSpreadsheetXML(File tmpFile, BibtexDatabase database, Set keySet) {
+ OpenDocumentRepresentation od = new OpenDocumentRepresentation(database, keySet);
try {
Writer ps = new OutputStreamWriter(new FileOutputStream(tmpFile), "UTF8");
diff --git a/src/java/net/sf/jabref/export/OpenOfficeDocumentCreator.java b/src/java/net/sf/jabref/export/OpenOfficeDocumentCreator.java
index 95673be..c869d2a 100644
--- a/src/java/net/sf/jabref/export/OpenOfficeDocumentCreator.java
+++ b/src/java/net/sf/jabref/export/OpenOfficeDocumentCreator.java
@@ -10,8 +10,8 @@ import net.sf.jabref.*;
import java.io.*;
import java.util.zip.*;
+import java.util.Set;
import java.net.URL;
-import javax.xml.parsers.*;
import javax.xml.transform.*;
import javax.xml.transform.dom.*;
import javax.xml.transform.stream.*;
@@ -19,12 +19,17 @@ import javax.xml.transform.stream.*;
/**
* @author alver
*/
-public class OpenOfficeDocumentCreator {
+public class OpenOfficeDocumentCreator extends ExportFormat {
/**
* Creates a new instance of OpenOfficeDocumentCreator
*/
- private OpenOfficeDocumentCreator() {
+ public OpenOfficeDocumentCreator() {
+ super(Globals.lang("OpenOffice Calc"), "oocalc", null, null, ".sxc");
+ }
+
+ public void performExport(final BibtexDatabase database, final String file, final String encoding, Set keySet) throws Exception {
+ exportOpenOfficeCalc(new File(file), database, keySet);
}
public static void storeOpenOfficeFile(File file, InputStream source) throws Exception {
@@ -51,11 +56,13 @@ public class OpenOfficeDocumentCreator {
}
}
- public static void exportOpenOfficeCalc(File file, BibtexDatabase database) throws Exception {
+ public static void exportOpenOfficeCalc(File file, BibtexDatabase database,
+ Set keySet) throws Exception {
+
// First store the xml formatted content to a temporary file.
File tmpFile = File.createTempFile("oocalc", null);
- exportOpenOfficeCalcXML(tmpFile, database);
+ exportOpenOfficeCalcXML(tmpFile, database, keySet);
// Then add the content to the zip file:
BufferedInputStream in = new BufferedInputStream(new FileInputStream(tmpFile));
@@ -65,8 +72,8 @@ public class OpenOfficeDocumentCreator {
tmpFile.delete();
}
- public static void exportOpenOfficeCalcXML(File tmpFile, BibtexDatabase database) {
- OOCalcDatabase od = new OOCalcDatabase(database);
+ public static void exportOpenOfficeCalcXML(File tmpFile, BibtexDatabase database, Set keySet) {
+ OOCalcDatabase od = new OOCalcDatabase(database, keySet);
try {
Writer ps = new OutputStreamWriter(new FileOutputStream(tmpFile), "UTF8");
diff --git a/src/java/net/sf/jabref/export/SaveException.java b/src/java/net/sf/jabref/export/SaveException.java
index ee2afa1..bf9c19b 100644
--- a/src/java/net/sf/jabref/export/SaveException.java
+++ b/src/java/net/sf/jabref/export/SaveException.java
@@ -33,7 +33,7 @@ import net.sf.jabref.BibtexEntry;
* Exception thrown if saving goes wrong. If caused by a specific
* entry, keeps track of which entry caused the problem.
*/
-public class SaveException extends Throwable
+public class SaveException extends Exception
{
//~ Instance fields ////////////////////////////////////////////////////////
diff --git a/src/java/net/sf/jabref/export/layout/LayoutEntry.java b/src/java/net/sf/jabref/export/layout/LayoutEntry.java
index 3b7f1cb..6d2e3f3 100755
--- a/src/java/net/sf/jabref/export/layout/LayoutEntry.java
+++ b/src/java/net/sf/jabref/export/layout/LayoutEntry.java
@@ -1,464 +1,417 @@
/*
-Copyright (C) 2003 Morten O. Alver
-All programs in this directory and
-subdirectories are published under the GNU General Public License as
-described below.
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or (at
-your option) any later version.
-
-This program is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
-USA
-
-Further information about the GNU GPL is available at:
-http://www.gnu.org/copyleft/gpl.ja.html
-
-*/
-package net.sf.jabref.export.layout;
+ Copyright (C) 2003 Morten O. Alver
+ All programs in this directory and
+ subdirectories are published under the GNU General Public License as
+ described below.
-import wsi.ra.tool.WSITools;
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or (at
+ your option) any later version.
-import wsi.ra.types.StringInt;
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA
+
+ Further information about the GNU GPL is available at:
+ http://www.gnu.org/copyleft/gpl.ja.html
+
+ */
+package net.sf.jabref.export.layout;
+
+import java.util.ArrayList;
+import java.util.Map;
import java.util.Vector;
import net.sf.jabref.BibtexDatabase;
import net.sf.jabref.BibtexEntry;
import net.sf.jabref.Globals;
-
+import net.sf.jabref.NameFormatterTab;
+import net.sf.jabref.Util;
+import net.sf.jabref.export.layout.format.NameFormat;
+import wsi.ra.tool.WSITools;
+import wsi.ra.types.StringInt;
/**
* DOCUMENT ME!
- *
+ *
* @author $author$
- * @version $Revision: 1.10 $
+ * @version $Revision: 1.15 $
*/
-public class LayoutEntry
-{
- //~ Instance fields ////////////////////////////////////////////////////////
-
- private LayoutFormatter[] option;
- private String text;
- private LayoutEntry[] layoutEntries;
- private int type;
- private String classPrefix;
-
- //~ Constructors ///////////////////////////////////////////////////////////
-
- public LayoutEntry(StringInt si, String classPrefix_) throws Exception
- {
- type = si.i;
- classPrefix = classPrefix_;
-
- if (si.i == LayoutHelper.IS_LAYOUT_TEXT)
- {
- text = si.s;
- }
- else if (si.i == LayoutHelper.IS_SIMPLE_FIELD)
- {
- text = si.s.trim();
- }
- else if (si.i == LayoutHelper.IS_FIELD_START)
- {
- }
- else if (si.i == LayoutHelper.IS_FIELD_END)
- {
- }
- else if (si.i == LayoutHelper.IS_OPTION_FIELD)
- {
- Vector v = new Vector();
- WSITools.tokenize(v, si.s, "\n");
-
- if (v.size() == 1)
- {
- text = (String) v.get(0);
- }
- else
- {
- text = ((String) v.get(0)).trim();
-
- //try
- //{
- option = getOptionalLayout((String) v.get(1));
- //}
- // catch (Exception e)
- //{
- // e.printStackTrace();
- //}
- }
- }
-
- // else if (si.i == LayoutHelper.IS_OPTION_FIELD_PARAM)
- // {
- // }
- }
-
- public LayoutEntry(Vector parsedEntries, String classPrefix_, int layoutType) throws Exception
- {
- classPrefix = classPrefix_;
- String blockStart = null;
- String blockEnd = null;
- StringInt si;
- Vector blockEntries = null;
- Vector tmpEntries = new Vector();
- LayoutEntry le;
- si = (StringInt) parsedEntries.get(0);
- blockStart = si.s;
- si = (StringInt) parsedEntries.get(parsedEntries.size() - 1);
- blockEnd = si.s;
-
- if (!blockStart.equals(blockEnd))
- {
- System.err.println("Field start and end entry must be equal.");
- }
-
- type = layoutType;
- text = si.s;
-
- for (int i = 1; i < (parsedEntries.size() - 1); i++)
- {
- si = (StringInt) parsedEntries.get(i);
-
- //System.out.println("PARSED-ENTRY: "+si.s+"="+si.i);
- if (si.i == LayoutHelper.IS_LAYOUT_TEXT)
- {
- }
- else if (si.i == LayoutHelper.IS_SIMPLE_FIELD)
- {
- }
- else if ((si.i == LayoutHelper.IS_FIELD_START) ||
- (si.i == LayoutHelper.IS_GROUP_START))
- {
- blockEntries = new Vector();
- blockStart = si.s;
- }
- else if ((si.i == LayoutHelper.IS_FIELD_END) ||
- (si.i == LayoutHelper.IS_GROUP_END))
- {
- if (blockStart.equals(si.s))
- {
- blockEntries.add(si);
- if (si.i == LayoutHelper.IS_GROUP_END)
- le = new LayoutEntry(blockEntries, classPrefix, LayoutHelper.IS_GROUP_START);
- else
- le = new LayoutEntry(blockEntries, classPrefix, LayoutHelper.IS_FIELD_START);
- tmpEntries.add(le);
- blockEntries = null;
- }
- else
- {
- System.out.println(
- "Nested field entries are not implemented !!!");
- }
- }
- else if (si.i == LayoutHelper.IS_OPTION_FIELD)
- {
- }
-
- // else if (si.i == LayoutHelper.IS_OPTION_FIELD_PARAM)
- // {
- // }
- if (blockEntries == null)
- {
- //System.out.println("BLOCK ADD: "+si.s+"="+si.i);
- tmpEntries.add(new LayoutEntry(si, classPrefix));
- }
- else
- {
- blockEntries.add(si);
- }
- }
-
- layoutEntries = new LayoutEntry[tmpEntries.size()];
-
- for (int i = 0; i < tmpEntries.size(); i++)
- {
- layoutEntries[i] = (LayoutEntry) tmpEntries.get(i);
-
- //System.out.println(layoutEntries[i].text);
- }
- }
-
- //~ Methods ////////////////////////////////////////////////////////////////
-
- public String doLayout(BibtexEntry bibtex, BibtexDatabase database)
- {
-
- if (type == LayoutHelper.IS_LAYOUT_TEXT)
- {
- return text;
- }
- else if (type == LayoutHelper.IS_SIMPLE_FIELD)
- {
- if (text.equals("bibtextype"))
- {
- return bibtex.getType().getName();
- }
-
- String field = getField(bibtex, text, database);
-
- if (field == null)
- {
-
- return null;
- }
- else
- {
-
- return field;
-
- }
- }
- else if ((type == LayoutHelper.IS_FIELD_START) ||
- (type == LayoutHelper.IS_GROUP_START))
- {
-
-
- String field = getField(bibtex, text, database);
- //String field = (String) bibtex.getField(text);
-
- if ((field == null) || ((type == LayoutHelper.IS_GROUP_START) &&
- (field.equalsIgnoreCase(LayoutHelper.getCurrentGroup()))))
- {
- return null;
- }
- else
- {
- if (type == LayoutHelper.IS_GROUP_START) {
- LayoutHelper.setCurrentGroup(field);
- }
- StringBuffer sb = new StringBuffer(100);
- String fieldText;
- boolean previousSkipped = false;
-
- for (int i = 0; i < layoutEntries.length; i++)
- {
- fieldText = layoutEntries[i].doLayout(bibtex, database);
-
- //System.out.println("'" + fieldText + "'");
- if (fieldText == null)
- {
- if ((i + 1) < layoutEntries.length)
- {
- if (layoutEntries[i + 1].doLayout(bibtex, database).trim()
- .length() == 0)
- {
- //System.out.println("MISSING: "+bibtex);
- i++;
- previousSkipped = true;
-
- continue;
- }
- }
- }
- else
- {
- // if previous was skipped --> remove leading line breaks
- if (previousSkipped)
- {
- int eol = 0;
-
- while ((eol < fieldText.length()) &&
- ((fieldText.charAt(eol) == '\n') ||
- (fieldText.charAt(eol) == '\r')))
- {
- eol++;
- }
-
- if (eol < fieldText.length())
- {
- sb.append(fieldText.substring(eol));
- }
- }
- else
- {
- //System.out.println("ENTRY-BLOCK: " + layoutEntries[i].doLayout(bibtex));
- sb.append(fieldText);
- }
- }
-
- previousSkipped = false;
- }
-
- return sb.toString();
- }
- }
- else if ((type == LayoutHelper.IS_FIELD_END) || (type == LayoutHelper.IS_GROUP_END))
- {
- }
- else if (type == LayoutHelper.IS_OPTION_FIELD)
- {
- //System.out.println("doLayout IS_OPTION_FIELD '"+text+"'");
- String fieldEntry;
-
- if (text.equals("bibtextype"))
- {
- fieldEntry = bibtex.getType().getName();
- }
- else{
- // changed section begin - arudert
- // resolve field (recognized by leading backslash) or text
- String field = text.startsWith("\\") ? getField(bibtex, text.substring(1), database) : getText(text, database);
- // changed section end - arudert
-
- //String field = (String) bibtex.getField(text);
-
- if (field == null)
- {
- fieldEntry = "";
- }
- else
- {
- fieldEntry = field;
- }
- }
-
- //System.out.println("OPTION: "+option);
- if (option != null)
- {
- for (int i=0; i<option.length; i++) {
- fieldEntry = option[i].format(fieldEntry);
- }
- }
-
- return fieldEntry;
- }
-
- // else if (type == LayoutHelper.IS_OPTION_FIELD_PARAM)
- // {
- // }
-
- return "";
- }
-
- // added section - begin (arudert)
- /**
- * Do layout for general formatters (no bibtex-entry fields).
- *
- * @param database Bibtex Database
- * @return
- */
- public String doLayout(BibtexDatabase database)
- {
- if (type == LayoutHelper.IS_LAYOUT_TEXT)
- {
- return text;
- }
- else if (type == LayoutHelper.IS_SIMPLE_FIELD)
- {
- throw new UnsupportedOperationException("bibtext entry fields not allowed in begin or end layout");
- }
- else if ((type == LayoutHelper.IS_FIELD_START) ||
- (type == LayoutHelper.IS_GROUP_START))
- {
- throw new UnsupportedOperationException("field and group starts not allowed in begin or end layout");
- }
- else if ((type == LayoutHelper.IS_FIELD_END) || (type == LayoutHelper.IS_GROUP_END))
- {
- throw new UnsupportedOperationException("field and group ends not allowed in begin or end layout");
- }
- else if (type == LayoutHelper.IS_OPTION_FIELD)
- {
- String field = getText(text, database);
- if (option != null)
- {
- for (int i=0; i<option.length; i++) {
- field = option[i].format(field);
- }
- }
-
- return field;
- }
- return "";
- }
- // added section - end (arudert)
-
- /**
- * @param string
- * @return
- */
- private LayoutFormatter[] getOptionalLayout(String formatterName)
- throws Exception
- {
- String[] formatters = formatterName.split(",");
- //System.out.println(":"+formatterName);
- LayoutFormatter[] formatter = new LayoutFormatter[formatters.length];
- for (int i=0; i<formatter.length; i++) {
- //System.out.println(":::"+formatters[i]);
- try
- {
- try {
- formatter[i] = (LayoutFormatter) Class.forName(classPrefix + formatters[i])
- .newInstance();
- } catch (Throwable ex2) {
- formatter[i] = (LayoutFormatter) Class.forName(formatters[i])
- .newInstance();
- }
- }
- catch (ClassNotFoundException ex)
- {
- throw new Exception(Globals.lang("Formatter not found")+": "+formatters[i]);
- }
- catch (InstantiationException ex)
- {
- throw new Exception(formatterName + " can not be instantiated.");
- }
- catch (IllegalAccessException ex)
- {
- throw new Exception(formatterName + " can't be accessed.");
- }
-
- if (formatter == null)
- {
- throw new Exception(Globals.lang("Formatter not found")+": "+formatters[i]);
- }
- }
-
- return formatter;
- }
-
-
- // changed section begin - arudert
- /**
- * Returns a text with references resolved according to an optionally given database.
- */
- private String getText(String text, BibtexDatabase database) {
- String res = text;
- // changed section end - arudert
- if ((res != null) && (database != null))
- res = database.resolveForStrings(res);
- return res;
- }
- // changed section end - arudert
-
- private String getField(BibtexEntry bibtex, String field, BibtexDatabase database) {
-
- // Change: Morten Alver, May 23, 2006. Formatter argument uses this method to
- // resolve field values. We need this part to resolve \bibtextype correctly in
- // constructs like \format[ToLowerCase]{\bibtextype}:
- if (field.equals("bibtextype"))
- {
- return bibtex.getType().getName();
- }
- // end change Morten Alver
-
- String res = (String)bibtex.getField(field);
-
- if ((res != null) && (database != null))
- res = database.resolveForStrings(res);
-
- return res;
- }
+public class LayoutEntry {
+ // ~ Instance fields
+ // ////////////////////////////////////////////////////////
+
+ private LayoutFormatter[] option;
+
+ private String text;
+
+ private LayoutEntry[] layoutEntries;
+
+ private int type;
+
+ private String classPrefix;
+
+ // ~ Constructors
+ // ///////////////////////////////////////////////////////////
+
+ public LayoutEntry(StringInt si, String classPrefix_) throws Exception {
+ type = si.i;
+ classPrefix = classPrefix_;
+
+ if (si.i == LayoutHelper.IS_LAYOUT_TEXT) {
+ text = si.s;
+ } else if (si.i == LayoutHelper.IS_SIMPLE_FIELD) {
+ text = si.s.trim();
+ } else if (si.i == LayoutHelper.IS_FIELD_START) {
+ } else if (si.i == LayoutHelper.IS_FIELD_END) {
+ } else if (si.i == LayoutHelper.IS_OPTION_FIELD) {
+ Vector v = new Vector();
+ WSITools.tokenize(v, si.s, "\n");
+
+ if (v.size() == 1) {
+ text = (String) v.get(0);
+ } else {
+ text = ((String) v.get(0)).trim();
+
+ // try
+ // {
+ option = getOptionalLayout((String) v.get(1), classPrefix);
+ // }
+ // catch (Exception e)
+ // {
+ // e.printStackTrace();
+ // }
+ }
+ }
+
+ // else if (si.i == LayoutHelper.IS_OPTION_FIELD_PARAM)
+ // {
+ // }
+ }
+
+ public LayoutEntry(Vector parsedEntries, String classPrefix_, int layoutType) throws Exception {
+ classPrefix = classPrefix_;
+ String blockStart = null;
+ String blockEnd = null;
+ StringInt si;
+ Vector blockEntries = null;
+ Vector tmpEntries = new Vector();
+ LayoutEntry le;
+ si = (StringInt) parsedEntries.get(0);
+ blockStart = si.s;
+ si = (StringInt) parsedEntries.get(parsedEntries.size() - 1);
+ blockEnd = si.s;
+
+ if (!blockStart.equals(blockEnd)) {
+ System.err.println("Field start and end entry must be equal.");
+ }
+
+ type = layoutType;
+ text = si.s;
+
+ for (int i = 1; i < (parsedEntries.size() - 1); i++) {
+ si = (StringInt) parsedEntries.get(i);
+
+ // System.out.println("PARSED-ENTRY: "+si.s+"="+si.i);
+ if (si.i == LayoutHelper.IS_LAYOUT_TEXT) {
+ } else if (si.i == LayoutHelper.IS_SIMPLE_FIELD) {
+ } else if ((si.i == LayoutHelper.IS_FIELD_START)
+ || (si.i == LayoutHelper.IS_GROUP_START)) {
+ blockEntries = new Vector();
+ blockStart = si.s;
+ } else if ((si.i == LayoutHelper.IS_FIELD_END) || (si.i == LayoutHelper.IS_GROUP_END)) {
+ if (blockStart.equals(si.s)) {
+ blockEntries.add(si);
+ if (si.i == LayoutHelper.IS_GROUP_END)
+ le = new LayoutEntry(blockEntries, classPrefix, LayoutHelper.IS_GROUP_START);
+ else
+ le = new LayoutEntry(blockEntries, classPrefix, LayoutHelper.IS_FIELD_START);
+ tmpEntries.add(le);
+ blockEntries = null;
+ } else {
+ System.out.println("Nested field entries are not implemented !!!");
+ }
+ } else if (si.i == LayoutHelper.IS_OPTION_FIELD) {
+ }
+
+ // else if (si.i == LayoutHelper.IS_OPTION_FIELD_PARAM)
+ // {
+ // }
+ if (blockEntries == null) {
+ // System.out.println("BLOCK ADD: "+si.s+"="+si.i);
+ tmpEntries.add(new LayoutEntry(si, classPrefix));
+ } else {
+ blockEntries.add(si);
+ }
+ }
+
+ layoutEntries = new LayoutEntry[tmpEntries.size()];
+
+ for (int i = 0; i < tmpEntries.size(); i++) {
+ layoutEntries[i] = (LayoutEntry) tmpEntries.get(i);
+
+ // System.out.println(layoutEntries[i].text);
+ }
+ }
+
+ // ~ Methods
+ // ////////////////////////////////////////////////////////////////
+
+ public String doLayout(BibtexEntry bibtex, BibtexDatabase database) {
+
+ if (type == LayoutHelper.IS_LAYOUT_TEXT) {
+ return text;
+ } else if (type == LayoutHelper.IS_SIMPLE_FIELD) {
+ if (text.equals("bibtextype")) {
+ return bibtex.getType().getName();
+ }
+
+ String field = getField(bibtex, text, database);
+
+ if (field == null) {
+
+ return null;
+ } else {
+
+ return field;
+
+ }
+ } else if ((type == LayoutHelper.IS_FIELD_START) || (type == LayoutHelper.IS_GROUP_START)) {
+
+ String field = getField(bibtex, text, database);
+ // String field = (String) bibtex.getField(text);
+
+ if ((field == null)
+ || ((type == LayoutHelper.IS_GROUP_START) && (field.equalsIgnoreCase(LayoutHelper
+ .getCurrentGroup())))) {
+ return null;
+ } else {
+ if (type == LayoutHelper.IS_GROUP_START) {
+ LayoutHelper.setCurrentGroup(field);
+ }
+ StringBuffer sb = new StringBuffer(100);
+ String fieldText;
+ boolean previousSkipped = false;
+
+ for (int i = 0; i < layoutEntries.length; i++) {
+ fieldText = layoutEntries[i].doLayout(bibtex, database);
+
+ // System.out.println("'" + fieldText + "'");
+ if (fieldText == null) {
+ if ((i + 1) < layoutEntries.length) {
+ if (layoutEntries[i + 1].doLayout(bibtex, database).trim().length() == 0) {
+ // System.out.println("MISSING: "+bibtex);
+ i++;
+ previousSkipped = true;
+
+ continue;
+ }
+ }
+ } else {
+ // if previous was skipped --> remove leading line
+ // breaks
+ if (previousSkipped) {
+ int eol = 0;
+
+ while ((eol < fieldText.length())
+ && ((fieldText.charAt(eol) == '\n') || (fieldText.charAt(eol) == '\r'))) {
+ eol++;
+ }
+
+ if (eol < fieldText.length()) {
+ sb.append(fieldText.substring(eol));
+ }
+ } else {
+ // System.out.println("ENTRY-BLOCK: " +
+ // layoutEntries[i].doLayout(bibtex));
+ sb.append(fieldText);
+ }
+ }
+
+ previousSkipped = false;
+ }
+
+ return sb.toString();
+ }
+ } else if ((type == LayoutHelper.IS_FIELD_END) || (type == LayoutHelper.IS_GROUP_END)) {
+ } else if (type == LayoutHelper.IS_OPTION_FIELD) {
+ // System.out.println("doLayout IS_OPTION_FIELD '"+text+"'");
+ String fieldEntry;
+
+ if (text.equals("bibtextype")) {
+ fieldEntry = bibtex.getType().getName();
+ } else {
+ // changed section begin - arudert
+ // resolve field (recognized by leading backslash) or text
+ String field = text.startsWith("\\") ? getField(bibtex, text.substring(1), database)
+ : getText(text, database);
+ // changed section end - arudert
+
+ // String field = (String) bibtex.getField(text);
+
+ if (field == null) {
+ fieldEntry = "";
+ } else {
+ fieldEntry = field;
+ }
+ }
+
+ // System.out.println("OPTION: "+option);
+ if (option != null) {
+ for (int i = 0; i < option.length; i++) {
+ fieldEntry = option[i].format(fieldEntry);
+ }
+ }
+
+ return fieldEntry;
+ }
+
+ // else if (type == LayoutHelper.IS_OPTION_FIELD_PARAM)
+ // {
+ // }
+
+ return "";
+ }
+
+ // added section - begin (arudert)
+ /**
+ * Do layout for general formatters (no bibtex-entry fields).
+ *
+ * @param database
+ * Bibtex Database
+ * @return
+ */
+ public String doLayout(BibtexDatabase database) {
+ if (type == LayoutHelper.IS_LAYOUT_TEXT) {
+ return text;
+ } else if (type == LayoutHelper.IS_SIMPLE_FIELD) {
+ throw new UnsupportedOperationException(
+ "bibtext entry fields not allowed in begin or end layout");
+ } else if ((type == LayoutHelper.IS_FIELD_START) || (type == LayoutHelper.IS_GROUP_START)) {
+ throw new UnsupportedOperationException(
+ "field and group starts not allowed in begin or end layout");
+ } else if ((type == LayoutHelper.IS_FIELD_END) || (type == LayoutHelper.IS_GROUP_END)) {
+ throw new UnsupportedOperationException(
+ "field and group ends not allowed in begin or end layout");
+ } else if (type == LayoutHelper.IS_OPTION_FIELD) {
+ String field = getText(text, database);
+ if (option != null) {
+ for (int i = 0; i < option.length; i++) {
+ field = option[i].format(field);
+ }
+ }
+
+ return field;
+ }
+ return "";
+ }
+
+ // added section - end (arudert)
+
+ public static LayoutFormatter getLayoutFormatter(String className, String classPrefix)
+ throws Exception {
+ LayoutFormatter f = null;
+
+ if (className.length() > 0) {
+ try {
+ try {
+ f = (LayoutFormatter) Class.forName(classPrefix + className).newInstance();
+ } catch (Throwable ex2) {
+ f = (LayoutFormatter) Class.forName(className).newInstance();
+ }
+ } catch (ClassNotFoundException ex) {
+ throw new Exception(Globals.lang("Formatter not found") + ": " + className);
+ } catch (InstantiationException ex) {
+ throw new Exception(className + " can not be instantiated.");
+ } catch (IllegalAccessException ex) {
+ throw new Exception(className + " can't be accessed.");
+ }
+ }
+ return f;
+ }
+
+ /**
+ * Return an array of LayoutFormatters found in the given formatterName
+ * string (in order of appearance).
+ *
+ */
+ public static LayoutFormatter[] getOptionalLayout(String formatterName, String classPrefix)
+ throws Exception {
+
+ ArrayList formatterStrings = Util.parseMethodsCalls(formatterName);
+
+ ArrayList results = new ArrayList(formatterStrings.size());
+
+ Map userNameFormatter = NameFormatterTab.getNameFormatters();
+
+ for (int i = 0; i < formatterStrings.size(); i++) {
+
+ String[] strings = (String[]) formatterStrings.get(i);
+
+ String className = strings[0].trim();
+
+ try {
+ LayoutFormatter f = getLayoutFormatter(className, classPrefix);
+ results.add(f);
+ } catch (Exception e) {
+
+ String formatterParameter = (String) userNameFormatter.get(className);
+
+ if (formatterParameter == null) {
+ throw new Exception(Globals.lang("Formatter not found") + ": " + className);
+ } else {
+ NameFormat nf = new NameFormat();
+ nf.setParameter(formatterParameter);
+ results.add(nf);
+ }
+ }
+ }
+
+ return (LayoutFormatter[]) results.toArray(new LayoutFormatter[] {});
+ }
+
+ // changed section begin - arudert
+ /**
+ * Returns a text with references resolved according to an optionally given
+ * database.
+ */
+ private String getText(String text, BibtexDatabase database) {
+ String res = text;
+ // changed section end - arudert
+ if ((res != null) && (database != null))
+ res = database.resolveForStrings(res);
+ return res;
+ }
+
+ // changed section end - arudert
+
+ private String getField(BibtexEntry bibtex, String field, BibtexDatabase database) {
+
+ // Change: Morten Alver, May 23, 2006. Formatter argument uses this
+ // method to
+ // resolve field values. We need this part to resolve \bibtextype
+ // correctly in
+ // constructs like \format[ToLowerCase]{\bibtextype}:
+ if (field.equals("bibtextype")) {
+ return bibtex.getType().getName();
+ }
+ // end change Morten Alver
+
+ String res = (String) bibtex.getField(field);
+
+ if ((res != null) && (database != null))
+ res = database.resolveForStrings(res);
+
+ return res;
+ }
}
-///////////////////////////////////////////////////////////////////////////////
-// END OF FILE.
-///////////////////////////////////////////////////////////////////////////////
+// /////////////////////////////////////////////////////////////////////////////
+// END OF FILE.
+// /////////////////////////////////////////////////////////////////////////////
diff --git a/src/java/net/sf/jabref/export/layout/LayoutFormatter.java b/src/java/net/sf/jabref/export/layout/LayoutFormatter.java
index 97a4a64..369472d 100755
--- a/src/java/net/sf/jabref/export/layout/LayoutFormatter.java
+++ b/src/java/net/sf/jabref/export/layout/LayoutFormatter.java
@@ -1,42 +1,54 @@
/*
-Copyright (C) 2003 Morten O. Alver
-All programs in this directory and
-subdirectories are published under the GNU General Public License as
-described below.
+ Copyright (C) 2003-2006 Morten O. Alver, JabRef-Team
+
+ All programs in this directory and subdirectories are published
+ under the GNU General Public License as described below.
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or (at
-your option) any later version.
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or (at
+ your option) any later version.
-This program is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
-USA
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA
-Further information about the GNU GPL is available at:
-http://www.gnu.org/copyleft/gpl.ja.html
+ Further information about the GNU GPL is available at:
+ http://www.gnu.org/copyleft/gpl.ja.html
-*/
+ */
package net.sf.jabref.export.layout;
/**
- * DOCUMENT ME!
+ * The LayoutFormatter is used for a Filter design-pattern.
+ *
+ * Implementing classes have to accept a String and returned a formatted version of it.
+ *
+ * Example:
+ *
+ * "John von Neumann" => "von Neumann, John"
*
- * @author $author$
- * @version $Revision: 1.1 $
+ * @version 1.2 - Documentation CO
*/
-public interface LayoutFormatter
-{
- //~ Methods ////////////////////////////////////////////////////////////////
-
- public String format(String fieldText);
+public interface LayoutFormatter {
+ /**
+ * Failure Mode:
+ * <p>
+ * Formatters should be robust in the sense that they always return some
+ * relevant string.
+ * <p>
+ * If the formatter can detect an invalid input it should return the
+ * original string otherwise it may simply return a wrong output.
+ *
+ * @param fieldText
+ * The text to layout.
+ * @return The layouted text.
+ */
+ public String format(String fieldText);
}
-///////////////////////////////////////////////////////////////////////////////
-// END OF FILE.
-///////////////////////////////////////////////////////////////////////////////
diff --git a/src/java/net/sf/jabref/export/layout/LayoutHelper.java b/src/java/net/sf/jabref/export/layout/LayoutHelper.java
index e426ef0..c5d42c8 100755
--- a/src/java/net/sf/jabref/export/layout/LayoutHelper.java
+++ b/src/java/net/sf/jabref/export/layout/LayoutHelper.java
@@ -42,7 +42,7 @@ import java.util.Vector;
* DOCUMENT ME!
*
* @author $author$
- * @version $Revision: 1.8 $
+ * @version $Revision: 1.10 $
*/
public class LayoutHelper
{
@@ -72,7 +72,6 @@ public class LayoutHelper
public LayoutHelper(Reader in)
{
-
if (in == null)
{
throw new NullPointerException();
@@ -316,77 +315,62 @@ public class LayoutHelper
return null;
}
- private Object parse() throws IOException
- {
- //_meta = new HashMap(); // Metadata in comments for Bibkeeper.
- skipWhitespace();
+ private Object parse() throws IOException {
+ skipWhitespace();
- int c;
+ int c;
- StringBuffer buffer = null;
- int previous = -1;
- boolean justParsedTag = false;
- boolean escaped = false;
+ StringBuffer buffer = null;
+ boolean escaped = false;
- while (!_eof)
- {
- c = read();
+ while (!_eof) {
+ c = read();
- //System.out.println((char)c);
- if (c == -1)
- {
- _eof = true;
- parsedEntries.add(new StringInt(buffer.toString(),
- IS_LAYOUT_TEXT));
+ if (c == -1) {
+ _eof = true;
- //System.out.println("aha: " + buffer.toString());
- return null;
- }
+ /*
+ * CO 2006-11-11: Added check for null, otherwise a Layout that
+ * finishs with a curly brace throws a NPE
+ */
+ if (buffer != null)
+ parsedEntries.add(new StringInt(buffer.toString(), IS_LAYOUT_TEXT));
- if ((c == '\\') && (peek() != '\\') && !escaped)
- //&& (justParsedTag || (previous != '\\')))
- {
- if (buffer != null)
- {
- parsedEntries.add(new StringInt(buffer.toString(),
- IS_LAYOUT_TEXT));
-
- buffer = null;
- }
+ return null;
+ }
- parseField();
+ if ((c == '\\') && (peek() != '\\') && !escaped) {
+ if (buffer != null) {
+ parsedEntries.add(new StringInt(buffer.toString(), IS_LAYOUT_TEXT));
- // To make sure the next character, if it is a backslash, doesn't get ignored,
- // since "previous" now holds a backslash:
- justParsedTag = true;
- escaped = false;
- }
- else
- {
- justParsedTag = false;
+ buffer = null;
+ }
- if (buffer == null)
- {
- buffer = new StringBuffer(100);
- }
+ parseField();
- if ((c != '\\') || escaped)//(previous == '\\')))
- {
- buffer.append((char) c);
- }
+ // To make sure the next character, if it is a backslash,
+ // doesn't get ignored, since "previous" now holds a backslash:
+ escaped = false;
+ } else {
+ if (buffer == null) {
+ buffer = new StringBuffer(100);
+ }
- escaped = (c == '\\') && !escaped;
- }
+ if ((c != '\\') || escaped)// (previous == '\\')))
+ {
+ buffer.append((char) c);
+ }
- previous = c;
- }
+ escaped = (c == '\\') && !escaped;
+ }
+ }
- return null;
- }
+ return null;
+ }
/**
- *
- */
+ *
+ */
private void parseField() throws IOException
{
int c;
@@ -396,7 +380,7 @@ public class LayoutHelper
while (!_eof)
{
c = read();
- //System.out.print((char)c);
+ // System.out.print((char)c);
if (c == -1)
{
_eof = true;
diff --git a/src/java/net/sf/jabref/export/layout/format/AuthorAbbreviator.java b/src/java/net/sf/jabref/export/layout/format/AuthorAbbreviator.java
index b77957b..75d858d 100644
--- a/src/java/net/sf/jabref/export/layout/format/AuthorAbbreviator.java
+++ b/src/java/net/sf/jabref/export/layout/format/AuthorAbbreviator.java
@@ -1,137 +1,49 @@
/*
- * Created on 12/10/2004
+ * Copyright (C) 2004-2006 Jabref-Team
+ *
+ * All programs in this directory and subdirectories are published under the GNU
+ * General Public License as described below.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Further information about the GNU GPL is available at:
+ * http://www.gnu.org/copyleft/gpl.ja.html
+ *
*/
package net.sf.jabref.export.layout.format;
import net.sf.jabref.export.layout.LayoutFormatter;
/**
+ * Duplicate of AuthorLastFirstAbbreviator.
*
- * Uses as input the fields (author or editor) in the LastFirst format.
- *
- * This formater enables to abbreviate the authors name in the following way:
- *
- * Ex: Someone, Van Something will be abbreviated as Someone, V. S.
+ * @see AuthorLastFirstAbbreviator
*
* @author Carlos Silla
*/
public class AuthorAbbreviator implements LayoutFormatter {
- /* (non-Javadoc)
- * @see net.sf.jabref.export.layout.LayoutFormatter#format(java.lang.String)
- */
- public String format(String fieldText)
- {
-
- // It seems to me that this formatter and AuthorLastFirstAbbreviator
- // are duplicates. Since the latter was patched to improve handling of
- // some names, we refer the operation there:
- return (new AuthorLastFirstAbbreviator()).format(fieldText);
-
- /*String[] authors = fieldText.split(" and ");
-
- String abbrev = getAbbreviations(authors);
- return abbrev;
- */
- }
-
- /**
- * Abbreviates the names in the Last First format.
+ /*
+ * (non-Javadoc)
*
- * @param authors List of authors or editors.
- * @return the names abbreviated.
- *
+ * @see net.sf.jabref.export.layout.LayoutFormatter#format(java.lang.String)
*/
- private String getAbbreviations(String[] authors)
- {
- String s = null;
-
- try
- {
-
- String[] authors_abrv = new String[authors.length];
-
- int i = 0;
-
- for(i=0; i<authors.length; i++)
- {
- authors_abrv[i] = getAbbreviation(authors[i]);
- }
-
- //Faz o merge em um "unico string" usando " and "
- StringBuffer sb = new StringBuffer();
-
- for(i=0; i<authors.length-1; i++)
- {
- sb.append(authors_abrv[i]).append(" and ");
- }
- sb.append(authors_abrv[i]);
-
- s = new String(sb);
- }
- catch(Exception e)
- {
- e.printStackTrace();
- // System.out.println(e);
- //System.exit(-1);
- }
-
- return s;
+ public String format(String fieldText) {
+ // It seems to me that this formatter and AuthorLastFirstAbbreviator
+ // are duplicates. Since the latter was patched to improve handling of
+ // some names, we refer the operation there:
+ return (new AuthorLastFirstAbbreviator()).format(fieldText);
}
-
- /**
- *
- * Abbreviates all but the last name of the author.
- *
- * @param string
- * @return
- */
- private String getAbbreviation(String string) {
- StringBuffer sb = new StringBuffer();
- String[] author = string.split(", ");
- char c;
-
- if (author.length < 2) {
- // There is no comma in the name. Abbreviate all but the
- // last word.
- author = string.split(" ");
- if (author.length > 1) {
- for (int i=0; i<author.length-1; i++) if (author[i].length() > 0) {
- c = author[i].charAt(0);
- sb.append(c).append(".");
- }
- }
- sb.append(" ").append(author[author.length - 1]);
- }
- else {
- //Gets the name:
- sb.append(author[0]).append(", ");
- int index = author[1].indexOf(" ");
- if(index==-1) {
- //Its a simple name like van Something, Someone or Something, Someone:
- c = author[1].charAt(0);
- // System.out.println("Char c: " + c + " Name: " + author[1]);
- sb.append(c).append(".");
- }
- else {
- //Its a "complex" name like van Something, Someone Something
- //System.out.println(author[1]);
- String[] nameParts = author[1].split(" ");
-
- int i = 0;
-
- for(i=0;i<nameParts.length;i++)
- if (nameParts[i].length() > 0) {
- c = nameParts[i].charAt(0);
- // System.out.println("Char c: " + c + " Name: " + nameParts[i]);
- sb.append(c).append(".");
- }
- }
- }
- //Replaces each "part of the name" for the corresponding Letter Dot Space format:
- String s = new String(sb);
-
- //System.out.println("The Abbreviated name is: " + s);
- return s;
- }
}
diff --git a/src/java/net/sf/jabref/export/layout/format/AuthorAndsCommaReplacer.java b/src/java/net/sf/jabref/export/layout/format/AuthorAndsCommaReplacer.java
index eaa8a3d..a1e3c59 100644
--- a/src/java/net/sf/jabref/export/layout/format/AuthorAndsCommaReplacer.java
+++ b/src/java/net/sf/jabref/export/layout/format/AuthorAndsCommaReplacer.java
@@ -3,7 +3,7 @@ package net.sf.jabref.export.layout.format;
import net.sf.jabref.export.layout.LayoutFormatter;
/**
- * Replaces and's for & (in case of two authors) and ; (in case
+ * Replaces and's for & (in case of two authors) and , (in case
* of more than two authors).
*
* @author Carlos Silla
diff --git a/src/java/net/sf/jabref/export/layout/format/AuthorFirstAbbrLastCommas.java b/src/java/net/sf/jabref/export/layout/format/AuthorFirstAbbrLastCommas.java
index 6b36f9c..874a08b 100644
--- a/src/java/net/sf/jabref/export/layout/format/AuthorFirstAbbrLastCommas.java
+++ b/src/java/net/sf/jabref/export/layout/format/AuthorFirstAbbrLastCommas.java
@@ -1,26 +1,44 @@
/*
- * AuthorFirstAbbrLastCommas.java
+ * Copyright (C) 2006 Jabref-Team
+ *
+ * All programs in this directory and subdirectories are published under the GNU
+ * General Public License as described below.
*
- * Created on September 7, 2005, 1:15 PM
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Further information about the GNU GPL is available at:
+ * http://www.gnu.org/copyleft/gpl.ja.html
*
- * To change this template, choose Tools | Options and locate the template under
- * the Source Creation and Management node. Right-click the template and choose
- * Open. You can then make changes to the template in the Source Editor.
*/
-
package net.sf.jabref.export.layout.format;
import net.sf.jabref.export.layout.LayoutFormatter;
import net.sf.jabref.AuthorList;
/**
- *
- * @author mkovtun
+ * <ul>
+ * <li>Names are given as first name, von and last name.</li>
+ * <li>First names will be abbreviated.</li>
+ * <li>Individual authors separated by comma.</li>
+ * <li>There is no command in front the and of a list of three or more authors.</li>
+ * </ul>
+ *
+ * @author Christopher Oezbek <oezi at oezi.de>
*/
public class AuthorFirstAbbrLastCommas implements LayoutFormatter {
-
- public String format(String fieldText) {
- return AuthorList.fixAuthor_firstNameFirstCommas(fieldText, true);
- }
-
+ public String format(String fieldText) {
+ return AuthorList.fixAuthor_firstNameFirstCommas(fieldText, true, false);
+ }
}
\ No newline at end of file
diff --git a/src/java/net/sf/jabref/export/layout/format/AuthorFirstAbbrLastOxfordCommas.java b/src/java/net/sf/jabref/export/layout/format/AuthorFirstAbbrLastOxfordCommas.java
new file mode 100644
index 0000000..5736f46
--- /dev/null
+++ b/src/java/net/sf/jabref/export/layout/format/AuthorFirstAbbrLastOxfordCommas.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2003 Jabref-Team
+ *
+ * All programs in this directory and subdirectories are published under the GNU
+ * General Public License as described below.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Further information about the GNU GPL is available at:
+ * http://www.gnu.org/copyleft/gpl.ja.html
+ *
+ */
+
+package net.sf.jabref.export.layout.format;
+
+import net.sf.jabref.export.layout.LayoutFormatter;
+import net.sf.jabref.AuthorList;
+
+/**
+ * <ul>
+ * <li>Names are given as first name, von and last name.</li>
+ * <li>First names will be abbreviated.</li>
+ * <li>Individual authors separated by comma.</li>
+ * <li>The and of a list of three or more authors is preceeded by a comma
+ * (Oxford comma)</li>
+ * </ul>
+ *
+ * @author mkovtun
+ * @author Christopher Oezbek <oezi at oezi.de>
+ *
+ */
+public class AuthorFirstAbbrLastOxfordCommas implements LayoutFormatter {
+
+ public String format(String fieldText) {
+ return AuthorList.fixAuthor_firstNameFirstCommas(fieldText, true, true);
+ }
+
+}
\ No newline at end of file
diff --git a/src/java/net/sf/jabref/export/layout/format/AuthorFirstFirst.java b/src/java/net/sf/jabref/export/layout/format/AuthorFirstFirst.java
index ecb539c..ebcea24 100644
--- a/src/java/net/sf/jabref/export/layout/format/AuthorFirstFirst.java
+++ b/src/java/net/sf/jabref/export/layout/format/AuthorFirstFirst.java
@@ -1,46 +1,47 @@
-///////////////////////////////////////////////////////////////////////////////
-// Filename: $RCSfile: AuthorFirstFirst.java,v $
-// Purpose: Atom representation.
-// Language: Java
-// Compiler: JDK 1.4
-// Authors: Joerg K. Wegner, Morten O. Alver
-// Version: $Revision: 1.4 $
-// $Date: 2005/10/23 03:36:09 $
-// $Author: mortenalver $
-//
-// Copyright (c) Dept. Computer Architecture, University of Tuebingen, Germany
-//
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation version 2 of the License.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-///////////////////////////////////////////////////////////////////////////////
-
+/*
+ * Copyright (C) 2006 Jabref-Team
+ * 2005 Dept. Computer Architecture, University of Tuebingen, Germany
+ * 2005 Joerg K. Wegner
+ * 2003 Morten O. Alver, Nizar N. Batada
+ *
+ * All programs in this directory and subdirectories are published under the GNU
+ * General Public License as described below.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Further information about the GNU GPL is available at:
+ * http://www.gnu.org/copyleft/gpl.ja.html
+ *
+ */
package net.sf.jabref.export.layout.format;
import net.sf.jabref.export.layout.LayoutFormatter;
import net.sf.jabref.AuthorList;
/**
- * Changes {\^o} or {\^{o}} to \uFFFD
- *
- * @author $author$
- * @version $Revision: 1.4 $
+ * Author First First prints ....
+ *
+ *
+ * @author $Author: coezbek $
+ * @version $Revision: 1.6 $ $Date: 2006/11/11 17:11:39 $
+ *
*/
public class AuthorFirstFirst implements LayoutFormatter
{
- //~ Methods ////////////////////////////////////////////////////////////////
public String format(String fieldText)
{
- //ConvertSpecialCharactersForHTML conv = new ConvertSpecialCharactersForHTML();
- //return conv.format(ImportFormatReader.fixAuthor_lastNameFirst(fieldText));
return AuthorList.fixAuthor_firstNameFirst(fieldText);
}
}
-///////////////////////////////////////////////////////////////////////////////
-// END OF FILE.
-///////////////////////////////////////////////////////////////////////////////
diff --git a/src/java/net/sf/jabref/export/layout/format/AuthorFirstLastCommas.java b/src/java/net/sf/jabref/export/layout/format/AuthorFirstLastCommas.java
index e418e5b..fd36df2 100644
--- a/src/java/net/sf/jabref/export/layout/format/AuthorFirstLastCommas.java
+++ b/src/java/net/sf/jabref/export/layout/format/AuthorFirstLastCommas.java
@@ -14,13 +14,21 @@ import net.sf.jabref.export.layout.LayoutFormatter;
import net.sf.jabref.AuthorList;
/**
- *
+ * <ul>
+ * <li>Names are given as first name, von and last name.</li>
+ * <li>First names will not be abbreviated.</li>
+ * <li>Individual authors separated by comma.</li>
+ * <li>There is no comma before the and of a list of three or more authors.</li>
+ * </ul>
+ *
* @author mkovtun
+ * @author Christopher Oezbek <oezi at oezi.de>
+ *
*/
public class AuthorFirstLastCommas implements LayoutFormatter {
public String format(String fieldText) {
- return AuthorList.fixAuthor_firstNameFirstCommas(fieldText, false);
+ return AuthorList.fixAuthor_firstNameFirstCommas(fieldText, false, false);
}
}
\ No newline at end of file
diff --git a/src/java/net/sf/jabref/export/layout/format/AuthorFirstLastCommas.java b/src/java/net/sf/jabref/export/layout/format/AuthorFirstLastOxfordCommas.java
similarity index 61%
copy from src/java/net/sf/jabref/export/layout/format/AuthorFirstLastCommas.java
copy to src/java/net/sf/jabref/export/layout/format/AuthorFirstLastOxfordCommas.java
index e418e5b..3612ddd 100644
--- a/src/java/net/sf/jabref/export/layout/format/AuthorFirstLastCommas.java
+++ b/src/java/net/sf/jabref/export/layout/format/AuthorFirstLastOxfordCommas.java
@@ -14,13 +14,21 @@ import net.sf.jabref.export.layout.LayoutFormatter;
import net.sf.jabref.AuthorList;
/**
- *
+ * <ul>
+ * <li>Names are given as first name, von and last name.</li>
+ * <li>Individual authors separated by comma.</li>
+ * <li>The and of a list of three or more authors is preceeded by a comma
+ * (Oxford comma)</li>
+ * </ul>
+ *
* @author mkovtun
+ * @author Christopher Oezbek <oezi at oezi.de>
+ *
*/
-public class AuthorFirstLastCommas implements LayoutFormatter {
+public class AuthorFirstLastOxfordCommas implements LayoutFormatter {
public String format(String fieldText) {
- return AuthorList.fixAuthor_firstNameFirstCommas(fieldText, false);
+ return AuthorList.fixAuthor_firstNameFirstCommas(fieldText, false, true);
}
}
\ No newline at end of file
diff --git a/src/java/net/sf/jabref/export/layout/format/AuthorLastFirst.java b/src/java/net/sf/jabref/export/layout/format/AuthorLastFirst.java
index 1a28d06..c83e5c7 100644
--- a/src/java/net/sf/jabref/export/layout/format/AuthorLastFirst.java
+++ b/src/java/net/sf/jabref/export/layout/format/AuthorLastFirst.java
@@ -1,6 +1,6 @@
-/* Version: $Revision: 1.3 $
- $Date: 2005/10/30 05:59:25 $
- $Author: mortenalver $
+/* Version: $Revision: 1.4 $
+ $Date: 2006/08/12 15:36:45 $
+ $Author: coezbek $
Copyright (c) Dept. Computer Architecture, University of Tuebingen, Germany
@@ -21,14 +21,8 @@ import net.sf.jabref.AuthorList;
public class AuthorLastFirst implements LayoutFormatter
{
- //~ Methods ////////////////////////////////////////////////////////////////
public String format(String fieldText)
{
- //ConvertSpecialCharactersForHTML conv = new ConvertSpecialCharactersForHTML();
- //return conv.format(ImportFormatReader.fixAuthor_lastNameFirst(fieldText));
return AuthorList.fixAuthor_lastNameFirst(fieldText);
}
}
-///////////////////////////////////////////////////////////////////////////////
-// END OF FILE.
-///////////////////////////////////////////////////////////////////////////////
diff --git a/src/java/net/sf/jabref/export/layout/format/AuthorLastFirstAbbrCommas.java b/src/java/net/sf/jabref/export/layout/format/AuthorLastFirstAbbrCommas.java
index 6730b4f..afe4cbe 100644
--- a/src/java/net/sf/jabref/export/layout/format/AuthorLastFirstAbbrCommas.java
+++ b/src/java/net/sf/jabref/export/layout/format/AuthorLastFirstAbbrCommas.java
@@ -1,26 +1,48 @@
/*
- * AuthorLastFirstAbbrCommas.java
+ * Copyright (C) 2005-2006 Jabref-Team
+ *
+ * All programs in this directory and subdirectories are published under the GNU
+ * General Public License as described below.
*
- * Created on September 7, 2005, 1:18 PM
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Further information about the GNU GPL is available at:
+ * http://www.gnu.org/copyleft/gpl.ja.html
*
- * To change this template, choose Tools | Options and locate the template under
- * the Source Creation and Management node. Right-click the template and choose
- * Open. You can then make changes to the template in the Source Editor.
*/
-
package net.sf.jabref.export.layout.format;
import net.sf.jabref.export.layout.LayoutFormatter;
import net.sf.jabref.AuthorList;
/**
- *
+ * <ul>
+ * <li>Names are given in order: von last, jr, first.</li>
+ * <li>First names will be abbreviated.</li>
+ * <li>Individual authors are separated by commas.</li>
+ * <li>There is no comma before the 'and' at the end of a list of three or more authors</li>
+ * </ul>
+ *
* @author mkovtun
+ * @author Christopher Oezbek <oezi at oezi.de>
+ *
*/
public class AuthorLastFirstAbbrCommas implements LayoutFormatter {
public String format(String fieldText) {
- return AuthorList.fixAuthor_lastNameFirstCommas(fieldText, true);
+ return AuthorList.fixAuthor_lastNameFirstCommas(fieldText, true, false);
}
}
\ No newline at end of file
diff --git a/src/java/net/sf/jabref/export/layout/format/AuthorLastFirstAbbrOxfordCommas.java b/src/java/net/sf/jabref/export/layout/format/AuthorLastFirstAbbrOxfordCommas.java
new file mode 100644
index 0000000..a387add
--- /dev/null
+++ b/src/java/net/sf/jabref/export/layout/format/AuthorLastFirstAbbrOxfordCommas.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2005-2006 Jabref-Team
+ *
+ * All programs in this directory and subdirectories are published under the GNU
+ * General Public License as described below.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Further information about the GNU GPL is available at:
+ * http://www.gnu.org/copyleft/gpl.ja.html
+ *
+ */
+package net.sf.jabref.export.layout.format;
+
+import net.sf.jabref.export.layout.LayoutFormatter;
+import net.sf.jabref.AuthorList;
+
+/**
+ * <ul>
+ * <li>Names are given in order: von last, jr, first.</li>
+ * <li>First names will be abbreviated.</li>
+ * <li>Individual authors are separated by commas.</li>
+ * <li>The 'and' of a list of three or more authors is preceeded by a comma
+ * (Oxford comma)</li>
+ * </ul>
+ *
+ * @author mkovtun
+ * @author Christopher Oezbek <oezi at oezi.de>
+ *
+ */
+public class AuthorLastFirstAbbrOxfordCommas implements LayoutFormatter {
+
+ public String format(String fieldText) {
+ return AuthorList.fixAuthor_lastNameFirstCommas(fieldText, true, true);
+ }
+
+}
\ No newline at end of file
diff --git a/src/java/net/sf/jabref/export/layout/format/AuthorLastFirstAbbreviator.java b/src/java/net/sf/jabref/export/layout/format/AuthorLastFirstAbbreviator.java
index 32d3256..977324d 100644
--- a/src/java/net/sf/jabref/export/layout/format/AuthorLastFirstAbbreviator.java
+++ b/src/java/net/sf/jabref/export/layout/format/AuthorLastFirstAbbreviator.java
@@ -1,5 +1,6 @@
package net.sf.jabref.export.layout.format;
+import net.sf.jabref.AuthorList;
import net.sf.jabref.export.layout.LayoutFormatter;
/**
@@ -22,11 +23,13 @@ public class AuthorLastFirstAbbreviator implements LayoutFormatter {
* @see net.sf.jabref.export.layout.LayoutFormatter#format(java.lang.String)
*/
public String format(String fieldText) {
+
+ // return AuthorList.fixAuthor_lastNameFirst(fieldText, true);
+
try {
return getAbbreviations(fieldText.split(" and "));
} catch(Exception e){
return fieldText;
- //return "Author names must be formatted \"Last, First\" or \"Last, Jr., First\" before formatting with AuthorLastFirstAbbreviator";
}
}
@@ -41,9 +44,9 @@ public class AuthorLastFirstAbbreviator implements LayoutFormatter {
if (authors.length == 0)
return "";
- /*if (!isProperFormat(authors)) {
- return "Author names must be formatted \"Last, First\" or \"Last, Jr., First\" before formatting with AuthorLastFirstAbbreviator";
- }*/
+ if (!isProperFormat(authors)) {
+ throw new IllegalArgumentException("Author names must be formatted \"Last, First\" or \"Last, Jr., First\" before formatting with AuthorLastFirstAbbreviator");
+ }
for (int i = 0; i < authors.length; i++) {
authors[i] = getAbbreviation(authors[i]);
@@ -102,7 +105,7 @@ public class AuthorLastFirstAbbreviator implements LayoutFormatter {
break;
case 3:
last = parts[0].trim();
- // jr = author[1];
+ // jr = parts[1];
first = parts[2].trim();
break;
default:
@@ -117,6 +120,8 @@ public class AuthorLastFirstAbbreviator implements LayoutFormatter {
for (int i = 0; i < firstNames.length; i++) {
sb.append(firstNames[i].charAt(0));
sb.append('.');
+ if (i < firstNames.length - 1)
+ sb.append(' ');
}
return sb.toString();
}
diff --git a/src/java/net/sf/jabref/export/layout/format/AuthorLastFirstCommas.java b/src/java/net/sf/jabref/export/layout/format/AuthorLastFirstCommas.java
index b193818..d847888 100644
--- a/src/java/net/sf/jabref/export/layout/format/AuthorLastFirstCommas.java
+++ b/src/java/net/sf/jabref/export/layout/format/AuthorLastFirstCommas.java
@@ -1,26 +1,47 @@
/*
- * AuthorLastFirstCommas.java
+ * Copyright (C) 2005-2006 Jabref-Team
+ *
+ * All programs in this directory and subdirectories are published under the GNU
+ * General Public License as described below.
*
- * Created on September 7, 2005, 1:17 PM
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Further information about the GNU GPL is available at:
+ * http://www.gnu.org/copyleft/gpl.ja.html
*
- * To change this template, choose Tools | Options and locate the template under
- * the Source Creation and Management node. Right-click the template and choose
- * Open. You can then make changes to the template in the Source Editor.
*/
-
package net.sf.jabref.export.layout.format;
import net.sf.jabref.export.layout.LayoutFormatter;
import net.sf.jabref.AuthorList;
/**
- *
+ * <ul>
+ * <li>Names are given in order: von last, jr, first.</li>
+ * <li>First names will NOT be abbreviated.</li>
+ * <li>Individual authors are separated by commas.</li>
+ * <li>There is no comma before the 'and' at the end of a list of three or more authors</li>
+ * </ul>
+ *
* @author mkovtun
+ * @author Christopher Oezbek <oezi at oezi.de>
+ *
*/
public class AuthorLastFirstCommas implements LayoutFormatter {
public String format(String fieldText) {
- return AuthorList.fixAuthor_lastNameFirstCommas(fieldText, false);
+ return AuthorList.fixAuthor_lastNameFirstCommas(fieldText, false, false);
}
-
}
\ No newline at end of file
diff --git a/src/java/net/sf/jabref/export/layout/format/AuthorLastFirstOxfordCommas.java b/src/java/net/sf/jabref/export/layout/format/AuthorLastFirstOxfordCommas.java
new file mode 100644
index 0000000..cf11cdc
--- /dev/null
+++ b/src/java/net/sf/jabref/export/layout/format/AuthorLastFirstOxfordCommas.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2005-2006 Jabref-Team
+ *
+ * All programs in this directory and subdirectories are published under the GNU
+ * General Public License as described below.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Further information about the GNU GPL is available at:
+ * http://www.gnu.org/copyleft/gpl.ja.html
+ *
+ */
+package net.sf.jabref.export.layout.format;
+
+import net.sf.jabref.export.layout.LayoutFormatter;
+import net.sf.jabref.AuthorList;
+
+/**
+ * <ul>
+ * <li>Names are given in order: von last, jr, first.</li>
+ * <li>First names will NOT be abbreviated.</li>
+ * <li>Individual authors are separated by commas.</li>
+ * <li>The 'and' of a list of three or more authors is preceeded by a comma
+ * (Oxford comma)</li>
+ *
+ * @author mkovtun
+ * @author Christopher Oezbek <oezi at oezi.de>
+ *
+ */
+public class AuthorLastFirstOxfordCommas implements LayoutFormatter {
+
+ public String format(String fieldText) {
+ return AuthorList.fixAuthor_lastNameFirstCommas(fieldText, false, true);
+ }
+}
\ No newline at end of file
diff --git a/src/java/net/sf/jabref/export/layout/format/AuthorOrgSci.java b/src/java/net/sf/jabref/export/layout/format/AuthorOrgSci.java
new file mode 100644
index 0000000..21f2ef2
--- /dev/null
+++ b/src/java/net/sf/jabref/export/layout/format/AuthorOrgSci.java
@@ -0,0 +1,42 @@
+package net.sf.jabref.export.layout.format;
+
+import net.sf.jabref.AuthorList;
+import net.sf.jabref.AuthorList.Author;
+import net.sf.jabref.export.layout.LayoutFormatter;
+
+/**
+ * Will return the Authors to match the OrgSci format:
+ *
+ * <ul>
+ * <li>That is the first author is LastFirst, but all others are FirstLast.</li>
+ * <li>First names are abbreviated</li>
+ * <li>Spaces between abbreviated first names are NOT removed. Use
+ * NoSpaceBetweenAbbreviations to achieve this.</li>
+ * </ul>
+ * <p>
+ * See the testcase for examples.
+ * </p>
+ * <p>
+ * Idea from: http://stuermer.ch/blog/bibliography-reference-management-with-jabref.html
+ * </p>
+ *
+ * @author $Author: coezbek $
+ * @version $Revision: 1.1 $ ($Date: 2006/09/03 15:19:08 $)
+ *
+ */
+public class AuthorOrgSci implements LayoutFormatter {
+
+ public String format(String fieldText) {
+ AuthorList a = AuthorList.getAuthorList(fieldText);
+ if (a.size() == 0) {
+ return fieldText;
+ }
+ Author first = a.getAuthor(0);
+ StringBuffer sb = new StringBuffer();
+ sb.append(first.getLastFirst(true));
+ for (int i = 1; i < a.size(); i++) {
+ sb.append(", ").append(a.getAuthor(i).getFirstLast(true));
+ }
+ return sb.toString();
+ }
+}
diff --git a/src/java/net/sf/jabref/export/layout/format/CompositeFormat.java b/src/java/net/sf/jabref/export/layout/format/CompositeFormat.java
new file mode 100644
index 0000000..b39570f
--- /dev/null
+++ b/src/java/net/sf/jabref/export/layout/format/CompositeFormat.java
@@ -0,0 +1,41 @@
+package net.sf.jabref.export.layout.format;
+
+import net.sf.jabref.export.layout.LayoutFormatter;
+
+/**
+ * A layout formatter that is the composite of the given Formatters executed in
+ * order.
+ *
+ * @author $Author: coezbek $
+ * @version $Revision: 1.1 $ ($Date: 2006/09/03 15:19:08 $)
+ *
+ */
+public class CompositeFormat implements LayoutFormatter {
+
+ LayoutFormatter[] formatters;
+
+ /**
+ * If called with this constructor, this formatter does nothing.
+ */
+ public CompositeFormat() {
+ // Nothing
+ }
+
+ public CompositeFormat(LayoutFormatter first, LayoutFormatter second) {
+ formatters = new LayoutFormatter[] { first, second };
+ }
+
+ public CompositeFormat(LayoutFormatter[] formatters) {
+ this.formatters = formatters;
+ }
+
+ public String format(String fieldText) {
+ if (formatters != null) {
+ for (int i = 0; i < formatters.length; i++) {
+ fieldText = formatters[i].format(fieldText);
+ }
+ }
+ return fieldText;
+ }
+
+}
diff --git a/src/java/net/sf/jabref/export/layout/format/DOICheck.java b/src/java/net/sf/jabref/export/layout/format/DOICheck.java
new file mode 100644
index 0000000..a8ad56c
--- /dev/null
+++ b/src/java/net/sf/jabref/export/layout/format/DOICheck.java
@@ -0,0 +1,34 @@
+package net.sf.jabref.export.layout.format;
+
+import net.sf.jabref.export.layout.LayoutFormatter;
+
+/**
+ * Used to fix [ 1588028 ] export HTML table doi url.
+ *
+ * Will prepend "http://dx.doi.org/" if only doi number and not a URL is given.
+ *
+ * @author $Author: coezbek $
+ * @version $Revision: 1.1 $ ($Date: 2006/11/12 02:42:42 $)
+ *
+ */
+public class DOICheck implements LayoutFormatter {
+
+ public String format(String fieldText) {
+
+ if (fieldText == null){
+ return null;
+ }
+
+ fieldText = fieldText.trim();
+
+ if (fieldText.length() == 0){
+ return fieldText;
+ }
+
+ if (fieldText.startsWith("10")){
+ return "http://dx.doi.org/" + fieldText;
+ }
+
+ return fieldText;
+ }
+}
diff --git a/src/java/net/sf/jabref/export/layout/format/HTMLParagraphs.java b/src/java/net/sf/jabref/export/layout/format/HTMLParagraphs.java
new file mode 100644
index 0000000..24c2d3f
--- /dev/null
+++ b/src/java/net/sf/jabref/export/layout/format/HTMLParagraphs.java
@@ -0,0 +1,48 @@
+package net.sf.jabref.export.layout.format;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import net.sf.jabref.export.layout.LayoutFormatter;
+
+/**
+ * Will interpret two consecutive newlines as the start of a new paragraph and thus
+ * wrap the paragraph in HTML-p-tags.
+ *
+ * @author $Author: coezbek $
+ * @version $Revision: 1.1 $ ($Date: 2006/08/21 20:58:27 $)
+ *
+ */
+public class HTMLParagraphs implements LayoutFormatter {
+
+ static Pattern beforeNewLines;
+
+ public String format(String fieldText) {
+
+ fieldText = fieldText.trim();
+
+ if (fieldText.length() == 0){
+ return fieldText;
+ }
+
+ if (beforeNewLines == null) {
+ beforeNewLines = Pattern.compile("(.*?)\\n\\s*\\n");
+ }
+
+ Matcher m = beforeNewLines.matcher(fieldText);
+ StringBuffer s = new StringBuffer();
+ while (m.find()) {
+ String middle = m.group(1).trim();
+ if (middle.length() > 0){
+ s.append("<p>\n");
+ m.appendReplacement(s, m.group(1));
+ s.append("\n</p>\n");
+ }
+ }
+ s.append("<p>\n");
+ m.appendTail(s);
+ s.append("\n</p>");
+
+ return s.toString();
+ }
+}
diff --git a/src/java/net/sf/jabref/export/layout/format/NameFormat.java b/src/java/net/sf/jabref/export/layout/format/NameFormat.java
new file mode 100644
index 0000000..6a9f71c
--- /dev/null
+++ b/src/java/net/sf/jabref/export/layout/format/NameFormat.java
@@ -0,0 +1,151 @@
+package net.sf.jabref.export.layout.format;
+
+import net.sf.jabref.AuthorList;
+import net.sf.jabref.BibtexEntry;
+import net.sf.jabref.bst.BibtexNameFormatter;
+import net.sf.jabref.export.layout.LayoutFormatter;
+
+/**
+ * This layout formatter uses the Bibtex name.format$ method and provides ultimate flexibility:
+ *
+ * The formatter needs a parameter to be passed in that follows the following format:
+ *
+ * <case1>@<range11>@"<format>"@<range12>@"<format>"@<range13>...@@
+ *
+ * <case2>@<range21>@... and so on.
+ *
+ * Individual cases are separated by @@ and items in a case by @.
+ *
+ * Cases are just integers or the character * and will tell the formatter to apply the following formats if there are
+ * less or equal authors given to it. The cases must be in strict increasing order with the * in the last position.
+ *
+ * For instance:
+ *
+ * case1 = 2
+ * case2 = 3
+ * case3 = *
+ *
+ * Ranges are either <integer>..<integer>, <integer> or the character * using a 1 based index for indexing
+ * authors from the given authorlist. Integer indexes can be negative to denote them to start from
+ * the end of the list where -1 is the last author.
+ *
+ * For instance with an authorlist of "Joe Doe and Mary Jane and Bruce Bar and Arthur Kay":
+ *
+ * 1..3 will affect Joe, Mary and Bruce
+ *
+ * 4..4 will affect Arthur
+ *
+ * * will affect all of them
+ *
+ * 2..-1 will affect Mary, Bruce and Arthur
+ *
+ * The <format> uses the Bibtex formatter format:
+ *
+ * The four letter v, f, l, j indicate the name parts von, first, last, jr which
+ * are used within curly braces. A single letter v, f, l, j indicates that the name should be abbreviated.
+ * To put a quote in the format string quote it using \" (mh. this doesn't work yet)
+ *
+ * I give some examples but would rather point you to the bibtex documentation.
+ *
+ * "{ll}, {f}." Will turn "Joe Doe" into "Doe, J."
+ *
+ * Complete example:
+ *
+ * To turn:
+ *
+ * "Joe Doe and Mary Jane and Bruce Bar and Arthur Kay"
+ *
+ * into
+ *
+ * "Doe, J., Jane, M., Bar, B. and Kay, A."
+ *
+ * you would use
+ *
+ * 1@*@{ll}, {f}.@@2 at 1@{ll}, {f}. at 2@ and {ll}, {f}.@@*@1..-3@{ll}, {f}., @-2@{ll}, {f}. at -1@ and {ll}, {f}.
+ *
+ * Yeah this is trouble-some to write, but should work.
+ *
+ * For more examples see the test-cases.
+ *
+ * @author $Author: coezbek $
+ * @version $Revision: 1.1 $ ($Date: 2006/11/11 17:11:39 $)
+ *
+ */
+public class NameFormat implements LayoutFormatter {
+
+ public static final String DEFAULT_FORMAT = "1@*@{ff }{vv }{ll}{, jj}@@*@1@{ff }{vv }{ll}{, jj}@*@, {ff }{vv }{ll}{, jj}";
+
+ public String format(String toFormat, AuthorList al, String[] formats){
+
+ StringBuffer sb = new StringBuffer();
+
+ int n = al.size();
+
+ for (int i = 1; i <= al.size(); i++){
+ for (int j = 1; j < formats.length; j+=2){
+ if (formats[j].equals("*")){
+ sb.append(BibtexNameFormatter.formatName(toFormat, i, formats[j+1], null));
+ break;
+ } else {
+ String[] range = formats[j].split("\\.\\.");
+
+ int s,e;
+ if (range.length == 2){
+ s = Integer.parseInt(range[0]);
+ e = Integer.parseInt(range[1]);
+ } else {
+ s = e = Integer.parseInt(range[0]);
+ }
+ if (s < 0) s += n + 1;
+ if (e < 0) e += n + 1;
+ if (e < s) { int temp = e; e = s; s = temp; }
+
+ if (s <= i && i <= e){
+ sb.append(BibtexNameFormatter.formatName(toFormat, i, formats[j+1], null));
+ break;
+ }
+ }
+ }
+ }
+ return sb.toString();
+
+ }
+
+ public String format(String toFormat, String parameters, BibtexEntry currentEntry) {
+
+ AuthorList al = AuthorList.getAuthorList(toFormat);
+
+ if (parameters == null || parameters.length() == 0){
+ parameters = "*:*:\"{ff}{vv}{ll}{,jj} \"";
+ }
+
+ String[] cases = parameters.split("@@");
+ for (int i = 0; i < cases.length; i++){
+ String[] formatString = cases[i].split("@");
+
+ if (formatString.length < 3){
+ // Error
+ return toFormat;
+ }
+
+ if (formatString[0].equals("*")){
+ return format(toFormat, al, formatString);
+ } else {
+ if (al.size() <= Integer.parseInt(formatString[0])){
+ return format(toFormat, al, formatString);
+ }
+ }
+ }
+ return toFormat;
+ }
+
+ public String format(String fieldText) {
+ return format(fieldText, parameter, null);
+ }
+
+ String parameter = DEFAULT_FORMAT;
+
+ public void setParameter(String parameter) {
+ this.parameter = parameter;
+ }
+}
diff --git a/src/java/net/sf/jabref/export/layout/format/NoSpaceBetweenAbbreviations.java b/src/java/net/sf/jabref/export/layout/format/NoSpaceBetweenAbbreviations.java
new file mode 100644
index 0000000..fb3d23b
--- /dev/null
+++ b/src/java/net/sf/jabref/export/layout/format/NoSpaceBetweenAbbreviations.java
@@ -0,0 +1,37 @@
+package net.sf.jabref.export.layout.format;
+
+import net.sf.jabref.export.layout.LayoutFormatter;
+
+/**
+ * <p>
+ * LayoutFormatter that removes the space between abbreviated First names
+ * </p>
+ * <p>
+ * What out that this regular expression might also remove other spaces that fit
+ * the pattern.
+ * </p>
+ * <p>
+ * Example: J. R. R. Tolkien becomes J.R.R. Tolkien.
+ * </p>
+ * <p>
+ * See Testcase for more examples.
+ * <p>
+ *
+ * @author $Author: coezbek $
+ * @version $Revision: 1.1 $ ($Date: 2006/09/03 15:19:08 $)
+ *
+ */
+public class NoSpaceBetweenAbbreviations implements LayoutFormatter {
+
+ /*
+ * Match '.' followed by spaces followed by uppercase char followed by '.'
+ * but don't include the last dot into the capturing group.
+ *
+ * Replace the match by removing the spaces.
+ *
+ * @see net.sf.jabref.export.layout.LayoutFormatter#format(java.lang.String)
+ */
+ public String format(String fieldText) {
+ return fieldText.replaceAll("\\.\\s+(\\p{Lu})(?=\\.)", "\\.$1");
+ }
+}
diff --git a/src/java/net/sf/jabref/export/layout/format/RTFChars.java b/src/java/net/sf/jabref/export/layout/format/RTFChars.java
index 0b6d7b1..6b47cf9 100644
--- a/src/java/net/sf/jabref/export/layout/format/RTFChars.java
+++ b/src/java/net/sf/jabref/export/layout/format/RTFChars.java
@@ -3,139 +3,156 @@ package net.sf.jabref.export.layout.format;
import net.sf.jabref.export.layout.*;
import net.sf.jabref.Globals;
+/**
+ * Transform a LaTeX-String to RTF.
+ *
+ * This method will:
+ *
+ * 1.) Remove LaTeX-Command sequences.
+ *
+ * 2.) Replace LaTeX-Special chars with RTF aquivalents.
+ *
+ * 3.) Replace emph and textit and textbf with their RTF replacements.
+ *
+ * 4.) Take special care to save all unicode characters correctly.
+ *
+ * @author $Author: coezbek $
+ * @version $Revision: 1.6 $ ($Date: 2006/10/31 21:55:04 $)
+ *
+ */
public class RTFChars implements LayoutFormatter {
-
- public String format(String field) {
-
- int i;
- field = firstFormat(field);
- StringBuffer sb = new StringBuffer("");
- StringBuffer currentCommand = null;
- char c;
- boolean escaped = false, incommand = false;
- for (i=0; i<field.length(); i++) {
- c = field.charAt(i);
- if (escaped && (c == '\\')) {
- sb.append('\\');
- escaped = false;
- }
-
- else if (c == '\\') {
- escaped = true;
- incommand = true;
- currentCommand = new StringBuffer();
- }
- else if (!incommand && (c=='{' || c=='}')) {
- // Swallow the brace.
- }
- else if (Character.isLetter((char)c) ||
- (Globals.SPECIAL_COMMAND_CHARS.indexOf(""+(char)c) >= 0)) {
- escaped = false;
- if (!incommand)
- sb.append((char)c);
- // Else we are in a command, and should not keep the letter.
- else {
- currentCommand.append( (char) c);
-
- testCharCom: if ((currentCommand.length() == 1)
- && (Globals.SPECIAL_COMMAND_CHARS.indexOf(currentCommand.toString()) >= 0)) {
- // This indicates that we are in a command of the type \^o or \~{n}
- if (i >= field.length()-1)
- break testCharCom;
-
- String command = currentCommand.toString();
- i++;
- c = field.charAt(i);
- //System.out.println("next: "+(char)c);
- String combody;
- if (c == '{') {
- IntAndString part = getPart(field, i);
- i += part.i;
- combody = part.s;
- }
- else {
- combody = field.substring(i,i+1);
- //System.out.println("... "+combody);
- }
- //System.out.println(command+combody);
- Object result = Globals.RTFCHARS.get(command+combody);
-
- if (result != null)
- sb.append((String)result);
-
- incommand = false;
- escaped = false;
-
- }
-
- }
-
- }
- else {
- //if (!incommand || ((c!='{') && !Character.isWhitespace(c)))
- testContent: if (!incommand || (!Character.isWhitespace(c) && (c != '{')))
- sb.append((char)c);
- else {
- // First test if we are already at the end of the string.
- if (i >= field.length()-1)
- break testContent;
-
- if (c == '{') {
-
- String command = currentCommand.toString();
- // Then test if we are dealing with a italics or bold command. If so, handle.
- if (command.equals("emph") || command.equals("textit")) {
- IntAndString part = getPart(field, i);
- i += part.i;
- sb.append("}{\\i ").append(part.s).append("}{");
- }
- else if (command.equals("textbf")) {
- IntAndString part = getPart(field, i);
- i += part.i;
- sb.append("}{\\b ").append(part.s).append("}{");
- }
- } else
- sb.append((char)c);
-
- }
- incommand = false;
- escaped = false;
- }
- }
-
- return sb.toString();
- //field.replaceAll("\\\\emph", "").replaceAll("\\\\em", "").replaceAll("\\\\textbf", "");
- }
-
- private String firstFormat(String s) {
- return s;//s.replaceAll("&|\\\\&","&");//.replaceAll("--", "—");
- }
-
- private IntAndString getPart(String text, int i) {
- char c;
- int count = 0;//, i=index;
- StringBuffer part = new StringBuffer();
- while ((count >= 0) && (i < text.length())) {
- i++;
- c = text.charAt(i);
- if (c == '}')
- count--;
- else if (c == '{')
- count++;
-
- part.append((char)c);
- }
- //System.out.println("part: "+part.toString()+"\nformatted: "+format(part.toString()));
- return new IntAndString(part.length(), format(part.toString()));
- }
-
- private class IntAndString{
- public int i;
- String s;
- public IntAndString(int i, String s) {
- this.i = i;
- this.s = s;
- }
- }
+ public String format(String field) {
+
+ StringBuffer sb = new StringBuffer("");
+ StringBuffer currentCommand = null;
+ boolean escaped = false, incommand = false;
+ for (int i = 0; i < field.length(); i++) {
+ char c = field.charAt(i);
+ if (escaped && (c == '\\')) {
+ sb.append('\\');
+ escaped = false;
+ }
+
+ else if (c == '\\') {
+ escaped = true;
+ incommand = true;
+ currentCommand = new StringBuffer();
+ } else if (!incommand && (c == '{' || c == '}')) {
+ // Swallow the brace.
+ } else if (Character.isLetter((char) c)
+ || (Globals.SPECIAL_COMMAND_CHARS.indexOf("" + (char) c) >= 0)) {
+ escaped = false;
+ if (!incommand){
+ sb.append((char) c);
+ } else {
+ // Else we are in a command, and should not keep the letter.
+ currentCommand.append((char) c);
+
+ testCharCom: if ((currentCommand.length() == 1)
+ && (Globals.SPECIAL_COMMAND_CHARS.indexOf(currentCommand.toString()) >= 0)) {
+ // This indicates that we are in a command of the type
+ // \^o or \~{n}
+ if (i >= field.length() - 1)
+ break testCharCom;
+
+ String command = currentCommand.toString();
+ i++;
+ c = field.charAt(i);
+ String combody;
+ if (c == '{') {
+ IntAndString part = getPart(field, i);
+ i += part.i;
+ combody = part.s;
+ } else {
+ combody = field.substring(i, i + 1);
+ }
+ String result = (String)Globals.RTFCHARS.get(command + combody);
+
+ if (result != null)
+ sb.append(result);
+
+ incommand = false;
+ escaped = false;
+
+ }
+
+ }
+
+ } else {
+ // if (!incommand || ((c!='{') && !Character.isWhitespace(c)))
+ testContent: if (!incommand || (!Character.isWhitespace(c) && (c != '{')))
+ sb.append((char) c);
+ else {
+ // First test if we are already at the end of the string.
+ if (i >= field.length() - 1)
+ break testContent;
+
+ if (c == '{') {
+
+ String command = currentCommand.toString();
+ // Then test if we are dealing with a italics or bold
+ // command. If so, handle.
+ if (command.equals("emph") || command.equals("textit")) {
+ IntAndString part = getPart(field, i);
+ i += part.i;
+ sb.append("}{\\i ").append(part.s).append("}{");
+ } else if (command.equals("textbf")) {
+ IntAndString part = getPart(field, i);
+ i += part.i;
+ sb.append("}{\\b ").append(part.s).append("}{");
+ }
+ } else
+ sb.append((char) c);
+
+ }
+ incommand = false;
+ escaped = false;
+ }
+ }
+
+ char[] chars = sb.toString().toCharArray();
+ sb = new StringBuffer();
+
+ for (int i = 0; i < chars.length; i++) {
+ char c = chars[i];
+
+ if (c < 128)
+ sb.append(c);
+ else
+ sb.append("\\u").append((long) c).append('?');
+ }
+
+ return sb.toString();
+ }
+
+ private IntAndString getPart(String text, int i) {
+ char c;
+ int count = 0;// , i=index;
+ StringBuffer part = new StringBuffer();
+ while ((count >= 0) && (i < text.length())) {
+ i++;
+ c = text.charAt(i);
+ if (c == '}')
+ count--;
+ else if (c == '{')
+ count++;
+
+ part.append((char) c);
+ }
+ // System.out.println("part: "+part.toString()+"\nformatted:
+ // "+format(part.toString()));
+ return new IntAndString(part.length(), format(part.toString()));
+ }
+
+ private class IntAndString {
+ public int i;
+
+ String s;
+
+ public IntAndString(int i, String s) {
+ this.i = i;
+ this.s = s;
+ }
+ }
}
diff --git a/src/java/net/sf/jabref/export/layout/format/ResolvePDF.java b/src/java/net/sf/jabref/export/layout/format/ResolvePDF.java
index 59fc3d8..d03f3d3 100644
--- a/src/java/net/sf/jabref/export/layout/format/ResolvePDF.java
+++ b/src/java/net/sf/jabref/export/layout/format/ResolvePDF.java
@@ -1,16 +1,35 @@
package net.sf.jabref.export.layout.format;
-import net.sf.jabref.export.layout.*;
-import net.sf.jabref.Util;
-import net.sf.jabref.Globals;
import java.io.File;
+import net.sf.jabref.Globals;
+import net.sf.jabref.Util;
+import net.sf.jabref.export.layout.LayoutFormatter;
+
+/**
+ * Will expand the relative PDF path and return a URI for the given file (which
+ * must exist).
+ *
+ * TODO Search also relative to Bib-file.
+ *
+ * @author $Author: coezbek $
+ * @version $Revision: 1.5 $ ($Date: 2006/08/27 21:04:28 $)
+ */
public class ResolvePDF implements LayoutFormatter {
- public String format(String field) {
- String dir = Globals.prefs.get("pdfDirectory");
- //Util.pr(""+field);
- File f = Util.expandFilename(field, dir);
- return (f != null ? "file://"+f.getPath() : field);
- }
+ public String format(String field) {
+ String dir = Globals.prefs.get("pdfDirectory");
+ File f = Util.expandFilename(field, new String[] { dir, "." });
+
+ /*
+ * Stumbled over this while investigating
+ *
+ * https://sourceforge.net/tracker/index.php?func=detail&aid=1469903&group_id=92314&atid=600306
+ */
+ if (f != null){
+ return f.toURI().toString();
+ } else {
+ return field;
+ }
+ }
}
diff --git a/src/java/net/sf/jabref/export/layout/format/ToLowerCase.java b/src/java/net/sf/jabref/export/layout/format/ToLowerCase.java
index 0e26f82..9fd9583 100755
--- a/src/java/net/sf/jabref/export/layout/format/ToLowerCase.java
+++ b/src/java/net/sf/jabref/export/layout/format/ToLowerCase.java
@@ -4,9 +4,9 @@
// Language: Java
// Compiler: JDK 1.4
// Authors: Egon Willighagen
-// Version: $Revision: 1.3 $
-// $Date: 2006/05/23 21:25:49 $
-// $Author: mortenalver $
+// Version: $Revision: 1.4 $
+// $Date: 2006/11/11 17:11:39 $
+// $Author: coezbek $
//
// Copyright (c) Egon Willighagen
//
@@ -24,22 +24,15 @@ package net.sf.jabref.export.layout.format;
import net.sf.jabref.export.layout.LayoutFormatter;
-
/**
* Remove brackets formatter.
- *
+ *
* @author $author$
- * @version $Revision: 1.3 $
+ * @version $Revision: 1.4 $
*/
-public class ToLowerCase implements LayoutFormatter
-{
- //~ Methods ////////////////////////////////////////////////////////////////
+public class ToLowerCase implements LayoutFormatter {
- public String format(String fieldText)
- {
- return fieldText.toLowerCase();
- }
+ public String format(String fieldText) {
+ return fieldText.toLowerCase();
+ }
}
-///////////////////////////////////////////////////////////////////////////////
-// END OF FILE.
-///////////////////////////////////////////////////////////////////////////////
diff --git a/src/java/net/sf/jabref/external/AutoSetExternalFileForEntries.java b/src/java/net/sf/jabref/external/AutoSetExternalFileForEntries.java
index 72c2c2a..ca81823 100644
--- a/src/java/net/sf/jabref/external/AutoSetExternalFileForEntries.java
+++ b/src/java/net/sf/jabref/external/AutoSetExternalFileForEntries.java
@@ -44,9 +44,8 @@ public class AutoSetExternalFileForEntries extends AbstractWorker {
public void init() {
// Get all entries, and make sure there are selected entries:
- panel.database().getEntries();
- sel = (BibtexEntry[])panel.database().getEntries().toArray(new BibtexEntry[0]);
- if (sel.length < 1) {
+ sel = panel.getSelectedEntries();
+ if (sel.length < 1) {
goOn = false;
return;
}
@@ -69,8 +68,10 @@ public class AutoSetExternalFileForEntries extends AbstractWorker {
public void run() {
- if (!goOn)
+ if (!goOn){
+ panel.output(Globals.lang("No entries selected."));
return;
+ }
skipped=0;
entriesChanged=0;
@@ -120,7 +121,7 @@ public class AutoSetExternalFileForEntries extends AbstractWorker {
// Check if a link is set:
if ((old != null) && !((String)old).equals("")) {
// Get an absolute path representation:
- File file = Util.expandFilename((String)old, dir);
+ File file = Util.expandFilename((String)old, new String[]{dir, "."});;
if ((file == null) || !file.exists()) {
diff --git a/src/java/net/sf/jabref/external/DroppedFileHandler.java b/src/java/net/sf/jabref/external/DroppedFileHandler.java
new file mode 100644
index 0000000..dd01e1f
--- /dev/null
+++ b/src/java/net/sf/jabref/external/DroppedFileHandler.java
@@ -0,0 +1,411 @@
+package net.sf.jabref.external;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.swing.ButtonGroup;
+import javax.swing.JCheckBox;
+import javax.swing.JLabel;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JRadioButton;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+
+import net.sf.jabref.BasePanel;
+import net.sf.jabref.BibtexEntry;
+import net.sf.jabref.Globals;
+import net.sf.jabref.JabRefFrame;
+import net.sf.jabref.KeyCollisionException;
+import net.sf.jabref.Util;
+import net.sf.jabref.gui.MainTable;
+import net.sf.jabref.undo.NamedCompound;
+import net.sf.jabref.undo.UndoableFieldChange;
+import net.sf.jabref.util.XMPUtil;
+
+import com.jgoodies.forms.builder.DefaultFormBuilder;
+import com.jgoodies.forms.layout.FormLayout;
+
+/**
+ * This class holds the functionality of autolinking to a file that's dropped
+ * onto an entry.
+ *
+ * Options for handling the files are: 1) Link to the file in its current
+ * position (disabled if the file is remote) 2) Copy the file to ??? directory,
+ * rename after bibtex key, and link 3) Move the file to ??? directory, rename
+ * after bibtex key, and link
+ */
+public class DroppedFileHandler {
+ private JabRefFrame frame;
+
+ private BasePanel panel;
+
+ private JRadioButton linkInPlace = new JRadioButton(), copyRadioButton = new JRadioButton(),
+ moveRadioButton = new JRadioButton();
+
+ private JLabel destDirLabel = new JLabel();
+
+ private JCheckBox renameCheckBox = new JCheckBox();
+
+ private JPanel optionsPanel = new JPanel();
+
+ private JPanel importAsNewPanel = new JPanel();
+
+ public DroppedFileHandler(JabRefFrame frame, BasePanel panel) {
+
+ this.frame = frame;
+ this.panel = panel;
+
+ ButtonGroup grp = new ButtonGroup();
+ grp.add(linkInPlace);
+ grp.add(copyRadioButton);
+ grp.add(moveRadioButton);
+ copyRadioButton.setSelected(true);
+
+ DefaultFormBuilder builder = new DefaultFormBuilder(optionsPanel, new FormLayout(
+ "left:pref", ""));
+ builder.append(linkInPlace);
+ builder.append(destDirLabel);
+ builder.append(copyRadioButton);
+ builder.append(moveRadioButton);
+ builder.append(renameCheckBox);
+ }
+
+ /**
+ * Offer copy/move/linking options for a dragged external file. Perform the
+ * chosen operation, if any.
+ *
+ * @param fileName
+ * The name of the dragged file.
+ * @param fileType
+ * The FileType associated with the file.
+ * @param localFile
+ * Indicate whether this is a local file, or a remote file copied
+ * to a local temporary file.
+ * @param mainTable
+ * The MainTable the file was dragged to.
+ * @param dropRow
+ * The row where the file was dropped.
+ */
+ public void handleDroppedfile(String fileName, ExternalFileType fileType, boolean localFile,
+ MainTable mainTable, int dropRow) {
+
+ NamedCompound edits = new NamedCompound(Globals.lang("Drop %0", fileType.extension));
+
+ if (tryXmpImport(fileName, fileType, localFile, mainTable, edits)) {
+ panel.undoManager.addEdit(edits);
+ return;
+ }
+
+ BibtexEntry entry = mainTable.getEntryAt(dropRow);
+
+ // Show dialog
+ boolean newEntry = false;
+ boolean rename = entry.getCiteKey() != null && entry.getCiteKey().length() > 0;
+ String citeKeyOrReason = (rename ? entry.getCiteKey() : "Entry has no citekey");
+ int reply = showLinkMoveCopyRenameDialog(Globals.lang("Link to file %0", fileName),
+ fileType, rename, citeKeyOrReason, newEntry, false);
+
+ if (reply != JOptionPane.OK_OPTION)
+ return;
+
+ /*
+ * Ok, we're ready to go. See first if we need to do a file copy before
+ * linking:
+ */
+ boolean success = true;
+ String destFilename;
+
+ if (linkInPlace.isSelected()) {
+ destFilename = fileName;
+ } else {
+ destFilename = (renameCheckBox.isSelected() ? entry.getCiteKey() + "." + fileType.extension : fileName);
+ if (copyRadioButton.isSelected()) {
+ success = doCopy(fileName, fileType, destFilename, edits);
+ } else if (moveRadioButton.isSelected()) {
+ success = doRename(fileName, fileType, destFilename, edits);
+ }
+ }
+
+ if (success) {
+ doLink(entry, fileType, destFilename, edits);
+ panel.markBaseChanged();
+ }
+
+ panel.undoManager.addEdit(edits);
+
+ }
+
+ private boolean tryXmpImport(String fileName, ExternalFileType fileType, boolean localFile,
+ MainTable mainTable, NamedCompound edits) {
+
+ if (!fileType.extension.equals("pdf")) {
+ return false;
+ }
+
+ List l = null;
+ try {
+ l = XMPUtil.readXMP(fileName);
+ } catch (Exception e) {
+ return false;
+ }
+
+ if ((l == null) || (l.size() == 0)) {
+ return false;
+ }
+
+ JLabel confirmationMessage = new JLabel(
+ Globals
+ .lang("The PDF contains one or several bibtex-records.\nDo you want to import these as new entries into the current database database?"));
+
+ int reply = JOptionPane.showConfirmDialog(frame, confirmationMessage, Globals.lang(
+ "XMP metadata found in PDF: %0", fileName), JOptionPane.YES_NO_CANCEL_OPTION,
+ JOptionPane.QUESTION_MESSAGE);
+
+ if (reply == JOptionPane.CANCEL_OPTION) {
+ return true; // The user canceled thus that we are done.
+ }
+ if (reply == JOptionPane.NO_OPTION) {
+ return false;
+ }
+
+ // reply == JOptionPane.YES_OPTION)
+
+ /*
+ * TODO Extract Import functionality from ImportMenuItem then we could
+ * do:
+ *
+ * ImportMenuItem importer = new ImportMenuItem(frame, (mainTable ==
+ * null), new PdfXmpImporter());
+ *
+ * importer.automatedImport(new String[] { fileName });
+ */
+
+ boolean isSingle = l.size() == 1;
+ BibtexEntry single = (isSingle ? (BibtexEntry) l.get(0) : null);
+
+ reply = showLinkMoveCopyRenameDialog(Globals.lang("Link to PDF %0", fileName), fileType,
+ isSingle, (isSingle ? single.getCiteKey() : "Cannot rename for several entries."),
+ false, !isSingle);
+
+ boolean success = true;
+
+ String destFilename;
+
+ if (linkInPlace.isSelected()) {
+ destFilename = fileName;
+ } else {
+ if (renameCheckBox.isSelected()) {
+ destFilename = fileName;
+ } else {
+ destFilename = single.getCiteKey() + "." + fileType.extension;
+ }
+
+ if (copyRadioButton.isSelected()) {
+ success = doCopy(fileName, fileType, destFilename, edits);
+ } else if (moveRadioButton.isSelected()) {
+ success = doRename(fileName, fileType, destFilename, edits);
+ }
+ }
+ if (success) {
+
+ Iterator it = l.iterator();
+
+ while (it.hasNext()) {
+ try {
+ BibtexEntry entry = (BibtexEntry) it.next();
+ entry.setId(Util.createNeutralId());
+ panel.getDatabase().insertEntry(entry);
+ doLink(entry, fileType, destFilename, edits);
+ } catch (KeyCollisionException ex) {
+
+ }
+ }
+ panel.markBaseChanged();
+ panel.updateEntryEditorIfShowing();
+ }
+ return true;
+ }
+
+ public int showLinkMoveCopyRenameDialog(String dialogTitle, ExternalFileType fileType,
+ final boolean allowRename, String citekeyOrReason, boolean newEntry,
+ final boolean multipleEntries) {
+
+ String dir = panel.metaData().getFileDirectory(fileType.getFieldName());
+ if ((dir == null) || !(new File(dir)).exists()) {
+ destDirLabel.setText(Globals.lang("%0 directory is not set or does not exist!", fileType.getName()));
+ copyRadioButton.setEnabled(false);
+ moveRadioButton.setEnabled(false);
+ linkInPlace.setSelected(true);
+ } else {
+ destDirLabel.setText(Globals.lang("%0 directory is '%1':", fileType.getName(), dir));
+ copyRadioButton.setEnabled(true);
+ moveRadioButton.setEnabled(true);
+ }
+
+ ChangeListener cl = new ChangeListener() {
+ public void stateChanged(ChangeEvent arg0) {
+ renameCheckBox.setEnabled(!linkInPlace.isSelected() && allowRename
+ && (!multipleEntries));
+ }
+ };
+
+ if (newEntry) {
+ if (multipleEntries) {
+ linkInPlace.setText(Globals.lang("Link from new entries."));
+
+ copyRadioButton.setText(Globals.lang(
+ "Copy to %0 directory and link from new entries.", fileType.getName()));
+ moveRadioButton.setText(Globals.lang(
+ "Move to %0 directory and link from new entries.", fileType.getName()));
+ } else {
+ linkInPlace.setText(Globals.lang("Link from new entry"));
+
+ copyRadioButton.setText(Globals.lang(
+ "Copy to %0 directory and link from new entry.", fileType.getName()));
+ moveRadioButton.setText(Globals.lang(
+ "Move to %0 directory and link from new entry.", fileType.getName()));
+ }
+ } else {
+ if (multipleEntries) {
+ linkInPlace.setText(Globals.lang("Link from entries."));
+
+ copyRadioButton.setText(Globals.lang("Copy to %0 directory and link from entries.",
+ fileType.getName()));
+ moveRadioButton.setText(Globals.lang("Move to %0 directory and link from entries.",
+ fileType.getName()));
+ } else {
+ linkInPlace.setText(Globals.lang("Link from entry"));
+
+ copyRadioButton.setText(Globals.lang("Copy to %0 directory and link from entry.",
+ fileType.getName()));
+ moveRadioButton.setText(Globals.lang("Move to %0 directory and link from entry.",
+ fileType.getName()));
+
+ }
+
+ }
+
+ renameCheckBox.setText("Rename to match citekey: " + citekeyOrReason);
+ linkInPlace.addChangeListener(cl);
+ cl.stateChanged(new ChangeEvent(linkInPlace));
+
+ try {
+ return JOptionPane.showConfirmDialog(frame, optionsPanel, dialogTitle,
+ JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE);
+ } finally {
+ linkInPlace.removeChangeListener(cl);
+ }
+ }
+
+ /**
+ * Make a link to the file.
+ *
+ * @param entry
+ * The entry to link from.
+ * @param fileType
+ * The FileType associated with the file.
+ * @param filename
+ * The path to the file.
+ * @param edits
+ * An NamedCompound action this action is to be added to. If none
+ * is given, the edit is added to the panel's undoManager.
+ */
+ private void doLink(BibtexEntry entry, ExternalFileType fileType, String filename,
+ NamedCompound edits) {
+
+ UndoableFieldChange edit = new UndoableFieldChange(entry, fileType.getFieldName(), entry
+ .getField(fileType.getFieldName()), filename);
+ entry.setField(fileType.getFieldName(), filename);
+
+ if (edits == null) {
+ panel.undoManager.addEdit(edit);
+ } else {
+ edits.addEdit(edit);
+ }
+ }
+
+ /**
+ * Move the given file to the base directory for its file type, and rename
+ * it to the given filename.
+ *
+ * @param fileName
+ * The name of the source file.
+ * @param fileType
+ * The FileType associated with the file.
+ * @param destFilename
+ * The destination filename.
+ * @param edits
+ * TODO we should be able to undo this action
+ * @return true if the operation succeeded.
+ */
+ private boolean doRename(String fileName, ExternalFileType fileType, String destFilename,
+ NamedCompound edits) {
+ String dir = panel.metaData().getFileDirectory(fileType.getFieldName());
+ if ((dir == null) || !(new File(dir)).exists()) {
+ // OOps, we don't know which directory to put it in, or the given
+ // dir doesn't exist....
+ // This should not happen!!
+ return false;
+ }
+ destFilename = new File(destFilename).getName();
+ File f = new File(fileName);
+ File destFile = new File(new StringBuffer(dir).append(System.getProperty("file.separator"))
+ .append(destFilename).toString());
+ f.renameTo(destFile);
+ return true;
+ }
+
+ /**
+ * Copy the given file to the base directory for its file type, and give it
+ * the given name.
+ *
+ * @param fileName
+ * The name of the source file.
+ * @param fileType
+ * The FileType associated with the file.
+ * @param toFile
+ * The destination filename. An existing path-component will be removed.
+ * @param edits
+ * TODO we should be able to undo this!
+ * @return
+ */
+ private boolean doCopy(String fileName, ExternalFileType fileType, String toFile,
+ NamedCompound edits) {
+
+ String dir = panel.metaData().getFileDirectory(fileType.getFieldName());
+ if ((dir == null) || !(new File(dir)).exists()) {
+ // OOps, we don't know which directory to put it in, or the given
+ // dir doesn't exist....
+ System.out.println("dir: " + dir + "\t ext: " + fileType.getExtension());
+ return false;
+ }
+ toFile = new File(toFile).getName();
+
+ File destFile = new File(new StringBuffer(dir).append(System.getProperty("file.separator"))
+ .append(toFile).toString());
+ if (destFile.equals(new File(fileName))){
+ // File is already in the correct position. Don't override!
+ return true;
+ }
+
+ if (destFile.exists()) {
+ int answer = JOptionPane.showConfirmDialog(frame, "'" + destFile.getPath() + "' "
+ + Globals.lang("exists.Overwrite?"), Globals.lang("File exists"),
+ JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
+ if (answer == JOptionPane.NO_OPTION)
+ return false;
+ }
+ try {
+ Util.copyFile(new File(fileName), destFile, true);
+ } catch (IOException e) {
+ e.printStackTrace();
+ return false;
+ }
+
+ return true;
+ }
+
+}
diff --git a/src/java/net/sf/jabref/external/ExternalFilePanel.java b/src/java/net/sf/jabref/external/ExternalFilePanel.java
index fc6d0df..1c30a49 100644
--- a/src/java/net/sf/jabref/external/ExternalFilePanel.java
+++ b/src/java/net/sf/jabref/external/ExternalFilePanel.java
@@ -1,305 +1,436 @@
package net.sf.jabref.external;
-import net.sf.jabref.*;
-import net.sf.jabref.net.URLDownload;
-
-import javax.swing.*;
+import java.awt.Component;
+import java.awt.GridLayout;
+import java.awt.dnd.DnDConstants;
+import java.awt.dnd.DropTarget;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
-import java.awt.*;
-import java.awt.dnd.DropTarget;
-import java.awt.dnd.DnDConstants;
import java.io.File;
import java.io.IOException;
-import java.net.URL;
import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.LinkedList;
+
+import javax.swing.JButton;
+import javax.swing.JComponent;
+import javax.swing.JFileChooser;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.SwingUtilities;
+import javax.xml.transform.TransformerException;
+
+import net.sf.jabref.BibtexEntry;
+import net.sf.jabref.BibtexFields;
+import net.sf.jabref.EntryEditor;
+import net.sf.jabref.FieldEditor;
+import net.sf.jabref.Globals;
+import net.sf.jabref.JabRefFrame;
+import net.sf.jabref.MetaData;
+import net.sf.jabref.OpenFileFilter;
+import net.sf.jabref.UrlDragDrop;
+import net.sf.jabref.Util;
+import net.sf.jabref.net.URLDownload;
+import net.sf.jabref.util.XMPUtil;
/**
- * Created by IntelliJ IDEA.
- * User: alver
- * Date: May 7, 2005
- * Time: 7:17:42 PM
- * To change this template use File | Settings | File Templates.
+ * Initial Version:
+ *
+ * @author alver
+ * @version Date: May 7, 2005 Time: 7:17:42 PM
+ *
+ * Current Version:
+ *
+ * @author $Author: coezbek $
+ * @version $Revision: 1.19 $ ($Date: 2006/09/01 20:59:39 $)
+ *
*/
public class ExternalFilePanel extends JPanel {
- private JButton browseBut, download, auto;
- private EntryEditor entryEditor;
- private JabRefFrame frame;
- private OpenFileFilter off;
- private BibtexEntry entry = null;
- private MetaData metaData;
-
- public ExternalFilePanel(final String fieldName, final MetaData metaData,
- final BibtexEntry entry, final OpenFileFilter off) {
- this(null, metaData, null, fieldName, off, null);
- this.entry = entry;
- }
-
- public ExternalFilePanel(final JabRefFrame frame, final MetaData metaData,
- final EntryEditor entryEditor,
- final String fieldName, final OpenFileFilter off, final FieldEditor editor) {
-
- this.frame = frame;
- this.metaData = metaData;
- this.off = off;
- this.entryEditor = entryEditor;
-
- setLayout(new GridLayout(2, 1));
-
- browseBut = new JButton(Globals.lang("Browse"));
- download = new JButton(Globals.lang("Download"));
- auto = new JButton(Globals.lang("Auto"));
- //((JComponent) editor).addMouseListener(new EntryEditor.ExternalViewerListener());
-
- browseBut.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- browseFile(fieldName, editor);
- //editor.setText(chosenValue);
- entryEditor.storeFieldAction.actionPerformed(new ActionEvent(editor, 0, ""));
- }
- });
- download.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- downLoadFile(fieldName, editor, frame);
- }
- });
-
- auto.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- autoSetFile(fieldName, editor);
- }
- });
-
- JPanel pan = new JPanel();
- pan.setLayout(new GridLayout(1,2));
- add(browseBut);
- pan.add(auto);
- pan.add(download);
- add(pan);
-
- // Add drag and drop support to the field
- if (editor != null)
- ((JComponent) editor).setDropTarget(new DropTarget((Component) editor,
- DnDConstants.ACTION_NONE, new UrlDragDrop(entryEditor, frame, editor)));
- }
-
- /**
- * Change which entry this panel is operating on. This is used only when this panel
- * is not attached to an entry editor.
- */
- public void setEntry(BibtexEntry entry) {
- this.entry = entry;
- }
-
- protected Object getKey() {
- return (entry != null ? entry.getField(BibtexFields.KEY_FIELD) :
- entryEditor.getEntry().getField(BibtexFields.KEY_FIELD));
- }
-
- protected void output(String s) {
- if (frame != null)
- frame.output(s);
- }
-
- public void browseFile(final String fieldName, final FieldEditor editor) {
-
- String directory = metaData.getFileDirectory(fieldName);
- if ((directory != null) && directory.equals(""))
- directory = null;
-
- String dir = editor.getText(), retVal = null;
-
- if ((directory == null) || !(new File(dir)).isAbsolute()) {
- if (directory != null)
- dir = directory;
- else
- dir = Globals.prefs.get(fieldName + Globals.FILETYPE_PREFS_EXT, "");
- }
-
- String chosenFile =
- Globals.getNewFile(frame, new File(dir), "."+fieldName,
- JFileChooser.OPEN_DIALOG, false);
-
- if (chosenFile != null) {
- File newFile = new File(chosenFile);
- String position = newFile.getParent();
-
- if ((directory != null) && position.startsWith(directory)) {
- // Construct path relative to pdf base dir
- String relPath =
- position.substring(directory.length(), position.length()) + File.separator
- + newFile.getName();
-
- // Remove leading path separator
- if (relPath.startsWith(File.separator)) {
- relPath = relPath.substring(File.separator.length(), relPath.length());
-
- // Set relative path as field value
- }
-
- retVal = relPath;
- } else
- retVal = newFile.getPath();
-
- editor.setText(retVal);
- Globals.prefs.put(fieldName + Globals.FILETYPE_PREFS_EXT, newFile.getPath());
- }
-
- }
-
-
- public void downLoadFile(final String fieldName,
- final FieldEditor editor, final Component parent) {
-
- String res = JOptionPane.showInputDialog(parent,
- Globals.lang("Enter URL to download"));
-
- if (res != null) {
- class Downloader extends Thread {
- String res;
- BibtexEntry targetEntry = null;
-
- public Downloader(String res) {
- this.res = res;
- // If this panel belongs in an entry editor, note which entry is
- // currently shown:
- if (entryEditor != null)
- targetEntry = entryEditor.getEntry();
- }
-
- public void run() {
- URL url;
- String textToSet = editor.getText();
- editor.setEnabled(false);
- boolean updateEditor = true;
- try {
- editor.setText(Globals.lang("Downloading..."));
- url = new URL(res);
-
- String suffix = off.getSuffix(res);
- if (suffix == null)
- suffix = "."+fieldName.toLowerCase();
-
- String plannedName = null;
- if (getKey() != null)
- plannedName = getKey() + suffix;
- else {
- plannedName = JOptionPane.showInputDialog(parent,
- Globals.lang("BibTeX key not set. Enter a name for the downloaded file"));
- if (plannedName == null)
- return;
-
- if (!off.accept(plannedName))
- plannedName += suffix;
- }
-
- // Find the default directory for this field type:
- String directory = metaData.getFileDirectory(fieldName);
- System.out.println(directory);
- File file = new File(new File(directory), plannedName);
-
- URLDownload udl = new URLDownload(parent, url, file);
- output(Globals.lang("Downloading..."));
-
- try {
- udl.download();
- } catch (IOException e2) {
- JOptionPane.showMessageDialog(parent, Globals.lang("Invalid URL: "+e2.getMessage()),
- Globals.lang("Download file"), JOptionPane.ERROR_MESSAGE);
- Globals.logger("Error while downloading " + url.toString());
- }
-
- // Check if we should update the editor text field, or update the
- // target entry directly:
- updateEditor = (entryEditor == null) ||
- (entryEditor.getEntry() == targetEntry);
- output(Globals.lang("Download completed"));
- String filename = file.getPath();
-
- if (filename.startsWith(directory)) {
- // Construct path relative to pdf base dir
- String relPath = filename.substring(directory.length(), filename.length());
-
- // Remove leading path separator
- if (relPath.startsWith(File.separator)) {
- relPath = relPath.substring(File.separator.length(), relPath.length());
- }
- filename = relPath;
- }
- textToSet = filename;
- if (updateEditor)
- SwingUtilities.invokeLater(new Thread() {
- public void run() {
- if (entryEditor != null)
- entryEditor.updateField(editor);
- }
- });
- else {
- // Editor has probably changed to show a different entry. So
- // we must update the target entry directly and not set the
- // text of the editor.
- targetEntry.setField(fieldName, textToSet);
- }
- } catch (MalformedURLException e1) {
- JOptionPane.showMessageDialog(parent, "Invalid URL: "+e1.getMessage(),
- "Download file", JOptionPane.ERROR_MESSAGE);
- } finally {
- if (updateEditor) {
- System.out.println("Juuu");
- editor.setText(textToSet);
- editor.setEnabled(true);
- }
- }
- }
- }
-
-
- (new Downloader(res)).start();
- }
- }
-
- /**
- * Starts a thread that searches the external file directory for the given field name,
- * including subdirectories, and looks for files named after the current entry's bibtex
- * key. Returns a reference to the thread for callers that may want to wait for the thread
- * to finish (using join()).
- *
- * @param fieldName The field to set.
- * @param editor An EntryEditor instance where to set the value found.
- * @return A reference to the Thread that performs the operation.
- */
- public Thread autoSetFile(final String fieldName, final FieldEditor editor) {
- Object o = getKey();
- if ((o == null) || (Globals.prefs.get(fieldName+"Directory") == null)) {
- output(Globals.lang("You must set both BibTeX key and %0 directory", fieldName.toUpperCase()) + ".");
- return null;
- }
- output(Globals.lang("Searching for %0 file", fieldName.toUpperCase()) + " '" + o +
- "."+fieldName+"'...");
- Thread t = (new Thread() {
- public void run() {
- Object o = getKey();
-
- // Find the default directory for this field type:
- String dir = metaData.getFileDirectory(fieldName);
-
- String found = Util.findPdf((String) o, fieldName, dir, off);
- if (found != null) {
- editor.setText(found);
- if (entryEditor != null)
- entryEditor.updateField(editor);
- output(Globals.lang("%0 field set", fieldName.toUpperCase()) + ".");
- } else {
- output(Globals.lang("No %0 found", fieldName.toUpperCase()) + ".");
- }
-
- }
- });
-
- t.start();
- return t;
-
- }
-
-}
+ private JButton browseBut, download, auto, xmp;
+
+ private EntryEditor entryEditor;
+
+ private JabRefFrame frame;
+
+ private OpenFileFilter off;
+
+ private BibtexEntry entry = null;
+
+ private MetaData metaData;
+
+ public ExternalFilePanel(final String fieldName, final MetaData metaData,
+ final BibtexEntry entry, final OpenFileFilter off) {
+ this(null, metaData, null, fieldName, off, null);
+ this.entry = entry;
+ }
+
+ public ExternalFilePanel(final JabRefFrame frame, final MetaData metaData,
+ final EntryEditor entryEditor, final String fieldName, final OpenFileFilter off,
+ final FieldEditor editor) {
+
+ this.frame = frame;
+ this.metaData = metaData;
+ this.off = off;
+ this.entryEditor = entryEditor;
+
+ setLayout(new GridLayout(2, 2));
+
+ browseBut = new JButton(Globals.lang("Browse"));
+ download = new JButton(Globals.lang("Download"));
+ auto = new JButton(Globals.lang("Auto"));
+ xmp = new JButton(Globals.lang("Write XMP"));
+ xmp.setToolTipText(Globals.lang("Write BibtexEntry as XMP-metadata to PDF."));
+
+ browseBut.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ browseFile(fieldName, editor);
+ // editor.setText(chosenValue);
+ entryEditor.storeFieldAction.actionPerformed(new ActionEvent(editor, 0, ""));
+ }
+ });
+
+ download.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ downLoadFile(fieldName, editor, frame);
+ }
+ });
+
+ auto.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ autoSetFile(fieldName, editor);
+ }
+ });
+ xmp.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ pushXMP(fieldName, editor);
+ }
+ });
+
+ add(browseBut);
+ add(download);
+ add(auto);
+ add(xmp);
+
+ // Add drag and drop support to the field
+ if (editor != null)
+ ((JComponent) editor).setDropTarget(new DropTarget((Component) editor,
+ DnDConstants.ACTION_NONE, new UrlDragDrop(entryEditor, frame, editor)));
+ }
+
+ /**
+ * Change which entry this panel is operating on. This is used only when
+ * this panel is not attached to an entry editor.
+ */
+ public void setEntry(BibtexEntry entry) {
+ this.entry = entry;
+ }
+
+ public BibtexEntry getEntry() {
+ return (entry != null ? entry : entryEditor.getEntry());
+ }
+
+ protected Object getKey() {
+ return getEntry().getField(BibtexFields.KEY_FIELD);
+ }
+
+ protected void output(String s) {
+ if (frame != null)
+ frame.output(s);
+ }
+
+ public void pushXMP(String fieldName, FieldEditor editor) {
+
+ // Find the default directory for this field type, if any:
+ String dir = metaData.getFileDirectory(fieldName);
+ File file = null;
+ if (dir != null) {
+ File tmp = Util.expandFilename(editor.getText(), new String[] { dir, "." });
+ if (tmp != null)
+ file = tmp;
+ }
+
+ if (file == null) {
+ file = new File(editor.getText());
+ }
+
+ if (file == null) {
+ output(Globals.lang("No file associated"));
+ }
+
+ try {
+ XMPUtil.writeXMP(file, getEntry());
+ output(Globals.lang("Wrote BibtexEntry as XMP to " + file.getName()));
+ } catch (IOException e) {
+ JOptionPane.showMessageDialog(editor.getParent(), Globals
+ .lang("Error writing XMP to file: " + e.getLocalizedMessage()), Globals
+ .lang("Writing XMP"), JOptionPane.ERROR_MESSAGE);
+ Globals.logger("Error while writing XMP " + file.getAbsolutePath());
+ } catch (TransformerException e) {
+ JOptionPane.showMessageDialog(editor.getParent(), Globals
+ .lang("Error converting Bibtex to XMP: " + e.getLocalizedMessage()), Globals
+ .lang("Writing XMP"), JOptionPane.ERROR_MESSAGE);
+ Globals.logger("Error while converting BibtexEntry to XMP " + file.getAbsolutePath());
+ }
+ }
+
+ public void browseFile(final String fieldName, final FieldEditor editor) {
+
+ String directory = metaData.getFileDirectory(fieldName);
+ if ((directory != null) && directory.equals(""))
+ directory = null;
+
+ String dir = editor.getText(), retVal = null;
+
+ if ((directory == null) || !(new File(dir)).isAbsolute()) {
+ if (directory != null)
+ dir = directory;
+ else
+ dir = Globals.prefs.get(fieldName + Globals.FILETYPE_PREFS_EXT, "");
+ }
+
+ String chosenFile = Globals.getNewFile(frame, new File(dir), "." + fieldName,
+ JFileChooser.OPEN_DIALOG, false);
+
+ if (chosenFile != null) {
+ File newFile = new File(chosenFile);
+ String position = newFile.getParent();
+
+ if ((directory != null) && position.startsWith(directory)) {
+ // Construct path relative to pdf base dir
+ String relPath = position.substring(directory.length(), position.length())
+ + File.separator + newFile.getName();
+
+ // Remove leading path separator
+ if (relPath.startsWith(File.separator)) {
+ relPath = relPath.substring(File.separator.length(), relPath.length());
+
+ // Set relative path as field value
+ }
+
+ retVal = relPath;
+ } else
+ retVal = newFile.getPath();
+
+ editor.setText(retVal);
+ Globals.prefs.put(fieldName + Globals.FILETYPE_PREFS_EXT, newFile.getPath());
+ }
+ }
+
+ public void downLoadFile(final String fieldName, final FieldEditor fieldEditor,
+ final Component parent) {
+
+ final String res = JOptionPane.showInputDialog(parent, Globals
+ .lang("Enter URL to download"));
+
+ if (res == null || res.trim().length() == 0)
+ return;
+
+ /*
+ * If this panel belongs in an entry editor, note which entry is
+ * currently shown:
+ */
+ final BibtexEntry targetEntry;
+ if (entryEditor != null)
+ targetEntry = entryEditor.getEntry();
+ else
+ targetEntry = null;
+
+ (new Thread() {
+
+ public String getPlannedFileName(String res) {
+ String suffix = off.getSuffix(res);
+ if (suffix == null)
+ suffix = "." + fieldName.toLowerCase();
+
+ String plannedName = null;
+ if (getKey() != null)
+ plannedName = getKey() + suffix;
+ else {
+ plannedName = JOptionPane.showInputDialog(parent, Globals
+ .lang("BibTeX key not set. Enter a name for the downloaded file"));
+ if (plannedName != null && !off.accept(plannedName))
+ plannedName += suffix;
+ }
+
+ /*
+ * [ 1548875 ] download pdf produces unsupported filename
+ *
+ * http://sourceforge.net/tracker/index.php?func=detail&aid=1548875&group_id=92314&atid=600306
+ *
+ */
+ if (Globals.ON_WIN) {
+ plannedName = plannedName.replaceAll(
+ "\\?|\\*|\\<|\\>|\\||\\\"|\\:|\\.$|\\[|\\]", "");
+ } else if (Globals.ON_MAC) {
+ plannedName = plannedName.replaceAll(":", "");
+ }
+
+ return plannedName;
+ }
+
+ public void run() {
+ String originalText = fieldEditor.getText();
+ fieldEditor.setEnabled(false);
+ boolean updateEditor = true;
+
+ try {
+ fieldEditor.setText(Globals.lang("Downloading..."));
+ output(Globals.lang("Downloading..."));
+ String plannedName = getPlannedFileName(res);
+
+ // Find the default directory for this field type:
+ String directory = metaData.getFileDirectory(fieldName);
+
+ if (!new File(directory).exists()) {
+ JOptionPane.showMessageDialog(parent, Globals.lang(
+ "Could not find directory for %0-files: %1", fieldName, directory),
+ Globals.lang("Download file"), JOptionPane.ERROR_MESSAGE);
+ Globals.logger(Globals.lang("Could not find directory for %0-files: %1",
+ fieldName, directory));
+ return;
+ }
+ File file = new File(new File(directory), plannedName);
+
+ URL url = new URL(res);
+
+ URLDownload udl = new URLDownload(parent, url, file);
+ try {
+ udl.download();
+ } catch (IOException e2) {
+ JOptionPane.showMessageDialog(parent, Globals.lang("Invalid URL: "
+ + e2.getMessage()), Globals.lang("Download file"),
+ JOptionPane.ERROR_MESSAGE);
+ Globals.logger("Error while downloading " + url.toString());
+ return;
+ }
+ output(Globals.lang("Download completed"));
+
+ String textToSet = file.getPath();
+ if (textToSet.startsWith(directory)) {
+ // Construct path relative to pdf base dir
+ textToSet = textToSet.substring(directory.length(), textToSet.length());
+
+ // Remove leading path separator
+ if (textToSet.startsWith(File.separator)) {
+ textToSet = textToSet.substring(File.separator.length());
+ }
+ }
+
+ /*
+ * Check if we should update the editor text field, or
+ * update the target entry directly:
+ */
+ if (entryEditor == null || entryEditor.getEntry() != targetEntry) {
+ /*
+ * Editor has probably changed to show a different
+ * entry. So we must update the target entry directly
+ * and not set the text of the editor.
+ */
+ targetEntry.setField(fieldName, textToSet);
+ updateEditor = false;
+ } else {
+ /*
+ * Need to set the fieldEditor first before running
+ * updateField-Action, because otherwise we might get a
+ * race condition.
+ *
+ * (Hopefully a) Fix for: [ 1545601 ] downloading pdf
+ * corrupts pdf field text
+ *
+ * http://sourceforge.net/tracker/index.php?func=detail&aid=1545601&group_id=92314&atid=600306
+ */
+ fieldEditor.setText(textToSet);
+ fieldEditor.setEnabled(true);
+ updateEditor = false;
+ SwingUtilities.invokeLater(new Thread() {
+ public void run() {
+ entryEditor.updateField(fieldEditor);
+ }
+ });
+ }
+
+ } catch (MalformedURLException e1) {
+ JOptionPane.showMessageDialog(parent, Globals.lang("Invalid URL"), Globals
+ .lang("Download file"), JOptionPane.ERROR_MESSAGE);
+ } finally {
+ // If stuff goes wrong along the road, put back original
+ // value
+ if (updateEditor) {
+ fieldEditor.setText(originalText);
+ fieldEditor.setEnabled(true);
+ }
+ }
+ }
+ }).start();
+ }
+
+ /**
+ * Starts a thread that searches the external file directory for the given
+ * field name, including subdirectories, and looks for files named after the
+ * current entry's bibtex key. Returns a reference to the thread for callers
+ * that may want to wait for the thread to finish (using join()).
+ *
+ * @param fieldName
+ * The field to set.
+ * @param editor
+ * An EntryEditor instance where to set the value found.
+ * @return A reference to the Thread that performs the operation.
+ */
+ public Thread autoSetFile(final String fieldName, final FieldEditor editor) {
+ Object o = getKey();
+ if ((o == null) || (Globals.prefs.get(fieldName + "Directory") == null)) {
+ output(Globals.lang("You must set both BibTeX key and %0 directory", fieldName
+ .toUpperCase())
+ + ".");
+ return null;
+ }
+ output(Globals.lang("Searching for %0 file", fieldName.toUpperCase()) + " '" + o + "."
+ + fieldName + "'...");
+ Thread t = (new Thread() {
+ public void run() {
+ Object o = getKey();
+
+ /*
+ * Find the following directories to look in for:
+ *
+ * default directory for this field type.
+ *
+ * directory of bibtex-file. // NOT POSSIBLE at the moment.
+ *
+ * JabRef-directory.
+ */
+ LinkedList list = new LinkedList();
+ list.add(metaData.getFileDirectory(fieldName));
+
+ /*
+ * File fileOfDb = frame.basePanel().file(); if (fileOfDb !=
+ * null){ list.add(fileOfDb.getParentFile().getPath()); }
+ */
+ list.add(".");
+
+ String found = Util.findPdf(getEntry(), fieldName, (String[]) list
+ .toArray(new String[list.size()]));// , off);
+
+ // To activate findFile:
+ // String found = Util.findFile(getEntry(), null, dir,
+ // ".*[bibtexkey].*");
+
+ if (found != null) {
+ editor.setText(found);
+ if (entryEditor != null)
+ entryEditor.updateField(editor);
+ output(Globals.lang("%0 field set", fieldName.toUpperCase()) + ".");
+ } else {
+ output(Globals.lang("No %0 found", fieldName.toUpperCase()) + ".");
+ }
+
+ }
+ });
+
+ t.start();
+ return t;
+
+ }
+
+}
\ No newline at end of file
diff --git a/src/java/net/sf/jabref/external/ExternalFileType.java b/src/java/net/sf/jabref/external/ExternalFileType.java
index a525bab..dbcfd0f 100644
--- a/src/java/net/sf/jabref/external/ExternalFileType.java
+++ b/src/java/net/sf/jabref/external/ExternalFileType.java
@@ -34,6 +34,15 @@ public class ExternalFileType {
return extension;
}
+ /**
+ * Get the bibtex field name used to link to this file type.
+ * Currently we assume that field name equals filename extension.
+ * @return The field name.
+ */
+ public String getFieldName() {
+ return extension;
+ }
+
public String getOpenWith() {
return openWith;
}
diff --git a/src/java/net/sf/jabref/external/PushToApplication.java b/src/java/net/sf/jabref/external/PushToApplication.java
index 0873eea..eee97b5 100644
--- a/src/java/net/sf/jabref/external/PushToApplication.java
+++ b/src/java/net/sf/jabref/external/PushToApplication.java
@@ -13,6 +13,8 @@ public interface PushToApplication {
public String getName();
+ public String getApplicationName();
+
public String getTooltip();
public Icon getIcon();
@@ -39,4 +41,5 @@ public interface PushToApplication {
public boolean requiresBibtexKeys();
+
}
diff --git a/src/java/net/sf/jabref/external/PushToApplicationAction.java b/src/java/net/sf/jabref/external/PushToApplicationAction.java
index d2a8fb6..7d69397 100644
--- a/src/java/net/sf/jabref/external/PushToApplicationAction.java
+++ b/src/java/net/sf/jabref/external/PushToApplicationAction.java
@@ -4,22 +4,19 @@ import net.sf.jabref.*;
import javax.swing.*;
import java.awt.event.ActionEvent;
+import java.awt.*;
import java.util.List;
import java.util.Iterator;
/**
- * Created by IntelliJ IDEA.
- * User: alver
- * Date: Apr 4, 2006
- * Time: 7:31:00 PM
- * To change this template use File | Settings | File Templates.
+ * An Action class representing the process of invoking a PushToApplication operation.
*/
public class PushToApplicationAction extends AbstractAction implements Runnable {
private PushToApplication operation;
private JabRefFrame frame;
private BasePanel panel;
private BibtexEntry[] entries;
-
+
public PushToApplicationAction(JabRefFrame frame, PushToApplication operation) {
this.frame = frame;
putValue(SMALL_ICON, operation.getIcon());
diff --git a/src/java/net/sf/jabref/external/PushToApplicationButton.java b/src/java/net/sf/jabref/external/PushToApplicationButton.java
new file mode 100644
index 0000000..bb870d3
--- /dev/null
+++ b/src/java/net/sf/jabref/external/PushToApplicationButton.java
@@ -0,0 +1,187 @@
+package net.sf.jabref.external;
+
+import net.sf.jabref.*;
+
+import javax.swing.*;
+import java.util.List;
+import java.util.Iterator;
+import java.util.HashMap;
+import java.util.ArrayList;
+import java.awt.*;
+import java.awt.event.ActionListener;
+import java.awt.event.ActionEvent;
+import java.net.URL;
+
+/**
+ * Customized UI component for pushing to external applications. Has a selection popup
+ * menu to change the selected external application.
+ * This class implements the ActionListener interface. When actionPerformed() is
+ * invoked, the currently selected PushToApplication is activated. The actionPerformed()
+ * method can be called with a null argument.
+ */
+public class PushToApplicationButton implements ActionListener {
+
+ public static List applications;
+
+ private JabRefFrame frame;
+ private List pushActions;
+ private JPanel comp;
+ private JButton pushButton, menuButton;
+ private int selected = 0;
+ private JPopupMenu popup = null;
+ private HashMap actions = new HashMap();
+ private final Dimension buttonDim = new Dimension(23, 23);
+ private static final URL ARROW_ICON = GUIGlobals.class.getResource("/images/secondary_sorted_reverse.png");
+ private MenuAction mAction = new MenuAction();
+
+ /**
+ * Set up the current available choices:
+ */
+ static {
+ applications = new ArrayList();
+ applications.add(new PushToLyx());
+ applications.add(new PushToEmacs());
+ applications.add(new PushToWinEdt());
+ applications.add(new PushToLatexEditor());
+
+ }
+
+
+ public PushToApplicationButton(JabRefFrame frame, List pushActions) {
+ this.frame = frame;
+ this.pushActions = pushActions;
+ init();
+ }
+
+ private void init() {
+ comp = new JPanel();
+ comp.setLayout(new BorderLayout());
+
+ menuButton = new JButton(new ImageIcon(ARROW_ICON));
+ menuButton.setMargin(new Insets(0,0,0,0));
+ menuButton.setPreferredSize(new Dimension(menuButton.getIcon().getIconWidth(),
+ menuButton.getIcon().getIconHeight()));
+ menuButton.addActionListener(new MenuButtonActionListener());
+ menuButton.setToolTipText(Globals.lang("Select external application"));
+ pushButton = new JButton();
+ if (Globals.prefs.hasKey("pushToApplication")) {
+ String appSelected = Globals.prefs.get("pushToApplication");
+ for (int i=0; i<pushActions.size(); i++) {
+ PushToApplication toApp = (PushToApplication)pushActions.get(i);
+ if (toApp.getName().equals(appSelected)) {
+ selected = i;
+ break;
+ }
+ }
+ }
+
+ setSelected(selected);
+ pushButton.addActionListener(this);
+
+ comp.add(pushButton, BorderLayout.CENTER);
+ comp.add(menuButton, BorderLayout.EAST);
+ comp.setBorder(BorderFactory.createLineBorder(Color.gray));
+ comp.setMaximumSize(comp.getPreferredSize());
+
+
+ }
+
+ /**
+ * Create a selection menu for the available "Push" options.
+ */
+ private void buildPopupMenu() {
+ popup = new JPopupMenu();
+ int j=0;
+ for (Iterator i = pushActions.iterator(); i.hasNext();) {
+ PushToApplication application = (PushToApplication) i.next();
+ JMenuItem item = new JMenuItem(application.getApplicationName(),
+ application.getIcon());
+ item.addActionListener(new PopupItemActionListener(j));
+ popup.add(item);
+ j++;
+ }
+ }
+
+ /**
+ * Update the PushButton to default to the given application.
+ * @param i The List index of the application to default to.
+ */
+ private void setSelected(int i) {
+ this.selected = i;
+ PushToApplication toApp = (PushToApplication)pushActions.get(i);
+ pushButton.setIcon(toApp.getIcon());
+ pushButton.setToolTipText(toApp.getTooltip());
+ pushButton.setPreferredSize(buttonDim);
+ Globals.prefs.put("pushToApplication", toApp.getName());
+ mAction.setTitle(toApp.getApplicationName());
+ }
+
+ /**
+ * Get the toolbar component for the push button.
+ * @return The component.
+ */
+ public Component getComponent() {
+ return comp;
+ }
+
+ public Action getMenuAction() {
+ return mAction;
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ PushToApplication toApp = (PushToApplication)pushActions.get(selected);
+
+ // Lazy initialization of the push action:
+ PushToApplicationAction action = (PushToApplicationAction)actions.get(toApp);
+ if (action == null) {
+ action = new PushToApplicationAction(frame, toApp);
+ actions.put(toApp, action);
+ }
+ action.actionPerformed(new ActionEvent(toApp, 0, "push"));
+ }
+
+ class PopupItemActionListener implements ActionListener {
+ private int index;
+ public PopupItemActionListener(int index) {
+ this.index = index;
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ // Change the selection:
+ setSelected(index);
+ // Invoke the selected operation (is that expected behaviour?):
+ PushToApplicationButton.this.actionPerformed(null);
+ // It makes sense to transfer focus to the push button after the
+ // menu closes:
+ pushButton.requestFocus();
+ }
+ }
+
+
+ class MenuButtonActionListener implements ActionListener {
+
+ public void actionPerformed(ActionEvent e) {
+ // Lazy initialization of the popup menu:
+ if (popup == null)
+ buildPopupMenu();
+ popup.show(comp, 0, menuButton.getHeight());
+ }
+ }
+
+ class MenuAction extends MnemonicAwareAction {
+
+ public MenuAction() {
+ putValue(ACCELERATOR_KEY, Globals.prefs.getKey("Push to application"));
+ }
+
+ public void setTitle(String appName) {
+ putValue(NAME, Globals.lang("Push entries to external application (%0)",
+ appName));
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ PushToApplicationButton.this.actionPerformed(null);
+ }
+ }
+
+}
diff --git a/src/java/net/sf/jabref/external/PushToEmacs.java b/src/java/net/sf/jabref/external/PushToEmacs.java
index 420f0bb..c88183e 100644
--- a/src/java/net/sf/jabref/external/PushToEmacs.java
+++ b/src/java/net/sf/jabref/external/PushToEmacs.java
@@ -23,6 +23,10 @@ public class PushToEmacs implements PushToApplication {
return Globals.menuTitle("Insert selected citations into Emacs") ;
}
+ public String getApplicationName() {
+ return "Emacs";
+ }
+
public String getTooltip() {
return Globals.lang("Push selection to Emacs");
}
diff --git a/src/java/net/sf/jabref/external/PushToLatexEditor.java b/src/java/net/sf/jabref/external/PushToLatexEditor.java
index ae778ae..cb5e052 100644
--- a/src/java/net/sf/jabref/external/PushToLatexEditor.java
+++ b/src/java/net/sf/jabref/external/PushToLatexEditor.java
@@ -3,6 +3,7 @@ package net.sf.jabref.external;
import net.sf.jabref.BasePanel;
import net.sf.jabref.BibtexEntry;
import net.sf.jabref.Globals;
+import net.sf.jabref.GUIGlobals;
import javax.swing.*;
import java.io.IOException;
@@ -22,12 +23,16 @@ public class PushToLatexEditor implements PushToApplication {
return Globals.menuTitle("Insert selected citations into LatexEditor");
}
+ public String getApplicationName() {
+ return "LatexEditor";
+ }
+
public String getTooltip() {
return Globals.lang("Push to LatexEditor");
}
public Icon getIcon() {
- return null;
+ return GUIGlobals.getImage("edit");
}
public String getKeyStrokeName() {
diff --git a/src/java/net/sf/jabref/external/PushToLyx.java b/src/java/net/sf/jabref/external/PushToLyx.java
index 88f896a..743554e 100644
--- a/src/java/net/sf/jabref/external/PushToLyx.java
+++ b/src/java/net/sf/jabref/external/PushToLyx.java
@@ -58,6 +58,10 @@ public class PushToLyx implements PushToApplication {
return Globals.lang("Insert selected citations into LyX/Kile");
}
+ public String getApplicationName() {
+ return "LyX/Kile";
+ }
+
public String getTooltip() {
return Globals.lang("Push selection to LyX/Kile");
}
diff --git a/src/java/net/sf/jabref/external/PushToWinEdt.java b/src/java/net/sf/jabref/external/PushToWinEdt.java
index 3ebbd49..8d5d191 100644
--- a/src/java/net/sf/jabref/external/PushToWinEdt.java
+++ b/src/java/net/sf/jabref/external/PushToWinEdt.java
@@ -25,6 +25,10 @@ public class PushToWinEdt implements PushToApplication {
return Globals.lang("Insert selected citations into WinEdt");
}
+ public String getApplicationName() {
+ return "WinEdt";
+ }
+
public String getTooltip() {
return Globals.lang("Push selection to WinEdt");
}
diff --git a/src/java/net/sf/jabref/external/WriteXMPAction.java b/src/java/net/sf/jabref/external/WriteXMPAction.java
new file mode 100644
index 0000000..64e3346
--- /dev/null
+++ b/src/java/net/sf/jabref/external/WriteXMPAction.java
@@ -0,0 +1,250 @@
+package net.sf.jabref.external;
+
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.File;
+
+import javax.swing.AbstractAction;
+import javax.swing.ActionMap;
+import javax.swing.BorderFactory;
+import javax.swing.InputMap;
+import javax.swing.JButton;
+import javax.swing.JComponent;
+import javax.swing.JDialog;
+import javax.swing.JFrame;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTextArea;
+import javax.swing.border.BevelBorder;
+
+import net.sf.jabref.AbstractWorker;
+import net.sf.jabref.BasePanel;
+import net.sf.jabref.BibtexEntry;
+import net.sf.jabref.FocusRequester;
+import net.sf.jabref.Globals;
+import net.sf.jabref.Util;
+import net.sf.jabref.util.XMPUtil;
+
+import com.jgoodies.forms.builder.ButtonBarBuilder;
+
+/**
+ *
+ * This action goes through all selected entries in the BasePanel, and attempts
+ * to write the XMP data to the external pdf.
+ *
+ * @author $Author: coezbek $
+ * @version $Revision: 1.2 $ ($Date: 2006/08/26 21:24:39 $)
+ *
+ */
+public class WriteXMPAction extends AbstractWorker {
+
+ BasePanel panel;
+
+ BibtexEntry[] entries;
+
+ OptionsDialog optDiag;
+
+ boolean goOn = true;
+
+ int skipped, entriesChanged, errors;
+
+ public WriteXMPAction(BasePanel panel) {
+ this.panel = panel;
+ }
+
+ public void init() {
+
+ // Get entries and check if it makes sense to perform this operation
+ entries = panel.getSelectedEntries();
+
+ if (entries.length == 0) {
+
+ entries = (BibtexEntry[]) panel.getDatabase().getEntries().toArray(new BibtexEntry[0]);
+
+ if (entries.length == 0) {
+
+ JOptionPane.showMessageDialog(panel, Globals
+ .lang("This operation requires at least one entry."), Globals
+ .lang("Write XMP-metadata"), JOptionPane.ERROR_MESSAGE);
+ goOn = false;
+ return;
+
+ } else {
+
+ int response = JOptionPane.showConfirmDialog(panel, Globals
+ .lang("Write XMP-metadata for all PDFs in current database?"), Globals
+ .lang("Write XMP-metadata"), JOptionPane.YES_NO_CANCEL_OPTION,
+ JOptionPane.QUESTION_MESSAGE);
+
+ if (response != JOptionPane.YES_OPTION) {
+ goOn = false;
+ return;
+ }
+ }
+ }
+
+ errors = entriesChanged = skipped = 0;
+
+ if (optDiag == null) {
+ optDiag = new OptionsDialog(panel.frame());
+ }
+ optDiag.open();
+
+ panel.output(Globals.lang("Writing XMP metadata..."));
+ }
+
+ public void run() {
+
+ if (!goOn)
+ return;
+
+ for (int i = 0; i < entries.length; i++) {
+
+ BibtexEntry entry = entries[i];
+
+ String pdf = (String) entry.getField("pdf");
+
+ String dir = panel.metaData().getFileDirectory("pdf");
+
+ File file = Util.expandFilename(pdf, new String[]{dir,"."});
+
+ optDiag.progressArea.append(entry.getCiteKey() + "\n");
+
+ if (file == null) {
+ skipped++;
+ optDiag.progressArea.append(" " + Globals.lang("Skipped - No PDF linked") + ".\n");
+ } else if (!file.exists()) {
+ skipped++;
+ optDiag.progressArea.append(" " + Globals.lang("Skipped - PDF does not exist")
+ + ":\n");
+ optDiag.progressArea.append(" " + file.getPath() + "\n");
+ } else {
+ try {
+ XMPUtil.writeXMP(file, entry);
+ optDiag.progressArea.append(" " + Globals.lang("Ok") + ".\n");
+ entriesChanged++;
+ } catch (Exception e) {
+ optDiag.progressArea.append(" " + Globals.lang("Error while writing") + " '"
+ + file.getPath() + "':\n");
+ optDiag.progressArea.append(" " + e.getLocalizedMessage() + "\n");
+ errors++;
+ }
+ }
+ if (optDiag.canceled){
+ optDiag.progressArea.append("\n"
+ + Globals.lang("Operation canceled.\n"));
+ break;
+ }
+ }
+ optDiag.progressArea.append("\n"
+ + Globals.lang("Finished writing XMP for %0 file (%1 skipped, %2 errors).", String
+ .valueOf(entriesChanged), String.valueOf(skipped), String.valueOf(errors)));
+ optDiag.done();
+ }
+
+ public void update() {
+ if (!goOn)
+ return;
+
+ panel.output(Globals.lang("Finished writing XMP for %0 file (%1 skipped, %2 errors).",
+ String.valueOf(entriesChanged), String.valueOf(skipped), String.valueOf(errors)));
+ }
+
+ class OptionsDialog extends JDialog {
+
+ private static final long serialVersionUID = 7459164400811785958L;
+
+ JButton okButton = new JButton(Globals.lang("Ok")), cancelButton = new JButton(Globals
+ .lang("Cancel"));
+
+ boolean canceled;
+
+ JTextArea progressArea;
+
+ public OptionsDialog(JFrame parent) {
+ super(parent, Globals.lang("Writing XMP metadata for selected entries..."), false);
+ okButton.setEnabled(false);
+
+ okButton.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ dispose();
+ }
+ });
+
+ AbstractAction cancel = new AbstractAction() {
+ private static final long serialVersionUID = -338601477652815366L;
+
+ public void actionPerformed(ActionEvent e) {
+ canceled = true;
+ }
+ };
+ cancelButton.addActionListener(cancel);
+
+ InputMap im = cancelButton.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
+ ActionMap am = cancelButton.getActionMap();
+ im.put(Globals.prefs.getKey("Close dialog"), "close");
+ am.put("close", cancel);
+
+ progressArea = new JTextArea(15, 60);
+
+ JScrollPane scrollPane = new JScrollPane(progressArea,
+ JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
+ Dimension d = progressArea.getPreferredSize();
+ d.height += scrollPane.getHorizontalScrollBar().getHeight() + 15;
+ d.width += scrollPane.getVerticalScrollBar().getWidth() + 15;
+
+ panel.setSize(d);
+
+ progressArea.setBackground(Color.WHITE);
+ progressArea.setEditable(false);
+ progressArea.setBorder(BorderFactory.createEmptyBorder(3, 3, 3,
+ 3));
+ progressArea.setText("");
+
+ JPanel panel = new JPanel();
+ panel.setBorder(BorderFactory.createEmptyBorder(3, 2, 3, 2));
+ panel.add(scrollPane);
+
+
+
+ // progressArea.setPreferredSize(new Dimension(300, 300));
+
+ ButtonBarBuilder bb = new ButtonBarBuilder();
+ bb.addGlue();
+ bb.addGridded(okButton);
+ bb.addRelatedGap();
+ bb.addGridded(cancelButton);
+ bb.addGlue();
+ JPanel bbPanel = bb.getPanel();
+ bbPanel.setBorder(BorderFactory.createEmptyBorder(0, 3, 3, 3));
+ getContentPane().add(panel, BorderLayout.CENTER);
+ getContentPane().add(bbPanel, BorderLayout.SOUTH);
+
+ pack();
+ this.setResizable(false);
+
+ }
+
+ public void done() {
+ okButton.setEnabled(true);
+ cancelButton.setEnabled(false);
+ }
+
+ public void open() {
+ progressArea.setText("");
+ canceled = false;
+ Util.placeDialog(optDiag, panel.frame());
+
+ okButton.setEnabled(false);
+ cancelButton.setEnabled(true);
+
+ new FocusRequester(okButton);
+
+ optDiag.setVisible(true);
+ }
+ }
+}
diff --git a/src/java/net/sf/jabref/groups/EntryTableTransferHandler.java b/src/java/net/sf/jabref/groups/EntryTableTransferHandler.java
index 264d91c..8eb2182 100644
--- a/src/java/net/sf/jabref/groups/EntryTableTransferHandler.java
+++ b/src/java/net/sf/jabref/groups/EntryTableTransferHandler.java
@@ -22,19 +22,29 @@
package net.sf.jabref.groups;
-import java.awt.datatransfer.*;
+import java.awt.datatransfer.Clipboard;
+import java.awt.datatransfer.DataFlavor;
+import java.awt.datatransfer.Transferable;
+import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.dnd.DnDConstants;
import java.awt.event.InputEvent;
-import java.io.*;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
import java.net.URL;
-import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;
+import java.util.List;
-import javax.swing.*;
+import javax.swing.JComponent;
+import javax.swing.JTable;
+import javax.swing.TransferHandler;
+import net.sf.jabref.BasePanel;
import net.sf.jabref.Globals;
import net.sf.jabref.JabRefFrame;
+import net.sf.jabref.external.DroppedFileHandler;
+import net.sf.jabref.external.ExternalFileType;
import net.sf.jabref.gui.MainTable;
import net.sf.jabref.imports.ImportMenuItem;
import net.sf.jabref.imports.OpenDatabaseAction;
@@ -42,251 +52,391 @@ import net.sf.jabref.imports.ParserResult;
import net.sf.jabref.net.URLDownload;
public class EntryTableTransferHandler extends TransferHandler {
- protected final MainTable entryTable;
- protected JabRefFrame frame;
- protected DataFlavor urlFlavor;
- protected DataFlavor stringFlavor;
- protected static boolean DROP_ALLOWED = true;
-
- /**
- * Construct the transfer handler.
- * @param entryTable The table this transfer handler should operate on. This argument is
- * allowed to equal @null, in which case the transfer handler can assume that it
- * works for a JabRef instance with no databases open, attached to the empty tabbed pane.
- * @param frame The JabRefFrame instance.
- */
- public EntryTableTransferHandler(MainTable entryTable, JabRefFrame frame) {
- this.entryTable = entryTable;
- this.frame = frame;
- stringFlavor = DataFlavor.stringFlavor;
- try {
- urlFlavor = new DataFlavor("application/x-java-url; class=java.net.URL");
- } catch (ClassNotFoundException e) {
- Globals.logger("Unable to configure drag and drop for main table");
- e.printStackTrace();
- }
- }
-
- public int getSourceActions(JComponent c) {
- return DnDConstants.ACTION_LINK;
- }
-
- public Transferable createTransferable(JComponent c) {
- // This method is called when dragging stuff *from* the table, so we can assume
- // it will never be called if entryTable==null:
- return new TransferableEntrySelection(entryTable.getSelectedEntries());
- }
-
- // add-ons -----------------------
-
-
- protected boolean handleDropTransfer(String dropStr) throws IOException {
- if (dropStr.startsWith("file:")) {
- // This appears to be a dragged file link and not a reference
- // format. Check if we can map this to a set of files:
- if (handleDraggedFilenames(dropStr))
- return true;
- // If not, handle it in the normal way...
- } else if (dropStr.startsWith("http:")) {
- // This is the way URL links are received on OS X and KDE (Gnome?):
- URL url = new URL(dropStr);
- //JOptionPane.showMessageDialog(null, "Making URL: "+url.toString());
- return handleDropTransfer(url);
- }
- File tmpfile = java.io.File.createTempFile("jabrefimport", "");
- tmpfile.deleteOnExit();
- FileWriter fw = new FileWriter(tmpfile);
- fw.write(dropStr);
- fw.close();
-
- //System.out.println("importing from " + tmpfile.getAbsolutePath());
-
- ImportMenuItem importer = new ImportMenuItem(frame, false);
- importer.automatedImport(new String[] { tmpfile.getAbsolutePath() } );
-
- return true;
- }
-
- /**
- * Handle a String describing a set of files or URLs dragged into JabRef.
- * @param s String describing a set of files or URLs dragged into JabRef
- */
- private boolean handleDraggedFilenames(String s) {
- // Split into lines:
- String[] lines = s.replaceAll("\r", "").split("\n");
- List files = new ArrayList();
- for (int i = 0; i < lines.length; i++) {
- String line = lines[i];
- if (line.startsWith("file:"))
- line = line.substring(5);
- else continue;
- // Under Gnome, the link is given as file:///...., so we
- // need to strip the extra slashes:
- if (line.startsWith("//"))
- line = line.substring(2);
- File f = new File(line);
- if (f.exists()) {
- files.add(f);
- }
- }
- return handleDraggedFiles(files);
-
- }
-
- /**
- * Handle a List containing File objects for a set of files to import.
- * @param files A List containing File instances pointing to files.
- */
- private boolean handleDraggedFiles(List files) {
- final String[] fileNames = new String[files.size()];
- int i=0;
- for (Iterator iterator = files.iterator(); iterator.hasNext();) {
- File file = (File) iterator.next();
- fileNames[i] = file.getAbsolutePath();
- i++;
- }
- // Try to load bib files normally, and import the rest into the current database.
- // This process must be spun off into a background thread:
- new Thread(new Runnable() {
- public void run() {
- loadOrImportFiles(fileNames);
- }
- }).start();
-
- return true;
- }
-
- /**
- * Take a set of filenames. Those with names indicating bib files are opened as such
- * if possible. All other files we will attempt to import into the current database.
- * @param fileNames The names of the files to open.
- */
- private void loadOrImportFiles(String[] fileNames) {
-
- OpenDatabaseAction openAction = new OpenDatabaseAction(frame, false);
- ArrayList notBibFiles = new ArrayList();
- String encoding = Globals.prefs.get("defaultEncoding");
- for (int i = 0; i < fileNames.length; i++) {
- if (fileNames[i].toLowerCase().endsWith(".bib")) {
- File f = new File(fileNames[i]);
- try {
- ParserResult pr = OpenDatabaseAction.loadDatabase
- (f, encoding);
- if ((pr == null) || (pr == ParserResult.INVALID_FORMAT)) {
- notBibFiles.add(fileNames[i]);
- } else {
- openAction.addNewDatabase(pr, f, false);
+
+ protected final MainTable entryTable;
+
+ protected JabRefFrame frame;
+
+ private BasePanel panel;
+
+ protected DataFlavor urlFlavor;
+
+ protected DataFlavor stringFlavor;
+
+ protected static boolean DROP_ALLOWED = true;
+
+ /**
+ * Construct the transfer handler.
+ *
+ * @param entryTable
+ * The table this transfer handler should operate on. This
+ * argument is allowed to equal
+ * @null, in which case the transfer handler can assume that it works for a
+ * JabRef instance with no databases open, attached to the empty
+ * tabbed pane.
+ * @param frame
+ * The JabRefFrame instance.
+ * @param panel
+ * The BasePanel this transferhandler works for.
+ */
+ public EntryTableTransferHandler(MainTable entryTable, JabRefFrame frame, BasePanel panel) {
+ this.entryTable = entryTable;
+ this.frame = frame;
+ this.panel = panel;
+ stringFlavor = DataFlavor.stringFlavor;
+ try {
+ urlFlavor = new DataFlavor("application/x-java-url; class=java.net.URL");
+ } catch (ClassNotFoundException e) {
+ Globals.logger("Unable to configure drag and drop for main table");
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Overriden to indicate which types of drags are supported (only LINK).
+ *
+ * @override
+ */
+ public int getSourceActions(JComponent c) {
+ return DnDConstants.ACTION_LINK;
+ }
+
+ /**
+ * This method is called when dragging stuff *from* the table.
+ */
+ public Transferable createTransferable(JComponent c) {
+ /* so we can assume it will never be called if entryTable==null: */
+ return new TransferableEntrySelection(entryTable.getSelectedEntries());
+ }
+
+ /**
+ * This method is called when stuff is drag to the component.
+ *
+ * Imports the dropped URL or plain text as a new entry in the current
+ * database.
+ *
+ * @todo It would be nice to support dropping of pdfs onto the table as a
+ * way to link them to the corresponding entries.
+ */
+ public boolean importData(JComponent comp, Transferable t) {
+
+ // If the drop target is the main table, we want to record which
+ // row the item was dropped on, to identify the entry if needed:
+ int dropRow = -1;
+ if (comp instanceof JTable) {
+ dropRow = ((JTable) comp).getSelectedRow();
+ }
+
+ try {
+
+ // This flavor is used for dragged file links in Windows:
+ if (t.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
+ // JOptionPane.showMessageDialog(null, "Received
+ // javaFileListFlavor");
+ List l = (List) t.getTransferData(DataFlavor.javaFileListFlavor);
+ return handleDraggedFiles(l, dropRow);
+ }
+
+ if (t.isDataFlavorSupported(urlFlavor)) {
+ URL dropLink = (URL) t.getTransferData(urlFlavor);
+ return handleDropTransfer(dropLink, dropRow);
+ }
+
+ if (t.isDataFlavorSupported(stringFlavor)) {
+ // JOptionPane.showMessageDialog(null, "Received stringFlavor:
+ // "+dropStr);
+ String dropStr = (String) t.getTransferData(stringFlavor);
+ return handleDropTransfer(dropStr, dropRow);
+ }
+
+ } catch (IOException ioe) {
+ System.err.println("failed to read dropped data: " + ioe.toString());
+ } catch (UnsupportedFlavorException ufe) {
+ System.err.println("drop type error: " + ufe.toString());
+ }
+
+ // all supported flavors failed
+ System.err.println("can't transfer input: ");
+ DataFlavor inflavs[] = t.getTransferDataFlavors();
+ for (int i = 0; i < inflavs.length; i++) {
+ System.out.println(" " + inflavs[i].toString());
+ }
+
+ return false;
+ }
+
+ /**
+ * This method is called to query whether the transfer can be imported.
+ *
+ * Will return true for urls, strings, javaFileLists
+ *
+ * @override
+ */
+ public boolean canImport(JComponent comp, DataFlavor[] transferFlavors) {
+ if (!DROP_ALLOWED)
+ return false;
+
+ // accept this if any input flavor matches any of our supported flavors
+ for (int i = 0; i < transferFlavors.length; i++) {
+ DataFlavor inflav = transferFlavors[i];
+ if (inflav.match(urlFlavor) || inflav.match(stringFlavor)
+ || inflav.match(DataFlavor.javaFileListFlavor))
+ return true;
+ }
+
+ // System.out.println("drop type forbidden");
+ // nope, never heard of this type
+ return false;
+ }
+
+ public void exportAsDrag(JComponent comp, InputEvent e, int action) {
+ // action is always LINK
+ super.exportAsDrag(comp, e, DnDConstants.ACTION_LINK);
+ }
+
+ protected void exportDone(JComponent source, Transferable data, int action) {
+ // default implementation is OK
+ super.exportDone(source, data, action);
+ }
+
+ public void exportToClipboard(JComponent comp, Clipboard clip, int action) {
+ // default implementation is OK
+ super.exportToClipboard(comp, clip, action);
+ }
+
+ // add-ons -----------------------
+
+ protected boolean handleDropTransfer(String dropStr, final int dropRow) throws IOException {
+ if (dropStr.startsWith("file:")) {
+ // This appears to be a dragged file link and not a reference
+ // format. Check if we can map this to a set of files:
+ if (handleDraggedFilenames(dropStr, dropRow))
+ return true;
+ // If not, handle it in the normal way...
+ } else if (dropStr.startsWith("http:")) {
+ // This is the way URL links are received on OS X and KDE (Gnome?):
+ URL url = new URL(dropStr);
+ // JOptionPane.showMessageDialog(null, "Making URL:
+ // "+url.toString());
+ return handleDropTransfer(url, dropRow);
+ }
+ File tmpfile = java.io.File.createTempFile("jabrefimport", "");
+ tmpfile.deleteOnExit();
+ FileWriter fw = new FileWriter(tmpfile);
+ fw.write(dropStr);
+ fw.close();
+
+ // System.out.println("importing from " + tmpfile.getAbsolutePath());
+
+ ImportMenuItem importer = new ImportMenuItem(frame, false);
+ importer.automatedImport(new String[] { tmpfile.getAbsolutePath() });
+
+ return true;
+ }
+
+ /**
+ * Handle a String describing a set of files or URLs dragged into JabRef.
+ *
+ * @param s
+ * String describing a set of files or URLs dragged into JabRef
+ * @param dropRow The row in the table where the files were dragged.
+ * @return success status for the operation
+ *
+ */
+ private boolean handleDraggedFilenames(String s, final int dropRow) {
+ // Split into lines:
+ String[] lines = s.replaceAll("\r", "").split("\n");
+ List files = new ArrayList();
+ for (int i = 0; i < lines.length; i++) {
+ String line = lines[i];
+ if (line.startsWith("file:"))
+ line = line.substring(5);
+ else
+ continue;
+ // Under Gnome, the link is given as file:///...., so we
+ // need to strip the extra slashes:
+ if (line.startsWith("//"))
+ line = line.substring(2);
+ File f = new File(line);
+ if (f.exists()) {
+ files.add(f);
+ }
+ }
+ return handleDraggedFiles(files, dropRow);
+
+ }
+
+ /**
+ * Handle a List containing File objects for a set of files to import.
+ *
+ * @param files
+ * A List containing File instances pointing to files.
+ * @param dropRow @param dropRow The row in the table where the files were dragged.
+ * @return success status for the operation
+ */
+ private boolean handleDraggedFiles(List files, final int dropRow) {
+ final String[] fileNames = new String[files.size()];
+ int i = 0;
+ for (Iterator iterator = files.iterator(); iterator.hasNext();) {
+ File file = (File) iterator.next();
+ fileNames[i] = file.getAbsolutePath();
+ i++;
+ }
+ // Try to load bib files normally, and import the rest into the current
+ // database.
+ // This process must be spun off into a background thread:
+ new Thread(new Runnable() {
+ public void run() {
+ loadOrImportFiles(fileNames, dropRow);
+ }
+ }).start();
+
+ return true;
+ }
+
+ /**
+ * Take a set of filenames. Those with names indicating bib files are opened
+ * as such if possible. All other files we will attempt to import into the
+ * current database.
+ *
+ * @param fileNames
+ * The names of the files to open.
+ * @param dropRow success status for the operation
+ */
+ private void loadOrImportFiles(String[] fileNames, int dropRow) {
+
+ OpenDatabaseAction openAction = new OpenDatabaseAction(frame, false);
+ ArrayList notBibFiles = new ArrayList();
+ String encoding = Globals.prefs.get("defaultEncoding");
+ for (int i = 0; i < fileNames.length; i++) {
+ // Find the file's extension, if any:
+ String extension = "";
+ ExternalFileType fileType = null;
+ int index = fileNames[i].lastIndexOf('.');
+ if ((index >= 0) && (index < fileNames[i].length())) {
+ extension = fileNames[i].substring(index + 1).toLowerCase();
+ // System.out.println(extension);
+ fileType = Globals.prefs.getExternalFileType(extension);
+ }
+ if (extension.equals("bib")) {
+ File f = new File(fileNames[i]);
+ try {
+ ParserResult pr = OpenDatabaseAction.loadDatabase(f, encoding);
+ if ((pr == null) || (pr == ParserResult.INVALID_FORMAT)) {
+ notBibFiles.add(fileNames[i]);
+ } else {
+ openAction.addNewDatabase(pr, f, true);
+ frame.getFileHistory().newFile(fileNames[i]);
}
- } catch (IOException e) {
- notBibFiles.add(fileNames[i]);
- // No error message, since we want to try importing the file?
- //
- //Util.showQuickErrorDialog(frame, Globals.lang("Open database"), e);
- }
- }
- else if (fileNames[i].toLowerCase().endsWith(".pdf") ||
- fileNames[i].toLowerCase().endsWith(".ps")) {
- // Handle PDF by linking to it from the entry where it was dropped?
- // Not implemented. We should not try to import the PDF file.
- }
- else notBibFiles.add(fileNames[i]);
- }
-
- if (notBibFiles.size() > 0) {
- String[] toImport = new String[notBibFiles.size()];
- notBibFiles.toArray(toImport);
-
- // Import into new if entryTable==null, otherwise into current database:
- ImportMenuItem importer = new ImportMenuItem(frame, (entryTable == null));
- importer.automatedImport(toImport);
- }
- }
-
- protected boolean handleDropTransfer(URL dropLink) throws IOException {
- File tmpfile = java.io.File.createTempFile("jabrefimport", "");
- tmpfile.deleteOnExit();
-
- //System.out.println("Import url: " + dropLink.toString());
- //System.out.println("Temp file: "+tmpfile.getAbsolutePath());
-
- new URLDownload(entryTable, dropLink, tmpfile).download();
-
- // Import into new if entryTable==null, otherwise into current database:
- ImportMenuItem importer = new ImportMenuItem(frame, (entryTable == null));
- importer.automatedImport(new String[] { tmpfile.getAbsolutePath() } );
-
- return true;
- }
-
- /**
- * Imports the dropped URL or plain text as a new entry in the current database.
- * @todo It would be nice to support dropping of pdfs onto the table as a way
- * to link them to the corresponding entries.
- */
- public boolean importData(JComponent comp, Transferable t) {
- try {
-
- if (t.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
- //JOptionPane.showMessageDialog(null, "Received javaFileListFlavor");
- // This flavor is used for dragged file links in Windows:
- List l = (List)t.getTransferData(DataFlavor.javaFileListFlavor);
- return handleDraggedFiles(l);
- }
- if (t.isDataFlavorSupported(urlFlavor)) {
- URL dropLink = (URL) t.getTransferData(urlFlavor);
- return handleDropTransfer(dropLink);
- } else if (t.isDataFlavorSupported(stringFlavor)) {
-
- String dropStr = (String) t.getTransferData(stringFlavor);
- //JOptionPane.showMessageDialog(null, "Received stringFlavor: "+dropStr);
-
- return handleDropTransfer(dropStr);
- }
- } catch (IOException ioe) {
- System.err.println("failed to read dropped data: " + ioe.toString());
- } catch (UnsupportedFlavorException ufe) {
- System.err.println("drop type error: " + ufe.toString());
- }
-
- // all supported flavors failed
- System.err.println("can't transfer input: ");
- DataFlavor inflavs[] = t.getTransferDataFlavors();
- for (int i = 0; i < inflavs.length; i++) {
- System.out.println(" " + inflavs[i].toString());
- }
-
- return false;
- }
-
-
- public boolean canImport(JComponent comp, DataFlavor[] transferFlavors) {
- if (!DROP_ALLOWED) return false;
-
-
- // accept this if any input flavor matches any of our supported flavors
- for (int i = 0; i < transferFlavors.length; i++) {
- DataFlavor inflav = transferFlavors[i];
- if (inflav.match(urlFlavor) || inflav.match(stringFlavor)
- || inflav.match(DataFlavor.javaFileListFlavor)) return true;
- }
-
- //System.out.println("drop type forbidden");
- // nope, never heard of this type
- return false;
- }
-
- public void exportAsDrag(JComponent comp, InputEvent e, int action) {
- // action is always LINK
- super.exportAsDrag(comp, e, DnDConstants.ACTION_LINK);
- }
-
- protected void exportDone(JComponent source, Transferable data, int action) {
- // default implementation is OK
- super.exportDone(source, data, action);
- }
-
- public void exportToClipboard(JComponent comp, Clipboard clip, int action) {
- // default implementation is OK
- super.exportToClipboard(comp, clip, action);
- }
+ } catch (IOException e) {
+ notBibFiles.add(fileNames[i]);
+ // No error message, since we want to try importing the
+ // file?
+ //
+ // Util.showQuickErrorDialog(frame, Globals.lang("Open
+ // database"), e);
+ }
+ continue;
+ }
+
+ /*
+ * This is a linkable file. If the user dropped it on an entry, we
+ * should offer options for autolinking to this files:
+ *
+ * TODO we should offer an option to highlight the row the user is on too.
+ */
+ if (fileType != null && dropRow >= 0) {
+
+ /*
+ * TODO: need to signal if this is a local or autodownloaded
+ * file
+ */
+ boolean local = true;
+
+ /*
+ * TODO: make this an instance variable?
+ */
+ DroppedFileHandler dfh = new DroppedFileHandler(frame, panel);
+ dfh.handleDroppedfile(fileNames[i], fileType, local, entryTable, dropRow);
+
+ continue;
+ }
+/*
+ if (extension.equals("pdf")) {
+ Collection c;
+ try {
+ c = XMPUtil.readXMP(fileNames[i]);
+ } catch (IOException e1) {
+ c = null;
+ frame.output(Globals.lang("No XMP metadata found in " + fileNames[i]));
+ }
+
+ if (c != null && c.size() > 0) {
+ Iterator it = c.iterator();
+
+ BasePanel panel = frame.basePanel();
+
+ if (panel == null) {
+ // // Create a new, empty, database.
+ BibtexDatabase database = new BibtexDatabase();
+ frame.addTab(database, null, null, Globals.prefs.get("defaultEncoding"),
+ true);
+ frame.output(Globals.lang("New database created."));
+ panel = frame.basePanel();
+ }
+
+ BibtexDatabase database = frame.basePanel().database();
+
+ NamedCompound ce = new NamedCompound(Globals.lang("Drog PDF"));
+
+ while (it.hasNext()) {
+ BibtexEntry e = (BibtexEntry) it.next();
+
+ try {
+ e.setId(Util.createNeutralId());
+ database.insertEntry(e);
+ ce.addEdit(new UndoableInsertEntry(database, e, panel));
+ } catch (Exception e2) {
+ // Should not happen?
+ }
+ }
+
+ ce.end();
+ panel.undoManager.addEdit(ce);
+ panel.markBaseChanged();
+ continue;
+ }
+ }
+ */
+
+ notBibFiles.add(fileNames[i]);
+ }
+
+ if (notBibFiles.size() > 0) {
+ String[] toImport = new String[notBibFiles.size()];
+ notBibFiles.toArray(toImport);
+
+ // Import into new if entryTable==null, otherwise into current
+ // database:
+ ImportMenuItem importer = new ImportMenuItem(frame, (entryTable == null));
+ importer.automatedImport(toImport);
+ }
+ }
+
+ protected boolean handleDropTransfer(URL dropLink, int dropRow) throws IOException {
+ File tmpfile = java.io.File.createTempFile("jabrefimport", "");
+ tmpfile.deleteOnExit();
+
+ // System.out.println("Import url: " + dropLink.toString());
+ // System.out.println("Temp file: "+tmpfile.getAbsolutePath());
+
+ new URLDownload(entryTable, dropLink, tmpfile).download();
+
+ // Import into new if entryTable==null, otherwise into current database:
+ ImportMenuItem importer = new ImportMenuItem(frame, (entryTable == null));
+ importer.automatedImport(new String[] { tmpfile.getAbsolutePath() });
+
+ return true;
+ }
+
}
\ No newline at end of file
diff --git a/src/java/net/sf/jabref/groups/GroupDialog.java b/src/java/net/sf/jabref/groups/GroupDialog.java
index d3f56c0..0928cf8 100644
--- a/src/java/net/sf/jabref/groups/GroupDialog.java
+++ b/src/java/net/sf/jabref/groups/GroupDialog.java
@@ -154,7 +154,7 @@ class GroupDialog extends JDialog {
builderKG.append(Globals.lang("Keyword"));
builderKG.append(m_kgSearchTerm);
builderKG.append(new FieldContentSelector(m_parent, m_basePanel, this,
- m_kgSearchTerm, m_basePanel.metaData(), null, true));
+ m_kgSearchTerm, m_basePanel.metaData(), null, true, ", "));
builderKG.nextLine();
builderKG.append(m_kgCaseSensitive, 3);
builderKG.nextLine();
diff --git a/src/java/net/sf/jabref/groups/GroupSelector.java b/src/java/net/sf/jabref/groups/GroupSelector.java
index f498f0f..e6e06cb 100644
--- a/src/java/net/sf/jabref/groups/GroupSelector.java
+++ b/src/java/net/sf/jabref/groups/GroupSelector.java
@@ -195,6 +195,9 @@ public class GroupSelector extends SidePaneComponent implements
GroupSelector.this.revalidate();
GroupSelector.this.repaint();
Globals.prefs.putInt("groupsVisibleRows", i);
+ System.out.println(GroupSelector.this.getHeight());
+ System.out.println(GroupSelector.this.getPreferredSize().getHeight());
+
}
});
reduce.addActionListener(new ActionListener() {
@@ -1173,11 +1176,12 @@ public class GroupSelector extends SidePaneComponent implements
new TreePath(groupsRoot.getPath()));
}
+
/** panel may be null to indicate that no file is currently open. */
public void setActiveBasePanel(BasePanel panel) {
super.setActiveBasePanel(panel);
if (panel == null) { // hide groups
- frame.sidePaneManager.ensureNotVisible("groups");
+ frame.sidePaneManager.hide("groups");
return;
}
MetaData metaData = panel.metaData();
@@ -1192,15 +1196,16 @@ public class GroupSelector extends SidePaneComponent implements
// auto show/hide groups interface
if (Globals.prefs.getBoolean("groupAutoShow") &&
!groupsRoot.isLeaf()) { // groups were defined
- frame.sidePaneManager.ensureVisible("groups");
+ frame.sidePaneManager.show("groups");
frame.groupToggle.setSelected(true);
} else if (Globals.prefs.getBoolean("groupAutoHide") &&
groupsRoot.isLeaf()) { // groups were not defined
- frame.sidePaneManager.ensureNotVisible("groups");
+ frame.sidePaneManager.hide("groups");
frame.groupToggle.setSelected(false);
}
validateTree();
+
}
diff --git a/src/java/net/sf/jabref/gui/DatabasePropertiesDialog.java b/src/java/net/sf/jabref/gui/DatabasePropertiesDialog.java
index 8fd7a7d..83d4478 100644
--- a/src/java/net/sf/jabref/gui/DatabasePropertiesDialog.java
+++ b/src/java/net/sf/jabref/gui/DatabasePropertiesDialog.java
@@ -32,6 +32,7 @@ public class DatabasePropertiesDialog extends JDialog {
JComboBox encoding;
JButton ok, cancel;
JTextField pdfDir = new JTextField(40), psDir = new JTextField(40);
+ String oldPdfVal="", oldPsVal=""; // Remember old values to see if they are changed.
public DatabasePropertiesDialog(JFrame parent) {
super(parent, Globals.lang("Database properties"), false);
@@ -119,10 +120,16 @@ public class DatabasePropertiesDialog extends JDialog {
if (psD.size() >= 1)
psDir.setText(((String)psD.get(0)).trim());
}
+
+ // Store original values to see if they get changed:
+ oldPdfVal = pdfDir.getText();
+ oldPsVal = psDir.getText();
}
public void storeSettings() {
- panel.setEncoding((String)encoding.getSelectedItem());
+ String oldEncoding = panel.getEncoding();
+ String newEncoding = (String)encoding.getSelectedItem();
+ panel.setEncoding(newEncoding);
Vector dir = new Vector(1);
String text = pdfDir.getText().trim();
@@ -141,5 +148,14 @@ public class DatabasePropertiesDialog extends JDialog {
}
else
metaData.remove("psDirectory");
+
+ // See if any of the values have been modified:
+ boolean changed = !newEncoding.equals(oldEncoding)
+ || !oldPdfVal.equals(pdfDir.getText())
+ || !oldPsVal.equals(psDir.getText());
+ // ... if so, mark base changed. Prevent the Undo button from removing
+ // change marking:
+ if (changed)
+ panel.markNonUndoableBaseChanged();
}
}
diff --git a/src/java/net/sf/jabref/gui/ImportInspectionDialog.java b/src/java/net/sf/jabref/gui/ImportInspectionDialog.java
index 1930fd4..e475789 100644
--- a/src/java/net/sf/jabref/gui/ImportInspectionDialog.java
+++ b/src/java/net/sf/jabref/gui/ImportInspectionDialog.java
@@ -114,7 +114,7 @@ public class ImportInspectionDialog extends JDialog {
this.fields = fields;
this.undoName = undoName;
this.newDatabase = newDatabase;
- preview = new PreviewPanel(Globals.prefs.get("preview1"), metaData);
+ preview = new PreviewPanel(metaData, Globals.prefs.get("preview1"));
duplLabel.setToolTipText(Globals.lang("Possible duplicate of existing entry. Click to resolve."));
diff --git a/src/java/net/sf/jabref/gui/MainTable.java b/src/java/net/sf/jabref/gui/MainTable.java
index 5a08a95..447184e 100644
--- a/src/java/net/sf/jabref/gui/MainTable.java
+++ b/src/java/net/sf/jabref/gui/MainTable.java
@@ -6,6 +6,7 @@ import net.sf.jabref.search.HitOrMissComparator;
import net.sf.jabref.groups.EntryTableTransferHandler;
import javax.swing.*;
+import javax.swing.plaf.TableUI;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableModel;
import javax.swing.table.TableColumnModel;
@@ -25,13 +26,15 @@ import java.awt.event.ActionEvent;
import java.util.Comparator;
/**
- * Created by IntelliJ IDEA.
+ * The central table which displays the bibtex entries.
+ *
* User: alver
* Date: Oct 12, 2005
* Time: 10:29:39 PM
- * To change this template use File | Settings | File Templates.
+ *
*/
public class MainTable extends JTable {
+
private MainTableFormat tableFormat;
private SortedList sortedForMarking, sortedForTable, sortedForSearch, sortedForGrouping;
private boolean tableColorCodes, showingFloatSearch=false, showingFloatGrouping=false;
@@ -55,7 +58,9 @@ public class MainTable extends JTable {
updateRenderers();
}
- public MainTable(MainTableFormat tableFormat, EventList list, JabRefFrame frame) {
+
+ public MainTable(MainTableFormat tableFormat, EventList list, JabRefFrame frame,
+ BasePanel panel) {
super();
this.tableFormat = tableFormat;
// This SortedList has a Comparator controlled by the TableComparatorChooser
@@ -85,12 +90,12 @@ public class MainTable extends JTable {
setGridColor(Globals.prefs.getColor("gridColor"));
comparatorChooser = new MyTableComparatorChooser(this, sortedForTable,
TableComparatorChooser.MULTIPLE_COLUMN_KEYBOARD);
-
+
final EventList selected = getSelected();
// enable DnD
setDragEnabled(true);
- TransferHandler xfer = new EntryTableTransferHandler(this, frame);
+ TransferHandler xfer = new EntryTableTransferHandler(this, frame, panel);
setTransferHandler(xfer);
pane.setTransferHandler(xfer);
@@ -516,4 +521,52 @@ public class MainTable extends JTable {
refreshSorting();
}*/
}
+
+ /**
+ * Morten Alver: This override is a workaround NullPointerException when
+ * dragging stuff into the table. I found this in a forum, but have no idea
+ * why it works.
+ * @param newUI
+ */
+ public void setUI(TableUI newUI) {
+ super.setUI(newUI);
+ TransferHandler handler = getTransferHandler();
+ setTransferHandler(null);
+ setTransferHandler(handler);
+
+ }
+
+ /**
+ * Get the first comparator set up for the given column.
+ * @param index The column number.
+ * @return The Comparator, or null if none is set.
+ */
+ public Comparator getComparatorForColumn(int index) {
+ java.util.List l = comparatorChooser.getComparatorsForColumn(index);
+ return l.size() == 0 ? null : (Comparator)l.get(0);
+ }
+
+ /**
+ * Find out which column is set as sort column.
+ * @param number The position in the sort hierarchy (primary, secondary, etc.)
+ * @return The sort column number.
+ */
+ public int getSortingColumn(int number) {
+ java.util.List l = comparatorChooser.getSortingColumns();
+ if (l.size() <= number)
+ return -1;
+ else
+ return ((Integer)l.get(number)).intValue();
+ }
+
+ /**
+ * Returns the List of entries sorted by a user-selected term. This is the
+ * sorting before marking, search etc. applies.
+ *
+ * Note: The returned List must not be modified from the outside
+ * @return The sorted list of entries.
+ */
+ public SortedList getSortedForTable() {
+ return sortedForTable;
+ }
}
diff --git a/src/java/net/sf/jabref/gui/MainTableFormat.java b/src/java/net/sf/jabref/gui/MainTableFormat.java
index 028c2b0..4efa940 100644
--- a/src/java/net/sf/jabref/gui/MainTableFormat.java
+++ b/src/java/net/sf/jabref/gui/MainTableFormat.java
@@ -122,9 +122,9 @@ public class MainTableFormat implements TableFormat {
}
if (namesAsIs) return o;
if (namesNatbib) o = AuthorList.fixAuthor_Natbib((String) o);
- else if (namesLastOnly) o = AuthorList.fixAuthor_lastNameOnlyCommas((String) o);
- else if (namesFf) o = AuthorList.fixAuthor_firstNameFirstCommas((String) o, abbr_names);
- else if (namesLf) o = AuthorList.fixAuthor_lastNameFirstCommas((String) o, abbr_names);
+ else if (namesLastOnly) o = AuthorList.fixAuthor_lastNameOnlyCommas((String) o, false);
+ else if (namesFf) o = AuthorList.fixAuthor_firstNameFirstCommas((String) o, abbr_names, false);
+ else if (namesLf) o = AuthorList.fixAuthor_lastNameFirstCommas((String) o, abbr_names, false);
return o;
}
diff --git a/src/java/net/sf/jabref/gui/MainTableSelectionListener.java b/src/java/net/sf/jabref/gui/MainTableSelectionListener.java
index 53227ce..f19f8d1 100644
--- a/src/java/net/sf/jabref/gui/MainTableSelectionListener.java
+++ b/src/java/net/sf/jabref/gui/MainTableSelectionListener.java
@@ -3,13 +3,15 @@ package net.sf.jabref.gui;
import ca.odell.glazedlists.event.ListEventListener;
import ca.odell.glazedlists.event.ListEvent;
import ca.odell.glazedlists.EventList;
+import ca.odell.glazedlists.SortedList;
import net.sf.jabref.*;
import net.sf.jabref.external.ExternalFileMenuItem;
import javax.swing.*;
-import java.awt.event.MouseListener;
-import java.awt.event.MouseEvent;
+import java.awt.event.*;
import java.io.IOException;
+import java.util.Comparator;
+import java.util.List;
/**
* Created by IntelliJ IDEA.
@@ -18,7 +20,8 @@ import java.io.IOException;
* Time: 3:02:52 AM
* To change this template use File | Settings | File Templates.
*/
-public class MainTableSelectionListener implements ListEventListener, MouseListener {
+public class MainTableSelectionListener implements ListEventListener, MouseListener,
+ KeyListener, FocusListener {
PreviewPanel[] previewPanel = null;
int activePreview = 1;
@@ -29,6 +32,14 @@ public class MainTableSelectionListener implements ListEventListener, MouseListe
private boolean previewActive = Globals.prefs.getBoolean("previewEnabled");
private boolean workingOnPreview = false;
+ // Register the last character pressed to quick jump in the table. Together
+ // with storing the last row number jumped to, this is used to let multiple
+ // key strokes cycle between all entries starting with the same letter:
+ private int lastPressed = '\n';
+ private int lastQuickJumpRow = -1;
+
+ //private int lastCharPressed = -1;
+
public MainTableSelectionListener(BasePanel panel, MainTable table) {
this.table = table;
this.panel = panel;
@@ -309,4 +320,100 @@ public class MainTableSelectionListener implements ListEventListener, MouseListe
}
}
}
+
+ /**
+ * We should implement a faster method than the one below, but this one doesn't
+ * work currently.
+ * @param e The KeyEvent
+ */
+ public void keyTyped_(KeyEvent e) {
+ //System.out.println(e.getKeyChar()+" "+table.getSortingColumn());
+ if ((!e.isActionKey()) && Character.isLetterOrDigit(e.getKeyChar())) {
+ int sortingColumn = table.getSortingColumn(0);
+ if (sortingColumn < 0)
+ return;
+ Comparator comp = table.getComparatorForColumn(sortingColumn);
+ int piv = 1;
+ while (((sortingColumn = table.getSortingColumn(piv)) >= 0)
+ && ((comp = table.getComparatorForColumn(sortingColumn)) != null)
+ && !(comp instanceof FieldComparator)) {
+ piv++;
+ }
+ if ((comp == null) || !(comp instanceof FieldComparator))
+ return;
+
+ // Ok, after all of this we should have either found a field name to go by
+ String field = ((FieldComparator)comp).getFieldName();
+ System.out.println(String.valueOf(e.getKeyChar())+" "+field);
+ SortedList list = table.getSortedForTable();
+ BibtexEntry testEntry = new BibtexEntry("0");
+ testEntry.setField(field, String.valueOf(e.getKeyChar()));
+ int i = list.sortIndex(testEntry);
+ System.out.println(i);
+ }
+ }
+
+ /**
+ * Receive key event on the main table. If the key is a letter or a digit,
+ * we should select the first entry in the table which starts with the given
+ * letter in the column by which the table is sorted.
+ * @param e The KeyEvent
+ */
+ public void keyTyped(KeyEvent e) {
+ if ((!e.isActionKey()) && Character.isLetterOrDigit(e.getKeyChar())
+ //&& !e.isControlDown() && !e.isAltDown() && !e.isMetaDown()) {
+ && (e.getModifiers() == 0)) {
+ int c = e.getKeyChar();
+ int sortingColumn = table.getSortingColumn(0);
+ if (sortingColumn == -1)
+ return; // No sorting? TODO: look up by author, etc.?
+ // TODO: the following lookup should be done by a faster algorithm,
+ // such as binary search. But the table may not be sorted properly,
+ // due to marked entries, search etc., which rules out the binary search.
+ int startRow = 0;
+ if ((c == lastPressed) && (lastQuickJumpRow >= 0)) {
+ if (lastQuickJumpRow < table.getRowCount()-1)
+ startRow = lastQuickJumpRow+1;
+ }
+
+ lastPressed = c;
+ boolean done = false;
+ while (!done) {
+ for (int i=startRow; i<table.getRowCount(); i++) {
+ Object o = table.getValueAt(i, sortingColumn);
+ if (o == null)
+ continue;
+ String s = o.toString().toLowerCase();
+ if ((s.length() >= 1) && (s.charAt(0) == c)) {
+ table.setRowSelectionInterval(i, i);
+ table.ensureVisible(i);
+ lastQuickJumpRow = i;
+ return;
+ }
+ }
+ // Finished, no result. If we didn't start at the beginning of
+ // the table, try that. Otherwise, exit the while loop.
+ if (startRow > 0)
+ startRow = 0;
+ else
+ done = true;
+
+ }
+
+ }
+ }
+
+ public void keyReleased(KeyEvent e) {
+ }
+
+ public void keyPressed(KeyEvent e) {
+ }
+
+ public void focusGained(FocusEvent e) {
+
+ }
+
+ public void focusLost(FocusEvent e) {
+ lastPressed = -1; // Reset quick jump when focus is lost.
+ }
}
diff --git a/src/java/net/sf/jabref/gui/date/DatePickerButton.java b/src/java/net/sf/jabref/gui/date/DatePickerButton.java
index 51ca0c8..22596fb 100644
--- a/src/java/net/sf/jabref/gui/date/DatePickerButton.java
+++ b/src/java/net/sf/jabref/gui/date/DatePickerButton.java
@@ -40,38 +40,38 @@
package net.sf.jabref.gui.date ;
import java.awt.event.* ;
+import java.awt.*;
import javax.swing.* ;
import com.michaelbaranov.microba.calendar.* ;
import net.sf.jabref.* ;
-import java.util.*;
-public class DatePickerButton implements ActionListener
-{
- private DatePicker datePicker = new DatePicker() ;
- private FieldEditor editor ;
+import java.util.*;
- public DatePickerButton(FieldEditor pEditor)
- {
- datePicker.showButtonOnly( true ) ;
- datePicker.addActionListener( this ) ;
+public class DatePickerButton implements ActionListener {
+ private DatePicker datePicker = new DatePicker();
+ private JPanel panel = new JPanel();
+ private FieldEditor editor;
- editor = pEditor ;
- }
+ public DatePickerButton(FieldEditor pEditor) {
+ datePicker.showButtonOnly(true);
+ datePicker.addActionListener(this);
+ panel.setLayout(new BorderLayout());
+ panel.add(datePicker, BorderLayout.WEST);
+ editor = pEditor;
+ }
- public void actionPerformed( ActionEvent e )
- {
- Date date = datePicker.getDate() ;
- if (date != null)
- {
- editor.setText( Util.easyDateFormat( date ) ) ;
- // Set focus to editor component after changing its text:
- new FocusRequester(editor.getTextComponent());
+ public void actionPerformed(ActionEvent e) {
+ Date date = datePicker.getDate();
+ if (date != null) {
+ editor.setText(Util.easyDateFormat(date));
+ // Set focus to editor component after changing its text:
+ new FocusRequester(editor.getTextComponent());
+ }
}
- }
- public JComponent getDatePicker()
- {
- return datePicker ;
- }
+ public JComponent getDatePicker() {
+ //return datePicker;
+ return panel;
+ }
}
diff --git a/src/java/net/sf/jabref/imports/BibtexParser.java b/src/java/net/sf/jabref/imports/BibtexParser.java
index 808fcc2..fe297e6 100644
--- a/src/java/net/sf/jabref/imports/BibtexParser.java
+++ b/src/java/net/sf/jabref/imports/BibtexParser.java
@@ -1,813 +1,840 @@
/*
-Copyright (C) 2003 David Weitzman, Nizar N. Batada, Morten O. Alver
+ Copyright (C) 2003-06 David Weitzman, Nizar N. Batada, Morten O. Alver
-All programs in this directory and
-subdirectories are published under the GNU General Public License as
-described below.
+ All programs in this directory and
+ subdirectories are published under the GNU General Public License as
+ described below.
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or (at
-your option) any later version.
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or (at
+ your option) any later version.
-This program is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
-USA
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA
-Further information about the GNU GPL is available at:
-http://www.gnu.org/copyleft/gpl.ja.html
+ Further information about the GNU GPL is available at:
+ http://www.gnu.org/copyleft/gpl.ja.html
-*/
+ */
package net.sf.jabref.imports;
-import java.io.*;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.PushbackReader;
+import java.io.Reader;
import java.util.HashMap;
import java.util.Iterator;
-import java.util.StringTokenizer;
import java.util.regex.Pattern;
-import net.sf.jabref.*;
-
-public class BibtexParser
-{
- private PushbackReader _in;
- private BibtexDatabase _db;
- private HashMap _meta, entryTypes;
- private boolean _eof = false;
- private int line = 1;
- private FieldContentParser fieldContentParser = new FieldContentParser();
-
- public BibtexParser(Reader in)
- {
- if (in == null)
- {
- throw new NullPointerException();
- }
-
- _in = new PushbackReader(in);
-
- }
-
- /**
- * Check whether the source is in the correct format for this importer.
- */
- public static boolean isRecognizedFormat(Reader inOrig)
- throws IOException {
- // Our strategy is to look for the "PY <year>" line.
- BufferedReader in =
- new BufferedReader(inOrig);
-
- //Pattern pat1 = Pattern.compile("PY: \\d{4}");
- Pattern pat1 = Pattern.compile("@[a-zA-Z]*\\s*\\{");
-
- String str;
-
- while ((str = in.readLine()) != null) {
-
- if (pat1.matcher(str).find())
- return true;
- else if (str.startsWith(GUIGlobals.SIGNATURE))
- return true;
- }
-
- return false;
- }
-
- private void skipWhitespace() throws IOException
- {
- int c;
-
- while (true)
- {
- c = read();
- if ((c == -1) || (c == 65535))
- {
- _eof = true;
- return;
- }
-
- if (Character.isWhitespace((char) c))
- {
- continue;
- }
- else
- // found non-whitespace char
- //Util.pr("SkipWhitespace, stops: "+c);
- unread(c);
- /* try {
- Thread.currentThread().sleep(500);
- } catch (InterruptedException ex) {}*/
- break;
- }
- }
-
- private String skipAndRecordWhitespace(int j) throws IOException
- {
- int c;
- StringBuffer sb = new StringBuffer();
- if (j != ' ')
- sb.append((char)j);
- while (true)
- {
- c = read();
- if ((c == -1) || (c == 65535))
- {
- _eof = true;
- return sb.toString();
- }
-
- if (Character.isWhitespace((char) c))
- {
- if (c != ' ')
- sb.append((char)c);
- continue;
- }
- else
- // found non-whitespace char
- //Util.pr("SkipWhitespace, stops: "+c);
- unread(c);
- /* try {
- Thread.currentThread().sleep(500);
- } catch (InterruptedException ex) {}*/
- break;
- }
- return sb.toString();
- }
-
-
- public ParserResult parse() throws IOException {
-
- _db = new BibtexDatabase(); // Bibtex related contents.
- _meta = new HashMap(); // Metadata in comments for Bibkeeper.
- entryTypes = new HashMap(); // To store custem entry types parsed.
- ParserResult _pr = new ParserResult(_db, _meta, entryTypes);
- skipWhitespace();
-
- try
- {
- while (!_eof)
- {
- boolean found = consumeUncritically('@');
- if (!found)
- break;
- skipWhitespace();
- String entryType = parseTextToken();
- BibtexEntryType tp = BibtexEntryType.getType(entryType);
- boolean isEntry = (tp != null);
- //Util.pr(tp.getName());
- if (!isEntry) {
- // The entry type name was not recognized. This can mean
- // that it is a string, preamble, or comment. If so,
- // parse and set accordingly. If not, assume it is an entry
- // with an unknown type.
- if (entryType.toLowerCase().equals("preamble")) {
- _db.setPreamble(parsePreamble());
- }
- else if (entryType.toLowerCase().equals("string")) {
- BibtexString bs = parseString();
- try {
- _db.addString(bs);
- } catch (KeyCollisionException ex) {
- _pr.addWarning(Globals.lang("Duplicate string name")+": "+bs.getName());
- //ex.printStackTrace();
- }
- }
- else if (entryType.toLowerCase().equals("comment")) {
- StringBuffer commentBuf = parseBracketedTextExactly();
- /**
- *
- * Metadata are used to store Bibkeeper-specific
- * information in .bib files.
- *
- * Metadata are stored in bibtex files in the format
- * @comment{jabref-meta: type:data0;data1;data2;...}
- *
- * Each comment that starts with the META_FLAG is stored
- * in the meta HashMap, with type as key.
- * Unluckily, the old META_FLAG bibkeeper-meta: was used
- * in JabRef 1.0 and 1.1, so we need to support it as
- * well. At least for a while. We'll always save with the
- * new one.
- */
- String comment = commentBuf.toString().replaceAll("[\\x0d\\x0a]","");
- if (comment.substring(0, Math.min(comment.length(), GUIGlobals.META_FLAG.length()))
- .equals(GUIGlobals.META_FLAG) ||
- comment.substring(0, Math.min(comment.length(), GUIGlobals.META_FLAG_OLD.length()))
- .equals(GUIGlobals.META_FLAG_OLD)) {
-
- String rest;
- if (comment.substring(0, GUIGlobals.META_FLAG.length())
- .equals(GUIGlobals.META_FLAG))
- rest = comment.substring
- (GUIGlobals.META_FLAG.length());
- else
- rest = comment.substring
- (GUIGlobals.META_FLAG_OLD.length());
-
- int pos = rest.indexOf(':');
-
- if (pos > 0)
- _meta.put
- (rest.substring(0, pos), rest.substring(pos+1));
- // We remove all line breaks in the metadata - these will have been inserted
- // to prevent too long lines when the file was saved, and are not part of the data.
- }
-
- /**
- * A custom entry type can also be stored in a @comment:
- */
- if (comment.substring(0, Math.min(comment.length(), GUIGlobals.ENTRYTYPE_FLAG.length()))
- .equals(GUIGlobals.ENTRYTYPE_FLAG)) {
-
- CustomEntryType typ = CustomEntryType.parseEntryType(comment);
- entryTypes.put(typ.getName().toLowerCase(), typ);
-
- }
- }
- else {
- // The entry type was not recognized. This may mean that
- // it is a custom entry type whose definition will appear
- // at the bottom of the file. So we use an UnknownEntryType
- // to remember the type name by.
- tp = new UnknownEntryType(entryType.toLowerCase());
- //System.out.println("unknown type: "+entryType);
- isEntry = true;
- }
- }
-
- if (isEntry) // True if not comment, preamble or string.
- {
- BibtexEntry be = parseEntry(tp);
-
- boolean duplicateKey = _db.insertEntry(be);
- if (duplicateKey) // JZTODO lyrics
- _pr.addWarning(Globals.lang("duplicate BibTeX key")+": "+be.getCiteKey()
- + " (" + Globals.lang("grouping may not work for this entry") + ")");
- else if (be.getCiteKey() == null || be.getCiteKey().equals("")) {
- _pr.addWarning(Globals.lang("empty BibTeX key")+": "+be.getAuthorTitleYear(40)
- + " (" + Globals.lang("grouping may not work for this entry") + ")");
- }
- }
-
- skipWhitespace();
- }
-
- // Before returning the database, update entries with unknown type
- // based on parsed type definitions, if possible.
- checkEntryTypes(_pr);
-
- return _pr;
- }
- catch (KeyCollisionException kce)
- {
- //kce.printStackTrace();
- throw new IOException("Duplicate ID in bibtex file: " +
- kce.toString());
- }
- }
-
- private int peek() throws IOException
- {
- int c = read();
- unread(c);
-
- return c;
- }
-
- private int read() throws IOException
- {
- int c = _in.read();
- if (c == '\n')
- line++;
- return c;
- }
-
- private void unread(int c) throws IOException
- {
- if (c == '\n')
- line--;
- _in.unread(c);
- }
-
- public BibtexString parseString() throws IOException
- {
- //Util.pr("Parsing string");
- skipWhitespace();
- consume('{','(');
- //while (read() != '}');
- skipWhitespace();
- //Util.pr("Parsing string name");
- String name = parseTextToken();
- //Util.pr("Parsed string name");
- skipWhitespace();
- //Util.pr("Now the contents");
- consume('=');
- String content = parseFieldContent();
- //Util.pr("Now I'm going to consume a }");
- consume('}',')');
- //Util.pr("Finished string parsing.");
- String id = Util.createNeutralId();
- return new BibtexString(id, name, content);
- }
-
- public String parsePreamble() throws IOException
- {
- return parseBracketedText().toString();
- }
-
- public BibtexEntry parseEntry(BibtexEntryType tp) throws IOException
- {
- String id = Util.createNeutralId();//createId(tp, _db);
- BibtexEntry result = new BibtexEntry(id, tp);
- skipWhitespace();
- consume('{','(');
- skipWhitespace();
- String key = null;
- boolean doAgain = true;
- while (doAgain) {
- doAgain = false;
- try {
- if (key != null)
- key = key+parseKey();//parseTextToken(),
- else key = parseKey();
- } catch (NoLabelException ex) {
- // This exception will be thrown if the entry lacks a key
- // altogether, like in "@article{ author = { ...".
- // It will also be thrown if a key contains =.
- char c = (char)peek();
- if (Character.isWhitespace(c) || (c == '{')
- || (c == '\"')) {
- String fieldName = ex.getMessage().trim().toLowerCase();
- String cont = parseFieldContent();
- result.setField(fieldName, cont);
- } else {
- if (key != null)
- key = key+ex.getMessage()+"=";
- else key = ex.getMessage()+"=";
- doAgain = true;
- }
- }
- }
-
- if ((key != null) && key.equals(""))
- key = null;
- //System.out.println("Key: "+key);
- if(result!=null)result.setField(BibtexFields.KEY_FIELD, key);
- skipWhitespace();
-
- while (true)
- {
- int c = peek();
- if ((c == '}') || (c == ')'))
- {
- break;
- }
-
- if (c == ',')
- consume(',');
-
- skipWhitespace();
-
- c = peek();
- if ((c == '}') || (c == ')'))
- {
- break;
- }
- parseField(result);
- }
-
- consume('}',')');
- return result;
- }
-
- private void parseField(BibtexEntry entry) throws IOException
- {
- String key = parseTextToken().toLowerCase();
- //Util.pr("Field: _"+key+"_");
- skipWhitespace();
- consume('=');
- String content = parseFieldContent();
- // Now, if the field in question is set up to be fitted automatically with braces around
- // capitals, we should remove those now when reading the field:
- if (Globals.prefs.putBracesAroundCapitals(key)) {
- content = Util.removeBracesAroundCapitals(content);
- }
- if (content.length() > 0) {
- if (entry.getField(key) == null)
- entry.setField(key, content);
- else {
- // The following hack enables the parser to deal with multiple author or
- // editor lines, stringing them together instead of getting just one of them.
- // Multiple author or editor lines are not allowed by the bibtex format, but
- // at least one online database exports bibtex like that, making it inconvenient
- // for users if JabRef didn't accept it.
- if (key.equals("author") || key.equals("editor"))
- entry.setField(key, entry.getField(key)+" and "+content);
- }
- }
- }
-
- private String parseFieldContent() throws IOException
- {
- skipWhitespace();
- StringBuffer value = new StringBuffer();
- int c,j='.';
-
- while (((c = peek()) != ',') && (c != '}') && (c != ')'))
- {
-
- if (_eof) {
- throw new RuntimeException("Error in line "+line+
- ": EOF in mid-string");
- }
- if (c == '"')
- {
- StringBuffer text = parseQuotedFieldExactly();
- value.append(fieldContentParser.format(text));
- /*
-
- The following code doesn't handle {"} correctly:
- // value is a string
- consume('"');
-
- while (!((peek() == '"') && (j != '\\')))
- {
- j = read();
- if (_eof || (j == -1) || (j == 65535))
- {
- throw new RuntimeException("Error in line "+line+
- ": EOF in mid-string");
- }
-
- value.append((char) j);
- }
-
- consume('"');
- */
- }
- else if (c == '{') {
- // Value is a string enclosed in brackets. There can be pairs
- // of brackets inside of a field, so we need to count the brackets
- // to know when the string is finished.
-
- //if (isStandardBibtexField || !Globals.prefs.getBoolean("preserveFieldFormatting")) {
- // value.append(parseBracketedText());
- // TEST TEST TEST TEST TEST
- StringBuffer text = parseBracketedTextExactly();
- value.append(fieldContentParser.format(text));
- //}
- //else
- // value.append(parseBracketedTextExactly());
- }
- else if (Character.isDigit((char) c))
- {
- // value is a number
- String numString = parseTextToken();
- int numVal = Integer.parseInt(numString);
- value.append((new Integer(numVal)).toString());
- //entry.setField(key, new Integer(numVal));
- }
- else if (c == '#')
- {
- //value.append(" # ");
- consume('#');
- }
- else
- {
- String textToken = parseTextToken();
- if (textToken.length() == 0)
- throw new IOException("Error in line "+line+" or above: "+
- "Empty text token.\nThis could be caused "+
- "by a missing comma between two fields.");
- value.append("#").append(textToken).append("#");
- //Util.pr(parseTextToken());
- //throw new RuntimeException("Unknown field type");
- }
- skipWhitespace();
- }
- //Util.pr("Returning field content: "+value.toString());
-
- // Check if we are to strip extra pairs of braces before returning:
- if (Globals.prefs.getBoolean("autoDoubleBraces")) {
- // Do it:
- while ((value.length()>1) && (value.charAt(0) == '{') && (value.charAt(value.length()-1) == '}')) {
- value.deleteCharAt(value.length()-1);
- value.deleteCharAt(0);
- }
- // Problem: if the field content is "{DNA} blahblah {EPA}", one pair too much will be removed.
- // Check if this is the case, and re-add as many pairs as needed.
- while (hasNegativeBraceCount(value.toString())) {
- value.insert(0, '{');
- value.append('}');
- }
-
- }
- return value.toString();
-
- }
-
- /**
- * Check if a string at any point has had more ending braces (}) than opening ones ({).
- * Will e.g. return true for the string "DNA} blahblal {EPA"
- * @param s The string to check.
- * @return true if at any index the brace count is negative.
- */
- private boolean hasNegativeBraceCount(String s) {
- //System.out.println(s);
- int i=0, count=0;
- while (i<s.length()) {
- if (s.charAt(i) == '{')
- count++;
- else if (s.charAt(i) == '}')
- count--;
- if (count < 0)
- return true;
- i++;
- }
- return false;
- }
-
- /**
- * This method is used to parse string labels, field names, entry
- * type and numbers outside brackets.
- */
- private String parseTextToken() throws IOException
- {
- StringBuffer token = new StringBuffer(20);
-
- while (true)
- {
- int c = read();
- //Util.pr(".. "+c);
- if (c == -1)
- {
- _eof = true;
-
- return token.toString();
- }
-
- if (Character.isLetterOrDigit((char) c) ||
- (c == ':') || (c == '-')
- || (c == '_') || (c == '*') || (c == '+') || (c == '.')
- || (c == '/') || (c == '\''))
- {
- token.append((char) c);
- }
- else
- {
- unread(c);
- //Util.pr("Pasted text token: "+token.toString());
- return token.toString();
- }
- }
- }
-
- /**
- * This method is used to parse the bibtex key for an entry.
- */
- private String parseKey() throws IOException,NoLabelException
- {
- StringBuffer token = new StringBuffer(20);
-
- while (true)
- {
- int c = read();
- //Util.pr(".. '"+(char)c+"'\t"+c);
- if (c == -1)
- {
- _eof = true;
-
- return token.toString();
- }
-
- // Ikke: #{}\uFFFD~\uFFFD
- //
- // G\uFFFDr: $_*+.-\/?"^
- if (!Character.isWhitespace((char)c) && (Character.isLetterOrDigit((char) c) ||
- ((c != '#') && (c != '{') && (c != '}') && (c != '\uFFFD')
- && (c != '~') && (c != '\uFFFD') && (c != ',') && (c != '=')
- )))
- {
- token.append((char) c);
- }
- else
- {
-
- if (Character.isWhitespace((char)c)) {
- // We have encountered white space instead of the comma at the end of
- // the key. Possibly the comma is missing, so we try to return what we
- // have found, as the key.
- return token.toString();
- }
- else if (c == ',') {
- unread(c);
- return token.toString();
- //} else if (Character.isWhitespace((char)c)) {
- //throw new NoLabelException(token.toString());
- } else if (c == '=') {
- // If we find a '=' sign, it is either an error, or
- // the entry lacked a comma signifying the end of the key.
-
- return token.toString();
- //throw new NoLabelException(token.toString());
-
- } else
- throw new IOException("Error in line "+line+":"+
- "Character '"+(char)c+"' is not "+
- "allowed in bibtex keys.");
-
- }
- }
-
-
- }
-
- private class NoLabelException extends Exception {
- public NoLabelException(String hasRead) {
- super(hasRead);
- }
- }
-
- private StringBuffer parseBracketedText() throws IOException
- {
- //Util.pr("Parse bracketed text");
- StringBuffer value = new StringBuffer();
-
- consume('{');
-
- int brackets = 0;
-
- while (!((peek() == '}') && (brackets == 0)))
- {
-
- int j = read();
- if ((j == -1) || (j == 65535))
- {
- throw new RuntimeException("Error in line "+line
- +": EOF in mid-string");
- }
- else if (j == '{')
- brackets++;
- else if (j == '}')
- brackets--;
-
- // If we encounter whitespace of any kind, read it as a
- // simple space, and ignore any others that follow immediately.
- /*if (j == '\n') {
- if (peek() == '\n')
- value.append('\n');
- }
- else*/ if (Character.isWhitespace((char)j)) {
- String whs = skipAndRecordWhitespace(j);
- //System.out.println(":"+whs+":");
- if (!whs.equals("") && !whs.equals("\n\t")) { // && !whs.equals("\n"))
- whs = whs.replaceAll("\t", ""); // Remove tabulators.
- //while (whs.endsWith("\t"))
- // whs = whs.substring(0, whs.length()-1);
- value.append(whs);
- }
- else
- value.append(' ');
-
-
- } else
- value.append((char) j);
-
- }
-
- consume('}');
-
- return value;
- }
-
- private StringBuffer parseBracketedTextExactly() throws IOException
- {
-
- StringBuffer value = new StringBuffer();
-
- consume('{');
-
- int brackets = 0;
-
- while (!((peek() == '}') && (brackets == 0)))
- {
+import net.sf.jabref.BibtexDatabase;
+import net.sf.jabref.BibtexEntry;
+import net.sf.jabref.BibtexEntryType;
+import net.sf.jabref.BibtexFields;
+import net.sf.jabref.BibtexString;
+import net.sf.jabref.CustomEntryType;
+import net.sf.jabref.GUIGlobals;
+import net.sf.jabref.Globals;
+import net.sf.jabref.JabRefPreferences;
+import net.sf.jabref.KeyCollisionException;
+import net.sf.jabref.UnknownEntryType;
+import net.sf.jabref.Util;
+
+/**
+ * Class for importing BibTeX-files.
+ *
+ * Use:
+ *
+ * BibtexParser parser = new BibtexParser(reader);
+ *
+ * ParserResult result = parser.parse();
+ *
+ * or
+ *
+ * ParserResult result = BibtexParser.parse(reader);
+ *
+ * Can be used stand-alone.
+ *
+ * @author David Weitzman
+ * @author Nizar N. Batada
+ * @author Morten O. Alver
+ * @author Christopher Oezbek
+ */
+public class BibtexParser {
+ private PushbackReader _in;
+
+ private BibtexDatabase _db;
+
+ private HashMap _meta, entryTypes;
+
+ private boolean _eof = false;
+
+ private int line = 1;
+
+ private FieldContentParser fieldContentParser = new FieldContentParser();
+
+ private ParserResult _pr;
+
+ public BibtexParser(Reader in) {
+
+ if (in == null) {
+ throw new NullPointerException();
+ }
+ if (Globals.prefs == null) {
+ Globals.prefs = JabRefPreferences.getInstance();
+ }
+ _in = new PushbackReader(in);
+ }
+
+ /**
+ * Shortcut usage to create a Parser and read the input.
+ *
+ * @param in -
+ * Reader to read from
+ * @throws IOException
+ */
+ public static ParserResult parse(Reader in) throws IOException {
+ BibtexParser parser = new BibtexParser(in);
+ return parser.parse();
+ }
+
+ /**
+ * Check whether the source is in the correct format for this importer.
+ */
+ public static boolean isRecognizedFormat(Reader inOrig) throws IOException {
+ // Our strategy is to look for the "PY <year>" line.
+ BufferedReader in = new BufferedReader(inOrig);
+
+ // Pattern pat1 = Pattern.compile("PY: \\d{4}");
+ Pattern pat1 = Pattern.compile("@[a-zA-Z]*\\s*\\{");
+
+ String str;
+
+ while ((str = in.readLine()) != null) {
+
+ if (pat1.matcher(str).find())
+ return true;
+ else if (str.startsWith(GUIGlobals.SIGNATURE))
+ return true;
+ }
+
+ return false;
+ }
+
+ private void skipWhitespace() throws IOException {
+ int c;
+
+ while (true) {
+ c = read();
+ if ((c == -1) || (c == 65535)) {
+ _eof = true;
+ return;
+ }
+
+ if (Character.isWhitespace((char) c)) {
+ continue;
+ } else
+ // found non-whitespace char
+ // Util.pr("SkipWhitespace, stops: "+c);
+ unread(c);
+ /*
+ * try { Thread.currentThread().sleep(500); } catch
+ * (InterruptedException ex) {}
+ */
+ break;
+ }
+ }
+
+ private String skipAndRecordWhitespace(int j) throws IOException {
+ int c;
+ StringBuffer sb = new StringBuffer();
+ if (j != ' ')
+ sb.append((char) j);
+ while (true) {
+ c = read();
+ if ((c == -1) || (c == 65535)) {
+ _eof = true;
+ return sb.toString();
+ }
+
+ if (Character.isWhitespace((char) c)) {
+ if (c != ' ')
+ sb.append((char) c);
+ continue;
+ } else
+ // found non-whitespace char
+ // Util.pr("SkipWhitespace, stops: "+c);
+ unread(c);
+ /*
+ * try { Thread.currentThread().sleep(500); } catch
+ * (InterruptedException ex) {}
+ */
+ break;
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Will parse the BibTex-Data found when reading from reader.
+ *
+ * The reader will be consumed.
+ *
+ * Multiple calls to parse() return the same results
+ *
+ * @return ParserResult
+ * @throws IOException
+ */
+ public ParserResult parse() throws IOException {
+
+ // If we already parsed this, just return it.
+ if (_pr != null)
+ return _pr;
+
+ _db = new BibtexDatabase(); // Bibtex related contents.
+ _meta = new HashMap(); // Metadata in comments for Bibkeeper.
+ entryTypes = new HashMap(); // To store custem entry types parsed.
+ _pr = new ParserResult(_db, _meta, entryTypes);
+ skipWhitespace();
+
+ try {
+ while (!_eof) {
+ boolean found = consumeUncritically('@');
+ if (!found)
+ break;
+ skipWhitespace();
+ String entryType = parseTextToken();
+ BibtexEntryType tp = BibtexEntryType.getType(entryType);
+ boolean isEntry = (tp != null);
+ // Util.pr(tp.getName());
+ if (!isEntry) {
+ // The entry type name was not recognized. This can mean
+ // that it is a string, preamble, or comment. If so,
+ // parse and set accordingly. If not, assume it is an entry
+ // with an unknown type.
+ if (entryType.toLowerCase().equals("preamble")) {
+ _db.setPreamble(parsePreamble());
+ } else if (entryType.toLowerCase().equals("string")) {
+ BibtexString bs = parseString();
+ try {
+ _db.addString(bs);
+ } catch (KeyCollisionException ex) {
+ _pr.addWarning(Globals.lang("Duplicate string name") + ": "
+ + bs.getName());
+ // ex.printStackTrace();
+ }
+ } else if (entryType.toLowerCase().equals("comment")) {
+ StringBuffer commentBuf = parseBracketedTextExactly();
+ /**
+ *
+ * Metadata are used to store Bibkeeper-specific
+ * information in .bib files.
+ *
+ * Metadata are stored in bibtex files in the format
+ *
+ * @comment{jabref-meta: type:data0;data1;data2;...}
+ *
+ * Each comment that starts with the META_FLAG is stored
+ * in the meta HashMap, with type as key. Unluckily, the
+ * old META_FLAG bibkeeper-meta: was used in JabRef 1.0
+ * and 1.1, so we need to support it as well. At least
+ * for a while. We'll always save with the new one.
+ */
+ String comment = commentBuf.toString().replaceAll("[\\x0d\\x0a]", "");
+ if (comment.substring(0,
+ Math.min(comment.length(), GUIGlobals.META_FLAG.length())).equals(
+ GUIGlobals.META_FLAG)
+ || comment.substring(0,
+ Math.min(comment.length(), GUIGlobals.META_FLAG_OLD.length()))
+ .equals(GUIGlobals.META_FLAG_OLD)) {
+
+ String rest;
+ if (comment.substring(0, GUIGlobals.META_FLAG.length()).equals(
+ GUIGlobals.META_FLAG))
+ rest = comment.substring(GUIGlobals.META_FLAG.length());
+ else
+ rest = comment.substring(GUIGlobals.META_FLAG_OLD.length());
+
+ int pos = rest.indexOf(':');
+
+ if (pos > 0)
+ _meta.put(rest.substring(0, pos), rest.substring(pos + 1));
+ // We remove all line breaks in the metadata - these
+ // will have been inserted
+ // to prevent too long lines when the file was
+ // saved, and are not part of the data.
+ }
+
+ /**
+ * A custom entry type can also be stored in a
+ *
+ * @comment:
+ */
+ if (comment.substring(0,
+ Math.min(comment.length(), GUIGlobals.ENTRYTYPE_FLAG.length())).equals(
+ GUIGlobals.ENTRYTYPE_FLAG)) {
+
+ CustomEntryType typ = CustomEntryType.parseEntryType(comment);
+ entryTypes.put(typ.getName().toLowerCase(), typ);
+
+ }
+ } else {
+ // The entry type was not recognized. This may mean that
+ // it is a custom entry type whose definition will
+ // appear
+ // at the bottom of the file. So we use an
+ // UnknownEntryType
+ // to remember the type name by.
+ tp = new UnknownEntryType(entryType.toLowerCase());
+ // System.out.println("unknown type: "+entryType);
+ isEntry = true;
+ }
+ }
+
+ if (isEntry) // True if not comment, preamble or string.
+ {
+ /**
+ * Morten Alver 13 Aug 2006: Trying to make the parser more
+ * robust. If an exception is thrown when parsing an entry,
+ * drop the entry and try to resume parsing. Add a warning
+ * for the user.
+ *
+ * An alternative solution is to try rescuing the entry for
+ * which parsing failed, by returning the entry with the
+ * exception and adding it before parsing is continued.
+ */
+ try {
+ BibtexEntry be = parseEntry(tp);
+
+ boolean duplicateKey = _db.insertEntry(be);
+ if (duplicateKey) // JZTODO lyrics
+ _pr.addWarning(Globals.lang("duplicate BibTeX key") + ": "
+ + be.getCiteKey() + " ("
+ + Globals.lang("grouping may not work for this entry") + ")");
+ else if (be.getCiteKey() == null || be.getCiteKey().equals("")) {
+ _pr.addWarning(Globals.lang("empty BibTeX key") + ": "
+ + be.getAuthorTitleYear(40) + " ("
+ + Globals.lang("grouping may not work for this entry") + ")");
+ }
+ } catch (IOException ex) {
+ ex.printStackTrace();
+ _pr.addWarning(Globals.lang("Error occured when parsing entry") + ": '"
+ + ex.getMessage() + "'. " + Globals.lang("Skipped entry."));
+
+ }
+ }
+
+ skipWhitespace();
+ }
+
+ // Before returning the database, update entries with unknown type
+ // based on parsed type definitions, if possible.
+ checkEntryTypes(_pr);
+
+ return _pr;
+ } catch (KeyCollisionException kce) {
+ // kce.printStackTrace();
+ throw new IOException("Duplicate ID in bibtex file: " + kce.toString());
+ }
+ }
+
+ private int peek() throws IOException {
+ int c = read();
+ unread(c);
+
+ return c;
+ }
+
+ private int read() throws IOException {
+ int c = _in.read();
+ if (c == '\n')
+ line++;
+ return c;
+ }
+
+ private void unread(int c) throws IOException {
+ if (c == '\n')
+ line--;
+ _in.unread(c);
+ }
+
+ public BibtexString parseString() throws IOException {
+ // Util.pr("Parsing string");
+ skipWhitespace();
+ consume('{', '(');
+ // while (read() != '}');
+ skipWhitespace();
+ // Util.pr("Parsing string name");
+ String name = parseTextToken();
+ // Util.pr("Parsed string name");
+ skipWhitespace();
+ // Util.pr("Now the contents");
+ consume('=');
+ String content = parseFieldContent();
+ // Util.pr("Now I'm going to consume a }");
+ consume('}', ')');
+ // Util.pr("Finished string parsing.");
+ String id = Util.createNeutralId();
+ return new BibtexString(id, name, content);
+ }
+
+ public String parsePreamble() throws IOException {
+ return parseBracketedText().toString();
+ }
+
+ public BibtexEntry parseEntry(BibtexEntryType tp) throws IOException {
+ String id = Util.createNeutralId();// createId(tp, _db);
+ BibtexEntry result = new BibtexEntry(id, tp);
+ skipWhitespace();
+ consume('{', '(');
+ skipWhitespace();
+ String key = null;
+ boolean doAgain = true;
+ while (doAgain) {
+ doAgain = false;
+ try {
+ if (key != null)
+ key = key + parseKey();// parseTextToken(),
+ else
+ key = parseKey();
+ } catch (NoLabelException ex) {
+ // This exception will be thrown if the entry lacks a key
+ // altogether, like in "@article{ author = { ...".
+ // It will also be thrown if a key contains =.
+ char c = (char) peek();
+ if (Character.isWhitespace(c) || (c == '{') || (c == '\"')) {
+ String fieldName = ex.getMessage().trim().toLowerCase();
+ String cont = parseFieldContent();
+ result.setField(fieldName, cont);
+ } else {
+ if (key != null)
+ key = key + ex.getMessage() + "=";
+ else
+ key = ex.getMessage() + "=";
+ doAgain = true;
+ }
+ }
+ }
+
+ if ((key != null) && key.equals(""))
+ key = null;
+ // System.out.println("Key: "+key);
+ if (result != null)
+ result.setField(BibtexFields.KEY_FIELD, key);
+ skipWhitespace();
+
+ while (true) {
+ int c = peek();
+ if ((c == '}') || (c == ')')) {
+ break;
+ }
+
+ if (c == ',')
+ consume(',');
+
+ skipWhitespace();
+
+ c = peek();
+ if ((c == '}') || (c == ')')) {
+ break;
+ }
+ parseField(result);
+ }
+
+ consume('}', ')');
+ return result;
+ }
+
+ private void parseField(BibtexEntry entry) throws IOException {
+ String key = parseTextToken().toLowerCase();
+ // Util.pr("Field: _"+key+"_");
+ skipWhitespace();
+ consume('=');
+ String content = parseFieldContent();
+ // Now, if the field in question is set up to be fitted automatically
+ // with braces around
+ // capitals, we should remove those now when reading the field:
+ if (Globals.prefs.putBracesAroundCapitals(key)) {
+ content = Util.removeBracesAroundCapitals(content);
+ }
+ if (content.length() > 0) {
+ if (entry.getField(key) == null)
+ entry.setField(key, content);
+ else {
+ // The following hack enables the parser to deal with multiple
+ // author or
+ // editor lines, stringing them together instead of getting just
+ // one of them.
+ // Multiple author or editor lines are not allowed by the bibtex
+ // format, but
+ // at least one online database exports bibtex like that, making
+ // it inconvenient
+ // for users if JabRef didn't accept it.
+ if (key.equals("author") || key.equals("editor"))
+ entry.setField(key, entry.getField(key) + " and " + content);
+ }
+ }
+ }
+
+ private String parseFieldContent() throws IOException {
+ skipWhitespace();
+ StringBuffer value = new StringBuffer();
+ int c, j = '.';
+
+ while (((c = peek()) != ',') && (c != '}') && (c != ')')) {
+
+ if (_eof) {
+ throw new RuntimeException("Error in line " + line + ": EOF in mid-string");
+ }
+ if (c == '"') {
+ StringBuffer text = parseQuotedFieldExactly();
+ value.append(fieldContentParser.format(text));
+ /*
+ *
+ * The following code doesn't handle {"} correctly: // value is
+ * a string consume('"');
+ *
+ * while (!((peek() == '"') && (j != '\\'))) { j = read(); if
+ * (_eof || (j == -1) || (j == 65535)) { throw new
+ * RuntimeException("Error in line "+line+ ": EOF in
+ * mid-string"); }
+ *
+ * value.append((char) j); }
+ *
+ * consume('"');
+ */
+ } else if (c == '{') {
+ // Value is a string enclosed in brackets. There can be pairs
+ // of brackets inside of a field, so we need to count the
+ // brackets to know when the string is finished.
+ StringBuffer text = parseBracketedTextExactly();
+ value.append(fieldContentParser.format(text));
+
+ } else if (Character.isDigit((char) c)) { // value is a number
+
+ String numString = parseTextToken();
+ try {
+ // Fixme: What is this for?
+ value.append(String.valueOf(Integer.parseInt(numString)));
+ } catch (NumberFormatException e) {
+ // If Integer could not be parsed then just add the text
+ // Used to fix [ 1594123 ] Failure to import big numbers
+ value.append(numString);
+ }
+ } else if (c == '#') {
+ consume('#');
+ } else {
+ String textToken = parseTextToken();
+ if (textToken.length() == 0)
+ throw new IOException("Error in line " + line + " or above: "
+ + "Empty text token.\nThis could be caused "
+ + "by a missing comma between two fields.");
+ value.append("#").append(textToken).append("#");
+ // Util.pr(parseTextToken());
+ // throw new RuntimeException("Unknown field type");
+ }
+ skipWhitespace();
+ }
+ // Util.pr("Returning field content: "+value.toString());
+
+ // Check if we are to strip extra pairs of braces before returning:
+ if (Globals.prefs.getBoolean("autoDoubleBraces")) {
+ // Do it:
+ while ((value.length() > 1) && (value.charAt(0) == '{')
+ && (value.charAt(value.length() - 1) == '}')) {
+ value.deleteCharAt(value.length() - 1);
+ value.deleteCharAt(0);
+ }
+ // Problem: if the field content is "{DNA} blahblah {EPA}", one pair
+ // too much will be removed.
+ // Check if this is the case, and re-add as many pairs as needed.
+ while (hasNegativeBraceCount(value.toString())) {
+ value.insert(0, '{');
+ value.append('}');
+ }
+
+ }
+ return value.toString();
+
+ }
+
+ /**
+ * Check if a string at any point has had more ending braces (}) than
+ * opening ones ({). Will e.g. return true for the string "DNA} blahblal
+ * {EPA"
+ *
+ * @param s
+ * The string to check.
+ * @return true if at any index the brace count is negative.
+ */
+ private boolean hasNegativeBraceCount(String s) {
+ // System.out.println(s);
+ int i = 0, count = 0;
+ while (i < s.length()) {
+ if (s.charAt(i) == '{')
+ count++;
+ else if (s.charAt(i) == '}')
+ count--;
+ if (count < 0)
+ return true;
+ i++;
+ }
+ return false;
+ }
+
+ /**
+ * This method is used to parse string labels, field names, entry type and
+ * numbers outside brackets.
+ */
+ private String parseTextToken() throws IOException {
+ StringBuffer token = new StringBuffer(20);
+
+ while (true) {
+ int c = read();
+ // Util.pr(".. "+c);
+ if (c == -1) {
+ _eof = true;
+
+ return token.toString();
+ }
+
+ if (Character.isLetterOrDigit((char) c) || (c == ':') || (c == '-') || (c == '_')
+ || (c == '*') || (c == '+') || (c == '.') || (c == '/') || (c == '\'')) {
+ token.append((char) c);
+ } else {
+ unread(c);
+ // Util.pr("Pasted text token: "+token.toString());
+ return token.toString();
+ }
+ }
+ }
+
+ /**
+ * This method is used to parse the bibtex key for an entry.
+ */
+ private String parseKey() throws IOException, NoLabelException {
+ StringBuffer token = new StringBuffer(20);
+
+ while (true) {
+ int c = read();
+ // Util.pr(".. '"+(char)c+"'\t"+c);
+ if (c == -1) {
+ _eof = true;
+
+ return token.toString();
+ }
+
+ // Ikke: #{}\uFFFD~\uFFFD
+ //
+ // G\uFFFDr: $_*+.-\/?"^
+ if (!Character.isWhitespace((char) c)
+ && (Character.isLetterOrDigit((char) c) || ((c != '#') && (c != '{') && (c != '}')
+ && (c != '\uFFFD') && (c != '~') && (c != '\uFFFD') && (c != ',') && (c != '=')))) {
+ token.append((char) c);
+ } else {
+
+ if (Character.isWhitespace((char) c)) {
+ // We have encountered white space instead of the comma at
+ // the end of
+ // the key. Possibly the comma is missing, so we try to
+ // return what we
+ // have found, as the key.
+ return token.toString();
+ } else if (c == ',') {
+ unread(c);
+ return token.toString();
+ // } else if (Character.isWhitespace((char)c)) {
+ // throw new NoLabelException(token.toString());
+ } else if (c == '=') {
+ // If we find a '=' sign, it is either an error, or
+ // the entry lacked a comma signifying the end of the key.
+
+ return token.toString();
+ // throw new NoLabelException(token.toString());
+
+ } else
+ throw new IOException("Error in line " + line + ":" + "Character '" + (char) c
+ + "' is not " + "allowed in bibtex keys.");
+
+ }
+ }
+
+ }
+
+ private class NoLabelException extends Exception {
+ public NoLabelException(String hasRead) {
+ super(hasRead);
+ }
+ }
+
+ private StringBuffer parseBracketedText() throws IOException {
+ // Util.pr("Parse bracketed text");
+ StringBuffer value = new StringBuffer();
- int j = read();
- if ((j == -1) || (j == 65535))
- {
- throw new RuntimeException("Error in line "+line
- +": EOF in mid-string");
- }
- else if (j == '{')
- brackets++;
- else if (j == '}')
- brackets--;
-
- value.append((char) j);
+ consume('{');
- }
+ int brackets = 0;
- consume('}');
+ while (!((peek() == '}') && (brackets == 0))) {
- return value;
- }
-
- private StringBuffer parseQuotedFieldExactly() throws IOException
- {
+ int j = read();
+ if ((j == -1) || (j == 65535)) {
+ throw new RuntimeException("Error in line " + line + ": EOF in mid-string");
+ } else if (j == '{')
+ brackets++;
+ else if (j == '}')
+ brackets--;
- StringBuffer value = new StringBuffer();
+ // If we encounter whitespace of any kind, read it as a
+ // simple space, and ignore any others that follow immediately.
+ /*
+ * if (j == '\n') { if (peek() == '\n') value.append('\n'); } else
+ */
+ if (Character.isWhitespace((char) j)) {
+ String whs = skipAndRecordWhitespace(j);
- consume('"');
+ // System.out.println(":"+whs+":");
- int brackets = 0;
-
- while (!((peek() == '"') && (brackets == 0)))
- {
-
- int j = read();
- if ((j == -1) || (j == 65535))
- {
- throw new RuntimeException("Error in line "+line
- +": EOF in mid-string");
- }
- else if (j == '{')
- brackets++;
- else if (j == '}')
- brackets--;
-
- value.append((char) j);
-
- }
-
- consume('"');
-
- return value;
- }
-
- private void consume(char expected) throws IOException
- {
- int c = read();
-
- if (c != expected)
- {
- throw new RuntimeException("Error in line "+line
- +": Expected "
- + expected + " but received " + (char) c);
- }
+ if (!whs.equals("") && !whs.equals("\n\t")) { // &&
+ // !whs.equals("\n"))
- }
+ whs = whs.replaceAll("\t", ""); // Remove tabulators.
- private boolean consumeUncritically(char expected) throws IOException
- {
- int c;
- while (((c = read()) != expected) && (c != -1) && (c != 65535));
- if ((c == -1) || (c == 65535))
- _eof = true;
+ // while (whs.endsWith("\t"))
+ // whs = whs.substring(0, whs.length()-1);
- // Return true if we actually found the character we were looking for:
- return c == expected;
- }
+ value.append(whs);
- private void consume(char expected1, char expected2) throws IOException
- {
- // Consumes one of the two, doesn't care which appears.
+ } else {
+ value.append(' ');
+ }
- int c = read();
+ } else
+ value.append((char) j);
- if ((c != expected1) && (c != expected2))
- {
- throw new RuntimeException("Error in line "+line+": Expected " +
- expected1 + " or " + expected2 + " but received " + (int) c);
+ }
- }
+ consume('}');
- }
+ return value;
+ }
- public void checkEntryTypes(ParserResult _pr) {
- for (Iterator i=_db.getKeySet().iterator(); i.hasNext();) {
- Object key = i.next();
- BibtexEntry be = (BibtexEntry)_db.getEntryById((String)key);
- if (be.getType() instanceof UnknownEntryType) {
- // Look up the unknown type name in our map of parsed types:
-
- Object o = entryTypes.get(be.getType().getName().toLowerCase());
- if (o != null) {
- BibtexEntryType type = (BibtexEntryType)o;
- be.setType(type);
- } else {
- //System.out.println("Unknown entry type: "+be.getType().getName());
- _pr.addWarning(Globals.lang("unknown entry type")+": "+be.getType().getName()+". "+
- Globals.lang("Type set to 'other'")+".");
- be.setType(BibtexEntryType.OTHER);
- }
- }
- }
- }
+ private StringBuffer parseBracketedTextExactly() throws IOException {
+
+ StringBuffer value = new StringBuffer();
+
+ consume('{');
+
+ int brackets = 0;
+
+ while (!((peek() == '}') && (brackets == 0))) {
+
+ int j = read();
+ if ((j == -1) || (j == 65535)) {
+ throw new RuntimeException("Error in line " + line + ": EOF in mid-string");
+ } else if (j == '{')
+ brackets++;
+ else if (j == '}')
+ brackets--;
+
+ value.append((char) j);
+
+ }
+
+ consume('}');
+
+ return value;
+ }
+
+ private StringBuffer parseQuotedFieldExactly() throws IOException {
+
+ StringBuffer value = new StringBuffer();
+
+ consume('"');
+
+ int brackets = 0;
+
+ while (!((peek() == '"') && (brackets == 0))) {
+
+ int j = read();
+ if ((j == -1) || (j == 65535)) {
+ throw new RuntimeException("Error in line " + line + ": EOF in mid-string");
+ } else if (j == '{')
+ brackets++;
+ else if (j == '}')
+ brackets--;
+
+ value.append((char) j);
+
+ }
+
+ consume('"');
+
+ return value;
+ }
+
+ private void consume(char expected) throws IOException {
+ int c = read();
+
+ if (c != expected) {
+ throw new RuntimeException("Error in line " + line + ": Expected " + expected
+ + " but received " + (char) c);
+ }
+
+ }
+
+ private boolean consumeUncritically(char expected) throws IOException {
+ int c;
+ while (((c = read()) != expected) && (c != -1) && (c != 65535))
+ ;
+ if ((c == -1) || (c == 65535))
+ _eof = true;
+
+ // Return true if we actually found the character we were looking for:
+ return c == expected;
+ }
+
+ private void consume(char expected1, char expected2) throws IOException {
+ // Consumes one of the two, doesn't care which appears.
+
+ int c = read();
+
+ if ((c != expected1) && (c != expected2)) {
+ throw new RuntimeException("Error in line " + line + ": Expected " + expected1 + " or "
+ + expected2 + " but received " + (int) c);
+
+ }
+
+ }
+
+ public void checkEntryTypes(ParserResult _pr) {
+ for (Iterator i = _db.getKeySet().iterator(); i.hasNext();) {
+ Object key = i.next();
+ BibtexEntry be = (BibtexEntry) _db.getEntryById((String) key);
+ if (be.getType() instanceof UnknownEntryType) {
+ // Look up the unknown type name in our map of parsed types:
+
+ Object o = entryTypes.get(be.getType().getName().toLowerCase());
+ if (o != null) {
+ BibtexEntryType type = (BibtexEntryType) o;
+ be.setType(type);
+ } else {
+ // System.out.println("Unknown entry type:
+ // "+be.getType().getName());
+ _pr
+ .addWarning(Globals.lang("unknown entry type") + ": "
+ + be.getType().getName() + ". " + Globals.lang("Type set to 'other'")
+ + ".");
+ be.setType(BibtexEntryType.OTHER);
+ }
+ }
+ }
+ }
}
diff --git a/src/java/net/sf/jabref/imports/CiteSeerFetcher.java b/src/java/net/sf/jabref/imports/CiteSeerFetcher.java
index 2be2189..e540d23 100644
--- a/src/java/net/sf/jabref/imports/CiteSeerFetcher.java
+++ b/src/java/net/sf/jabref/imports/CiteSeerFetcher.java
@@ -362,7 +362,7 @@ public class CiteSeerFetcher extends SidePaneComponent {
progressBar.setString("");
progressBar2.setVisible(false);
citeSeerProgress.setText("");
- sidePaneManager.ensureVisible("CiteSeerProgress");
+ sidePaneManager.show("CiteSeerProgress");
}
public void endImportCiteSeerProgress() {
progressBar.setIndeterminate(false);
diff --git a/src/java/net/sf/jabref/imports/CiteSeerFetcherPanel.java b/src/java/net/sf/jabref/imports/CiteSeerFetcherPanel.java
index a5411e9..9f09ed6 100644
--- a/src/java/net/sf/jabref/imports/CiteSeerFetcherPanel.java
+++ b/src/java/net/sf/jabref/imports/CiteSeerFetcherPanel.java
@@ -1,21 +1,32 @@
package net.sf.jabref.imports;
-import java.net.*;
-import javax.swing.*;
-import java.awt.*;
-import java.awt.event.ActionListener;
+import java.awt.BorderLayout;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
import java.awt.event.ActionEvent;
-import java.util.*;
-//import java.util.regex.Pattern;
-//import java.util.regex.Matcher;
-import net.sf.jabref.*;
-import net.sf.jabref.undo.NamedCompound;
-import net.sf.jabref.undo.UndoableInsertEntry;
-
-import java.io.*;
-
+import java.awt.event.ActionListener;
+import java.util.Arrays;
+import java.util.Hashtable;
+
+import javax.swing.BorderFactory;
+import javax.swing.JButton;
+import javax.swing.JFrame;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JTextField;
+
+import net.sf.jabref.BibtexEntry;
+import net.sf.jabref.BibtexEntryType;
+import net.sf.jabref.BibtexFields;
+import net.sf.jabref.GUIGlobals;
+import net.sf.jabref.Globals;
import net.sf.jabref.HelpAction;
+import net.sf.jabref.SidePaneComponent;
+import net.sf.jabref.SidePaneManager;
+import net.sf.jabref.Util;
import net.sf.jabref.gui.ImportInspectionDialog;
+import net.sf.jabref.undo.NamedCompound;
/**
* <p>Title: </p>
diff --git a/src/java/net/sf/jabref/imports/GeneralFetcher.java b/src/java/net/sf/jabref/imports/GeneralFetcher.java
index 9aa3514..f1c0e7b 100644
--- a/src/java/net/sf/jabref/imports/GeneralFetcher.java
+++ b/src/java/net/sf/jabref/imports/GeneralFetcher.java
@@ -44,9 +44,9 @@ public class GeneralFetcher extends SidePaneComponent implements ActionListener
action = new FetcherAction();
help = new HelpAction(Globals.helpDiag, fetcher.getHelpPage(), "Help");
-
helpBut.addActionListener(help);
helpBut.setMargin(new Insets(0, 0, 0, 0));
+
JPanel main = new JPanel();
main.setLayout(gbl);
con.fill = GridBagConstraints.BOTH;
@@ -59,14 +59,24 @@ public class GeneralFetcher extends SidePaneComponent implements ActionListener
con.fill = GridBagConstraints.BOTH;
gbl.setConstraints(tf, con);
main.add(tf);
+
+ // Go Button
con.weighty = 0;
- con.gridwidth = 1;
+ if (fetcher.getHelpPage() != null){
+ con.gridwidth = 1;
+ } else {
+ con.gridwidth = GridBagConstraints.REMAINDER;
+ }
gbl.setConstraints(go, con);
main.add(go);
- con.gridwidth = GridBagConstraints.REMAINDER;
- gbl.setConstraints(helpBut, con);
- main.add(helpBut);
-
+
+ // Help Button
+ if (fetcher.getHelpPage() != null) {
+ con.gridwidth = GridBagConstraints.REMAINDER;
+ gbl.setConstraints(helpBut, con);
+ main.add(helpBut);
+ }
+
JPanel pan = fetcher.getOptionsPanel();
if (pan != null) {
gbl.setConstraints(pan, con);
@@ -95,7 +105,6 @@ public class GeneralFetcher extends SidePaneComponent implements ActionListener
dialog.addCallBack(fetcher);
Util.placeDialog(dialog, frame);
fetcher.processQuery(tf.getText().trim(), dialog, frame);
-
}
class FetcherAction extends AbstractAction {
@@ -104,8 +113,18 @@ public class GeneralFetcher extends SidePaneComponent implements ActionListener
putValue(ACCELERATOR_KEY, Globals.prefs.getKey(fetcher.getKeyName()));
}
public void actionPerformed(ActionEvent e) {
- sidePaneManager.add(fetcher.getTitle(), GeneralFetcher.this);
+ String fetcherTitle = fetcher.getTitle();
+
+ if (!sidePaneManager.hasComponent(fetcherTitle)){
+ sidePaneManager.register(fetcherTitle, GeneralFetcher.this);
+ }
+
+ if (frame.getTabbedPane().getTabCount() > 0) {
+ sidePaneManager.toggle(fetcherTitle);
+ if (sidePaneManager.isComponentVisible(fetcherTitle)) {
+ new FocusRequester(getTextField());
+ }
+ }
}
}
-
}
diff --git a/src/java/net/sf/jabref/imports/ImportFileFilter.java b/src/java/net/sf/jabref/imports/ImportFileFilter.java
new file mode 100644
index 0000000..f70e640
--- /dev/null
+++ b/src/java/net/sf/jabref/imports/ImportFileFilter.java
@@ -0,0 +1,38 @@
+package net.sf.jabref.imports;
+
+import javax.swing.filechooser.FileFilter;
+import java.io.File;
+
+/**
+ * File filter that lets the user choose export format while choosing file to
+ * export to. Contains a reference to the ExportFormat in question.
+ */
+public class ImportFileFilter extends FileFilter implements Comparable {
+ private ImportFormat format;
+ private String name;
+
+ public ImportFileFilter(ImportFormat format) {
+ this.format = format;
+ this.name = format.getFormatName();
+ }
+
+ public ImportFormat getImportFormat() {
+ return format;
+ }
+
+ public boolean accept(File file) {
+ return true;
+ /*if (file.isDirectory())
+ return true;
+ else
+ return file.getPath().toLowerCase().endsWith(extension);*/
+ }
+
+ public String getDescription() {
+ return name;
+ }
+
+ public int compareTo(Object o) {
+ return name.compareTo(((ImportFileFilter)o).name);
+ }
+}
\ No newline at end of file
diff --git a/src/java/net/sf/jabref/imports/ImportFormatReader.java b/src/java/net/sf/jabref/imports/ImportFormatReader.java
index 5893798..f6ee34d 100644
--- a/src/java/net/sf/jabref/imports/ImportFormatReader.java
+++ b/src/java/net/sf/jabref/imports/ImportFormatReader.java
@@ -83,7 +83,8 @@ public class ImportFormatReader {
formats.add(new JstorImporter());
formats.add(new SilverPlatterImporter());
formats.add(new BiomailImporter());
- formats.add(new RepecNepImporter());
+ formats.add(new RepecNepImporter());
+ formats.add(new PdfXmpImporter());
// add all custom importers
for (Iterator i = Globals.prefs.customImports.iterator(); i.hasNext(); ) {
@@ -454,33 +455,31 @@ public class ImportFormatReader {
int bestResult = 0;
// Cycle through all importers:
- for (Iterator i = getImportFormats().iterator(); i.hasNext();) {
- ImportFormat imFo = (ImportFormat)i.next();
-
- try {
- //System.out.println("Trying format: "+imFo.getFormatName());
- List entries = importFromFile(imFo, filename);
-
- if (entries != null)
- purgeEmptyEntries(entries);
-
- int entryCount = ((entries != null) ? entries.size() : 0);
-
- //System.out.println("Entries: "+entryCount);
- //BibtexDatabase base = importFile(formats[i], filename);
- if (entryCount > bestResult) {
- bestResult = entryCount;
- usedFormat = imFo.getFormatName();
- entryList = entries;
- //System.out.println("Looks good: "+imFo.getFormatName());
- }
- } catch (IOException ex) {
- //ex.printStackTrace();
- //System.out.println("Import failed");
- }
- }
-
- // Finally, if all else fails, see if it is a BibTeX file:
+ for (Iterator i = getImportFormats().iterator(); i.hasNext();) {
+ ImportFormat imFo = (ImportFormat) i.next();
+
+ try {
+ // System.out.println("Trying format: "+imFo.getFormatName());
+ List entries = importFromFile(imFo, filename);
+
+ if (entries != null)
+ purgeEmptyEntries(entries);
+
+ int entryCount = ((entries != null) ? entries.size() : 0);
+
+ // System.out.println("Entries: "+entryCount);
+ // BibtexDatabase base = importFile(formats[i], filename);
+ if (entryCount > bestResult) {
+ bestResult = entryCount;
+ usedFormat = imFo.getFormatName();
+ entryList = entries;
+ // System.out.println("Looks good: "+imFo.getFormatName());
+ }
+ } catch (Exception e) {
+ }
+ }
+ System.out.println("Used format: "+usedFormat);
+ // Finally, if all else fails, see if it is a BibTeX file:
if (entryList == null) {
try {
ParserResult pr = OpenDatabaseAction.loadDatabase(new File(filename), Globals.prefs.get("defaultEncoding"));
diff --git a/src/java/net/sf/jabref/imports/ImportFormats.java b/src/java/net/sf/jabref/imports/ImportFormats.java
new file mode 100644
index 0000000..3006c36
--- /dev/null
+++ b/src/java/net/sf/jabref/imports/ImportFormats.java
@@ -0,0 +1,122 @@
+package net.sf.jabref.imports;
+
+import net.sf.jabref.Globals;
+import net.sf.jabref.JabRefFrame;
+import net.sf.jabref.MnemonicAwareAction;
+import net.sf.jabref.BibtexEntry;
+
+import javax.swing.*;
+import javax.swing.filechooser.FileFilter;
+import java.util.*;
+import java.awt.event.ActionEvent;
+import java.io.File;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: alver
+ * Date: Oct 22, 2006
+ * Time: 12:06:09 PM
+ * To change this template use File | Settings | File Templates.
+ */
+public class ImportFormats {
+
+ public static JFileChooser createImportFileChooser(String currentDir) {
+ SortedSet builtImporters = Globals.importFormatReader.getBuiltInInputFormats();
+ SortedSet customImporters = Globals.importFormatReader.getCustomImportFormats();
+ SortedSet importers = new TreeSet();
+ for (Iterator i = builtImporters.iterator(); i.hasNext();) {
+ importers.add(i.next());
+ }
+ for (Iterator i = customImporters.iterator(); i.hasNext();) {
+ importers.add(i.next());
+ }
+ String lastUsedFormat = Globals.prefs.get("lastUsedImport");
+ FileFilter defaultFilter = null;
+ JFileChooser fc = new JFileChooser(currentDir);
+ TreeSet filters = new TreeSet();
+ for (Iterator i = importers.iterator(); i.hasNext();) {
+ ImportFormat format = (ImportFormat)i.next();
+ ImportFileFilter filter = new ImportFileFilter(format);
+ filters.add(filter);
+ if (format.getFormatName().equals(lastUsedFormat))
+ defaultFilter = filter;
+ }
+ for (Iterator i=filters.iterator(); i.hasNext();) {
+ fc.addChoosableFileFilter((ImportFileFilter)i.next());
+ }
+ //fc.setAcceptAllFileFilterUsed(false);
+ if (defaultFilter != null)
+ fc.setFileFilter(defaultFilter);
+ else
+ fc.setFileFilter(fc.getAcceptAllFileFilter());
+ return fc;
+ }
+
+ /**
+ * Create an AbstractAction for performing an Import operation.
+ * @param frame The JabRefFrame of this JabRef instance.
+ * @param openInNew Indicate whether the action should open into a new database or
+ * into the currently open one.
+ * @return The action.
+ */
+ public static AbstractAction getImportAction(JabRefFrame frame, boolean openInNew) {
+
+ class ImportAction extends MnemonicAwareAction {
+ private JabRefFrame frame;
+ private boolean openInNew;
+
+
+ public ImportAction(JabRefFrame frame, boolean openInNew) {
+ this.frame = frame;
+ this.openInNew = openInNew;
+
+ putValue(NAME, openInNew ? "Import into new database" :
+ "Import into current database");
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ JFileChooser fc = ImportFormats.createImportFileChooser
+ (Globals.prefs.get("importWorkingDirectory"));
+ fc.showOpenDialog(frame);
+ File file = fc.getSelectedFile();
+ if (file == null)
+ return;
+ FileFilter ff = fc.getFileFilter();
+ ImportFileFilter iff = null;
+ ImportFormat format = null;
+ if (ff instanceof ImportFileFilter)
+ format = ((ImportFileFilter)ff).getImportFormat();
+
+ try {
+ String path = file.getPath();
+ if (!file.exists()) {
+ // Warn that the file doesn't exists:
+ JOptionPane.showMessageDialog(frame,
+ Globals.lang("File not found")+
+ ": '"+file.getName()+"'.",
+ Globals.lang("Import"), JOptionPane.ERROR_MESSAGE);
+ return;
+ }
+
+ ImportMenuItem imi = new ImportMenuItem(frame,
+ openInNew, format);
+ imi.automatedImport(new String[] {file.getAbsolutePath()});
+
+
+ // Make sure we remember which filter was used, to set the default
+ // for next time:
+ if (format != null)
+ Globals.prefs.put("lastUsedImport", format.getFormatName());
+ else
+ Globals.prefs.put("lastUsedImport", "__all");
+ Globals.prefs.put("importWorkingDirectory", file.getParent());
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ }
+
+ }
+ };
+
+ return new ImportAction(frame, openInNew);
+ }
+}
diff --git a/src/java/net/sf/jabref/imports/ImportMenuItem.java b/src/java/net/sf/jabref/imports/ImportMenuItem.java
index 7c7e4ab..9df3097 100644
--- a/src/java/net/sf/jabref/imports/ImportMenuItem.java
+++ b/src/java/net/sf/jabref/imports/ImportMenuItem.java
@@ -189,9 +189,11 @@ public class ImportMenuItem extends JMenuItem implements ActionListener {
}
public void done(int entriesImported) {
+
+ /*
final BasePanel panel = (BasePanel) frame.getTabbedPane().getSelectedComponent();
BibtexDatabase toAddTo = panel.database();
- /*
+
// Add the strings, if any:
for (Iterator i = bibtexResult.getDatabase().getStringKeySet().iterator(); i.hasNext();) {
BibtexString s = bibtexResult.getDatabase().getString(i.next());
@@ -216,10 +218,8 @@ public class ImportMenuItem extends JMenuItem implements ActionListener {
}
*/
- if ((worker != null) && (worker.bibtexResult != null)) {
- frame.output(Globals.lang("Imported entries") + ": " + entriesImported);
- // + " " + Globals.lang("Format used") + ": " + worker.formatName);
- }
+ frame.output(Globals.lang("Imported entries") + ": " + entriesImported);
+
}
public void cancelled() {
diff --git a/src/java/net/sf/jabref/imports/IsiImporter.java b/src/java/net/sf/jabref/imports/IsiImporter.java
index c64454d..b16d60c 100644
--- a/src/java/net/sf/jabref/imports/IsiImporter.java
+++ b/src/java/net/sf/jabref/imports/IsiImporter.java
@@ -1,248 +1,423 @@
package net.sf.jabref.imports;
-import net.sf.jabref.BibtexEntry;
-import net.sf.jabref.Globals;
-import net.sf.jabref.AuthorList;
-
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
-
import java.util.ArrayList;
import java.util.HashMap;
-import java.util.List;
import java.util.Iterator;
+import java.util.List;
+import java.util.regex.Matcher;
import java.util.regex.Pattern;
-import net.sf.jabref.BibtexFields;
+import net.sf.jabref.BibtexEntry;
+import net.sf.jabref.BibtexFields;
+import net.sf.jabref.Globals;
+import net.sf.jabref.Util;
+import net.sf.jabref.util.CaseChanger;
/**
- * Importer for the ISI Web of Science format.
+ * Importer for the ISI Web of Science, INSPEC and Medline format.
+ *
+ * Documentation about ISI WOS format:
+ *
+ * <ul>
+ * <li>http://wos.isitrial.com/help/helpprn.html</li>
+ * </ul>
+ *
+ * Todo:
+ * <ul>
+ * <li>Check compatibility with other ISI2Bib tools like:
+ * http://www-lab.imr.tohoku.ac.jp/~t-nissie/computer/software/isi/ or
+ * http://www.tug.org/tex-archive/biblio/bibtex/utils/isi2bibtex/isi2bibtex or
+ * http://web.mit.edu/emilio/www/utils.html</li>
+ * <li>Deal with capitalization correctly</li>
+ * </ul>
+ *
+ * @author $Author: mortenalver $
+ * @version $Revision: 1.21 $ ($Date: 2006/09/05 21:50:23 $)
+ *
*/
public class IsiImporter extends ImportFormat {
- /**
- * Return the name of this import format.
- */
- public String getFormatName() {
- return "ISI";
- }
-
- /*
- * (non-Javadoc)
- * @see net.sf.jabref.imports.ImportFormat#getCLIId()
- */
- public String getCLIId() {
- return "isi";
- }
-
- /**
- * Check whether the source is in the correct format for this importer.
- */
- public boolean isRecognizedFormat(InputStream stream)
- throws IOException {
- // Our strategy is to look for the "PY <year>" line.
- BufferedReader in =
- new BufferedReader(ImportFormatReader.getReaderDefaultEncoding(stream));
- Pattern pat1 = Pattern.compile("PY \\d{4}");
-
- //was PY \\\\d{4}? before
- String str;
-
- while ((str = in.readLine()) != null) {
-
- // The following line gives false positives for RIS files, so it should
- // not be uncommented. The hypen is a characteristic of the RIS format.
- //str = str.replace(" - ", "");
-
-
- if (pat1.matcher(str).find())
- return true;
- }
-
- return false;
- }
-
- /**
- * Parse the entries in the source, and return a List of BibtexEntry
- * objects.
- */
- public List importEntries(InputStream stream) throws IOException {
- ArrayList bibitems = new ArrayList();
- StringBuffer sb = new StringBuffer();
-
- BufferedReader in =
- new BufferedReader(ImportFormatReader.getReaderDefaultEncoding(stream));
-
- //Pattern fieldPattern = Pattern.compile("^AU |^TI |^SO |^DT |^C1 |^AB
- // |^ID |^BP |^PY |^SE |^PY |^VL |^IS ");
- String str;
-
- while ((str = in.readLine()) != null) {
- if (str.length() < 3)
- continue;
-
- // begining of a new item
- if (str.substring(0, 3).equals("PT "))
- sb.append("::").append(str);
- else {
- String beg = str.substring(0, 3).trim();
-
- // I could have used the fieldPattern regular expression instead
- // however this seems to be
- // quick and dirty and it works!
- if (beg.length() == 2) {
- sb.append(" ## "); // mark the begining of each field
- sb.append(str);
- } else {
- sb.append("EOLEOL"); // mark the end of each line
- sb.append(str.substring(2, str.length())); //remove the initial " "
- }
- }
- }
-
- String[] entries = sb.toString().split("::");
-
- // skip the first entry as it is either empty or has document header
- HashMap hm = new HashMap();
-
- for (int i = 0; i < entries.length; i++) {
- String[] fields = entries[i].split(" ## ");
-
- if (fields.length == 0)
- fields = entries[i].split("\n");
-
- String Type = "";
- String PT = "";
- String pages = "";
- hm.clear();
-
- for (int j = 0; j < fields.length; j++) {
- //empty field don't do anything
- if (fields[j].length() <= 2)
- continue;
-
- // this is Java 1.5.0 code:
- // fields[j] = fields[j].replace(" - ", "");
- // TODO: switch to 1.5.0 some day; until then, use 1.4.2 code:
- fields[j] = fields[j].replaceAll(" - ", "");
-
- String beg = fields[j].substring(0, 2);
- String value = fields[j].substring(2);
- value = value.trim();
-
- if (beg.equals("PT")) {
- PT = value.replaceAll("Journal", "article").replaceAll("J", "article");
- Type = "article"; //make all of them PT?
- } else if (beg.equals("TY")) {
- if ("CONF".equals(value))
- Type = "inproceedings";
- } else if (beg.equals("JO"))
- hm.put("booktitle", value);
- else if (beg.equals("AU")) {
- String author = isiAuthorConvert(
- AuthorList.fixAuthor_lastNameFirst(value.replaceAll("EOLEOL", " and ")));
-
- // if there is already someone there then append with "and"
- if (hm.get("author") != null)
- author = (String) hm.get("author") + " and " + author;
-
- hm.put("author", author);
- } else if (beg.equals("TI"))
- hm.put("title", value.replaceAll("EOLEOL", " "));
- else if (beg.equals("SO"))
- hm.put("journal", value.replaceAll("EOLEOL", " "));
- else if (beg.equals("ID"))
- hm.put("keywords", value.replaceAll("EOLEOL", " "));
- else if (beg.equals("AB"))
- hm.put("abstract", value.replaceAll("EOLEOL", " "));
- else if (beg.equals("BP") || beg.equals("BR") || beg.equals("SP"))
- pages = value;
- else if (beg.equals("EP")) {
- int detpos = value.indexOf(' ');
-
- // tweak for IEEE Explore
- if (detpos != -1)
- value = value.substring(0, detpos);
-
- pages = pages + "--" + value;
- } else if (beg.equals("AR"))
- pages = value;
- else if (beg.equals("IS"))
- hm.put("number", value);
- else if (beg.equals("PY"))
- hm.put("year", value);
- else if (beg.equals("VL"))
- hm.put("volume", value);
- else if (beg.equals("PD")) {
- String[] parts = value.split(" ");
- for (int ii=0; ii<parts.length; ii++) {
- if (Globals.MONTH_STRINGS.containsKey(parts[ii].toLowerCase())) {
- hm.put("month", "#"+parts[ii].toLowerCase()+"#");
- }
- }
- }
- else if (beg.equals("DT")) {
- Type = value;
- if (Type.equals("Review")) {
- Type = "article";
- // set "Review" in Note/Comment?
- }
- else if (!Type.equals("Article") && !PT.equals("Journal"))
- Type = "misc";
- else
- Type = "article";
- } //ignore
- else if (beg.equals("CR"))
- hm.put("CitedReferences", value.replaceAll("EOLEOL", " ; ").trim());
- }
-
- if (!"".equals(pages))
- hm.put("pages", pages);
-
- BibtexEntry b =
- new BibtexEntry(BibtexFields.DEFAULT_BIBTEXENTRY_ID, Globals.getEntryType(Type)); // id assumes an existing database so don't
-
- // Remove empty fields:
- ArrayList toRemove = new ArrayList();
- for (Iterator it = hm.keySet().iterator(); it.hasNext();) {
- Object key = it.next();
- String content = (String)hm.get(key);
- if ((content == null) || (content.trim().length() == 0))
- toRemove.add(key);
- }
- for (Iterator iterator = toRemove.iterator(); iterator.hasNext();) {
- hm.remove(iterator.next());
-
- }
- b.setField(hm);
-
- bibitems.add(b);
- }
-
- return bibitems;
- }
-
- private String isiAuthorConvert(String authors) {
- String[] author = authors.split(" and ");
- StringBuffer sb = new StringBuffer();
- for (int i=0; i<author.length; i++) {
- int pos = author[i].indexOf(", ");
- if (pos > 0) {
- sb.append(author[i].substring(0, pos));
- sb.append(", ");
-
- for (int j=pos+2; j<author[i].length(); j++) {
- sb.append(author[i].charAt(j));
- sb.append(".");
- if (j<author[i].length()-1)
- sb.append(" ");
- }
- } else
- sb.append(author[i]);
- if (i<author.length-1)
- sb.append(" and ");
- }
- return sb.toString();
- }
+ /**
+ * Return the name of this import format.
+ */
+ public String getFormatName() {
+ return "ISI";
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see net.sf.jabref.imports.ImportFormat#getCLIId()
+ */
+ public String getCLIId() {
+ return "isi";
+ }
+
+ // 2006.09.05: Modified pattern to avoid false positives for other files due to an
+ // extra | at the end:
+ static final Pattern isiPattern = Pattern.compile("FN ISI Export Format|VR 1.|PY \\d{4}");
+
+ /**
+ * Check whether the source is in the correct format for this importer.
+ */
+ public boolean isRecognizedFormat(InputStream stream) throws IOException {
+
+ BufferedReader in = new BufferedReader(ImportFormatReader.getReaderDefaultEncoding(stream));
+
+ String str;
+
+ while ((str = in.readLine()) != null) {
+
+ /**
+ * The following line gives false positives for RIS files, so it
+ * should not be uncommented. The hypen is a characteristic of the
+ * RIS format.
+ *
+ * str = str.replace(" - ", "")
+ */
+ if (isiPattern.matcher(str).find())
+ return true;
+ }
+
+ return false;
+ }
+
+ static Pattern subsupPattern = Pattern.compile("/(sub|sup)\\s+(.*?)\\s*/");
+
+ static public void processSubSup(HashMap map) {
+
+ String[] subsup = { "title", "abstract", "review", "notes" };
+
+ for (int i = 0; i < subsup.length; i++) {
+ if (map.containsKey(subsup[i])) {
+
+ Matcher m = subsupPattern.matcher((String) map.get(subsup[i]));
+ StringBuffer sb = new StringBuffer();
+
+ while (m.find()) {
+
+ String group2 = m.group(2);
+ group2 = group2.replaceAll("\\$", "\\\\\\\\\\\\\\$"); // Escaping
+ // insanity!
+ // :-)
+ if (group2.length() > 1) {
+ group2 = "{" + group2 + "}";
+ }
+ if (m.group(1).equals("sub")) {
+ m.appendReplacement(sb, "\\$_" + group2 + "\\$");
+ } else {
+ m.appendReplacement(sb, "\\$^" + group2 + "\\$");
+ }
+ }
+ m.appendTail(sb);
+ map.put(subsup[i], sb.toString());
+ }
+ }
+ }
+
+ static public void processCapitalization(HashMap map) {
+
+ String[] subsup = { "title", "journal", "publisher" };
+
+ for (int i = 0; i < subsup.length; i++) {
+
+ if (map.containsKey(subsup[i])) {
+
+ String s = (String) map.get(subsup[i]);
+
+ if (s.toUpperCase().equals(s)) {
+ s = CaseChanger.changeCase(s, CaseChanger.UPPER_EACH_FIRST);
+ map.put(subsup[i], s);
+ }
+ }
+ }
+ }
+
+ /**
+ * Parse the entries in the source, and return a List of BibtexEntry
+ * objects.
+ */
+ public List importEntries(InputStream stream) throws IOException {
+ if (stream == null) {
+ throw new IOException("No stream given.");
+ }
+
+ ArrayList bibitems = new ArrayList();
+ StringBuffer sb = new StringBuffer();
+
+ BufferedReader in = new BufferedReader(ImportFormatReader.getReaderDefaultEncoding(stream));
+
+ // Pattern fieldPattern = Pattern.compile("^AU |^TI |^SO |^DT |^C1 |^AB
+ // |^ID |^BP |^PY |^SE |^PY |^VL |^IS ");
+ String str;
+
+ while ((str = in.readLine()) != null) {
+ if (str.length() < 3)
+ continue;
+
+ // begining of a new item
+ if (str.substring(0, 3).equals("PT "))
+ sb.append("::").append(str);
+ else {
+ String beg = str.substring(0, 3).trim();
+
+ // I could have used the fieldPattern regular expression instead
+ // however this seems to be
+ // quick and dirty and it works!
+ if (beg.length() == 2) {
+ sb.append(" ## "); // mark the begining of each field
+ sb.append(str);
+ } else {
+ sb.append("EOLEOL"); // mark the end of each line
+ sb.append(str.trim()); // remove the initial spaces
+ }
+ }
+ }
+
+ String[] entries = sb.toString().split("::");
+
+ HashMap hm = new HashMap();
+
+ // skip the first entry as it is either empty or has document header
+ for (int i = 0; i < entries.length; i++) {
+ String[] fields = entries[i].split(" ## ");
+
+ if (fields.length == 0)
+ fields = entries[i].split("\n");
+
+ String Type = "";
+ String PT = "";
+ String pages = "";
+ hm.clear();
+
+ nextField: for (int j = 0; j < fields.length; j++) {
+ // empty field don't do anything
+ if (fields[j].length() <= 2)
+ continue;
+
+ String beg = fields[j].substring(0, 2);
+ String value = fields[j].substring(3);
+ if (value.startsWith(" - ")) {
+ value = value.substring(3);
+ }
+ value = value.trim();
+
+ if (beg.equals("PT")) {
+ if (value.startsWith("J")) {
+ PT = "article";
+ } else {
+ PT = value;
+ }
+ Type = "article"; // make all of them PT?
+ } else if (beg.equals("TY")) {
+ if ("JOUR".equals(value))
+ Type = "article";
+ else if ("CONF".equals(value))
+ Type = "inproceedings";
+ } else if (beg.equals("JO"))
+ hm.put("booktitle", value);
+ else if (beg.equals("AU")) {
+ String author = isiAuthorsConvert(value.replaceAll("EOLEOL", " and "));
+
+ // if there is already someone there then append with "and"
+ if (hm.get("author") != null)
+ author = (String) hm.get("author") + " and " + author;
+
+ hm.put("author", author);
+ } else if (beg.equals("TI"))
+ hm.put("title", value.replaceAll("EOLEOL", " "));
+ else if (beg.equals("SO") || beg.equals("JA"))
+ hm.put("journal", value.replaceAll("EOLEOL", " "));
+ else if (beg.equals("ID") || beg.equals("KW")) {
+
+ value = value.replaceAll("EOLEOL", " ");
+ String existingKeywords = (String) hm.get("keywords");
+ if (existingKeywords != null && existingKeywords.indexOf(value) == -1) {
+ existingKeywords += ", " + value;
+ } else {
+ existingKeywords = value;
+ }
+ hm.put("keywords", existingKeywords);
+
+ } else if (beg.equals("AB"))
+ hm.put("abstract", value.replaceAll("EOLEOL", " "));
+ else if (beg.equals("BP") || beg.equals("BR") || beg.equals("SP"))
+ pages = value;
+ else if (beg.equals("EP")) {
+ int detpos = value.indexOf(' ');
+
+ // tweak for IEEE Explore
+ if (detpos != -1 && value.substring(0, detpos).trim().length() > 0)
+ value = value.substring(0, detpos);
+
+ pages = pages + "--" + value;
+ } else if (beg.equals("PS")) {
+ pages = parsePages(value);
+ } else if (beg.equals("AR"))
+ pages = value;
+ else if (beg.equals("IS"))
+ hm.put("number", value);
+ else if (beg.equals("PY"))
+ hm.put("year", value);
+ else if (beg.equals("VL"))
+ hm.put("volume", value);
+ else if (beg.equals("PU"))
+ hm.put("publisher", value);
+ else if (beg.equals("PD")) {
+
+ String month = parseMonth(value);
+ if (month != null) {
+ hm.put("month", month);
+ continue nextField;
+ }
+
+ } else if (beg.equals("DT")) {
+ Type = value;
+ if (Type.equals("Review")) {
+ Type = "article"; // set "Review" in Note/Comment?
+ } else if (Type.startsWith("Article") || Type.startsWith("Journal")
+ || PT.equals("article")) {
+ Type = "article";
+ continue;
+ } else {
+ Type = "misc";
+ }
+ } else if (beg.equals("CR")) {
+ hm.put("CitedReferences", value.replaceAll("EOLEOL", " ; ").trim());
+ } else {
+ // Preserve all other entries except
+ if (beg.equals("ER") || beg.equals("EF") || beg.equals("VR")
+ || beg.equals("FN"))
+ continue nextField;
+ hm.put(beg, value);
+ }
+ }
+
+ if (!"".equals(pages))
+ hm.put("pages", pages);
+
+ // Skip empty entries
+ if (hm.size() == 0)
+ continue;
+
+ BibtexEntry b = new BibtexEntry(BibtexFields.DEFAULT_BIBTEXENTRY_ID, Globals
+ .getEntryType(Type));
+ // id assumes an existing database so don't
+
+ // Remove empty fields:
+ ArrayList toRemove = new ArrayList();
+ for (Iterator it = hm.keySet().iterator(); it.hasNext();) {
+ Object key = it.next();
+ String content = (String) hm.get(key);
+ if ((content == null) || (content.trim().length() == 0))
+ toRemove.add(key);
+ }
+ for (Iterator iterator = toRemove.iterator(); iterator.hasNext();) {
+ hm.remove(iterator.next());
+
+ }
+
+ // Polish entries
+ processSubSup(hm);
+ processCapitalization(hm);
+
+ b.setField(hm);
+
+ bibitems.add(b);
+ }
+
+ return bibitems;
+ }
+
+ public static String parsePages(String value) {
+ int lastDash = value.lastIndexOf("-");
+ return value.substring(0, lastDash) + "--" + value.substring(lastDash + 1);
+ }
+
+ public static String parseMonth(String value) {
+
+ String[] parts = value.split("\\s|\\-");
+ for (int ii = 0; ii < parts.length; ii++) {
+ if (Globals.MONTH_STRINGS.containsKey(parts[ii].toLowerCase())) {
+ return "#" + parts[ii].toLowerCase() + "#";
+ }
+ }
+
+ // Try two digit month
+ for (int ii = 0; ii < parts.length; ii++) {
+ int number;
+ try {
+ number = Integer.parseInt(parts[ii]);
+ if (number >= 1 && number <= 12) {
+ return "#" + Globals.MONTHS[number - 1] + "#";
+ }
+ } catch (NumberFormatException e) {
+
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Will expand ISI first names.
+ *
+ * Fixed bug from:
+ * http://sourceforge.net/tracker/index.php?func=detail&aid=1542552&group_id=92314&atid=600306
+ *
+ */
+ public static String isiAuthorConvert(String author) {
+
+ String[] s = author.split(",");
+ if (s.length != 2)
+ return author;
+
+ StringBuffer sb = new StringBuffer();
+
+ String last = s[0].trim();
+ sb.append(last).append(", ");
+
+ String first = s[1].trim();
+
+ String[] firstParts = first.split("\\s+");
+
+ for (int i = 0; i < firstParts.length; i++) {
+
+ first = firstParts[i];
+
+ // Do we have only uppercase chars?
+ if (first.toUpperCase().equals(first)) {
+ first = first.replaceAll("\\.", "");
+ for (int j = 0; j < first.length(); j++) {
+ sb.append(first.charAt(j)).append(".");
+
+ if (j < first.length() - 1)
+ sb.append(" ");
+ }
+ } else {
+ sb.append(first);
+ }
+ if (i < firstParts.length - 1) {
+ sb.append(" ");
+ }
+ }
+ return sb.toString();
+
+ }
+
+ public static String[] isiAuthorsConvert(String[] authors) {
+
+ String[] result = new String[authors.length];
+ for (int i = 0; i < result.length; i++) {
+ result[i] = isiAuthorConvert(authors[i]);
+ }
+ return result;
+ }
+
+ public static String isiAuthorsConvert(String authors) {
+ String[] s = isiAuthorsConvert(authors.split(" and |;"));
+ return Util.join(s, " and ", 0, s.length);
+ }
}
diff --git a/src/java/net/sf/jabref/imports/OAI2Fetcher.java b/src/java/net/sf/jabref/imports/OAI2Fetcher.java
new file mode 100644
index 0000000..e01f129
--- /dev/null
+++ b/src/java/net/sf/jabref/imports/OAI2Fetcher.java
@@ -0,0 +1,267 @@
+package net.sf.jabref.imports;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.net.URLEncoder;
+import java.util.Calendar;
+import java.util.Date;
+
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+import net.sf.jabref.*;
+import net.sf.jabref.gui.ImportInspectionDialog;
+
+/**
+ *
+ * This class can be used to access any archive offering an OAI2 interface. By
+ * default it will access ArXiv.org
+ *
+ * @author Ulrich Stärk
+ * @author Christian Kopf
+ *
+ * @version $Revision: 1.1 $ ($Date: 2006/11/24 15:29:11 $)
+ *
+ */
+public class OAI2Fetcher implements EntryFetcher, Runnable {
+
+ public static final String OAI2_ARXIV_PREFIXIDENTIFIER = "oai%3AarXiv.org%3A";
+
+ public static final String OAI2_ARXIV_HOST = "arxiv.org";
+
+ public static final String OAI2_ARXIV_SCRIPT = "oai2";
+
+ public static final String OAI2_ARXIV_METADATAPREFIX = "arXiv";
+
+ public static final String OAI2_ARXIV_ARCHIVENAME = "ArXiv.org";
+
+ public static final String OAI2_IDENTIFIER_FIELD = "oai2identifier";
+
+ private SAXParserFactory parserFactory;
+
+ private SAXParser saxParser;
+
+ private String oai2Host;
+
+ private String oai2Script;
+
+ private String oai2MetaDataPrefix;
+
+ private String oai2PrefixIdentifier;
+
+ private String oai2ArchiveName;
+
+ private boolean shouldContinue = true;
+
+ private String query;
+
+ private ImportInspectionDialog dialog;
+
+ private JabRefFrame frame;
+
+ /* some archives - like arxive.org - might expect of you to wait some time */
+
+ private boolean shouldWait(){
+ return waitTime > 0;
+ }
+
+ private long waitTime = -1;
+
+ private Date lastCall;
+
+ /**
+ *
+ *
+ * @param oai2Host
+ * the host to query without leading http:// and without trailing /
+ * @param oai2Script
+ * the relative location of the oai2 interface without leading
+ * and trailing /
+ * @param oai2Metadataprefix
+ * the urlencoded metadataprefix
+ * @param oai2Prefixidentifier
+ * the urlencoded prefix identifier
+ * @param waitTimeMs
+ * Time to wait in milliseconds between query-requests.
+ */
+ public OAI2Fetcher(String oai2Host, String oai2Script, String oai2Metadataprefix,
+ String oai2Prefixidentifier, String oai2ArchiveName, long waitTimeMs) {
+ this.oai2Host = oai2Host;
+ this.oai2Script = oai2Script;
+ this.oai2MetaDataPrefix = oai2Metadataprefix;
+ this.oai2PrefixIdentifier = oai2Prefixidentifier;
+ this.oai2ArchiveName = oai2ArchiveName;
+ this.waitTime = waitTimeMs;
+ try {
+ parserFactory = SAXParserFactory.newInstance();
+ saxParser = parserFactory.newSAXParser();
+ } catch (ParserConfigurationException e) {
+ e.printStackTrace();
+ } catch (SAXException e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Default Constructor. The archive queried will be ArXiv.org
+ *
+ */
+ public OAI2Fetcher() {
+ this(OAI2_ARXIV_HOST, OAI2_ARXIV_SCRIPT, OAI2_ARXIV_METADATAPREFIX,
+ OAI2_ARXIV_PREFIXIDENTIFIER, OAI2_ARXIV_ARCHIVENAME, 20000L);
+ }
+
+ /**
+ * Construct the query URL
+ *
+ * @param be
+ * The BibtexEntry containing the field OAI2_IDENTIFIER_FIELD
+ * @return a String denoting the query URL
+ */
+ public String constructUrl(BibtexEntry be) {
+ String identifier = "";
+ try {
+ identifier = URLEncoder.encode((String) be.getField(OAI2_IDENTIFIER_FIELD), "UTF-8");
+ } catch (UnsupportedEncodingException e) {
+ return "";
+ }
+ StringBuffer sb = new StringBuffer("http://").append(oai2Host).append("/");
+ sb.append(oai2Script).append("?");
+ sb.append("verb=GetRecord");
+ sb.append("&identifier=");
+ sb.append(oai2PrefixIdentifier);
+ sb.append(identifier);
+ sb.append("&metadataPrefix=").append(oai2MetaDataPrefix);
+ return sb.toString();
+ }
+
+ /**
+ * Import an entry from an OAI2 archive. The BibtexEntry provided has to
+ * have the field OAI2_IDENTIFIER_FIELD set to the search string.
+ *
+ * @param be
+ * The BibtexEntry to store the results in.
+ */
+ public void importOai2Entry(BibtexEntry be) {
+ String url = constructUrl(be);
+ try {
+ URL oai2Url = new URL(url);
+ HttpURLConnection oai2Connection = (HttpURLConnection) oai2Url.openConnection();
+ oai2Connection.setRequestProperty("User-Agent", "Jabref");
+ InputStream inputStream = oai2Connection.getInputStream();
+ DefaultHandler handlerBase = new OAI2Handler(be);
+ /* parse the result */
+ saxParser.parse(inputStream, handlerBase);
+ } catch (IOException e) {
+ JOptionPane.showMessageDialog(frame, Globals.lang(
+ "An Exception ocurred while accessing '%0'", url)
+ + "\n\n" + e.toString(), Globals.lang(getKeyName()), JOptionPane.ERROR_MESSAGE);
+ } catch (SAXException e) {
+ JOptionPane.showMessageDialog(frame, Globals.lang(
+ "An SAXException ocurred while parsing '%0'", url), Globals.lang(getKeyName()),
+ JOptionPane.ERROR_MESSAGE);
+ }
+ }
+
+ public String getHelpPage() {
+ // there is no helppage
+ return null;
+ }
+
+ public URL getIcon() {
+ return GUIGlobals.getIconUrl("www");
+ }
+
+ public String getKeyName() {
+ return "Fetch " + oai2ArchiveName;
+ }
+
+ public JPanel getOptionsPanel() {
+ // we have no additional options
+ return null;
+ }
+
+ public String getTitle() {
+ return Globals.menuTitle(getKeyName());
+ }
+
+ public void processQuery(String query, ImportInspectionDialog dialog, JabRefFrame frame) {
+ this.query = query;
+ this.dialog = dialog;
+ this.frame = frame;
+ (new Thread(this)).start();
+ }
+
+ public void cancelled() {
+ shouldContinue = false;
+ }
+
+ public void done(int entriesImported) {
+ // do nothing
+ }
+
+ public void stopFetching() {
+ shouldContinue = false;
+ }
+
+ public void run() {
+ try {
+ dialog.setVisible(true);
+ shouldContinue = true;
+ /* multiple keys can be delimited by ; or space */
+ query = query.replaceAll(" ", ";");
+ String[] keys = query.split(";");
+ for (int i = 0; i < keys.length; i++) {
+ String key = keys[i];
+ /*
+ * some archives - like arxive.org - might expect of you to wait
+ * some time
+ */
+ if (shouldWait() && lastCall != null) {
+
+ long elapsed = new Date().getTime() - lastCall.getTime();
+
+ while (elapsed < waitTime) {
+ frame.output("Waiting for ArXiv..." + ((waitTime - elapsed) / 1000) + " s");
+ Thread.sleep(1000);
+ elapsed = new Date().getTime() - lastCall.getTime();
+ }
+ }
+
+ frame.output("Processing " + key);
+
+ /* the cancel button has been hit */
+ if (!shouldContinue)
+ break;
+ /* create an empty BibtexEntry and set the oai2identifier field */
+ BibtexEntry be = new BibtexEntry(Util.createNeutralId(), BibtexEntryType.ARTICLE);
+ be.setField(OAI2_IDENTIFIER_FIELD, key);
+ /* query the archive and load the results into the BibtexEntry */
+ importOai2Entry(be);
+
+ if (shouldWait())
+ lastCall = new Date();
+
+ /* add the entry to the inspection dialog */
+ dialog.addEntry(be);
+
+ /* update the dialogs progress bar */
+ dialog.setProgress(i + 1, keys.length);
+ }
+ /* inform the inspection dialog, that we're done */
+ dialog.entryListComplete();
+ frame.output("");
+ } catch (InterruptedException e) {
+
+ }
+ }
+}
diff --git a/src/java/net/sf/jabref/imports/OAI2Handler.java b/src/java/net/sf/jabref/imports/OAI2Handler.java
new file mode 100644
index 0000000..c259bcd
--- /dev/null
+++ b/src/java/net/sf/jabref/imports/OAI2Handler.java
@@ -0,0 +1,131 @@
+package net.sf.jabref.imports;
+
+import net.sf.jabref.BibtexEntry;
+import net.sf.jabref.BibtexFields;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+/**
+ * SAX-Handler to parse OAI2-xml files.
+ *
+ * @author Ulrich Stärk
+ * @author Christian Kopf
+ *
+ * @version $Revision: 1.1 $ ($Date: 2006/11/24 15:29:11 $)
+ *
+ */
+public class OAI2Handler extends DefaultHandler {
+
+ BibtexEntry be;
+ String nextField;
+ String authors = "";
+ String keyname;
+ String forenames;
+ String key = "";
+ String year = "";
+ boolean assigned = false;
+
+ public OAI2Handler(BibtexEntry be) {
+ this.be = be;
+ }
+
+ public void endDocument() throws SAXException {
+ be.setField("author",authors);
+ if(year.length() > 0)
+ key += year.substring(year.length()-2, year.length());
+ be.setField(BibtexFields.KEY_FIELD,key);
+ }
+
+
+ public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
+ if(localName.equals("id")) {
+ nextField = "id";
+ assigned = true;
+ } else if(localName.equals("keyname")) {
+ nextField = "keyname";
+ assigned = true;
+ } else if(localName.equals("author")) {
+ keyname = "";
+ forenames = "";
+ } else if(localName.equals("forenames")) {
+ nextField = "forenames";
+ assigned = true;
+ } else if(localName.equals("journal-ref")) {
+ nextField = "journal-ref";
+ assigned = true;
+ } else if(localName.equals("datestamp")) {
+ nextField = "datestamp";
+ assigned = true;
+ } else if(localName.equals("title")) {
+ nextField = "title";
+ assigned = true;
+ } else if(localName.equals("abstract")) {
+ nextField = "abstract";
+ assigned = true;
+ } else if(localName.equals("comments")) {
+ nextField = "comments";
+ assigned = true;
+ } else if(localName.equals("report-no")) {
+ nextField = "reportno";
+ assigned = true;
+ }
+ }
+
+
+ public void endElement(String uri, String localName, String qName) throws SAXException {
+ if(localName.equals("author")) {
+ String temp = forenames + " " + keyname;
+ if(!authors.equals(""))
+ authors += " and ";
+ authors += temp;
+ }
+ }
+
+
+ public void characters(char[] ch, int start, int length) throws SAXException {
+ String content = new String(ch,start,length);
+ if(assigned) {
+ if(nextField.equals("id")) {
+ be.setField("eprint",content);
+ } else if(nextField.equals("keyname")) {
+ keyname = content;
+ key += content.substring(0,3);
+ } else if(nextField.equals("forenames")) {
+ forenames = content;
+ } else if(nextField.equals("journal-ref")) {
+ String journal = content.replaceFirst("[0-9].*", "");
+ be.setField("journal", journal);
+ String volume = content.replaceFirst(journal,"");
+ volume = volume.replaceFirst(" .*", "");
+ be.setField("volume", volume);
+ year = content.replaceFirst(".*?\\(", "");
+ year = year.replaceFirst("\\).*", "");
+ be.setField("year", year);
+ String pages = content.replaceFirst(journal,"");
+ pages = pages.replaceFirst(volume, "");
+ pages = pages.replaceFirst("\\("+year+"\\)", "");
+ pages = pages.replaceAll(" ", "");
+ be.setField("pages", pages);
+ } else if(nextField.equals("datestamp")) {
+ if(year.equals(""))
+ year = content.replaceFirst("-.*", "");
+ be.setField("year", year);
+ } else if(nextField.equals("title")) {
+ be.setField("title",content);
+ } else if(nextField.equals("abstract")) {
+ be.setField("abstract",content);
+ } else if(nextField.equals("comments")) {
+ be.setField("comments",content);
+ } else if(nextField.equals("reportno")) {
+ be.setField("reportno",content);
+ }
+ assigned = false;
+ }
+ }
+
+
+
+
+}
diff --git a/src/java/net/sf/jabref/imports/OpenDatabaseAction.java b/src/java/net/sf/jabref/imports/OpenDatabaseAction.java
index d804edc..25bee7a 100644
--- a/src/java/net/sf/jabref/imports/OpenDatabaseAction.java
+++ b/src/java/net/sf/jabref/imports/OpenDatabaseAction.java
@@ -218,13 +218,16 @@ public class OpenDatabaseAction extends MnemonicAwareAction {
//System.out.println("Result of UTF-16 test: "+suppliedEncoding);
}
+ //System.out.println(suppliedEncoding != null ? "Encoding: '"+suppliedEncoding+"' Len: "+suppliedEncoding.length() : "no supplied encoding");
+
if ((suppliedEncoding != null)) {
try {
reader = ImportFormatReader.getReader(fileToOpen, suppliedEncoding);
encoding = suppliedEncoding; // Just so we put the right info into the ParserResult.
- } catch (IOException ex) {
- reader = ImportFormatReader.getReader(fileToOpen, encoding); // The supplied encoding didn't work out, so we use the default.
- }
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ reader = ImportFormatReader.getReader(fileToOpen, encoding); // The supplied encoding didn't work out, so we use the default.
+ }
} else {
// We couldn't find a header with info about encoding. Use default:
reader = ImportFormatReader.getReader(fileToOpen, encoding);
@@ -288,6 +291,6 @@ public class OpenDatabaseAction extends MnemonicAwareAction {
}
} catch (IOException ex) {
}
- return suppliedEncoding;
+ return suppliedEncoding != null ? suppliedEncoding.trim() : null;
}
}
diff --git a/src/java/net/sf/jabref/imports/PdfXmpImporter.java b/src/java/net/sf/jabref/imports/PdfXmpImporter.java
new file mode 100644
index 0000000..c4310e8
--- /dev/null
+++ b/src/java/net/sf/jabref/imports/PdfXmpImporter.java
@@ -0,0 +1,50 @@
+package net.sf.jabref.imports;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.List;
+
+import net.sf.jabref.Globals;
+import net.sf.jabref.util.XMPUtil;
+
+/**
+ * Wraps the XMPUtility function to be used as an ImportFormat.
+ *
+ * @author $Author: coezbek $
+ * @version $Revision: 1.1 $ ($Date: 2006/08/13 13:17:00 $)
+ *
+ */
+public class PdfXmpImporter extends ImportFormat {
+
+ public String getFormatName() {
+ return Globals.lang("XMP-annotated PDF");
+ }
+
+ /**
+ * Returns a list of all BibtexEntries found in the inputstream.
+ */
+ public List importEntries(InputStream in) throws IOException {
+ return XMPUtil.readXMP(in);
+ }
+
+ /**
+ * Returns whether the given stream contains data that is a.) a pdf and b.)
+ * contains at least one BibtexEntry.
+ *
+ * @override
+ */
+ public boolean isRecognizedFormat(InputStream in) throws IOException {
+ return XMPUtil.hasMetadata(in);
+ }
+
+ /**
+ * String used to identify this import filter on the command line.
+ *
+ * @override
+ * @return "xmp"
+ */
+ public String getCLIid() {
+ return "xmp";
+ }
+
+}
diff --git a/src/java/net/sf/jabref/mods/MODSDatabase.java b/src/java/net/sf/jabref/mods/MODSDatabase.java
index b5ca6e8..74bdc30 100644
--- a/src/java/net/sf/jabref/mods/MODSDatabase.java
+++ b/src/java/net/sf/jabref/mods/MODSDatabase.java
@@ -24,10 +24,21 @@ public class MODSDatabase {
}
public MODSDatabase(BibtexDatabase bibtex) {
- this();
- Collection c = bibtex.getEntries();
- for(Iterator iter = c.iterator(); iter.hasNext(); ) {
- BibtexEntry entry = (BibtexEntry) iter.next();
+ Set keySet = bibtex.getKeySet();
+ addEntries(bibtex, keySet);
+ }
+
+ public MODSDatabase(BibtexDatabase bibtex, Set keySet) {
+ if (keySet == null)
+ keySet = bibtex.getKeySet();
+ addEntries(bibtex, keySet);
+ }
+
+
+ private void addEntries(BibtexDatabase database, Set keySet) {
+ entries = new HashSet();
+ for(Iterator iter = keySet.iterator(); iter.hasNext(); ) {
+ BibtexEntry entry = database.getEntryById((String)iter.next());
MODSEntry newMods = new MODSEntry(entry);
entries.add(newMods);
}
diff --git a/src/java/net/sf/jabref/search/BasicSearch.java b/src/java/net/sf/jabref/search/BasicSearch.java
new file mode 100644
index 0000000..3d10e0b
--- /dev/null
+++ b/src/java/net/sf/jabref/search/BasicSearch.java
@@ -0,0 +1,146 @@
+package net.sf.jabref.search;
+
+import net.sf.jabref.SearchRule;
+import net.sf.jabref.BibtexEntry;
+import net.sf.jabref.export.layout.format.RemoveBrackets;
+
+import java.util.Map;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.HashMap;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Search rule for simple search.
+ */
+public class BasicSearch implements SearchRule {
+ private boolean caseSensitive;
+ private boolean regExp;
+ Pattern[] pattern;
+ static RemoveBrackets removeBrackets = new RemoveBrackets();
+
+
+ public BasicSearch(boolean caseSensitive, boolean regExp) {
+
+ this.caseSensitive = caseSensitive;
+ this.regExp = regExp;
+ }
+
+ private static void print(ArrayList list) {
+ for (Iterator i = list.iterator(); i.hasNext();) {
+ String s = (String) i.next();
+ System.out.print("'"+s+"' ");
+ }
+ System.out.println();
+ }
+
+ public int applyRule(String query, BibtexEntry bibtexEntry) {
+ HashMap map = new HashMap();
+ map.put("1", query);
+ return applyRule(map, bibtexEntry);
+ }
+
+ public int applyRule(Map searchStrings, BibtexEntry bibtexEntry) {
+
+ int flags = 0;
+ String searchString = (String) searchStrings.values().iterator().next();
+ if (!caseSensitive) {
+ searchString = searchString.toLowerCase();
+ flags = Pattern.CASE_INSENSITIVE;
+ }
+
+ ArrayList words = parseQuery(searchString);
+
+ if (regExp) {
+ pattern = new Pattern[words.size()];
+ for (int i = 0; i < pattern.length; i++) {
+ pattern[i] = Pattern.compile((String)words.get(i), flags);
+ }
+ }
+
+ //print(words);
+ // We need match for all words:
+ boolean[] matchFound = new boolean[words.size()];
+
+ Object fieldContentAsObject;
+ String fieldContent;
+ Object[] fields = bibtexEntry.getAllFields();
+ for (int i = 0; i < fields.length; i++) {
+ fieldContentAsObject = bibtexEntry.getField(fields[i].toString());
+ if (fieldContentAsObject != null) {
+ fieldContent = removeBrackets.format(fieldContentAsObject.toString());
+ if (!caseSensitive)
+ fieldContent = fieldContent.toLowerCase();
+ int index = 0;
+ // Check if we have a match for each of the query words, ignoring
+ // those words for which we already have a match:
+ for (int j=0; j<words.size(); j++) {
+ if (!regExp) {
+ String s = (String) words.get(j);
+ matchFound[index] = matchFound[index]
+ || (fieldContent.indexOf(s) >= 0);
+ } else {
+ if (fieldContent != null) {
+ Matcher m = pattern[j].matcher
+ (removeBrackets.format(fieldContent));
+ matchFound[index] = matchFound[index]
+ || m.find();
+ }
+ }
+
+ index++;
+ }
+ }
+
+ }
+ for (int i = 0; i < matchFound.length; i++) {
+ if (!matchFound[i])
+ return 0; // Didn't match all words.
+ }
+ return 1; // Matched all words.
+ }
+
+ private ArrayList parseQuery(String query) {
+ StringBuffer sb = new StringBuffer();
+ ArrayList result = new ArrayList();
+ int c;
+ boolean escaped = false, quoted = false;
+ for (int i=0; i<query.length(); i++) {
+ c = query.charAt(i);
+ // Check if we are entering an escape sequence:
+ if (!escaped && (c == '\\'))
+ escaped = true;
+ else {
+ // See if we have reached the end of a word:
+ if (!escaped && !quoted && Character.isWhitespace((char)c)) {
+ if (sb.length() > 0) {
+ result.add(sb.toString());
+ sb = new StringBuffer();
+ }
+ }
+ else if (c == '"') {
+ // Whether it is a start or end quote, store the current
+ // word if any:
+ if (sb.length() > 0) {
+ result.add(sb.toString());
+ sb = new StringBuffer();
+ }
+ quoted = !quoted;
+ }
+ else {
+ // All other possibilities exhausted, we add the char to
+ // the current word:
+ sb.append((char)c);
+ }
+ escaped = false;
+ }
+ }
+ // Finished with the loop. If we have a current word, add it:
+ if (sb.length() > 0) {
+ result.add(sb.toString());
+ }
+
+ return result;
+ }
+}
diff --git a/src/java/net/sf/jabref/search/SearchExpressionParser.java b/src/java/net/sf/jabref/search/SearchExpressionParser.java
index a48b9a2..a2d02d4 100644
--- a/src/java/net/sf/jabref/search/SearchExpressionParser.java
+++ b/src/java/net/sf/jabref/search/SearchExpressionParser.java
@@ -3,24 +3,18 @@
package net.sf.jabref.search;
import java.io.StringReader;
-import antlr.TokenBuffer;
-import antlr.TokenStreamException;
-import antlr.TokenStreamIOException;
-import antlr.ANTLRException;
-import antlr.LLkParser;
-import antlr.Token;
-import antlr.TokenStream;
-import antlr.RecognitionException;
+import antlr.ASTFactory;
+import antlr.ASTPair;
import antlr.NoViableAltException;
-import antlr.MismatchedTokenException;
-import antlr.SemanticException;
import antlr.ParserSharedInputState;
-import antlr.collections.impl.BitSet;
+import antlr.RecognitionException;
+import antlr.Token;
+import antlr.TokenBuffer;
+import antlr.TokenStream;
+import antlr.TokenStreamException;
import antlr.collections.AST;
-import java.util.Hashtable;
-import antlr.ASTFactory;
-import antlr.ASTPair;
import antlr.collections.impl.ASTArray;
+import antlr.collections.impl.BitSet;
public class SearchExpressionParser extends antlr.LLkParser implements SearchExpressionParserTokenTypes
{
diff --git a/src/java/net/sf/jabref/undo/CountingUndoManager.java b/src/java/net/sf/jabref/undo/CountingUndoManager.java
index 613fb53..2160d8b 100644
--- a/src/java/net/sf/jabref/undo/CountingUndoManager.java
+++ b/src/java/net/sf/jabref/undo/CountingUndoManager.java
@@ -73,10 +73,10 @@ public class CountingUndoManager extends UndoManager {
}
public synchronized void markUnchanged() {
- unchangedPoint = current;
+ unchangedPoint = current;
}
public boolean hasChanged() {
- return !(current == unchangedPoint);
+ return !(current == unchangedPoint);
}
}
diff --git a/src/java/net/sf/jabref/util/CaseChanger.java b/src/java/net/sf/jabref/util/CaseChanger.java
index 21b1c7b..fa0c56b 100644
--- a/src/java/net/sf/jabref/util/CaseChanger.java
+++ b/src/java/net/sf/jabref/util/CaseChanger.java
@@ -2,7 +2,7 @@ package net.sf.jabref.util;
/* Mp3dings - manage mp3 meta-information
* Copyright (C) 2003 Moritz Ringler
- * $Id: CaseChanger.java,v 1.4 2006/04/05 21:41:25 mortenalver Exp $
+ * $Id: CaseChanger.java,v 1.5 2006/08/03 22:22:00 coezbek Exp $
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -19,102 +19,126 @@ package net.sf.jabref.util;
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
-
import java.util.regex.Pattern;
import java.util.regex.Matcher;
-/** Class used to manage case changing
+/**
+ *
+ * Class with static methods for changing the case of strings and arrays of
+ * strings.
+ *
* @author Moritz Ringler
- * @version $Revision: 1.4 $ ($Date: 2006/04/05 21:41:25 $)
+ *
+ * @version $Revision: 1.5 $ ($Date: 2006/08/03 22:22:00 $)
*/
-public class CaseChanger{
- /** Lowercase */
- public final static int LOWER=0;
- /** Uppercase */
- public final static int UPPER=1;
- /** First letter of string uppercase */
- public final static int UPPER_FIRST=2;
- /** First letter of each word uppercase */
- public final static int UPPER_EACH_FIRST=3;
- private final static Matcher UF_MATCHER =
- //Pattern.compile("(?i)\\b\\w").matcher("");
- Pattern.compile("\\b\\w").matcher("");
-
- /* you can add more modes here */
- private final static int numModes=4;
- private final static String[] modeNames={"lower", "UPPER", "Upper first", "Upper Each First"};
-
- public CaseChanger(){
- }
-
- /** Gets the name of a case changing mode
- * @param mode by default one of LOWER, UPPER, UPPER_FIRST or
- * UPPER_EACH_FIRST
- */
- public String getModeName(int mode){
- return modeNames[mode];
- }
-
- /** Gets the names of all available case changing modes */
- public String[] getModeNames(){
- return modeNames;
- }
-
- /** Gets the number of available case changing modes */
- public int getNumModes(){
- return numModes;
- }
-
- /** Changes the case of the specified strings.
- * wrapper for {@link #changeCase(String input, int mode)}
- * @see #changeCase(String input, int mode)
- */
- public String[] changeCase(String[] input,int mode){
- int n=input.length;
- String[] output = new String[n];
- for(int i=0;i<n;i++){
- output[i]=changeCase(input[i], mode);
- }
- return output;
- }
-
- /** Changes the case of the specified string
- * @param input String to change
- * @param mode by default one of LOWER, UPPER, UPPER_FIRST or
- * UPPER_EACH_FIRST
- * @return casechanged string
- */
- public String changeCase(String input, int mode){
- switch (mode){
- case UPPER: return input.toUpperCase();
- case LOWER: return input.toLowerCase();
- case UPPER_FIRST:
- String s = input.toLowerCase();
- UF_MATCHER.reset(s);
- if (UF_MATCHER.find()){
- return UF_MATCHER.replaceFirst(UF_MATCHER.
- group(0).toUpperCase());
- } else {
- return input;
- }
- case UPPER_EACH_FIRST:
- s = input.toLowerCase();
- StringBuffer sb = new StringBuffer();
- boolean found = false;
- UF_MATCHER.reset(s);
- while (UF_MATCHER.find()) {
- UF_MATCHER.appendReplacement(sb,
- UF_MATCHER.group(0).toUpperCase());
- found = true;
- }
- if (found){
- UF_MATCHER.appendTail(sb);
- return sb.toString();
- } else {
- return input;
- }
- default: return input;
- }
- }
-}
+public class CaseChanger {
+
+ /** Lowercase */
+ public final static int LOWER = 0;
+
+ /** Uppercase */
+ public final static int UPPER = 1;
+
+ /** First letter of string uppercase */
+ public final static int UPPER_FIRST = 2;
+
+ /** First letter of each word uppercase */
+ public final static int UPPER_EACH_FIRST = 3;
+
+ /**
+ * I don't think it is thread-safe to use the same matcher at the same time for all calls.
+ */
+ private final static Pattern UF_PATTERN = Pattern.compile("\\b\\w");
+
+ // private final static Matcher UF_MATCHER =
+ // // Pattern.compile("(?i)\\b\\w").matcher("");
+ // Pattern.compile("\\b\\w").matcher("");
+ /* you can add more modes here */
+ private final static int numModes = 4;
+
+ private final static String[] modeNames = { "lower", "UPPER", "Upper first", "Upper Each First" };
+
+ /**
+ * Gets the name of a case changing mode
+ *
+ * @param mode
+ * by default one of LOWER, UPPER, UPPER_FIRST or
+ * UPPER_EACH_FIRST
+ */
+ public static String getModeName(int mode) {
+ return modeNames[mode];
+ }
+
+ /** Gets the names of all available case changing modes */
+ public static String[] getModeNames() {
+ return modeNames;
+ }
+
+ /** Gets the number of available case changing modes */
+ public static int getNumModes() {
+ return numModes;
+ }
+
+ /**
+ * Changes the case of the specified strings. wrapper for
+ * {@link #changeCase(String input, int mode)}
+ *
+ * @see #changeCase(String input, int mode)
+ */
+ public static String[] changeCase(String[] input, int mode) {
+ int n = input.length;
+ String[] output = new String[n];
+ for (int i = 0; i < n; i++) {
+ output[i] = changeCase(input[i], mode);
+ }
+ return output;
+ }
+
+ /**
+ * Changes the case of the specified string
+ *
+ * @param input
+ * String to change
+ * @param mode
+ * by default one of LOWER, UPPER, UPPER_FIRST or
+ * UPPER_EACH_FIRST
+ * @return casechanged string
+ */
+ public static String changeCase(String input, int mode) {
+ switch (mode) {
+ case UPPER:
+ return input.toUpperCase();
+ case LOWER:
+ return input.toLowerCase();
+ case UPPER_FIRST: {
+ String s = input.toLowerCase();
+
+ Matcher matcher = UF_PATTERN.matcher(s);
+ if (matcher.find()) {
+ return matcher.replaceFirst(matcher.group(0).toUpperCase());
+ } else {
+ return input;
+ }
+ }
+ case UPPER_EACH_FIRST: {
+ String s = input.toLowerCase();
+ StringBuffer sb = new StringBuffer();
+ boolean found = false;
+ Matcher matcher = UF_PATTERN.matcher(s);
+ while (matcher.find()) {
+ matcher.appendReplacement(sb, matcher.group(0).toUpperCase());
+ found = true;
+ }
+ if (found) {
+ matcher.appendTail(sb);
+ return sb.toString();
+ } else {
+ return input;
+ }
+ }
+ default:
+ return input;
+ }
+ }
+}
diff --git a/src/java/net/sf/jabref/util/EncryptionNotSupportedException.java b/src/java/net/sf/jabref/util/EncryptionNotSupportedException.java
new file mode 100644
index 0000000..d542a2c
--- /dev/null
+++ b/src/java/net/sf/jabref/util/EncryptionNotSupportedException.java
@@ -0,0 +1,13 @@
+package net.sf.jabref.util;
+
+import java.io.IOException;
+
+public class EncryptionNotSupportedException extends IOException {
+
+ private static final long serialVersionUID = 3280233692527372333L;
+
+ public EncryptionNotSupportedException(String string) {
+ super(string);
+ }
+
+}
diff --git a/src/java/net/sf/jabref/util/ErrorConsole.java b/src/java/net/sf/jabref/util/ErrorConsole.java
index 4ff169f..b89c434 100644
--- a/src/java/net/sf/jabref/util/ErrorConsole.java
+++ b/src/java/net/sf/jabref/util/ErrorConsole.java
@@ -18,7 +18,6 @@ import java.awt.event.ActionEvent;
* User: alver
* Date: Mar 1, 2006
* Time: 11:13:03 PM
- * To change this template use File | Settings | File Templates.
*/
public class ErrorConsole {
diff --git a/src/java/net/sf/jabref/util/MassSetFieldAction.java b/src/java/net/sf/jabref/util/MassSetFieldAction.java
new file mode 100644
index 0000000..0ab1e77
--- /dev/null
+++ b/src/java/net/sf/jabref/util/MassSetFieldAction.java
@@ -0,0 +1,171 @@
+package net.sf.jabref.util;
+
+import net.sf.jabref.*;
+import net.sf.jabref.undo.NamedCompound;
+
+import javax.swing.*;
+import javax.swing.event.ChangeListener;
+import javax.swing.event.ChangeEvent;
+import javax.swing.undo.UndoableEdit;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.*;
+import java.util.List;
+import java.util.Collection;
+import java.util.ArrayList;
+import java.util.Arrays;
+
+import com.jgoodies.forms.builder.DefaultFormBuilder;
+import com.jgoodies.forms.builder.ButtonBarBuilder;
+import com.jgoodies.forms.layout.FormLayout;
+import com.jgoodies.uif_lite.panel.SimpleInternalFrame;
+
+/**
+ * An Action for launching mass field.
+ *
+ * Functionality:
+ * * Defaults to selected entries, or all entries if none are selected.
+ * * Input field name
+ * * Either set field, or clear field.
+ */
+public class MassSetFieldAction extends MnemonicAwareAction {
+ private JabRefFrame frame;
+ private JDialog diag;
+ private JRadioButton all, selected, clear, set;
+ private JTextField field, text;
+ private JButton ok, cancel;
+ boolean cancelled = true;
+ private JCheckBox overwrite;
+
+ public MassSetFieldAction(JabRefFrame frame) {
+ putValue(NAME, "Set/clear fields");
+ this.frame = frame;
+ }
+
+ private void createDialog() {
+ diag = new JDialog(frame, Globals.lang("Set/clear fields"), true);
+
+ field = new JTextField();
+ text = new JTextField();
+ ok = new JButton(Globals.lang("Ok"));
+ cancel = new JButton(Globals.lang("Cancel"));
+
+ all = new JRadioButton(Globals.lang("All entries"));
+ selected = new JRadioButton(Globals.lang("Selected entries"));
+ clear = new JRadioButton(Globals.lang("Clear fields"));
+ set = new JRadioButton(Globals.lang("Set fields"));
+ set.addChangeListener(new ChangeListener() {
+ public void stateChanged(ChangeEvent e) {
+ // Entering a text is only relevant if we are setting, not clearing:
+ text.setEnabled(set.isSelected());
+ // Overwrite protection makes no sense if we are clearing the field:
+ overwrite.setEnabled(set.isSelected());
+ }
+ });
+
+ overwrite = new JCheckBox(Globals.lang("Overwrite existing field values"), true);
+ ButtonGroup bg = new ButtonGroup();
+ bg.add(all);
+ bg.add(selected);
+ bg = new ButtonGroup();
+ bg.add(clear);
+ bg.add(set);
+ DefaultFormBuilder builder = new DefaultFormBuilder(new FormLayout(
+ "left:pref, 4dlu, fill:100dlu", ""));
+ builder.appendSeparator(Globals.lang("Field name"));
+ builder.append(Globals.lang("Field name"));
+ builder.append(field);
+ builder.nextLine();
+ builder.appendSeparator(Globals.lang("Include entries"));
+ builder.append(all, 3);
+ builder.nextLine();
+ builder.append(selected, 3);
+ builder.nextLine();
+ builder.appendSeparator(Globals.lang("New field value"));
+ builder.append(set);
+ builder.append(text);
+ builder.nextLine();
+ builder.append(clear);
+ builder.nextLine();
+ builder.append(overwrite, 3);
+
+
+ ButtonBarBuilder bb = new ButtonBarBuilder();
+ bb.addGlue();
+ bb.addGridded(ok);
+ bb.addGridded(cancel);
+ bb.addGlue();
+ builder.getPanel().setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+ bb.getPanel().setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+ diag.getContentPane().add(builder.getPanel(), BorderLayout.CENTER);
+ diag.getContentPane().add(bb.getPanel(), BorderLayout.SOUTH);
+ diag.pack();
+
+ ok.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ cancelled = false;
+ diag.dispose();
+ }
+ });
+
+ cancel.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ cancelled = true;
+ diag.dispose();
+ }
+ });
+
+ }
+
+ private void prepareDialog(boolean selection) {
+ selected.setEnabled(selection);
+ if (selection)
+ selected.setSelected(true);
+ else
+ all.setSelected(true);
+ // Make sure one of the following ones is selected:
+ if (!set.isSelected() && !clear.isSelected())
+ set.setSelected(true);
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ BasePanel bp = frame.basePanel();
+ if (bp == null)
+ return;
+ BibtexEntry[] entries = bp.getSelectedEntries();
+ // Lazy creation of the dialog:
+ if (diag == null)
+ createDialog();
+ cancelled = true;
+ prepareDialog(entries.length > 0);
+ Util.placeDialog(diag, frame);
+ diag.setVisible(true);
+ if (cancelled)
+ return;
+
+ Collection entryList;
+ // If all entries should be treated, change the entries array:
+ if (all.isSelected())
+ entryList = bp.database().getEntries();
+ else
+ entryList = Arrays.asList(entries);
+ String toSet = text.getText();
+ if (toSet.length() == 0)
+ toSet = null;
+ String[] fields = getFieldNames(field.getText().trim().toLowerCase());
+ NamedCompound ce = new NamedCompound(Globals.lang("Set field"));
+ for (int i = 0; i < fields.length; i++) {
+ ce.addEdit(Util.massSetField(entryList, fields[i],
+ set.isSelected() ? toSet : null,
+ overwrite.isSelected()));
+
+ }
+ ce.end();
+ bp.undoManager.addEdit(ce);
+ bp.markBaseChanged();
+ }
+
+ private String[] getFieldNames(String s) {
+ return s.split("[^a-z]");
+ }
+}
diff --git a/src/java/net/sf/jabref/util/XMPSchemaBibtex.java b/src/java/net/sf/jabref/util/XMPSchemaBibtex.java
new file mode 100644
index 0000000..75a08b4
--- /dev/null
+++ b/src/java/net/sf/jabref/util/XMPSchemaBibtex.java
@@ -0,0 +1,280 @@
+package net.sf.jabref.util;
+
+import java.io.IOException;
+import java.util.Calendar;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.xml.transform.TransformerException;
+
+import net.sf.jabref.AuthorList;
+import net.sf.jabref.BibtexEntry;
+import net.sf.jabref.BibtexEntryType;
+import net.sf.jabref.Util;
+
+import org.jempbox.xmp.XMPMetadata;
+import org.jempbox.xmp.XMPSchema;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+public class XMPSchemaBibtex extends XMPSchema {
+
+ /**
+ * The namespace of this schema.
+ */
+ public static final String NAMESPACE = "http://jabref.sourceforge.net/bibteXMP/";
+
+ public static final String KEY = "bibtex";
+
+ /**
+ * Create a new empty XMPSchemaBibtex as a child in the given XMPMetadata.
+ *
+ * @param parent
+ */
+ public XMPSchemaBibtex(XMPMetadata parent) {
+ super(parent, KEY, NAMESPACE);
+ }
+
+ /**
+ * Create schema from an existing XML element.
+ *
+ * @param element
+ * The existing XML element.
+ */
+ public XMPSchemaBibtex(Element e) {
+ super(e);
+ }
+
+ protected String makeProperty(String propertyName) {
+ return KEY + ":" + propertyName;
+ }
+
+ /**
+ *
+ * @param field
+ * @return
+ * @derived Uses XMPSchema methods
+ */
+ public List getPersonList(String field) {
+ return getSequenceList(field);
+ }
+
+ /**
+ *
+ * @param field
+ * @param value
+ * @derived Uses XMPSchema methods
+ */
+ public void setPersonList(String field, String value) {
+ AuthorList list = AuthorList.getAuthorList(value);
+
+ int n = list.size();
+ for (int i = 0; i < n; i++) {
+ addSequenceValue(field, list.getAuthor(i).getFirstLast(false));
+ }
+ }
+
+ public String getTextProperty(String field) {
+ return super.getTextProperty(makeProperty(field));
+ }
+
+ public void setTextProperty(String field, String value) {
+ super.setTextProperty(makeProperty(field), value);
+ }
+
+ public List getBagList(String bagName) {
+ return super.getBagList(makeProperty(bagName));
+ }
+
+ public void removeBagValue(String bagName, String value) {
+ super.removeBagValue(makeProperty(bagName), value);
+ }
+
+ public void addBagValue(String bagName, String value) {
+ super.addBagValue(makeProperty(bagName), value);
+ }
+
+ public List getSequenceList(String seqName) {
+ return super.getSequenceList(makeProperty(seqName));
+ }
+
+ public void removeSequenceValue(String seqName, String value) {
+ super.removeSequenceValue(makeProperty(seqName), value);
+ }
+
+ public void addSequenceValue(String seqName, String value) {
+ super.addSequenceValue(makeProperty(seqName), value);
+ }
+
+ public List getSequenceDateList(String seqName) throws IOException {
+ return super.getSequenceDateList(makeProperty(seqName));
+ }
+
+ public void removeSequenceDateValue(String seqName, Calendar date) {
+ super.removeSequenceDateValue(makeProperty(seqName), date);
+ }
+
+ public void addSequenceDateValue(String field, Calendar date) {
+ super.addSequenceDateValue(makeProperty(field), date);
+ }
+
+ /**
+ * Returns a map of all properties and their values. LIs in seqs are
+ * concatenated using " and ".
+ *
+ * @return Map from name of textproperty (String) to value (String). For
+ * instance: "year" => "2005". Empty map if none found.
+ * @throws TransformerException
+ */
+ public Map getAllProperties() {
+ NodeList nodes = getElement().getChildNodes();
+
+ Map result = new HashMap();
+
+ if (nodes == null) {
+ return result;
+ }
+
+ // Check child-nodes first
+ int n = nodes.getLength();
+
+ for (int i = 0; i < n; i++) {
+ Node node = nodes.item(i);
+ if (node.getNodeType() != Node.ATTRIBUTE_NODE
+ && node.getNodeType() != Node.ELEMENT_NODE)
+ continue;
+
+ String nodeName = node.getNodeName();
+
+ String[] split = nodeName.split(":");
+ if (split.length == 2 && split[0].equals("bibtex")) {
+
+ NodeList seqList = ((Element) node).getElementsByTagName("rdf:Seq");
+ if (seqList.getLength() > 0) {
+ Element seqNode = (Element) seqList.item(0);
+ StringBuffer seq = null;
+
+ NodeList items = seqNode.getElementsByTagName("rdf:li");
+ for (int j = 0; j < items.getLength(); j++) {
+ Element li = (Element) items.item(j);
+ if (seq == null) {
+ seq = new StringBuffer();
+ } else {
+ seq.append(" and ");
+ }
+ seq.append(getTextContent(li));
+ }
+ if (seq != null) {
+ result.put(split[1], seq.toString());
+ }
+ } else {
+ result.put(split[1], getTextContent(node));
+ }
+ }
+ }
+
+ // Then check Attributes
+ NamedNodeMap attrs = getElement().getAttributes();
+ int m = attrs.getLength();
+ for (int j = 0; j < m; j++) {
+ Node attr = attrs.item(j);
+
+ String nodeName = attr.getNodeName();
+ String[] split = nodeName.split(":");
+ if (split.length == 2 && split[0].equals("bibtex")) {
+ result.put(split[1], attr.getNodeValue());
+ }
+ }
+
+ /*
+ * Collapse Whitespace
+ *
+ * Quoting from
+ * http://www.gerg.ca/software/btOOL/doc/bt_postprocess.html: <cite>
+ * "The exact rules for collapsing whitespace are simple: non-space
+ * whitespace characters (tabs and newlines mainly) are converted to
+ * space, any strings of more than one space within are collapsed to a
+ * single space, and any leading or trailing spaces are deleted."
+ * </cite>
+ */
+ Set entries = result.entrySet();
+ Iterator it = entries.iterator();
+ while (it.hasNext()) {
+ Map.Entry entry = (Map.Entry) it.next();
+ String key = (String)entry.getKey();
+ if (preserveWhiteSpace.containsKey(key))
+ continue;
+ entry.setValue(((String) entry.getValue()).replaceAll("\\s+", " ").trim());
+ }
+
+ return result;
+ }
+
+ public static HashMap preserveWhiteSpace = new HashMap();
+ static {
+ preserveWhiteSpace.put("abstract", null);
+ preserveWhiteSpace.put("note", null);
+ preserveWhiteSpace.put("review", null);
+ }
+
+ public void setBibtexEntry(BibtexEntry entry) {
+ // Set all the values including key and entryType
+ Object[] fields = entry.getAllFields();
+
+ for (int i = 0; i < fields.length; i++) {
+ if (fields[i].equals("author") || fields[i].equals("editor")) {
+ setPersonList(fields[i].toString(), entry.getField(fields[i].toString()).toString());
+ } else {
+ setTextProperty(fields[i].toString(), entry.getField(fields[i].toString())
+ .toString());
+ }
+ }
+ setTextProperty("entrytype", entry.getType().getName());
+ }
+
+ public BibtexEntry getBibtexEntry() {
+
+ String type = getTextProperty("entrytype");
+ BibtexEntryType t;
+ if (type != null)
+ t = BibtexEntryType.getStandardType(type);
+ else
+ t = BibtexEntryType.OTHER;
+
+ BibtexEntry e = new BibtexEntry(Util.createNeutralId(), t);
+
+ // Get Text Properties
+ Map text = getAllProperties();
+ text.remove("entrytype");
+ e.setField(text);
+ return e;
+
+ }
+
+ /**
+ * Taken from DOM2Utils.java:
+ *
+ * JBoss, the OpenSource EJB server
+ *
+ * Distributable under LGPL license. See terms of license at gnu.org.
+ */
+ public static String getTextContent(Node node) {
+ boolean hasTextContent = false;
+ StringBuffer buffer = new StringBuffer();
+ NodeList nlist = node.getChildNodes();
+ for (int i = 0; i < nlist.getLength(); i++) {
+ Node child = nlist.item(i);
+ if (child.getNodeType() == Node.TEXT_NODE) {
+ buffer.append(child.getNodeValue());
+ hasTextContent = true;
+ }
+ }
+ return (hasTextContent ? buffer.toString() : "");
+ }
+
+}
diff --git a/src/java/net/sf/jabref/util/XMPUtil.java b/src/java/net/sf/jabref/util/XMPUtil.java
new file mode 100644
index 0000000..42dd697
--- /dev/null
+++ b/src/java/net/sf/jabref/util/XMPUtil.java
@@ -0,0 +1,506 @@
+package net.sf.jabref.util;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.StringWriter;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+import javax.xml.transform.TransformerException;
+
+import net.sf.jabref.BibtexEntry;
+import net.sf.jabref.Globals;
+import net.sf.jabref.JabRefPreferences;
+import net.sf.jabref.imports.BibtexParser;
+import net.sf.jabref.imports.ParserResult;
+
+import org.jempbox.impl.XMLUtil;
+import org.jempbox.xmp.XMPMetadata;
+import org.pdfbox.exceptions.COSVisitorException;
+import org.pdfbox.pdmodel.PDDocument;
+import org.pdfbox.pdmodel.PDDocumentCatalog;
+import org.pdfbox.pdmodel.common.PDMetadata;
+
+/**
+ * XMPUtils provide support for reading and writing BibTex data as XMP-Metadata
+ * in PDF-documents.
+ *
+ * @author Christopher Oezbek <oezi at oezi.de>
+ *
+ * @version $Revision: 1.2 $ ($Date: 2006/08/13 13:17:52 $)
+ */
+public class XMPUtil {
+
+ /**
+ * Convenience method for readXMP(File).
+ *
+ * @param filename
+ * The filename from which to open the file.
+ * @return BibtexEntryies found in the PDF or an empty list
+ * @throws IOException
+ */
+ public static List readXMP(String filename) throws IOException {
+ return readXMP(new File(filename));
+ }
+
+ /**
+ * Try to write the given BibTexEntry in the XMP-stream of the given
+ * PDF-file.
+ *
+ * Throws an IOException if the file cannot be read or written, so the user
+ * can remove a lock or cancel the operation.
+ *
+ * The method will overwrite existing BibTeX-XMP-data, but keep other
+ * existing metadata.
+ *
+ * This is a convenience method for writeXMP(File, BibtexEntry).
+ *
+ * @param filename
+ * The filename from which to open the file.
+ * @param entry
+ * The entry to write.
+ * @throws TransformerException
+ * If the entry was malformed or unsupported.
+ * @throws IOException
+ * If the file could not be written to or could not be found.
+ */
+ public static void writeXMP(String filename, BibtexEntry entry) throws IOException,
+ TransformerException {
+ writeXMP(new File(filename), entry);
+ }
+
+ /**
+ * Try to read the given BibTexEntry from the XMP-stream of the given
+ * PDF-file.
+ *
+ * @param file
+ * The file to read from.
+ *
+ * @throws IOException
+ * Throws an IOException if the file cannot be read, so the user
+ * than remove a lock or cancel the operation.
+ */
+ public static List readXMP(File file) throws IOException {
+ FileInputStream is = new FileInputStream(file);
+ try {
+ return readXMP(is);
+ } finally {
+ is.close();
+ }
+ }
+
+ /**
+ * Try to read the given BibTexEntry from the XMP-stream of the given
+ * inputstream containing a PDF-file.
+ *
+ * @param file
+ * The inputstream to read from.
+ *
+ * @throws IOException
+ * Throws an IOException if the file cannot be read, so the user
+ * than remove a lock or cancel the operation.
+ */
+ public static List readXMP(InputStream inputStream) throws IOException {
+
+ XMPMetadata meta = readRawXMP(inputStream);
+
+ // If we did not find any metadata, there is nothing to return.
+ if (meta == null)
+ return null;
+
+ List schemas = meta.getSchemasByNamespaceURI(XMPSchemaBibtex.NAMESPACE);
+ List result = new LinkedList();
+
+ Iterator it = schemas.iterator();
+ while (it.hasNext()) {
+ XMPSchemaBibtex bib = (XMPSchemaBibtex) it.next();
+
+ result.add(bib.getBibtexEntry());
+ }
+ return result;
+ }
+
+ /**
+ * Try to write the given BibTexEntry in the XMP-stream of the given
+ * PDF-file.
+ *
+ * Throws an IOException if the file cannot be read or written, so the user
+ * can remove a lock or cancel the operation.
+ *
+ * The method will overwrite existing BibTeX-XMP-data, but keep other
+ * existing metadata.
+ *
+ * This is a convenience method for writeXMP(File, Collection).
+ *
+ * @param file
+ * The file to write to.
+ * @param entry
+ * The entry to write.
+ * @throws TransformerException
+ * If the entry was malformed or unsupported.
+ * @throws IOException
+ * If the file could not be written to or could not be found.
+ */
+ public static void writeXMP(File file, BibtexEntry entry) throws IOException,
+ TransformerException {
+ List l = new LinkedList();
+ l.add(entry);
+ writeXMP(file, l);
+ }
+
+ /**
+ * Write the given BibtexEntries as XMP-metadata text to the given stream.
+ *
+ * The text that is written to the stream contains a complete XMP-document.
+ *
+ * @param bibtexEntries
+ * The BibtexEntries to write XMP-metadata for.
+ * @throws TransformerException
+ * Thrown if the bibtexEntries could not transformed to XMP.
+ * @throws IOException
+ * Thrown if an IOException occured while writing to the stream.
+ */
+ public static void toXMP(Collection bibtexEntries, OutputStream outputStream)
+ throws IOException, TransformerException {
+
+ XMPMetadata x = new XMPMetadata();
+
+ Iterator it = bibtexEntries.iterator();
+ while (it.hasNext()) {
+ BibtexEntry e = (BibtexEntry) it.next();
+ XMPSchemaBibtex schema = new XMPSchemaBibtex(x);
+ x.addSchema(schema);
+ schema.setBibtexEntry(e);
+ }
+
+ x.save(outputStream);
+
+ }
+
+ /**
+ * Convenience method for toXMP(Collection, OutputStream) returning a String
+ * containing the XMP-metadata of the given collection of BibtexEntries.
+ *
+ * The resulting metadata string is wrapped as a complete XMP-document.
+ *
+ * @param bibtexEntries
+ * The BibtexEntries to return XMP-metadata for.
+ * @return The XMP representation of the given bibtexEntries.
+ * @throws TransformerException
+ * Thrown if the bibtexEntries could not transformed to XMP.
+ */
+ public static String toXMP(Collection bibtexEntries) throws TransformerException {
+ try {
+ ByteArrayOutputStream bs = new ByteArrayOutputStream();
+ toXMP(bibtexEntries, bs);
+ return bs.toString();
+ } catch (IOException e) {
+ throw new TransformerException(e);
+ }
+ }
+
+ /**
+ * Will read the XMPMetadata from the given pdf file, closing the file
+ * afterwards.
+ *
+ * @param inputStream
+ * The inputStream representing a PDF-file to read the
+ * XMPMetadata from.
+ * @return The XMPMetadata object found in the file or null if none is
+ * found.
+ * @throws IOException
+ */
+ public static XMPMetadata readRawXMP(InputStream inputStream) throws IOException {
+ PDDocument document = null;
+
+ try {
+ document = PDDocument.load(inputStream);
+ if (document.isEncrypted()) {
+ throw new EncryptionNotSupportedException(
+ "Error: Cannot read metadata from encrypted document.");
+ }
+ PDDocumentCatalog catalog = document.getDocumentCatalog();
+ PDMetadata metaRaw = catalog.getMetadata();
+
+ if (metaRaw == null) {
+ return null;
+ }
+
+ XMPMetadata meta = new XMPMetadata(XMLUtil.parse(metaRaw.createInputStream()));
+ meta.addXMLNSMapping(XMPSchemaBibtex.NAMESPACE, XMPSchemaBibtex.class);
+ return meta;
+
+ } finally {
+ if (document != null)
+ document.close();
+ }
+ }
+
+ /**
+ * Will read the XMPMetadata from the given pdf file, closing the file
+ * afterwards.
+ *
+ * @param file
+ * The file to read the XMPMetadata from.
+ * @return The XMPMetadata object found in the file or null if none is
+ * found.
+ * @throws IOException
+ */
+ public static XMPMetadata readRawXMP(File file) throws IOException {
+ FileInputStream is = new FileInputStream(file);
+ try {
+ return readRawXMP(is);
+ } finally {
+ is.close();
+ }
+ }
+
+ /**
+ * Try to write the given BibTexEntry in the XMP-stream of the given
+ * PDF-file.
+ *
+ * Throws an IOException if the file cannot be read or written, so the user
+ * can remove a lock or cancel the operation.
+ *
+ * The method will overwrite existing BibTeX-XMP-data, but keep other
+ * existing metadata.
+ *
+ * @param file
+ * The file to write the entries to.
+ * @param bibtexEntries
+ * The entries to write to the file.
+ * @throws TransformerException
+ * If the entry was malformed or unsupported.
+ * @throws IOException
+ * If the file could not be written to or could not be found.
+ */
+ public static void writeXMP(File file, Collection bibtexEntries) throws IOException,
+ TransformerException {
+
+ PDDocument document = null;
+
+ try {
+ document = PDDocument.load(file.getAbsoluteFile());
+ if (document.isEncrypted()) {
+ throw new EncryptionNotSupportedException(
+ "Error: Cannot add metadata to encrypted document.");
+ }
+ PDDocumentCatalog catalog = document.getDocumentCatalog();
+ PDMetadata metaRaw = catalog.getMetadata();
+
+ XMPMetadata meta;
+ if (metaRaw != null) {
+ meta = new XMPMetadata(XMLUtil.parse(metaRaw.createInputStream()));
+ } else {
+ meta = new XMPMetadata();
+ }
+ meta.addXMLNSMapping(XMPSchemaBibtex.NAMESPACE, XMPSchemaBibtex.class);
+
+ // Remove all current Bibtex-schemas
+ List schemas = meta.getSchemasByNamespaceURI(XMPSchemaBibtex.NAMESPACE);
+ Iterator it = schemas.iterator();
+ while (it.hasNext()) {
+ XMPSchemaBibtex bib = (XMPSchemaBibtex) it.next();
+ bib.getElement().getParentNode().removeChild(bib.getElement());
+ }
+
+ it = bibtexEntries.iterator();
+ while (it.hasNext()) {
+ BibtexEntry e = (BibtexEntry) it.next();
+ XMPSchemaBibtex bibtex = new XMPSchemaBibtex(meta);
+ meta.addSchema(bibtex);
+ bibtex.setBibtexEntry(e);
+ }
+
+ // Save to stream and then input that stream to the PDF
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+ meta.save(os);
+ ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray());
+ PDMetadata metadataStream = new PDMetadata(document, is, false);
+ catalog.setMetadata(metadataStream);
+
+ // Save
+ try {
+ document.save(file.getAbsolutePath());
+ } catch (COSVisitorException e) {
+ throw new TransformerException("Could not write XMP-metadata: "
+ + e.getLocalizedMessage());
+ }
+
+ } finally {
+ if (document != null) {
+ document.close();
+ }
+ }
+ }
+
+ /**
+ * Print usage information for the command line tool xmpUtil.
+ *
+ * @see net.sf.jabref.util.XMUtil.main()
+ */
+ protected static void usage() {
+ System.out.println("Read or write XMP-metadata from or to pdf file.");
+ System.out.println("");
+ System.out.println("Usage:");
+ System.out.println("Read from PDF and print as bibtex:");
+ System.out.println(" xmpUtil <pdf>");
+ System.out.println("Read from PDF and print raw XMP:");
+ System.out.println(" xmpUtil -x <pdf>");
+ System.out.println("Write the entry in <bib> given by <key> to the PDF:");
+ System.out.println(" xmpUtil <key> <bib> <pdf>");
+ System.out.println("Write all entries in <bib> to the PDF:");
+ System.out.println(" xmpUtil <bib> <pdf>");
+ System.out.println("");
+ System.out.println("To report bugs visit http://jabref.sourceforge.net");
+ }
+
+ /**
+ * Command-line tool for working with XMP-data.
+ *
+ * Read or write XMP-metadata from or to pdf file.
+ *
+ * Usage:
+ * <dl>
+ * <dd>Read from PDF and print as bibtex:</dd>
+ * <dt>xmpUtil PDF</dt>
+ * <dd>Read from PDF and print raw XMP:</dd>
+ * <dt>xmpUtil -x PDF</dt>
+ * <dd>Write the entry in BIB given by KEY to the PDF:</dd>
+ * <dt>xmpUtil KEY BIB PDF</dt>
+ * <dd>Write all entries in BIB to the PDF:</dd>
+ * <dt>xmpUtil BIB PDF</dt>
+ * </dl>
+ *
+ * @param args
+ * Command line strings passed to utility.
+ * @throws IOException
+ * If any of the given files could not be read or written.
+ * @throws TransformerException
+ * If the given BibtexEntry is malformed.
+ */
+ public static void main(String[] args) throws IOException, TransformerException {
+
+ // Don't forget to initialize the preferences
+ if (Globals.prefs == null) {
+ Globals.prefs = JabRefPreferences.getInstance();
+ }
+
+ switch (args.length) {
+ case 0:
+ usage();
+ break;
+ case 1: {
+
+ if (args[0].endsWith(".pdf")) {
+ // Read from pdf and write as BibTex
+ List l = XMPUtil.readXMP(new File(args[0]));
+
+ Iterator it = l.iterator();
+ while (it.hasNext()) {
+ BibtexEntry e = (BibtexEntry) it.next();
+ StringWriter sw = new StringWriter();
+ e.write(sw, new net.sf.jabref.export.LatexFieldFormatter(), false);
+ System.out.println(sw.getBuffer().toString());
+ }
+
+ } else if (args[0].endsWith(".bib")) {
+ // Read from bib and write as XMP
+
+ ParserResult result = BibtexParser.parse(new FileReader(args[0]));
+ Collection c = result.getDatabase().getEntries();
+
+ if (c.size() == 0) {
+ System.err.println("Could not find BibtexEntry in " + args[0]);
+ } else {
+ System.out.println(XMPUtil.toXMP(c));
+ }
+
+ } else {
+ usage();
+ }
+ break;
+ }
+ case 2: {
+ if (args[0].equals("-x") && args[1].endsWith(".pdf")) {
+ // Read from pdf and write as BibTex
+ XMPMetadata meta = XMPUtil.readRawXMP(new File(args[1]));
+
+ if (meta == null) {
+ System.err.println("The given pdf does not contain any XMP-metadata.");
+ } else {
+ XMLUtil.save(meta.getXMPDocument(), System.out, "UTF-8");
+ }
+ break;
+ }
+
+ if (args[0].endsWith(".bib") && args[1].endsWith(".pdf")) {
+ ParserResult result = BibtexParser.parse(new FileReader(args[0]));
+
+ Collection c = result.getDatabase().getEntries();
+
+ if (c.size() == 0) {
+ System.err.println("Could not find BibtexEntry in " + args[0]);
+ } else {
+ XMPUtil.writeXMP(new File(args[1]), c);
+ System.out.println("XMP written.");
+ }
+ break;
+ }
+
+ usage();
+ break;
+ }
+ case 3: {
+ if (!args[1].endsWith(".bib") && !args[2].endsWith(".pdf")) {
+ usage();
+ break;
+ }
+
+ ParserResult result = BibtexParser.parse(new FileReader(args[1]));
+
+ BibtexEntry e = result.getDatabase().getEntryByKey(args[0]);
+
+ if (e == null) {
+ System.err.println("Could not find BibtexEntry " + args[0] + " in " + args[0]);
+ } else {
+ XMPUtil.writeXMP(new File(args[2]), e);
+
+ System.out.println("XMP written.");
+ }
+ break;
+ }
+
+ default:
+ usage();
+ }
+ }
+
+ /**
+ * Will try to read XMP metadata from the given file, returning whether
+ * metadata was found.
+ *
+ * Caution: This method is as expensive as reading the actual metadata
+ * itself from the PDF.
+ *
+ * @param is
+ * The inputstream to read the PDF from.
+ * @return whether a BibtexEntry was found in the given PDF.
+ */
+ public static boolean hasMetadata(InputStream is) {
+ try {
+ List l = XMPUtil.readXMP(is);
+ return l.size() > 0;
+ } catch (Exception e) {
+ return false;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/java/net/sf/jabref/wizard/integrity/IntegrityCheck.java b/src/java/net/sf/jabref/wizard/integrity/IntegrityCheck.java
index 5edb651..eb8b826 100644
--- a/src/java/net/sf/jabref/wizard/integrity/IntegrityCheck.java
+++ b/src/java/net/sf/jabref/wizard/integrity/IntegrityCheck.java
@@ -241,8 +241,17 @@ public class IntegrityCheck
}
if (upLowCounter > 0)
{
+
+ /*
+ Morten Alver (2006.10.10):
+
+ Disabling this warning because we have a feature for automatically adding
+ braces when saving, which makes this warning misleading. It could be modified
+ to suggest to use this feature if not enabled, and not give a warning if the
+ feature is enabled.
+
messages.add( new IntegrityMessage( IntegrityMessage.UPPER_AND_LOWER_HINT,
- entry, fieldName, null)) ;
+ entry, fieldName, null)) ;*/
}
}
diff --git a/src/java/tests/net/sf/jabref/AllTests.java b/src/java/tests/net/sf/jabref/AllTests.java
new file mode 100644
index 0000000..6eb1f28
--- /dev/null
+++ b/src/java/tests/net/sf/jabref/AllTests.java
@@ -0,0 +1,28 @@
+package tests.net.sf.jabref;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+public class AllTests {
+
+ public static Test suite() {
+ TestSuite suite = new TestSuite("Test for test.net.sf.jabref");
+ //$JUnit-BEGIN$
+ suite.addTestSuite(UtilTest.class);
+ suite.addTestSuite(FileBasedTestCase.class);
+ suite.addTestSuite(UtilFindFileTest.class);
+ suite.addTestSuite(AuthorListTest.class);
+ suite.addTestSuite(JabRefTestCase.class);
+ //$JUnit-END$
+
+ suite.addTest(tests.net.sf.jabref.export.layout.format.AllTests.suite());
+ suite.addTest(tests.net.sf.jabref.imports.AllTests.suite());
+ suite.addTest(tests.net.sf.jabref.search.AllTests.suite());
+ suite.addTest(tests.net.sf.jabref.util.AllTests.suite());
+ suite.addTest(tests.net.sf.jabref.export.layout.AllTests.suite());
+ suite.addTest(tests.net.sf.jabref.bst.AllTests.suite());
+
+ return suite;
+ }
+
+}
diff --git a/src/java/tests/net/sf/jabref/AuthorListTest.java b/src/java/tests/net/sf/jabref/AuthorListTest.java
new file mode 100644
index 0000000..e7f9d40
--- /dev/null
+++ b/src/java/tests/net/sf/jabref/AuthorListTest.java
@@ -0,0 +1,547 @@
+package tests.net.sf.jabref;
+
+import junit.framework.TestCase;
+import net.sf.jabref.AuthorList;
+
+/**
+ *
+ * @see net.sf.jabref.AuthorList Class tested.
+ *
+ * @author Christopher Oezbek <oezi at oezi.de>
+ *
+ * @version 0.1 - Still fails for stuff in AuthorList that is ambiguous
+ */
+public class AuthorListTest extends TestCase {
+
+ public void testFixAuthor_Natbib() {
+ assertEquals("", AuthorList.fixAuthor_Natbib(""));
+ assertEquals("Smith", AuthorList.fixAuthor_Natbib("John Smith"));
+ assertEquals("Smith and Black Brown", AuthorList
+ .fixAuthor_Natbib("John Smith and Black Brown, Peter"));
+ assertEquals("von Neumann et al.", AuthorList
+ .fixAuthor_Natbib("John von Neumann and John Smith and Black Brown, Peter"));
+
+ // Is not cached!
+ assertTrue(AuthorList
+ .fixAuthor_Natbib("John von Neumann and John Smith and Black Brown, Peter") == AuthorList
+ .fixAuthor_Natbib("John von Neumann" + (0 == 1 ? "" : " and ")
+ + "John Smith and Black Brown, Peter"));
+ }
+
+ public void testGetAuthorList() {
+ // Test caching in authorCache.
+ AuthorList al = AuthorList.getAuthorList("John Smith");
+ assertTrue(al == AuthorList.getAuthorList("John Smith"));
+ assertFalse(al == AuthorList.getAuthorList("Smith"));
+ }
+
+ public void testFixAuthor_firstNameFirstCommas() {
+
+ { // No Commas
+ assertEquals("", AuthorList.fixAuthor_firstNameFirstCommas("", true, false));
+ assertEquals("", AuthorList.fixAuthor_firstNameFirstCommas("", false, false));
+
+ assertEquals("John Smith", AuthorList.fixAuthor_firstNameFirstCommas("John Smith",
+ false, false));
+ assertEquals("J. Smith", AuthorList.fixAuthor_firstNameFirstCommas("John Smith", true,
+ false));
+
+ // Check caching
+ assertTrue(AuthorList.fixAuthor_firstNameFirstCommas(
+ "John von Neumann and John Smith and Black Brown, Peter", true, false) == AuthorList
+ .fixAuthor_firstNameFirstCommas("John von Neumann" + (0 == 1 ? "" : " and ")
+ + "John Smith and Black Brown, Peter", true, false));
+
+ assertEquals("John Smith and Peter Black Brown", AuthorList
+ .fixAuthor_firstNameFirstCommas("John Smith and Black Brown, Peter", false, false));
+ assertEquals("J. Smith and P. Black Brown", AuthorList.fixAuthor_firstNameFirstCommas(
+ "John Smith and Black Brown, Peter", true, false));
+
+ // Method description is different than code -> additional comma
+ // there
+ assertEquals("John von Neumann, John Smith and Peter Black Brown", AuthorList
+ .fixAuthor_firstNameFirstCommas(
+ "John von Neumann and John Smith and Black Brown, Peter", false, false));
+ assertEquals("J. von Neumann, J. Smith and P. Black Brown", AuthorList
+ .fixAuthor_firstNameFirstCommas(
+ "John von Neumann and John Smith and Black Brown, Peter", true, false));
+
+ assertEquals("J. P. von Neumann", AuthorList.fixAuthor_firstNameFirstCommas(
+ "John Peter von Neumann", true, false));
+ }
+ { // Oxford Commas
+ assertEquals("", AuthorList.fixAuthor_firstNameFirstCommas("", true, true));
+ assertEquals("", AuthorList.fixAuthor_firstNameFirstCommas("", false, true));
+
+ assertEquals("John Smith", AuthorList.fixAuthor_firstNameFirstCommas("John Smith",
+ false, true));
+ assertEquals("J. Smith", AuthorList.fixAuthor_firstNameFirstCommas("John Smith", true,
+ true));
+
+ // Check caching
+ assertTrue(AuthorList.fixAuthor_firstNameFirstCommas(
+ "John von Neumann and John Smith and Black Brown, Peter", true, true) == AuthorList
+ .fixAuthor_firstNameFirstCommas("John von Neumann" + (0 == 1 ? "" : " and ")
+ + "John Smith and Black Brown, Peter", true, true));
+
+ assertEquals("John Smith and Peter Black Brown", AuthorList
+ .fixAuthor_firstNameFirstCommas("John Smith and Black Brown, Peter", false, true));
+ assertEquals("J. Smith and P. Black Brown", AuthorList.fixAuthor_firstNameFirstCommas(
+ "John Smith and Black Brown, Peter", true, true));
+
+ // Method description is different than code -> additional comma
+ // there
+ assertEquals("John von Neumann, John Smith, and Peter Black Brown", AuthorList
+ .fixAuthor_firstNameFirstCommas(
+ "John von Neumann and John Smith and Black Brown, Peter", false, true));
+ assertEquals("J. von Neumann, J. Smith, and P. Black Brown", AuthorList
+ .fixAuthor_firstNameFirstCommas(
+ "John von Neumann and John Smith and Black Brown, Peter", true, true));
+
+ assertEquals("J. P. von Neumann", AuthorList.fixAuthor_firstNameFirstCommas(
+ "John Peter von Neumann", true, true));
+
+ }
+ }
+
+ public void testFixAuthor_firstNameFirst() {
+ assertEquals("John Smith", AuthorList.fixAuthor_firstNameFirst("John Smith"));
+
+ assertEquals("John Smith and Peter Black Brown", AuthorList
+ .fixAuthor_firstNameFirst("John Smith and Black Brown, Peter"));
+
+ assertEquals("John von Neumann and John Smith and Peter Black Brown", AuthorList
+ .fixAuthor_firstNameFirst("John von Neumann and John Smith and Black Brown, Peter"));
+
+ assertEquals("First von Last, Jr. III", AuthorList
+ .fixAuthor_firstNameFirst("von Last, Jr. III, First"));
+
+ // Check caching
+ assertTrue(AuthorList
+ .fixAuthor_firstNameFirst("John von Neumann and John Smith and Black Brown, Peter") == AuthorList
+ .fixAuthor_firstNameFirst("John von Neumann" + (0 == 1 ? "" : " and ")
+ + "John Smith and Black Brown, Peter"));
+
+ }
+
+ public void testFixAuthor_lastNameFirstCommas() {
+
+ { // No commas before and
+ assertEquals("", AuthorList.fixAuthor_lastNameFirstCommas("", true, false));
+ assertEquals("", AuthorList.fixAuthor_lastNameFirstCommas("", false, false));
+
+ assertEquals("Smith, John", AuthorList.fixAuthor_lastNameFirstCommas("John Smith",
+ false, false));
+ assertEquals("Smith, J.", AuthorList.fixAuthor_lastNameFirstCommas("John Smith", true,
+ false));
+
+ String a = AuthorList.fixAuthor_lastNameFirstCommas(
+ "John von Neumann and John Smith and Black Brown, Peter", true, false);
+ String b = AuthorList.fixAuthor_lastNameFirstCommas("John von Neumann"
+ + (0 == 1 ? "" : " and ") + "John Smith and Black Brown, Peter", true, false);
+
+ // Check caching
+ assertEquals(a, b);
+ assertTrue(a == b);
+
+ assertEquals("Smith, John and Black Brown, Peter", AuthorList
+ .fixAuthor_lastNameFirstCommas("John Smith and Black Brown, Peter", false, false));
+ assertEquals("Smith, J. and Black Brown, P.", AuthorList.fixAuthor_lastNameFirstCommas(
+ "John Smith and Black Brown, Peter", true, false));
+
+ assertEquals("von Neumann, John, Smith, John and Black Brown, Peter", AuthorList
+ .fixAuthor_lastNameFirstCommas(
+ "John von Neumann and John Smith and Black Brown, Peter", false, false));
+ assertEquals("von Neumann, J., Smith, J. and Black Brown, P.", AuthorList
+ .fixAuthor_lastNameFirstCommas(
+ "John von Neumann and John Smith and Black Brown, Peter", true, false));
+
+ assertEquals("von Neumann, J. P.", AuthorList.fixAuthor_lastNameFirstCommas(
+ "John Peter von Neumann", true, false));
+ }
+ { // Oxford Commas
+ assertEquals("", AuthorList.fixAuthor_lastNameFirstCommas("", true, true));
+ assertEquals("", AuthorList.fixAuthor_lastNameFirstCommas("", false, true));
+
+ assertEquals("Smith, John", AuthorList.fixAuthor_lastNameFirstCommas("John Smith",
+ false, true));
+ assertEquals("Smith, J.", AuthorList.fixAuthor_lastNameFirstCommas("John Smith", true,
+ true));
+
+ String a = AuthorList.fixAuthor_lastNameFirstCommas(
+ "John von Neumann and John Smith and Black Brown, Peter", true, true);
+ String b = AuthorList.fixAuthor_lastNameFirstCommas("John von Neumann"
+ + (0 == 1 ? "" : " and ") + "John Smith and Black Brown, Peter", true, true);
+
+ // Check caching
+ assertEquals(a, b);
+ assertTrue(a == b);
+
+ assertEquals("Smith, John and Black Brown, Peter", AuthorList
+ .fixAuthor_lastNameFirstCommas("John Smith and Black Brown, Peter", false, true));
+ assertEquals("Smith, J. and Black Brown, P.", AuthorList.fixAuthor_lastNameFirstCommas(
+ "John Smith and Black Brown, Peter", true, true));
+
+ assertEquals("von Neumann, John, Smith, John, and Black Brown, Peter", AuthorList
+ .fixAuthor_lastNameFirstCommas(
+ "John von Neumann and John Smith and Black Brown, Peter", false, true));
+ assertEquals("von Neumann, J., Smith, J., and Black Brown, P.", AuthorList
+ .fixAuthor_lastNameFirstCommas(
+ "John von Neumann and John Smith and Black Brown, Peter", true, true));
+
+ assertEquals("von Neumann, J. P.", AuthorList.fixAuthor_lastNameFirstCommas(
+ "John Peter von Neumann", true, true));
+ }
+ }
+
+ public void testFixAuthor_lastNameFirst() {
+
+ // Test helper method
+
+ assertEquals("Smith, John", AuthorList.fixAuthor_lastNameFirst("John Smith"));
+
+ assertEquals("Smith, John and Black Brown, Peter", AuthorList
+ .fixAuthor_lastNameFirst("John Smith and Black Brown, Peter"));
+
+ assertEquals("von Neumann, John and Smith, John and Black Brown, Peter", AuthorList
+ .fixAuthor_lastNameFirst("John von Neumann and John Smith and Black Brown, Peter"));
+
+ assertEquals("von Last, Jr, First", AuthorList
+ .fixAuthor_lastNameFirst("von Last, Jr ,First"));
+
+ assertTrue(AuthorList
+ .fixAuthor_lastNameFirst("John von Neumann and John Smith and Black Brown, Peter") == AuthorList
+ .fixAuthor_lastNameFirst("John von Neumann" + (0 == 1 ? "" : " and ")
+ + "John Smith and Black Brown, Peter"));
+
+ // Test Abbreviation == false
+ assertEquals("Smith, John", AuthorList.fixAuthor_lastNameFirst("John Smith", false));
+
+ assertEquals("Smith, John and Black Brown, Peter", AuthorList.fixAuthor_lastNameFirst(
+ "John Smith and Black Brown, Peter", false));
+
+ assertEquals("von Neumann, John and Smith, John and Black Brown, Peter", AuthorList
+ .fixAuthor_lastNameFirst("John von Neumann and John Smith and Black Brown, Peter",
+ false));
+
+ assertEquals("von Last, Jr, First", AuthorList.fixAuthor_lastNameFirst(
+ "von Last, Jr ,First", false));
+
+ assertTrue(AuthorList.fixAuthor_lastNameFirst(
+ "John von Neumann and John Smith and Black Brown, Peter", false) == AuthorList
+ .fixAuthor_lastNameFirst("John von Neumann" + (0 == 1 ? "" : " and ")
+ + "John Smith and Black Brown, Peter", false));
+
+ // Test Abbreviate == true
+ assertEquals("Smith, J.", AuthorList.fixAuthor_lastNameFirst("John Smith", true));
+
+ assertEquals("Smith, J. and Black Brown, P.", AuthorList.fixAuthor_lastNameFirst(
+ "John Smith and Black Brown, Peter", true));
+
+ assertEquals("von Neumann, J. and Smith, J. and Black Brown, P.",
+ AuthorList.fixAuthor_lastNameFirst(
+ "John von Neumann and John Smith and Black Brown, Peter", true));
+
+ assertEquals("von Last, Jr, F.", AuthorList.fixAuthor_lastNameFirst("von Last, Jr ,First",
+ true));
+
+ assertTrue(AuthorList.fixAuthor_lastNameFirst(
+ "John von Neumann and John Smith and Black Brown, Peter", true) == AuthorList
+ .fixAuthor_lastNameFirst("John von Neumann" + (0 == 1 ? "" : " and ")
+ + "John Smith and Black Brown, Peter", true));
+
+ }
+
+ public void testFixAuthor_lastNameOnlyCommas() {
+
+ { // No comma before and
+ assertEquals("", AuthorList.fixAuthor_lastNameOnlyCommas("", false));
+ assertEquals("Smith", AuthorList.fixAuthor_lastNameOnlyCommas("John Smith", false));
+ assertEquals("Smith", AuthorList.fixAuthor_lastNameOnlyCommas("Smith, Jr, John", false));
+
+ assertTrue(AuthorList.fixAuthor_lastNameOnlyCommas(
+ "John von Neumann and John Smith and Black Brown, Peter", false) == AuthorList
+ .fixAuthor_lastNameOnlyCommas("John von Neumann" + (0 == 1 ? "" : " and ")
+ + "John Smith and Black Brown, Peter", false));
+
+ assertEquals("von Neumann, Smith and Black Brown", AuthorList
+ .fixAuthor_lastNameOnlyCommas(
+ "John von Neumann and John Smith and Black Brown, Peter", false));
+ }
+ { // Oxford Comma
+ assertEquals("", AuthorList.fixAuthor_lastNameOnlyCommas("", true));
+ assertEquals("Smith", AuthorList.fixAuthor_lastNameOnlyCommas("John Smith", true));
+ assertEquals("Smith", AuthorList.fixAuthor_lastNameOnlyCommas("Smith, Jr, John", true));
+
+ assertTrue(AuthorList.fixAuthor_lastNameOnlyCommas(
+ "John von Neumann and John Smith and Black Brown, Peter", true) == AuthorList
+ .fixAuthor_lastNameOnlyCommas("John von Neumann" + (0 == 1 ? "" : " and ")
+ + "John Smith and Black Brown, Peter", true));
+
+ assertEquals("von Neumann, Smith, and Black Brown", AuthorList
+ .fixAuthor_lastNameOnlyCommas(
+ "John von Neumann and John Smith and Black Brown, Peter", true));
+ }
+ }
+
+ public void testFixAuthorForAlphabetization() {
+ assertEquals("Smith, J.", AuthorList.fixAuthorForAlphabetization("John Smith"));
+ assertEquals("Neumann, J.", AuthorList.fixAuthorForAlphabetization("John von Neumann"));
+ assertEquals("Neumann, J.", AuthorList.fixAuthorForAlphabetization("J. von Neumann"));
+ assertEquals(
+ "Neumann, J. and Smith, J. and Black Brown, Jr., P.",
+ AuthorList
+ .fixAuthorForAlphabetization("John von Neumann and John Smith and de Black Brown, Jr., Peter"));
+ }
+
+ public static int size(String bibtex) {
+ return (AuthorList.getAuthorList(bibtex)).size();
+ }
+
+ public void testSize() {
+
+ assertEquals(0, size(""));
+ assertEquals(1, size("Bar"));
+ assertEquals(1, size("Foo Bar"));
+ assertEquals(1, size("Foo von Bar"));
+ assertEquals(1, size("von Bar, Foo"));
+ assertEquals(1, size("Bar, Foo"));
+ assertEquals(1, size("Bar, Jr., Foo"));
+ assertEquals(1, size("Bar, Foo"));
+ assertEquals(2, size("John Neumann and Foo Bar"));
+ assertEquals(2, size("John von Neumann and Bar, Jr, Foo"));
+
+ assertEquals(3, size("John von Neumann and John Smith and Black Brown, Peter"));
+
+ String s = "John von Neumann";
+ for (int i = 0; i < 25; i++) {
+ assertEquals(i + 1, size(s));
+ s += " and Albert Einstein";
+ }
+ }
+
+ public void testGetAuthor() {
+
+ try {
+ AuthorList.getAuthorList("").getAuthor(0);
+ fail();
+ } catch (Exception e) {
+ }
+
+ AuthorList.Author author = AuthorList.getAuthorList("John Smith and von Neumann, Jr, John")
+ .getAuthor(0);
+ assertEquals("John", author.getFirst());
+ assertEquals("J.", author.getFirstAbbr());
+ assertEquals("John Smith", author.getFirstLast(false));
+ assertEquals("J. Smith", author.getFirstLast(true));
+ assertEquals(null, author.getJr());
+ assertEquals("Smith", author.getLast());
+ assertEquals("Smith, John", author.getLastFirst(false));
+ assertEquals("Smith, J.", author.getLastFirst(true));
+ assertEquals("Smith", author.getLastOnly());
+ assertEquals("Smith, J.", author.getNameForAlphabetization());
+ assertEquals(null, author.getVon());
+
+ author = AuthorList.getAuthorList("Peter Black Brown").getAuthor(0);
+ assertEquals("Peter Black", author.getFirst());
+ assertEquals("P. B.", author.getFirstAbbr());
+ assertEquals("Peter Black Brown", author.getFirstLast(false));
+ assertEquals("P. B. Brown", author.getFirstLast(true));
+ assertEquals(null, author.getJr());
+ assertEquals(null, author.getVon());
+
+ author = AuthorList.getAuthorList("John Smith and von Neumann, Jr, John").getAuthor(1);
+ assertEquals("John", author.getFirst());
+ assertEquals("J.", author.getFirstAbbr());
+ assertEquals("John von Neumann, Jr", author.getFirstLast(false));
+ assertEquals("J. von Neumann, Jr", author.getFirstLast(true));
+ assertEquals("Jr", author.getJr());
+ assertEquals("Neumann", author.getLast());
+ assertEquals("von Neumann, Jr, John", author.getLastFirst(false));
+ assertEquals("von Neumann, Jr, J.", author.getLastFirst(true));
+ assertEquals("von Neumann", author.getLastOnly());
+ assertEquals("Neumann, Jr, J.", author.getNameForAlphabetization());
+ assertEquals("von", author.getVon());
+ }
+
+ public void testGetAuthorsNatbib() {
+ assertEquals("", AuthorList.getAuthorList("").getAuthorsNatbib());
+ assertEquals("Smith", AuthorList.getAuthorList("John Smith").getAuthorsNatbib());
+ assertEquals("Smith and Black Brown", AuthorList.getAuthorList(
+ "John Smith and Black Brown, Peter").getAuthorsNatbib());
+ assertEquals("von Neumann et al.", AuthorList.getAuthorList(
+ "John von Neumann and John Smith and Black Brown, Peter").getAuthorsNatbib());
+
+ /*
+ * [ 1465610 ] (Double-)Names containing hyphen (-) not handled correctly
+ */
+ assertEquals("Last-Name et al.", AuthorList.getAuthorList(
+ "First Second Last-Name" + " and John Smith and Black Brown, Peter").getAuthorsNatbib());
+
+ // Test caching
+ AuthorList al = AuthorList
+ .getAuthorList("John von Neumann and John Smith and Black Brown, Peter");
+ assertTrue(al.getAuthorsNatbib() == al.getAuthorsNatbib());
+ }
+
+ public void testGetAuthorsLastOnly() {
+
+ { // No comma before and
+ assertEquals("", AuthorList.getAuthorList("").getAuthorsLastOnly(false));
+ assertEquals("Smith", AuthorList.getAuthorList("John Smith").getAuthorsLastOnly(false));
+ assertEquals("Smith", AuthorList.getAuthorList("Smith, Jr, John").getAuthorsLastOnly(
+ false));
+
+ assertEquals("von Neumann, Smith and Black Brown", AuthorList.getAuthorList(
+ "John von Neumann and John Smith and Black Brown, Peter").getAuthorsLastOnly(false));
+ }
+ { // Oxford comma
+ assertEquals("", AuthorList.getAuthorList("").getAuthorsLastOnly(true));
+ assertEquals("Smith", AuthorList.getAuthorList("John Smith").getAuthorsLastOnly(true));
+ assertEquals("Smith", AuthorList.getAuthorList("Smith, Jr, John").getAuthorsLastOnly(
+ true));
+
+ assertEquals("von Neumann, Smith, and Black Brown", AuthorList.getAuthorList(
+ "John von Neumann and John Smith and Black Brown, Peter").getAuthorsLastOnly(true));
+ }
+ }
+
+ public void testGetAuthorsLastFirst() {
+ { // No commas before and
+ AuthorList al;
+
+ al = AuthorList.getAuthorList("");
+ assertEquals("", al.getAuthorsLastFirst(true, false));
+ assertEquals("", al.getAuthorsLastFirst(false, false));
+
+ al = AuthorList.getAuthorList("John Smith");
+ assertEquals("Smith, John", al.getAuthorsLastFirst(false, false));
+ assertEquals("Smith, J.", al.getAuthorsLastFirst(true, false));
+
+ al = AuthorList.getAuthorList("John Smith and Black Brown, Peter");
+ assertEquals("Smith, John and Black Brown, Peter", al.getAuthorsLastFirst(false, false));
+ assertEquals("Smith, J. and Black Brown, P.", al.getAuthorsLastFirst(true, false));
+
+ al = AuthorList.getAuthorList("John von Neumann and John Smith and Black Brown, Peter");
+ // Method description is different than code -> additional comma
+ // there
+ assertEquals("von Neumann, John, Smith, John and Black Brown, Peter", al
+ .getAuthorsLastFirst(false, false));
+ assertEquals("von Neumann, J., Smith, J. and Black Brown, P.", al.getAuthorsLastFirst(
+ true, false));
+
+ al = AuthorList.getAuthorList("John Peter von Neumann");
+ assertEquals("von Neumann, J. P.", al.getAuthorsLastFirst(true, false));
+ }
+ { // Oxford comma
+ AuthorList al;
+
+ al = AuthorList.getAuthorList("");
+ assertEquals("", al.getAuthorsLastFirst(true, true));
+ assertEquals("", al.getAuthorsLastFirst(false, true));
+
+ al = AuthorList.getAuthorList("John Smith");
+ assertEquals("Smith, John", al.getAuthorsLastFirst(false, true));
+ assertEquals("Smith, J.", al.getAuthorsLastFirst(true, true));
+
+ al = AuthorList.getAuthorList("John Smith and Black Brown, Peter");
+ assertEquals("Smith, John and Black Brown, Peter", al.getAuthorsLastFirst(false, true));
+ assertEquals("Smith, J. and Black Brown, P.", al.getAuthorsLastFirst(true, true));
+
+ al = AuthorList.getAuthorList("John von Neumann and John Smith and Black Brown, Peter");
+ assertEquals("von Neumann, John, Smith, John, and Black Brown, Peter", al
+ .getAuthorsLastFirst(false, true));
+ assertEquals("von Neumann, J., Smith, J., and Black Brown, P.", al.getAuthorsLastFirst(
+ true, true));
+
+ al = AuthorList.getAuthorList("John Peter von Neumann");
+ assertEquals("von Neumann, J. P.", al.getAuthorsLastFirst(true, true));
+ }
+ }
+
+ public void testGetAuthorsLastFirstAnds() {
+ assertEquals("Smith, John", AuthorList.getAuthorList("John Smith").getAuthorsLastFirstAnds(
+ false));
+ assertEquals("Smith, John and Black Brown, Peter", AuthorList.getAuthorList(
+ "John Smith and Black Brown, Peter").getAuthorsLastFirstAnds(false));
+ assertEquals("von Neumann, John and Smith, John and Black Brown, Peter", AuthorList
+ .getAuthorList("John von Neumann and John Smith and Black Brown, Peter")
+ .getAuthorsLastFirstAnds(false));
+ assertEquals("von Last, Jr, First", AuthorList.getAuthorList("von Last, Jr ,First")
+ .getAuthorsLastFirstAnds(false));
+
+ assertEquals("Smith, J.", AuthorList.getAuthorList("John Smith").getAuthorsLastFirstAnds(
+ true));
+ assertEquals("Smith, J. and Black Brown, P.", AuthorList.getAuthorList(
+ "John Smith and Black Brown, Peter").getAuthorsLastFirstAnds(true));
+ assertEquals("von Neumann, J. and Smith, J. and Black Brown, P.", AuthorList.getAuthorList(
+ "John von Neumann and John Smith and Black Brown, Peter").getAuthorsLastFirstAnds(true));
+ assertEquals("von Last, Jr, F.", AuthorList.getAuthorList("von Last, Jr ,First")
+ .getAuthorsLastFirstAnds(true));
+
+ }
+
+ public void testGetAuthorsFirstFirst() {
+
+ AuthorList al;
+
+ al = AuthorList.getAuthorList("");
+ assertEquals("", al.getAuthorsFirstFirst(true, false));
+ assertEquals("", al.getAuthorsFirstFirst(false, false));
+ assertEquals("", al.getAuthorsFirstFirst(true, true));
+ assertEquals("", al.getAuthorsFirstFirst(false, true));
+
+ al = AuthorList.getAuthorList("John Smith");
+ assertEquals("John Smith", al.getAuthorsFirstFirst(false, false));
+ assertEquals("J. Smith", al.getAuthorsFirstFirst(true, false));
+ assertEquals("John Smith", al.getAuthorsFirstFirst(false, true));
+ assertEquals("J. Smith", al.getAuthorsFirstFirst(true, true));
+
+ al = AuthorList.getAuthorList("John Smith and Black Brown, Peter");
+ assertEquals("John Smith and Peter Black Brown", al.getAuthorsFirstFirst(false, false));
+ assertEquals("J. Smith and P. Black Brown", al.getAuthorsFirstFirst(true, false));
+ assertEquals("John Smith and Peter Black Brown", al.getAuthorsFirstFirst(false, true));
+ assertEquals("J. Smith and P. Black Brown", al.getAuthorsFirstFirst(true, true));
+
+ al = AuthorList.getAuthorList("John von Neumann and John Smith and Black Brown, Peter");
+ assertEquals("John von Neumann, John Smith and Peter Black Brown", al.getAuthorsFirstFirst(
+ false, false));
+ assertEquals("J. von Neumann, J. Smith and P. Black Brown", al.getAuthorsFirstFirst(true,
+ false));
+ assertEquals("John von Neumann, John Smith, and Peter Black Brown", al
+ .getAuthorsFirstFirst(false, true));
+ assertEquals("J. von Neumann, J. Smith, and P. Black Brown", al.getAuthorsFirstFirst(true,
+ true));
+
+ al = AuthorList.getAuthorList("John Peter von Neumann");
+ assertEquals("John Peter von Neumann", al.getAuthorsFirstFirst(false, false));
+ assertEquals("John Peter von Neumann", al.getAuthorsFirstFirst(false, true));
+ assertEquals("J. P. von Neumann", al.getAuthorsFirstFirst(true, false));
+ assertEquals("J. P. von Neumann", al.getAuthorsFirstFirst(true, true));
+ }
+
+ public void testGetAuthorsFirstFirstAnds() {
+ assertEquals("John Smith", AuthorList.getAuthorList("John Smith")
+ .getAuthorsFirstFirstAnds());
+ assertEquals("John Smith and Peter Black Brown", AuthorList.getAuthorList(
+ "John Smith and Black Brown, Peter").getAuthorsFirstFirstAnds());
+ assertEquals("John von Neumann and John Smith and Peter Black Brown", AuthorList
+ .getAuthorList("John von Neumann and John Smith and Black Brown, Peter")
+ .getAuthorsFirstFirstAnds());
+ assertEquals("First von Last, Jr. III", AuthorList
+ .getAuthorList("von Last, Jr. III, First").getAuthorsFirstFirstAnds());
+ }
+
+ public void testGetAuthorsForAlphabetization() {
+ assertEquals("Smith, J.", AuthorList.getAuthorList("John Smith")
+ .getAuthorsForAlphabetization());
+ assertEquals("Neumann, J.", AuthorList.getAuthorList("John von Neumann")
+ .getAuthorsForAlphabetization());
+ assertEquals("Neumann, J.", AuthorList.getAuthorList("J. von Neumann")
+ .getAuthorsForAlphabetization());
+ assertEquals("Neumann, J. and Smith, J. and Black Brown, Jr., P.", AuthorList
+ .getAuthorList("John von Neumann and John Smith and de Black Brown, Jr., Peter")
+ .getAuthorsForAlphabetization());
+ }
+
+}
diff --git a/src/java/tests/net/sf/jabref/FileBasedTestCase.java b/src/java/tests/net/sf/jabref/FileBasedTestCase.java
new file mode 100644
index 0000000..ca3bb98
--- /dev/null
+++ b/src/java/tests/net/sf/jabref/FileBasedTestCase.java
@@ -0,0 +1,222 @@
+package tests.net.sf.jabref;
+
+import java.io.File;
+import java.io.StringReader;
+
+import junit.framework.TestCase;
+import net.sf.jabref.BibtexDatabase;
+import net.sf.jabref.BibtexEntry;
+import net.sf.jabref.Globals;
+import net.sf.jabref.JabRefPreferences;
+import net.sf.jabref.imports.BibtexParser;
+import net.sf.jabref.imports.ParserResult;
+
+/**
+ * A base class for Testing in JabRef that comes along with some useful
+ * functions.
+ *
+ * @author $Author: coezbek $
+ * @version $Revision: 1.4 $ ($Date: 2006/11/23 22:37:19 $)
+ *
+ */
+public class FileBasedTestCase extends TestCase {
+
+ /**
+ * Will check if two paths are the same.
+ */
+ public static void assertEqualPaths(String path1, String path2) {
+
+ if (path1 == path2)
+ return;
+
+ if ((path1 == null || path2 == null) && path1 != path2)
+ fail("Expected: " + path1 + " but was: " + path2);
+
+ assertEquals(path1.replaceAll("\\\\", "/"), path2.replaceAll("\\\\", "/"));
+ }
+
+ /**
+ * Creates a temp directory in the System temp directory.
+ *
+ * Taken from
+ * http://forum.java.sun.com/thread.jspa?threadID=470197&messageID=2169110
+ *
+ * Author: jfbriere
+ *
+ * @return returns null if directory could not created.
+ */
+ public static File createTempDir(String prefix) {
+ return createTempDir(prefix, null);
+ }
+
+ /**
+ * Creates a temp directory in a given directory.
+ *
+ * Taken from
+ * http://forum.java.sun.com/thread.jspa?threadID=470197&messageID=2169110
+ *
+ * Author: jfbriere
+ *
+ * @param directory
+ * MayBeNull - null indicates that the system tmp directory
+ * should be used.
+ *
+ * @return returns null if directory could not created.
+ */
+ public static File createTempDir(String prefix, File directory) {
+ try {
+ File tempFile = File.createTempFile(prefix, "", directory);
+
+ if (!tempFile.delete())
+ return null;
+ if (!tempFile.mkdir())
+ return null;
+
+ return tempFile;
+
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+ /**
+ * Deletes a directory or file
+ *
+ * Taken from
+ * http://forum.java.sun.com/thread.jspa?threadID=470197&messageID=2169110
+ *
+ * Author: jfbriere
+ *
+ * @param file
+ */
+ public static void deleteRecursive(File file) {
+ if (file.isDirectory()) {
+ File[] fileArray = file.listFiles();
+
+ if (fileArray != null)
+ for (int i = 0; i < fileArray.length; i++)
+ deleteRecursive(fileArray[i]);
+ }
+ file.delete();
+ }
+
+ static BibtexDatabase database;
+
+ static BibtexEntry entry;
+
+ File root;
+
+ private String oldPdfDirectory;
+
+ private boolean oldUseRegExp;
+
+ public static BibtexEntry getBibtexEntry() {
+
+ if (database == null) {
+
+ StringReader reader = new StringReader(
+ "@ARTICLE{HipKro03,\n"
+ + " author = {Eric von Hippel and Georg von Krogh},\n"
+ + " title = {Open Source Software and the \"Private-Collective\" Innovation Model: Issues for Organization Science},\n"
+ + " journal = {Organization Science},\n"
+ + " year = {2003},\n"
+ + " volume = {14},\n"
+ + " pages = {209--223},\n"
+ + " number = {2},\n"
+ + " address = {Institute for Operations Research and the Management Sciences (INFORMS), Linthicum, Maryland, USA},\n"
+ + " doi = {http://dx.doi.org/10.1287/orsc.14.2.209.14992}," + "\n"
+ + " issn = {1526-5455}," + "\n" + " publisher = {INFORMS}\n" + "}");
+
+ BibtexParser parser = new BibtexParser(reader);
+ ParserResult result = null;
+ try {
+ result = parser.parse();
+ } catch (Exception e) {
+ fail();
+ }
+ database = result.getDatabase();
+ entry = database.getEntriesByKey("HipKro03")[0];
+ }
+ return entry;
+ }
+
+ public void setUp() throws Exception {
+
+ Globals.prefs = JabRefPreferences.getInstance();
+ oldUseRegExp = Globals.prefs.getBoolean(JabRefPreferences.USE_REG_EXP_SEARCH_KEY);
+ oldPdfDirectory = Globals.prefs.get("pdfDirectory");
+
+ Globals.prefs.putBoolean(JabRefPreferences.USE_REG_EXP_SEARCH_KEY, false);
+
+ getBibtexEntry();
+ assertNotNull(database);
+ assertNotNull(entry);
+
+ // Create file structure
+ try {
+ root = createTempDir("UtilFindFileTest");
+
+ Globals.prefs.put("pdfDirectory", root.getPath());
+
+ File subDir1 = new File(root, "Organization Science");
+ subDir1.mkdir();
+
+ File pdf1 = new File(subDir1, "HipKro03 - Hello.pdf");
+ pdf1.createNewFile();
+
+ File pdf1a = new File(root, "HipKro03 - Hello.pdf");
+ pdf1a.createNewFile();
+
+ File subDir2 = new File(root, "pdfs");
+ subDir2.mkdir();
+
+ File subsubDir1 = new File(subDir2, "sub");
+ subsubDir1.mkdir();
+
+ File pdf2 = new File(subsubDir1, "HipKro03-sub.pdf");
+ pdf2.createNewFile();
+
+ File dir2002 = new File(root, "2002");
+ dir2002.mkdir();
+
+ File dir2003 = new File(root, "2003");
+ dir2003.mkdir();
+
+ File pdf3 = new File(dir2003, "Paper by HipKro03.pdf");
+ pdf3.createNewFile();
+
+ File dirTest = new File(root, "test");
+ dirTest.mkdir();
+
+ File pdf4 = new File(dirTest, "HipKro03.pdf");
+ pdf4.createNewFile();
+
+ File pdf5 = new File(dirTest, ".TEST");
+ pdf5.createNewFile();
+
+ File pdf6 = new File(dirTest, "TEST[");
+ pdf6.createNewFile();
+
+ File pdf7 = new File(dirTest, "TE.ST");
+ pdf7.createNewFile();
+
+ File foo = new File(dirTest, "foo.dat");
+ foo.createNewFile();
+
+ } catch (Exception e) {
+ throw new RuntimeException();
+ }
+ }
+
+ public void tearDown() {
+ deleteRecursive(root);
+ Globals.prefs.putBoolean(JabRefPreferences.USE_REG_EXP_SEARCH_KEY, oldUseRegExp);
+ Globals.prefs.put("pdfDirectory", oldPdfDirectory);
+ // TODO: This is not a great way to do this, sure ;-)
+ }
+
+ public void testVoid(){
+ // to remove warning
+ }
+
+}
diff --git a/src/java/tests/net/sf/jabref/JabRefTestCase.java b/src/java/tests/net/sf/jabref/JabRefTestCase.java
new file mode 100644
index 0000000..afd8048
--- /dev/null
+++ b/src/java/tests/net/sf/jabref/JabRefTestCase.java
@@ -0,0 +1,24 @@
+package tests.net.sf.jabref;
+
+import junit.framework.TestCase;
+import net.sf.jabref.BibtexEntry;
+
+public class JabRefTestCase extends TestCase {
+
+ public void assertEquals(BibtexEntry e, BibtexEntry x){
+ assertEquals(e.getCiteKey(), x.getCiteKey());
+ assertEquals(e.getType(), x.getType());
+
+ Object[] o = e.getAllFields();
+ assertEquals(o.length, x.getAllFields().length);
+
+ for (int i = 0; i < o.length; i++) {
+ assertEquals(e.getField(o.toString()), x.getField(o.toString()));
+ }
+ }
+
+ public void testVoid(){
+ // to remove warning
+ }
+
+}
diff --git a/src/java/tests/net/sf/jabref/UtilFindFileTest.java b/src/java/tests/net/sf/jabref/UtilFindFileTest.java
new file mode 100644
index 0000000..35e123b
--- /dev/null
+++ b/src/java/tests/net/sf/jabref/UtilFindFileTest.java
@@ -0,0 +1,191 @@
+package tests.net.sf.jabref;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.StringReader;
+
+import junit.framework.TestCase;
+import net.sf.jabref.BibtexDatabase;
+import net.sf.jabref.BibtexEntry;
+import net.sf.jabref.Globals;
+import net.sf.jabref.JabRefPreferences;
+import net.sf.jabref.Util;
+import net.sf.jabref.imports.BibtexParser;
+import net.sf.jabref.imports.ParserResult;
+
+/**
+ * Testing Util.findFile for finding files based on regular expressions.
+ *
+ * @author Christopher Oezbek <oezi at oezi.de>
+ */
+public class UtilFindFileTest extends FileBasedTestCase {
+
+ String findFile(String dir, String file) {
+ return Util.findFile(entry, database, dir, file, true);
+ }
+
+ /**
+ * Test that more than one slash is taken to mean that a relative path is to
+ * be returned.
+ *
+ * @throws IOException
+ */
+ public void testFindFileRelative() throws IOException {
+
+ // Most basic case
+ assertEqualPaths("/HipKro03.pdf", findFile(root.getAbsolutePath() + "/test/",
+ "[bibtexkey].pdf"));
+
+ // Including directory
+ assertEqualPaths("/test/HipKro03.pdf", findFile(root.getAbsolutePath(),
+ "test/[bibtexkey].pdf"));
+
+ // No relative paths
+ assertEqualPaths(new File(root, "/test/HipKro03.pdf").getCanonicalPath(), findFile(null,
+ root.getAbsolutePath() + "/test/" + "[bibtexkey].pdf"));
+
+ // No relative paths
+ assertEqualPaths(new File(root, "/test/HipKro03.pdf").getCanonicalPath(), Util.findFile(
+ entry, database, root.getAbsolutePath() + "/test/" + "[bibtexkey].pdf"));
+
+ }
+
+
+
+
+ public void testFindPdf() throws IOException {
+
+ {
+ String pdf = Util.findPdf(entry, "pdf", root.getAbsolutePath());
+ assertEqualPaths("/HipKro03 - Hello.pdf", pdf);
+
+ File fullPath = Util.expandFilename(pdf, root.getAbsolutePath());
+ assertTrue(fullPath.exists());
+ }
+ {
+ String pdf = Util.findPdf(entry, "pdf", root.getAbsolutePath() + "/pdfs/");
+
+ assertEqualPaths("/sub/HipKro03-sub.pdf", pdf);
+
+ File fullPath = Util.expandFilename(pdf, root.getAbsolutePath() + "/pdfs/");
+ assertTrue(fullPath.exists());
+ }
+ }
+
+ public void testFindPdfInMultiple() throws IOException {
+
+ {
+ String[] dirsToSearch = new String[] { root.getAbsolutePath(),
+ root.getAbsolutePath() + "/pdfs/" };
+ String pdf = Util.findPdf(entry, "pdf", dirsToSearch);
+ assertEqualPaths("/HipKro03 - Hello.pdf", pdf);
+
+ File fullPath = Util.expandFilename(pdf, dirsToSearch);
+ assertTrue(fullPath.exists());
+ assertEqualPaths(root.getAbsolutePath() + "/HipKro03 - Hello.pdf", fullPath
+ .getAbsolutePath());
+
+ String tmp = dirsToSearch[1];
+ dirsToSearch[1] = dirsToSearch[0];
+ dirsToSearch[0] = tmp;
+
+ fullPath = Util.expandFilename(pdf, dirsToSearch);
+ assertTrue(fullPath.exists());
+ assertEqualPaths(root.getAbsolutePath() + "/HipKro03 - Hello.pdf", fullPath
+ .getAbsolutePath());
+
+ fullPath = Util.expandFilename(pdf, new String[] { dirsToSearch[0] });
+ assertEquals(null, fullPath);
+
+ fullPath = Util.expandFilename(pdf, new String[] { dirsToSearch[1] });
+ assertTrue(fullPath.exists());
+ assertEqualPaths(root.getAbsolutePath() + "/HipKro03 - Hello.pdf", fullPath
+ .getAbsolutePath());
+ }
+
+ {
+ String[] dirsToSearch = new String[] { root.getAbsolutePath() + "/pdfs/",
+ root.getAbsolutePath() };
+ String pdf = Util.findPdf(entry, "pdf", dirsToSearch);
+ assertEqualPaths("/sub/HipKro03-sub.pdf", pdf);
+
+ File fullPath = Util.expandFilename(pdf, dirsToSearch);
+ assertTrue(fullPath.exists());
+ assertEqualPaths(root.getAbsolutePath() + "/pdfs/sub/HipKro03-sub.pdf", fullPath
+ .getAbsolutePath());
+
+ String tmp = dirsToSearch[1];
+ dirsToSearch[1] = dirsToSearch[0];
+ dirsToSearch[0] = tmp;
+
+ fullPath = Util.expandFilename(pdf, dirsToSearch);
+ assertTrue(fullPath.exists());
+ assertEqualPaths(root.getAbsolutePath() + "/pdfs/sub/HipKro03-sub.pdf", fullPath
+ .getAbsolutePath());
+
+ fullPath = Util.expandFilename(pdf, new String[] { dirsToSearch[0] });
+ assertEquals(null, fullPath);
+
+ fullPath = Util.expandFilename(pdf, new String[] { dirsToSearch[1] });
+ assertTrue(fullPath.exists());
+ assertEqualPaths(root.getAbsolutePath() + "/pdfs/sub/HipKro03-sub.pdf", fullPath
+ .getAbsolutePath());
+ }
+
+ }
+
+ public void testFindFile() throws IOException {
+
+ // Simple case
+ assertEqualPaths("/HipKro03.pdf", Util.findFile(entry, database, root.getAbsolutePath()
+ + "/test/", "[bibtexkey].pdf", true));
+
+ // Not found
+ assertEqualPaths(null, Util.findFile(entry, database, root.getAbsolutePath() + "/test/",
+ "Not there [bibtexkey].pdf", true));
+
+ // Test current dir
+ assertEqualPaths(new File(new File("."), "build.xml").getCanonicalPath(), Util.findFile(
+ entry, database, "./build.xml"));
+ assertEqualPaths("/build.xml", Util.findFile(entry, database, ".", "build.xml", true));
+
+ // Test keys in path and regular expression in file
+ assertEqualPaths(new File(root, "/2003/Paper by HipKro03.pdf").getCanonicalPath(), Util
+ .findFile(entry, database, root.getAbsolutePath() + "/[year]/.*[bibtexkey].pdf"));
+
+ // Test . and ..
+ assertEqualPaths(new File(root, "/Organization Science/HipKro03 - Hello.pdf")
+ .getCanonicalPath(), Util.findFile(entry, database, root.getAbsolutePath()
+ + "/[year]/../2003/.././././[journal]\\" + ".*[bibtexkey].*.pdf"));
+
+ // Test Escape
+ assertEqualPaths(new File(root, "/Organization Science/HipKro03 - Hello.pdf")
+ .getCanonicalPath(), Util.findFile(entry, database, root.getAbsolutePath() + "/*/"
+ + "[bibtexkey] - Hello\\\\.pdf"));
+
+ assertEqualPaths("/TE.ST", Util.findFile(entry, database, root.getAbsolutePath() + "/test/",
+ "TE\\\\.ST", true));
+ assertEqualPaths("/.TEST", Util.findFile(entry, database, root.getAbsolutePath() + "/test/",
+ "\\\\.TEST", true));
+ assertEqualPaths("/TEST[", Util.findFile(entry, database, root.getAbsolutePath() + "/test/",
+ "TEST\\\\[", true));
+
+ // Test *
+ assertEqualPaths(new File(root, "/Organization Science/HipKro03 - Hello.pdf")
+ .getCanonicalPath(), Util.findFile(entry, database, root.getAbsolutePath() + "/*/"
+ + "[bibtexkey].+?.pdf"));
+
+ // Test **
+ assertEqualPaths(new File(root, "/pdfs/sub/HipKro03-sub.pdf").getCanonicalPath(), Util
+ .findFile(entry, database, root.getAbsolutePath() + "/**/" + "[bibtexkey]-sub.pdf"));
+
+ // Test ** - Find in level itself too
+ assertEqualPaths(new File(root, "/pdfs/sub/HipKro03-sub.pdf").getCanonicalPath(), Util
+ .findFile(entry, database, root.getAbsolutePath() + "/pdfs/sub/**/"
+ + "[bibtexkey]-sub.pdf"));
+
+ // Test ** - Find lowest level first (Rest is Depth first)
+ assertEqualPaths(new File(root, "/HipKro03 - Hello.pdf").getCanonicalPath(), Util.findFile(
+ entry, database, root.getAbsolutePath() + "/**/" + "[bibtexkey].*Hello.pdf"));
+ }
+}
diff --git a/src/java/tests/net/sf/jabref/UtilTest.java b/src/java/tests/net/sf/jabref/UtilTest.java
new file mode 100644
index 0000000..043008f
--- /dev/null
+++ b/src/java/tests/net/sf/jabref/UtilTest.java
@@ -0,0 +1,379 @@
+package tests.net.sf.jabref;
+
+import java.awt.Container;
+import java.awt.Dialog;
+import java.io.StringReader;
+import java.net.URISyntaxException;
+import java.text.DecimalFormat;
+import java.text.NumberFormat;
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+
+import javax.swing.JDialog;
+import javax.swing.JWindow;
+
+import junit.framework.TestCase;
+import net.sf.jabref.BibtexDatabase;
+import net.sf.jabref.BibtexEntry;
+import net.sf.jabref.Globals;
+import net.sf.jabref.NameFormatterTab;
+import net.sf.jabref.Util;
+import net.sf.jabref.imports.BibtexParser;
+import net.sf.jabref.imports.ParserResult;
+
+public class UtilTest extends TestCase {
+
+ public void testNCase() {
+ assertEquals("", Util.nCase(""));
+ assertEquals("Hello world", Util.nCase("Hello World"));
+ assertEquals("A", Util.nCase("a"));
+ assertEquals("Aa", Util.nCase("AA"));
+ }
+
+ public void testCheckName() {
+ assertEquals("aa.bib", Util.checkName("aa"));
+ assertEquals(".bib", Util.checkName(""));
+ assertEquals("a.bib", Util.checkName("a.bib"));
+ assertEquals("a.bib", Util.checkName("a"));
+ assertEquals("a.bb.bib", Util.checkName("a.bb"));
+ }
+
+ public void testCreateNeutralId() {
+
+ HashSet set = new HashSet();
+ for (int i = 0; i < 10000; i++){
+ String string = Util.createNeutralId();
+ assertFalse(set.contains(string));
+ set.add(string);
+ }
+
+ }
+
+ public void testPlaceDialog() {
+ Dialog d = new JDialog();
+ d.setSize(50, 50);
+ Container c = new JWindow();
+ c.setBounds(100, 200, 100, 50);
+
+ Util.placeDialog(d, c);
+ assertEquals(125, d.getX());
+ assertEquals(200, d.getY());
+
+ // Test upper left corner
+ c.setBounds(0,0,100,100);
+ d.setSize(200, 200);
+
+ Util.placeDialog(d, c);
+ assertEquals(0, d.getX());
+ assertEquals(0, d.getY());
+ }
+
+ public void testParseField() {
+
+ assertEquals("", Util.parseField(""));
+
+ // Three basic types (references, { } and " ")
+ assertEquals("#hallo#", Util.parseField("hallo"));
+ assertEquals("hallo", Util.parseField("{hallo}"));
+ assertEquals("bye", Util.parseField("\"bye\""));
+
+ // Concatenation
+ assertEquals("longlonglonglong", Util.parseField("\"long\" # \"long\" # \"long\" # \"long\""));
+
+ assertEquals("hallo#bye#", Util.parseField("{hallo} # bye"));
+ }
+
+ public void testShaveString() {
+
+ assertEquals(null, Util.shaveString(null));
+ assertEquals("", Util.shaveString(""));
+ assertEquals("aaa", Util.shaveString(" aaa\t\t\n\r"));
+ assertEquals("a", Util.shaveString(" {a} "));
+ assertEquals("a", Util.shaveString(" \"a\" "));
+ assertEquals("{a}", Util.shaveString(" {{a}} "));
+ assertEquals("{a}", Util.shaveString(" \"{a}\" "));
+ assertEquals("\"{a\"}", Util.shaveString(" \"{a\"} "));
+ }
+
+ public void testCheckLegalKey() {
+
+ assertEquals("AAAA", Util.checkLegalKey("AA AA"));
+ assertEquals("SPECIALCHARS", Util.checkLegalKey("SPECIAL CHARS#{\\\"}~,^"));
+ assertEquals("AeaeaAAA", Util.checkLegalKey("������"));
+ assertEquals("", Util.checkLegalKey("\n\t\r"));
+ }
+
+ public void testReplaceSpecialCharacters() {
+ // Shouldn't German � be resolved to Ae
+ assertEquals("AeaeaAAA", Util.replaceSpecialCharacters("������"));
+ assertEquals("Hallo Arger", Util.replaceSpecialCharacters("Hallo Arger"));
+ }
+
+ public void testJoin() {
+ String[] s = "ab/cd/ed".split("/");
+ assertEquals("ab\\cd\\ed", Util.join(s, "\\", 0, s.length));
+
+ assertEquals("cd\\ed", Util.join(s, "\\", 1, s.length));
+
+ assertEquals("ed", Util.join(s, "\\", 2, s.length));
+
+ assertEquals("", Util.join(s, "\\", 3, s.length));
+
+ assertEquals("", Util.join(new String[]{}, "\\", 0, 0));
+ }
+
+ public void testStripBrackets() {
+ assertEquals("foo", Util.stripBrackets("[foo]"));
+ assertEquals("[foo]", Util.stripBrackets("[[foo]]"));
+ assertEquals("foo", Util.stripBrackets("foo]"));
+ assertEquals("foo", Util.stripBrackets("[foo"));
+ assertEquals("", Util.stripBrackets(""));
+ assertEquals("", Util.stripBrackets("[]"));
+ assertEquals("", Util.stripBrackets("["));
+ assertEquals("", Util.stripBrackets("]"));
+ assertEquals("f[]f", Util.stripBrackets("f[]f"));
+
+ try {
+ Util.stripBrackets(null);
+ fail();
+ } catch(NullPointerException npe){
+
+ }
+ }
+
+ BibtexDatabase database;
+ BibtexEntry entry;
+
+ public void setUp(){
+
+ StringReader reader = new StringReader(
+ "@ARTICLE{HipKro03," + "\n" +
+ " author = {Eric von Hippel and Georg von Krogh}," + "\n" +
+ " title = {Open Source Software and the \"Private-Collective\" Innovation Model: Issues for Organization Science}," + "\n" +
+ " journal = {Organization Science}," + "\n" +
+ " year = {2003}," + "\n" +
+ " volume = {14}," + "\n" +
+ " pages = {209--223}," + "\n" +
+ " number = {2}," + "\n" +
+ " address = {Institute for Operations Research and the Management Sciences (INFORMS), Linthicum, Maryland, USA}," + "\n" +
+ " doi = {http://dx.doi.org/10.1287/orsc.14.2.209.14992}," + "\n" +
+ " issn = {1526-5455}," + "\n" +
+ " publisher = {INFORMS}" + "\n" +
+ "}");
+
+ BibtexParser parser = new BibtexParser(reader);
+ ParserResult result = null;
+ try {
+ result = parser.parse();
+ } catch (Exception e){
+ fail();
+ }
+ database = result.getDatabase();
+ entry = database.getEntriesByKey("HipKro03")[0];
+
+ assertNotNull(database);
+ assertNotNull(entry);
+ }
+
+ public void testParseMethodCalls(){
+
+ assertEquals(1, Util.parseMethodsCalls("bla").size());
+ assertEquals("bla", ((String[])(Util.parseMethodsCalls("bla").get(0)))[0]);
+
+ assertEquals(1, Util.parseMethodsCalls("bla,").size());
+ assertEquals("bla", ((String[])(Util.parseMethodsCalls("bla,").get(0)))[0]);
+
+ assertEquals(1, Util.parseMethodsCalls("_bla.bla.blub,").size());
+ assertEquals("_bla.bla.blub", ((String[])(Util.parseMethodsCalls("_bla.bla.blub,").get(0)))[0]);
+
+
+ assertEquals(2, Util.parseMethodsCalls("bla,foo").size());
+ assertEquals("bla", ((String[])(Util.parseMethodsCalls("bla,foo").get(0)))[0]);
+ assertEquals("foo", ((String[])(Util.parseMethodsCalls("bla,foo").get(1)))[0]);
+
+ assertEquals(2, Util.parseMethodsCalls("bla(\"test\"),foo(\"fark\")").size());
+ assertEquals("bla", ((String[])(Util.parseMethodsCalls("bla(\"test\"),foo(\"fark\")").get(0)))[0]);
+ assertEquals("foo", ((String[])(Util.parseMethodsCalls("bla(\"test\"),foo(\"fark\")").get(1)))[0]);
+ assertEquals("test", ((String[])(Util.parseMethodsCalls("bla(\"test\"),foo(\"fark\")").get(0)))[1]);
+ assertEquals("fark", ((String[])(Util.parseMethodsCalls("bla(\"test\"),foo(\"fark\")").get(1)))[1]);
+ }
+
+
+ public void testFieldAndFormat(){
+ assertEquals("Eric von Hippel and Georg von Krogh", Util.getFieldAndFormat("[author]", entry, database));
+
+ assertEquals("Eric von Hippel and Georg von Krogh", Util.getFieldAndFormat("author", entry, database));
+
+ assertEquals(null, Util.getFieldAndFormat("[unknownkey]", entry, database));
+
+ assertEquals(null, Util.getFieldAndFormat("[:]", entry, database));
+
+ assertEquals(null, Util.getFieldAndFormat("[:ToLowerCase]", entry, database));
+
+ assertEquals("eric von hippel and georg von krogh", Util.getFieldAndFormat("[author:net.sf.jabref.export.layout.format.ToLowerCase]", entry, database));
+
+ assertEquals("HipKro03", Util.getFieldAndFormat("[bibtexkey]", entry, database));
+
+ assertEquals("HipKro03", Util.getFieldAndFormat("[bibtexkey:]", entry, database));
+ }
+
+ public void testUserFieldAndFormat(){
+
+ String[] names = Globals.prefs.getStringArray(NameFormatterTab.NAME_FORMATER_KEY);
+ if (names == null)
+ names = new String[]{};
+
+ String[] formats = Globals.prefs.getStringArray(NameFormatterTab.NAME_FORMATTER_VALUE);
+ if (formats == null)
+ formats = new String[]{};
+
+ try {
+
+ List f = new LinkedList(Arrays.asList(formats));
+ List n = new LinkedList(Arrays.asList(names));
+
+ n.add("testMe123454321");
+ f.add("*@*@test");
+
+ String[] newNames = (String[])n.toArray(new String[n.size()]);
+ String[] newFormats = (String[])f.toArray(new String[f.size()]);
+
+ Globals.prefs.putStringArray(NameFormatterTab.NAME_FORMATER_KEY, newNames);
+ Globals.prefs.putStringArray(NameFormatterTab.NAME_FORMATTER_VALUE, newFormats);
+
+ assertEquals("testtest", Util.getFieldAndFormat("[author:testMe123454321]", entry, database));
+
+ } finally {
+ Globals.prefs.putStringArray(NameFormatterTab.NAME_FORMATER_KEY, names);
+ Globals.prefs.putStringArray(NameFormatterTab.NAME_FORMATTER_VALUE, formats);
+ }
+ }
+
+
+
+ public void testExpandBrackets(){
+
+ assertEquals("", Util.expandBrackets("", entry, database));
+
+ assertEquals("dropped", Util.expandBrackets("drop[unknownkey]ped", entry, database));
+
+ assertEquals("Eric von Hippel and Georg von Krogh",
+ Util.expandBrackets("[author]", entry, database));
+
+ assertEquals("Eric von Hippel and Georg von Krogh are two famous authors.",
+ Util.expandBrackets("[author] are two famous authors.", entry, database));
+
+ assertEquals("Eric von Hippel and Georg von Krogh are two famous authors.",
+ Util.expandBrackets("[author] are two famous authors.", entry, database));
+
+ assertEquals("Eric von Hippel and Georg von Krogh have published Open Source Software and the \"Private-Collective\" Innovation Model: Issues for Organization Science in Organization Science.",
+ Util.expandBrackets("[author] have published [title] in [journal].", entry, database));
+ }
+
+ public void testSanitizeUrl() {
+ try {
+
+ assertEquals("http://www.vg.no", Util.sanitizeUrl("http://www.vg.no"));
+ assertEquals("http://www.vg.no/fil%20e.html",
+ Util.sanitizeUrl("http://www.vg.no/fil e.html"));
+ assertEquals("http://www.vg.no/fil%20e.html",
+ Util.sanitizeUrl("http://www.vg.no/fil%20e.html"));
+ assertEquals("http://www.vg.no/fil%20e.html",
+ Util.sanitizeUrl("www.vg.no/fil%20e.html"));
+
+
+ } catch (URISyntaxException e) {
+ e.printStackTrace();
+ }
+
+ }
+
+ public void test2to4DigitsYear(){
+ assertEquals("1990", Util.toFourDigitYear("1990"));
+ assertEquals("190", Util.toFourDigitYear("190"));
+ assertEquals("1990", Util.toFourDigitYear("90", 1990));
+ assertEquals("1990", Util.toFourDigitYear("90", 1991));
+ assertEquals("2020", Util.toFourDigitYear("20", 1990));
+ assertEquals("1921", Util.toFourDigitYear("21", 1990));
+ assertEquals("1922", Util.toFourDigitYear("22", 1990));
+ assertEquals("2022", Util.toFourDigitYear("22", 1992));
+ assertEquals("1999", Util.toFourDigitYear("99", 2001));
+ assertEquals("1931", Util.toFourDigitYear("1931", 2001));
+ assertEquals("2031", Util.toFourDigitYear("31", 2001));
+ assertEquals("1932", Util.toFourDigitYear("32", 2001));
+ assertEquals("1944", Util.toFourDigitYear("44", 2001));
+ assertEquals("2011", Util.toFourDigitYear("11", 2001));
+
+ int thisYear = Calendar.getInstance().get(Calendar.YEAR);
+ int d2 = thisYear % 100;
+
+ NumberFormat f = new DecimalFormat("00");
+
+ for (int i = 0; i <= 30; i++){
+ assertTrue("" + i, thisYear <= Integer.parseInt(Util.toFourDigitYear(f.format((d2 + i) % 100))));
+ }
+ for (int i = 0; i < 70; i++){
+ assertTrue("" + i, thisYear >= Integer.parseInt(Util.toFourDigitYear(f.format((d2 - i + 100) % 100))));
+ }
+ }
+
+ public void testToMonthNumber(){
+
+ assertEquals(0, Util.getMonthNumber("jan"));
+ assertEquals(1, Util.getMonthNumber("feb"));
+ assertEquals(2, Util.getMonthNumber("mar"));
+ assertEquals(3, Util.getMonthNumber("apr"));
+ assertEquals(4, Util.getMonthNumber("may"));
+ assertEquals(5, Util.getMonthNumber("jun"));
+ assertEquals(6, Util.getMonthNumber("jul"));
+ assertEquals(7, Util.getMonthNumber("aug"));
+ assertEquals(8, Util.getMonthNumber("sep"));
+ assertEquals(9, Util.getMonthNumber("oct"));
+ assertEquals(10,Util.getMonthNumber("nov"));
+ assertEquals(11,Util.getMonthNumber("dec"));
+
+ assertEquals(0, Util.getMonthNumber("January"));
+ assertEquals(1, Util.getMonthNumber("February"));
+ assertEquals(2, Util.getMonthNumber("March"));
+ assertEquals(3, Util.getMonthNumber("April"));
+ assertEquals(4, Util.getMonthNumber("May"));
+ assertEquals(5, Util.getMonthNumber("June"));
+ assertEquals(6, Util.getMonthNumber("July"));
+ assertEquals(7, Util.getMonthNumber("August"));
+ assertEquals(8, Util.getMonthNumber("September"));
+ assertEquals(9, Util.getMonthNumber("October"));
+ assertEquals(10,Util.getMonthNumber("November"));
+ assertEquals(11,Util.getMonthNumber("Decembre"));
+
+ assertEquals(0, Util.getMonthNumber("01"));
+ assertEquals(1, Util.getMonthNumber("02"));
+ assertEquals(2, Util.getMonthNumber("03"));
+ assertEquals(3, Util.getMonthNumber("04"));
+ assertEquals(4, Util.getMonthNumber("05"));
+ assertEquals(5, Util.getMonthNumber("06"));
+ assertEquals(6, Util.getMonthNumber("07"));
+ assertEquals(7, Util.getMonthNumber("08"));
+ assertEquals(8, Util.getMonthNumber("09"));
+ assertEquals(9, Util.getMonthNumber("10"));
+
+ assertEquals(0, Util.getMonthNumber("1"));
+ assertEquals(1, Util.getMonthNumber("2"));
+ assertEquals(2, Util.getMonthNumber("3"));
+ assertEquals(3, Util.getMonthNumber("4"));
+ assertEquals(4, Util.getMonthNumber("5"));
+ assertEquals(5, Util.getMonthNumber("6"));
+ assertEquals(6, Util.getMonthNumber("7"));
+ assertEquals(7, Util.getMonthNumber("8"));
+ assertEquals(8, Util.getMonthNumber("9"));
+
+ assertEquals(10,Util.getMonthNumber("11"));
+ assertEquals(11,Util.getMonthNumber("12"));
+
+ assertEquals(-1,Util.getMonthNumber(";lkjasdf"));
+ assertEquals(-1,Util.getMonthNumber("3.2"));
+ assertEquals(-1,Util.getMonthNumber(""));
+ }
+}
diff --git a/src/java/tests/net/sf/jabref/bst/AllTests.java b/src/java/tests/net/sf/jabref/bst/AllTests.java
new file mode 100644
index 0000000..5fd934b
--- /dev/null
+++ b/src/java/tests/net/sf/jabref/bst/AllTests.java
@@ -0,0 +1,21 @@
+package tests.net.sf.jabref.bst;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+public class AllTests {
+
+ public static Test suite() {
+ TestSuite suite = new TestSuite("Test for tests.net.sf.jabref.bst.test");
+ //$JUnit-BEGIN$
+ suite.addTestSuite(BibtexNameFormatterTest.class);
+ suite.addTestSuite(BibtexCaseChangerTest.class);
+ suite.addTestSuite(TestVM.class);
+ suite.addTestSuite(BibtexWidthTest.class);
+ suite.addTestSuite(TextPrefixFunctionTest.class);
+ suite.addTestSuite(BibtexPurifyTest.class);
+ //$JUnit-END$
+ return suite;
+ }
+
+}
diff --git a/src/java/tests/net/sf/jabref/bst/BibtexCaseChangerTest.java b/src/java/tests/net/sf/jabref/bst/BibtexCaseChangerTest.java
new file mode 100644
index 0000000..2ba3aa4
--- /dev/null
+++ b/src/java/tests/net/sf/jabref/bst/BibtexCaseChangerTest.java
@@ -0,0 +1,125 @@
+package tests.net.sf.jabref.bst;
+
+import net.sf.jabref.bst.BibtexCaseChanger;
+import net.sf.jabref.bst.Warn;
+import junit.framework.TestCase;
+
+public class BibtexCaseChangerTest extends TestCase {
+
+ public void testChangeCase() {
+
+ assertCaseChangerT("i", "i");
+ assertCaseChangerL("i", "i");
+ assertCaseChangerU("I", "i");
+ assertCaseChangerT("0i~ ", "0I~ ");
+ assertCaseChangerL("0i~ ", "0I~ ");
+ assertCaseChangerU("0I~ ", "0I~ ");
+ assertCaseChangerT("Hi hi ", "Hi Hi ");
+ assertCaseChangerL("hi hi ", "Hi Hi ");
+ assertCaseChangerU("HI HI ", "Hi Hi ");
+ assertCaseChangerT("{\\oe}", "{\\oe}");
+ assertCaseChangerL("{\\oe}", "{\\oe}");
+ assertCaseChangerU("{\\OE}", "{\\oe}");
+ assertCaseChangerT("Hi {\\oe }hi ", "Hi {\\oe }Hi ");
+ assertCaseChangerL("hi {\\oe }hi ", "Hi {\\oe }Hi ");
+ assertCaseChangerU("HI {\\OE }HI ", "Hi {\\oe }Hi ");
+ assertCaseChangerT(
+ "Jonathan meyer and charles louis xavier joseph de la vall{\\'e}e poussin",
+ "Jonathan Meyer and Charles Louis Xavier Joseph de la Vall{\\'e}e Poussin");
+ assertCaseChangerL(
+ "jonathan meyer and charles louis xavier joseph de la vall{\\'e}e poussin",
+ "Jonathan Meyer and Charles Louis Xavier Joseph de la Vall{\\'e}e Poussin");
+ assertCaseChangerU(
+ "JONATHAN MEYER AND CHARLES LOUIS XAVIER JOSEPH DE LA VALL{\\'E}E POUSSIN",
+ "Jonathan Meyer and Charles Louis Xavier Joseph de la Vall{\\'e}e Poussin");
+ assertCaseChangerT("{\\'e}", "{\\'e}");
+ assertCaseChangerL("{\\'e}", "{\\'e}");
+ assertCaseChangerU("{\\'E}", "{\\'e}");
+ assertCaseChangerT("{\\'{E}}douard masterly", "{\\'{E}}douard Masterly");
+ assertCaseChangerL("{\\'{e}}douard masterly", "{\\'{E}}douard Masterly");
+ assertCaseChangerU("{\\'{E}}DOUARD MASTERLY", "{\\'{E}}douard Masterly");
+ assertCaseChangerT("Ulrich {\\\"{u}}nderwood and ned {\\~n}et and paul {\\={p}}ot",
+ "Ulrich {\\\"{U}}nderwood and Ned {\\~N}et and Paul {\\={P}}ot");
+ assertCaseChangerL("ulrich {\\\"{u}}nderwood and ned {\\~n}et and paul {\\={p}}ot",
+ "Ulrich {\\\"{U}}nderwood and Ned {\\~N}et and Paul {\\={P}}ot");
+ assertCaseChangerU("ULRICH {\\\"{U}}NDERWOOD AND NED {\\~N}ET AND PAUL {\\={P}}OT",
+ "Ulrich {\\\"{U}}nderwood and Ned {\\~N}et and Paul {\\={P}}ot");
+ assertCaseChangerT("An {$O(n \\log n / \\! \\log\\log n)$} sorting algorithm",
+ "An {$O(n \\log n / \\! \\log\\log n)$} Sorting Algorithm");
+ assertCaseChangerL("an {$O(n \\log n / \\! \\log\\log n)$} sorting algorithm",
+ "An {$O(n \\log n / \\! \\log\\log n)$} Sorting Algorithm");
+ assertCaseChangerU("AN {$O(n \\log n / \\! \\log\\log n)$} SORTING ALGORITHM",
+ "An {$O(n \\log n / \\! \\log\\log n)$} Sorting Algorithm");
+
+ assertCaseChangerT("hallo", "hallo");
+ assertCaseChangerT("Hallo", "HAllo");
+ assertCaseChangerT("Hallo world", "HAllo World");
+ assertCaseChangerT("Hallo world. how", "HAllo WORLD. HOW");
+ assertCaseChangerT("Hallo {WORLD}. how", "HAllo {WORLD}. HOW");
+ assertCaseChangerT("Hallo {\\world}. how", "HAllo {\\WORLD}. HOW");
+
+ assertCaseChangerL("hallo", "hallo");
+ assertCaseChangerL("hallo", "HAllo");
+ assertCaseChangerL("hallo world", "HAllo World");
+ assertCaseChangerL("hallo world. how", "HAllo WORLD. HOW");
+ assertCaseChangerL("hallo {worLD}. how", "HAllo {worLD}. HOW");
+ assertCaseChangerL("hallo {\\world}. how", "HAllo {\\WORLD}. HOW");
+
+ assertCaseChangerU("HALLO", "hallo");
+ assertCaseChangerU("HALLO", "HAllo");
+ assertCaseChangerU("HALLO WORLD", "HAllo World");
+ assertCaseChangerU("HALLO WORLD. HOW", "HAllo World. How");
+ assertCaseChangerU("HALLO {worLD}. HOW", "HAllo {worLD}. how");
+ assertCaseChangerU("HALLO {\\WORLD}. HOW", "HAllo {\\woRld}. hoW");
+
+ assertCaseChangerT("On notions of information transfer in {VLSI} circuits",
+ "On Notions of Information Transfer in {VLSI} Circuits");
+
+ }
+
+ public void testColon() {
+
+ assertCaseChangerT("Hallo world: How", "HAllo WORLD: HOW");
+ assertCaseChangerT("Hallo world! how", "HAllo WORLD! HOW");
+ assertCaseChangerT("Hallo world? how", "HAllo WORLD? HOW");
+ assertCaseChangerT("Hallo world. how", "HAllo WORLD. HOW");
+ assertCaseChangerT("Hallo world, how", "HAllo WORLD, HOW");
+ assertCaseChangerT("Hallo world; how", "HAllo WORLD; HOW");
+ assertCaseChangerT("Hallo world- how", "HAllo WORLD- HOW");
+ }
+
+ private void assertCaseChangerT(final String string, final String string2) {
+ assertEquals(string, BibtexCaseChanger.changeCase(string2, 't', new Warn() {
+
+ public void warn(String s) {
+ fail("Should not Warn (" + s + ")! changeCase('t') should be " + string + " for "
+ + string2);
+
+ }
+ }));
+
+ }
+
+ private void assertCaseChangerL(final String string, final String string2) {
+ assertEquals(string, BibtexCaseChanger.changeCase(string2, 'l', new Warn() {
+
+ public void warn(String s) {
+ fail("Should not Warn (" + s + ")! changeCase('l') should be " + string + " for "
+ + string2);
+
+ }
+ }));
+
+ }
+
+ private void assertCaseChangerU(final String string, final String string2) {
+ assertEquals(string, BibtexCaseChanger.changeCase(string2, 'u', new Warn() {
+ public void warn(String s) {
+ fail("Should not Warn (" + s + ")! changeCase('u') should be " + string + " for "
+ + string2);
+
+ }
+ }));
+
+ }
+}
diff --git a/src/java/tests/net/sf/jabref/bst/BibtexNameFormatterTest.java b/src/java/tests/net/sf/jabref/bst/BibtexNameFormatterTest.java
new file mode 100644
index 0000000..c32bf29
--- /dev/null
+++ b/src/java/tests/net/sf/jabref/bst/BibtexNameFormatterTest.java
@@ -0,0 +1,135 @@
+package tests.net.sf.jabref.bst;
+
+import junit.framework.TestCase;
+import net.sf.jabref.AuthorList;
+import net.sf.jabref.bst.BibtexNameFormatter;
+import net.sf.jabref.bst.Warn;
+
+public class BibtexNameFormatterTest extends TestCase {
+
+ public void testFormatName() {
+ {
+ AuthorList al = AuthorList
+ .getAuthorList("Charles Louis Xavier Joseph de la Vall{\\'e}e Poussin");
+
+ assertEquals("de~laVall{\\'e}e~PoussinCharles Louis Xavier~Joseph", BibtexNameFormatter.formatName(al
+ .getAuthor(0), "{vv}{ll}{jj}{ff}", new Warn() {
+ public void warn(String s) {
+ fail(s);
+ }
+ }));
+ }
+
+ {
+ AuthorList al = AuthorList
+ .getAuthorList("Charles Louis Xavier Joseph de la Vall{\\'e}e Poussin");
+
+ assertEquals("de~la Vall{\\'e}e~Poussin, C.~L. X.~J.", BibtexNameFormatter.formatName(al
+ .getAuthor(0), "{vv~}{ll}{, jj}{, f.}", new Warn() {
+ public void warn(String s) {
+ fail(s);
+ }
+ }));
+ }
+
+ {
+ AuthorList al = AuthorList
+ .getAuthorList("Charles Louis Xavier Joseph de la Vall{\\'e}e Poussin");
+
+ assertEquals("de~la Vall{\\'e}e~Poussin, C.~L. X.~J?", BibtexNameFormatter.formatName(al
+ .getAuthor(0), "{vv~}{ll}{, jj}{, f}?", new Warn() {
+ public void warn(String s) {
+ fail(s);
+ }
+ }));
+ }
+
+ {
+ AuthorList al = AuthorList
+ .getAuthorList("Charles Louis Xavier Joseph de la Vall{\\'e}e Poussin");
+
+ assertEquals("dlVP", BibtexNameFormatter.formatName(al.getAuthor(0), "{v{}}{l{}}",
+ new Warn() {
+ public void warn(String s) {
+ fail(s);
+ }
+ }));
+ }
+
+ assertNameFormatA("Meyer, J?", "Jonathan Meyer and Charles Louis Xavier Joseph de la Vall{\\'e}e Poussin");
+ assertNameFormatB("J.~Meyer", "Jonathan Meyer and Charles Louis Xavier Joseph de la Vall{\\'e}e Poussin");
+ assertNameFormatC("Jonathan Meyer", "Jonathan Meyer and Charles Louis Xavier Joseph de la Vall{\\'e}e Poussin");
+ assertNameFormatA("Masterly, {\\'{E}}?", "{\\'{E}}douard Masterly");
+ assertNameFormatB("{\\'{E}}.~Masterly", "{\\'{E}}douard Masterly");
+ assertNameFormatC("{\\'{E}}douard Masterly", "{\\'{E}}douard Masterly");
+ assertNameFormatA("{\\\"{U}}nderwood, U?", "Ulrich {\\\"{U}}nderwood and Ned {\\~N}et and Paul {\\={P}}ot");
+ assertNameFormatB("U.~{\\\"{U}}nderwood", "Ulrich {\\\"{U}}nderwood and Ned {\\~N}et and Paul {\\={P}}ot");
+ assertNameFormatC("Ulrich {\\\"{U}}nderwood", "Ulrich {\\\"{U}}nderwood and Ned {\\~N}et and Paul {\\={P}}ot");
+ assertNameFormatA("Victor, P.~{\\'E}?", "Paul {\\'E}mile Victor and and de la Cierva y Codorn{\\�\\i}u, Juan");
+ assertNameFormatB("P.~{\\'E}. Victor", "Paul {\\'E}mile Victor and and de la Cierva y Codorn{\\�\\i}u, Juan");
+ assertNameFormatC("Paul~{\\'E}mile Victor", "Paul {\\'E}mile Victor and and de la Cierva y Codorn{\\�\\i}u, Juan");
+
+ }
+
+ private void assertNameFormat(String string, String string2, int which, String format){
+ assertEquals(string, BibtexNameFormatter.formatName(string2, which, format,
+ new Warn() {
+ public void warn(String s) {
+ fail(s);
+ }
+ }));
+ }
+
+ private void assertNameFormatC(String string, String string2) {
+ assertNameFormat(string, string2, 1, "{ff }{vv }{ll}{ jj}");
+ }
+
+ private void assertNameFormatB(String string, String string2) {
+ assertNameFormat(string, string2, 1, "{f.~}{vv~}{ll}{, jj}");
+ }
+
+ private void assertNameFormatA(String string, String string2) {
+ assertNameFormat(string, string2, 1, "{vv~}{ll}{, jj}{, f}?");
+ }
+
+ public void testConsumeToMatchingBrace() {
+ {
+ StringBuffer sb = new StringBuffer();
+ assertEquals(6, BibtexNameFormatter.consumeToMatchingBrace(sb, "{HELLO} {WORLD}"
+ .toCharArray(), 0));
+ assertEquals("{HELLO}", sb.toString());
+ }
+ {
+ StringBuffer sb = new StringBuffer();
+ assertEquals(18, BibtexNameFormatter.consumeToMatchingBrace(sb, "{HE{L{}L}O} {WORLD}"
+ .toCharArray(), 12));
+ assertEquals("{WORLD}", sb.toString());
+ }
+ {
+ StringBuffer sb = new StringBuffer();
+ assertEquals(10, BibtexNameFormatter.consumeToMatchingBrace(sb, "{HE{L{}L}O} {WORLD}"
+ .toCharArray(), 0));
+ assertEquals("{HE{L{}L}O}", sb.toString());
+ }
+ }
+
+ public void testGetFirstCharOfString() {
+ assertEquals("C", BibtexNameFormatter.getFirstCharOfString("Charles"));
+ assertEquals("V", BibtexNameFormatter.getFirstCharOfString("Vall{\\'e}e"));
+ assertEquals("{\\'e}", BibtexNameFormatter.getFirstCharOfString("{\\'e}"));
+ assertEquals("{\\'e", BibtexNameFormatter.getFirstCharOfString("{\\'e"));
+ assertEquals("E", BibtexNameFormatter.getFirstCharOfString("{E"));
+ }
+
+ public void testNumberOfChars() {
+
+ assertEquals(6, BibtexNameFormatter.numberOfChars("Vall{\\'e}e", -1));
+ assertEquals(2, BibtexNameFormatter.numberOfChars("Vall{\\'e}e", 2));
+ assertEquals(1, BibtexNameFormatter.numberOfChars("Vall{\\'e}e", 1));
+ assertEquals(6, BibtexNameFormatter.numberOfChars("Vall{\\'e}e", 6));
+ assertEquals(6, BibtexNameFormatter.numberOfChars("Vall{\\'e}e", 7));
+ assertEquals(8, BibtexNameFormatter.numberOfChars("Vall{e}e", -1));
+ assertEquals(6, BibtexNameFormatter.numberOfChars("Vall{\\'e this will be skipped}e", -1));
+ }
+
+}
diff --git a/src/java/tests/net/sf/jabref/bst/BibtexPurifyTest.java b/src/java/tests/net/sf/jabref/bst/BibtexPurifyTest.java
new file mode 100644
index 0000000..265c634
--- /dev/null
+++ b/src/java/tests/net/sf/jabref/bst/BibtexPurifyTest.java
@@ -0,0 +1,27 @@
+package tests.net.sf.jabref.bst;
+
+import net.sf.jabref.bst.BibtexPurify;
+import net.sf.jabref.bst.Warn;
+import junit.framework.TestCase;
+
+public class BibtexPurifyTest extends TestCase {
+
+ public void testPurify() {
+ assertPurify("i", "i");
+ assertPurify("0I ", "0I~ ");
+ assertPurify("Hi Hi ", "Hi Hi ");
+ assertPurify("oe", "{\\oe}");
+ assertPurify("Hi oeHi ", "Hi {\\oe }Hi ");
+ assertPurify("Jonathan Meyer and Charles Louis Xavier Joseph de la Vallee Poussin", "Jonathan Meyer and Charles Louis Xavier Joseph de la Vall{\\'e}e Poussin");
+ assertPurify("e", "{\\'e}");
+ assertPurify("Edouard Masterly", "{\\'{E}}douard Masterly");
+ assertPurify("Ulrich Underwood and Ned Net and Paul Pot", "Ulrich {\\\"{U}}nderwood and Ned {\\~N}et and Paul {\\={P}}ot");}
+
+ private void assertPurify(final String string, final String string2) {
+ assertEquals(string, BibtexPurify.purify(string2, new Warn() {
+ public void warn(String s) {
+ fail("Should not Warn ("+s+")! purify should be " + string + " for " + string2);
+ }
+ }));
+ }
+}
diff --git a/src/java/tests/net/sf/jabref/bst/BibtexWidthTest.java b/src/java/tests/net/sf/jabref/bst/BibtexWidthTest.java
new file mode 100644
index 0000000..a19abac
--- /dev/null
+++ b/src/java/tests/net/sf/jabref/bst/BibtexWidthTest.java
@@ -0,0 +1,78 @@
+package tests.net.sf.jabref.bst;
+
+import net.sf.jabref.bst.BibtexWidth;
+import net.sf.jabref.bst.Warn;
+import junit.framework.TestCase;
+
+/**
+ * How to create these test using Bibtex:
+ *
+ * Execute this charWidth.bst with the following charWidth.aux:
+ *
+ *
+ * <code>
+ ENTRY{}{}{}
+ FUNCTION{test}
+ {
+ "i" width$ int.to.str$ write$ newline$
+ "0I~ " width$ int.to.str$ write$ newline$
+ "Hi Hi " width$ int.to.str$ write$ newline$
+ "{\oe}" width$ int.to.str$ write$ newline$
+ "Hi {\oe }Hi " width$ int.to.str$ write$ newline$
+ }
+ READ
+ EXECUTE{test}
+ </code>
+ *
+ * <code>
+ \bibstyle{charWidth}
+ \citation{canh05}
+ \bibdata{test}
+ \bibcite{canh05}{CMM{$^{+}$}05}
+ </code>
+ *
+ * @author $Author: coezbek $
+ * @version $Revision: 1.1 $ ($Date: 2006/11/11 17:11:39 $)
+ *
+ */
+public class BibtexWidthTest extends TestCase {
+
+ public void assertBibtexWidth(final int i, final String string) {
+ assertEquals(i, BibtexWidth.width(string, new Warn() {
+ public void warn(String s) {
+ fail("Should not Warn! Width should be " + i + " for " + string);
+ }
+ }));
+ }
+
+ public void testWidth() {
+
+ assertBibtexWidth(278, "i");
+
+ assertBibtexWidth(1639, "0I~ ");
+
+ assertBibtexWidth(2612, "Hi Hi ");
+
+ assertBibtexWidth(778, "{\\oe}");
+
+ assertBibtexWidth(3390, "Hi {\\oe }Hi ");
+
+ assertBibtexWidth(444, "{\\'e}");
+
+ assertBibtexWidth(19762, "Ulrich {\\\"{U}}nderwood and Ned {\\~N}et and Paul {\\={P}}ot");
+
+ assertBibtexWidth(7861, "{\\'{E}}douard Masterly");
+
+ assertBibtexWidth(30514, "Jonathan Meyer and Charles Louis Xavier Joseph de la Vall{\\'e}e Poussin");
+
+ }
+
+
+ public void testGetCharWidth() {
+ assertEquals(500, BibtexWidth.getCharWidth('0'));
+ assertEquals(361, BibtexWidth.getCharWidth('I'));
+ assertEquals(500, BibtexWidth.getCharWidth('~'));
+ assertEquals(500, BibtexWidth.getCharWidth('}'));
+ assertEquals(278, BibtexWidth.getCharWidth(' '));
+ }
+}
diff --git a/src/java/tests/net/sf/jabref/bst/TestVM.java b/src/java/tests/net/sf/jabref/bst/TestVM.java
new file mode 100644
index 0000000..d941329
--- /dev/null
+++ b/src/java/tests/net/sf/jabref/bst/TestVM.java
@@ -0,0 +1,648 @@
+package tests.net.sf.jabref.bst;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.util.Collection;
+import java.util.Vector;
+
+import junit.framework.TestCase;
+import net.sf.jabref.BibtexEntry;
+import net.sf.jabref.bst.VM;
+import net.sf.jabref.bst.VMException;
+import net.sf.jabref.bst.VM.BstEntry;
+import net.sf.jabref.bst.VM.StackFunction;
+import net.sf.jabref.imports.BibtexParser;
+import net.sf.jabref.imports.ParserResult;
+
+import org.antlr.runtime.RecognitionException;
+
+
+public class TestVM extends TestCase {
+
+ public void testAbbrv() throws RecognitionException, IOException {
+ VM vm = new VM(new File("src/tests/net/sf/jabref/bst/abbrv.bst"));
+ Vector v = new Vector();
+ v.add(t1BibtexEntry());
+
+ String expected = "\\begin{thebibliography}{1}\\bibitem{canh05}K.~Crowston, H.~Annabi, J.~Howison, and C.~Masango.\\newblock Effective work practices for floss development: A model and propositions.\\newblock In {\\em Hawaii International Conference On System Sciences (HICSS)}, 2005.\\end{thebibliography}";
+
+ assertEquals(expected.replaceAll("\\s", ""), vm.run(v).replaceAll("\\s", ""));
+ }
+
+ public void testVMSimple() throws RecognitionException, IOException {
+
+ VM vm = new VM("" + "ENTRY { " + " address " + " author " + " title " + " type "
+ + "} {} { label }" + "INTEGERS { output.state before.all"
+ + " mid.sentence after.sentence after.block }"
+ + "FUNCTION {init.state.consts}{ #0 'before.all := "
+ + " #1 'mid.sentence := #2 'after.sentence := #3 'after.block := } "
+ + "STRINGS { s t } " + "READ");
+
+ Vector v = new Vector();
+ v.add(t1BibtexEntry());
+
+ vm.run(v);
+
+ assertEquals(2, vm.getStrings().size());
+ assertEquals(7, vm.getIntegers().size());
+ assertEquals(1, vm.getEntries().size());
+ assertEquals(5, ((BstEntry)vm.getEntries().get(0)).getFields().size());
+ assertEquals(38, vm.getFunctions().size());
+
+ }
+
+ public void testLabel() throws RecognitionException, IOException {
+
+ VM vm = new VM("" + "ENTRY { title } {} { label } "
+ + "FUNCTION { test } { label #0 = title 'label := #5 label #6 pop$ } " + "READ "
+ + "ITERATE { test }");
+
+ Vector v = new Vector();
+ v.add(t1BibtexEntry());
+
+ vm.run(v);
+
+ assertEquals("Effective work practices for floss development: A model and propositions", vm
+ .getStack().pop());
+
+ }
+
+ public void testQuote() throws RecognitionException, IOException {
+
+ VM vm = new VM("FUNCTION {a}{ quote$ quote$ * } EXECUTE {a}");
+
+ Vector v = new Vector();
+ vm.run(v);
+
+ assertEquals("\"\"", vm.getStack().pop());
+ }
+
+ public void testVMFunction1() throws RecognitionException, IOException {
+
+ VM vm = new VM("FUNCTION {init.state.consts}{ #0 'before.all := } ");
+
+ Vector v = new Vector();
+ vm.run(v);
+
+ assertEquals(38, vm.getFunctions().size());
+
+ assertTrue(vm.getFunctions().get("init.state.consts") instanceof StackFunction);
+
+ StackFunction fun = (StackFunction) vm.getFunctions().get("init.state.consts");
+ assertEquals(3, fun.getTree().getChildCount());
+ }
+
+ public void testVMExecuteSimple() throws RecognitionException, IOException {
+
+ {
+ VM vm = new VM("" + "INTEGERS { variable.a } "
+ + "FUNCTION {init.state.consts}{ #5 'variable.a := } "
+ + "EXECUTE {init.state.consts}");
+
+ Vector v = new Vector();
+ vm.run(v);
+ assertEquals(new Integer(5), (Integer) vm.getIntegers().get("variable.a"));
+ }
+ {
+ VM vm = new VM("FUNCTION {a}{ #5 #5 = " + "#1 #2 = " + "#3 #4 < " + "#4 #3 < "
+ + "#4 #4 < " + "#3 #4 > " + "#4 #3 > " + "#4 #4 > " + "\"H\" \"H\" = "
+ + "\"H\" \"Ha\" = } " + "EXECUTE {a}");
+
+ Vector v = new Vector();
+ vm.run(v);
+
+ assertEquals(VM.FALSE, vm.getStack().pop());
+ assertEquals(VM.TRUE, vm.getStack().pop());
+ assertEquals(VM.FALSE, vm.getStack().pop());
+ assertEquals(VM.TRUE, vm.getStack().pop());
+ assertEquals(VM.FALSE, vm.getStack().pop());
+ assertEquals(VM.FALSE, vm.getStack().pop());
+ assertEquals(VM.FALSE, vm.getStack().pop());
+ assertEquals(VM.TRUE, vm.getStack().pop());
+ assertEquals(VM.FALSE, vm.getStack().pop());
+ assertEquals(VM.TRUE, vm.getStack().pop());
+ assertEquals(0, vm.getStack().size());
+ }
+ }
+
+ public void testVMIfSkipPop() throws RecognitionException, IOException {
+ VM vm = new VM("FUNCTION {not} { { #0 } { #1 } if$ }"
+ + "FUNCTION {and} { 'skip$ { pop$ #0 } if$ }"
+ + "FUNCTION {or} { { pop$ #1 } 'skip$ if$ }" + "FUNCTION {test} { "
+ + "#1 #1 and #0 #1 and #1 #0 and #0 #0 and " + "#0 not #1 not "
+ + "#1 #1 or #0 #1 or #1 #0 or #0 #0 or }" + "EXECUTE {test}");
+
+ Vector v = new Vector();
+ vm.run(v);
+ assertEquals(VM.FALSE, vm.getStack().pop());
+ assertEquals(VM.TRUE, vm.getStack().pop());
+ assertEquals(VM.TRUE, vm.getStack().pop());
+ assertEquals(VM.TRUE, vm.getStack().pop());
+ assertEquals(VM.FALSE, vm.getStack().pop());
+ assertEquals(VM.TRUE, vm.getStack().pop());
+ assertEquals(VM.FALSE, vm.getStack().pop());
+ assertEquals(VM.FALSE, vm.getStack().pop());
+ assertEquals(VM.FALSE, vm.getStack().pop());
+ assertEquals(VM.TRUE, vm.getStack().pop());
+ assertEquals(0, vm.getStack().size());
+ }
+
+ public void testVMArithmetic() throws RecognitionException, IOException {
+ {
+ VM vm = new VM("FUNCTION {test} { " + "#1 #1 + #5 #2 - }" + "EXECUTE {test}");
+
+ Vector v = new Vector();
+ vm.run(v);
+ assertEquals(new Integer(3), vm.getStack().pop());
+ assertEquals(new Integer(2), vm.getStack().pop());
+ assertEquals(0, vm.getStack().size());
+ }
+ {
+ VM vm = new VM("FUNCTION {test} { " + "#1 \"HELLO\" + #5 #2 - }" + "EXECUTE {test}");
+
+ Vector v = new Vector();
+
+ try {
+ vm.run(v);
+ fail();
+ } catch (VMException e) {
+
+ }
+ }
+ }
+
+ public void testNumNames() throws RecognitionException, IOException {
+ {
+ VM vm = new VM("FUNCTION {test} { \"Johnny Foo and Mary Bar\" num.names$ }"
+ + "EXECUTE {test}");
+
+ Vector v = new Vector();
+ vm.run(v);
+ assertEquals(new Integer(2), vm.getStack().pop());
+ assertEquals(0, vm.getStack().size());
+ }
+ {
+ VM vm = new VM("FUNCTION {test} { \"Johnny Foo { and } Mary Bar\" num.names$ }"
+ + "EXECUTE {test}");
+
+ Vector v = new Vector();
+ vm.run(v);
+ assertEquals(new Integer(1), vm.getStack().pop());
+ assertEquals(0, vm.getStack().size());
+ }
+ }
+
+ public void testVMStringOps1() throws RecognitionException, IOException {
+ {
+ VM vm = new VM(
+ "FUNCTION {test} { \"H\" \"allo\" * \"Johnny\" add.period$ \"Johnny.\" add.period$"
+ + "\"Johnny!\" add.period$ \"Johnny?\" add.period$ \"Johnny} }}}\" add.period$"
+ + "\"Johnny!}\" add.period$ \"Johnny?}\" add.period$ \"Johnny.}\" add.period$ }"
+ + "EXECUTE {test}");
+
+ Vector v = new Vector();
+ vm.run(v);
+ assertEquals("Johnny.}", vm.getStack().pop());
+ assertEquals("Johnny?}", vm.getStack().pop());
+ assertEquals("Johnny!}", vm.getStack().pop());
+ assertEquals("Johnny.}", vm.getStack().pop());
+ assertEquals("Johnny?", vm.getStack().pop());
+ assertEquals("Johnny!", vm.getStack().pop());
+ assertEquals("Johnny.", vm.getStack().pop());
+ assertEquals("Johnny.", vm.getStack().pop());
+ assertEquals("Hallo", vm.getStack().pop());
+ assertEquals(0, vm.getStack().size());
+ }
+ }
+
+ public void testSubstring() throws RecognitionException, IOException {
+ VM vm = new VM("FUNCTION {test} " + "{ \"123456789\" #2 #1 substring$ " + // 2
+ " \"123456789\" #4 global.max$ substring$ " + // 456789
+ " \"123456789\" #1 #9 substring$ " + // 123456789
+ " \"123456789\" #1 #10 substring$ " + // 123456789
+ " \"123456789\" #1 #99 substring$ " + // 123456789
+
+ " \"123456789\" #-7 #3 substring$ " + // 123
+ " \"123456789\" #-1 #1 substring$ " + // 9
+ " \"123456789\" #-1 #3 substring$ " + // 789
+ " \"123456789\" #-2 #2 substring$ " + // 78
+
+ "} EXECUTE {test} ");
+
+ Vector v = new Vector();
+ vm.run(v);
+ assertEquals("78", vm.getStack().pop());
+ assertEquals("789", vm.getStack().pop());
+ assertEquals("9", vm.getStack().pop());
+ assertEquals("123", vm.getStack().pop());
+
+ assertEquals("123456789", vm.getStack().pop());
+ assertEquals("123456789", vm.getStack().pop());
+ assertEquals("123456789", vm.getStack().pop());
+ assertEquals("456789", vm.getStack().pop());
+ assertEquals("2", vm.getStack().pop());
+ assertEquals(0, vm.getStack().size());
+ }
+
+ public void testEmpty() throws RecognitionException, IOException {
+ VM vm = new VM("ENTRY {title}{}{} READ STRINGS { s } FUNCTION {test} " + "{ s empty$ " + // FALSE
+ "\"\" empty$ " + // FALSE
+ "\" \" empty$ " + // FALSE
+ " title empty$ " + // FALSE
+ " \" HALLO \" empty$ } ITERATE {test} ");
+
+ Vector v = new Vector();
+ v.add(bibtexString2BibtexEntry("@article{a, author=\"AAA\"}"));
+ vm.run(v);
+ assertEquals(VM.FALSE, vm.getStack().pop());
+ assertEquals(VM.TRUE, vm.getStack().pop());
+ assertEquals(VM.TRUE, vm.getStack().pop());
+ assertEquals(VM.TRUE, vm.getStack().pop());
+ assertEquals(VM.TRUE, vm.getStack().pop());
+ assertEquals(0, vm.getStack().size());
+ }
+
+ public void testDuplicateEmptyPopSwapIf() throws RecognitionException, IOException {
+ VM vm = new VM("FUNCTION {emphasize} " + "{ duplicate$ empty$ " + " { pop$ \"\" } "
+ + " { \"{\\em \" swap$ * \"}\" * } " + " if$ " + "} " + "FUNCTION {test} {"
+ + " \"\" emphasize " + " \"Hello\" emphasize " + "}" + "EXECUTE {test} ");
+
+ Vector v = new Vector();
+ vm.run(v);
+ assertEquals("{\\em Hello}", vm.getStack().pop());
+ assertEquals("", vm.getStack().pop());
+ assertEquals(0, vm.getStack().size());
+ }
+
+ public void testChangeCase() throws RecognitionException, IOException {
+ VM vm = new VM(
+ "STRINGS { title } "
+ + "READ "
+ + "FUNCTION {format.title}"
+ + " { duplicate$ empty$ "
+ + " { pop$ \"\" } "
+ + " { \"t\" change.case$ } "
+ + " if$ "
+ + "} "
+ + "FUNCTION {test} {"
+ + " \"hello world\" \"u\" change.case$ format.title "
+ + " \"Hello World\" format.title "
+ + " \"\" format.title "
+ + " \"{A}{D}/{C}ycle: {I}{B}{M}'s {F}ramework for {A}pplication {D}evelopment and {C}ase\" \"u\" change.case$ format.title "
+ + "}" + "EXECUTE {test} ");
+
+ Vector v = new Vector();
+ vm.run(v);
+ assertEquals(
+ "{A}{D}/{C}ycle: {I}{B}{M}'s {F}ramework for {A}pplication {D}evelopment and {C}ase",
+ vm.getStack().pop());
+ assertEquals("", vm.getStack().pop());
+ assertEquals("Hello world", vm.getStack().pop());
+ assertEquals("Hello world", vm.getStack().pop());
+ assertEquals(0, vm.getStack().size());
+ }
+
+ public void testTextLength() throws RecognitionException, IOException {
+ VM vm = new VM("FUNCTION {test} {" + " \"hello world\" text.length$ "
+ + " \"Hello {W}orld\" text.length$ " + " \"\" text.length$ "
+ + " \"{A}{D}/{Cycle}\" text.length$ "
+ + " \"{\\This is one character}\" text.length$ "
+ + " \"{\\This {is} {one} {c{h}}aracter as well}\" text.length$ "
+ + " \"{\\And this too\" text.length$ " + " \"These are {\\11}\" text.length$ " + "} "
+ + "EXECUTE {test} ");
+
+ Vector v = new Vector();
+ vm.run(v);
+ assertEquals(new Integer(11), vm.getStack().pop());
+ assertEquals(new Integer(1), vm.getStack().pop());
+ assertEquals(new Integer(1), vm.getStack().pop());
+ assertEquals(new Integer(1), vm.getStack().pop());
+ assertEquals(new Integer(8), vm.getStack().pop());
+ assertEquals(new Integer(0), vm.getStack().pop());
+ assertEquals(new Integer(11), vm.getStack().pop());
+ assertEquals(new Integer(11), vm.getStack().pop());
+ assertEquals(0, vm.getStack().size());
+ }
+
+ public void testVMIntToStr() throws RecognitionException, IOException {
+ VM vm = new VM("FUNCTION {test} { #3 int.to.str$ #9999 int.to.str$}" + "EXECUTE {test}");
+
+ Vector v = new Vector();
+ vm.run(v);
+ assertEquals("9999", (String) vm.getStack().pop());
+ assertEquals("3", vm.getStack().pop());
+ assertEquals(0, vm.getStack().size());
+ }
+
+ public void testVMChrToInt() throws RecognitionException, IOException {
+ {
+ VM vm = new VM("FUNCTION {test} { \"H\" chr.to.int$ }" + "EXECUTE {test}");
+
+ Vector v = new Vector();
+ vm.run(v);
+ assertEquals(new Integer(72), vm.getStack().pop());
+ assertEquals(0, vm.getStack().size());
+ }
+ {
+ VM vm = new VM("FUNCTION {test} { \"H\" chr.to.int$ int.to.chr$ }" + "EXECUTE {test}");
+
+ Vector v = new Vector();
+ vm.run(v);
+ assertEquals("H", vm.getStack().pop());
+ assertEquals(0, vm.getStack().size());
+ }
+ }
+
+ public void testSort() throws RecognitionException, IOException {
+
+ VM vm = new VM("" + "ENTRY { title } { } { label }"
+ + "FUNCTION {presort} { cite$ 'sort.key$ := } ITERATE { presort } SORT");
+
+ Vector v = new Vector();
+ v.add(bibtexString2BibtexEntry("@article{a, author=\"AAA\"}"));
+ v.add(bibtexString2BibtexEntry("@article{b, author=\"BBB\"}"));
+ v.add(bibtexString2BibtexEntry("@article{d, author=\"DDD\"}"));
+ v.add(bibtexString2BibtexEntry("@article{c, author=\"CCC\"}"));
+ vm.run(v);
+
+ Vector v2 = vm.getEntries();
+ assertEquals("a", ((BstEntry)v2.get(0)).getBibtexEntry().getCiteKey());
+ assertEquals("b", ((BstEntry)v2.get(1)).getBibtexEntry().getCiteKey());
+ assertEquals("c", ((BstEntry)v2.get(2)).getBibtexEntry().getCiteKey());
+ assertEquals("d", ((BstEntry)v2.get(3)).getBibtexEntry().getCiteKey());
+ }
+
+ public void testBuildIn() throws RecognitionException, IOException {
+ VM vm = new VM("EXECUTE {global.max$}");
+
+ Vector v = new Vector();
+ vm.run(v);
+
+ assertEquals(new Integer(Integer.MAX_VALUE), vm.getStack().pop());
+ assertTrue(vm.getStack().empty());
+ }
+
+ public void testVariables() throws RecognitionException, IOException {
+
+ VM vm = new VM(" STRINGS { t } "
+ + " FUNCTION {not} { { #0 } { #1 } if$ } "
+ + " FUNCTION {n.dashify} { \"HELLO-WORLD\" 't := t empty$ not } "
+ + " EXECUTE {n.dashify} ");
+
+ vm.run(new Vector());
+
+ assertEquals(VM.TRUE, vm.getStack().pop());
+ }
+
+ public void testWhile() throws RecognitionException, IOException {
+
+ VM vm = new VM(
+ "STRINGS { t } "
+ + "FUNCTION {not} { "
+ + " { #0 } { #1 } if$ } "
+ + "FUNCTION {n.dashify} "
+ + "{ \"HELLO-WORLD\" "
+ + " 't := "
+ + " \"\" "
+ + " { t empty$ not } "
+ + " { t #1 #1 substring$ \"-\" = "
+ + " { t #1 #2 substring$ \"--\" = not "
+ + " { \"--\" * "
+ + " t #2 global.max$ substring$ 't := "
+ + " } "
+ + " { { t #1 #1 substring$ \"-\" = } "
+ + " { \"-\" * "
+ + " t #2 global.max$ substring$ 't := "
+ + " } "
+ + " while$ "
+ + " } "
+ + " if$ "
+ + " } "
+ + " { t #1 #1 substring$ * "
+ + " t #2 global.max$ substring$ 't := "
+ + " } "
+ + " if$ "
+ + " } "
+ + " while$ "
+ + " } "
+ + " EXECUTE {n.dashify} ");
+
+ Vector v = new Vector();
+ vm.run(v);
+
+ assertEquals(1, vm.getStack().size());
+ assertEquals("HELLO--WORLD", vm.getStack().pop());
+ }
+
+ public void testType() throws RecognitionException, IOException {
+
+ VM vm = new VM(
+ ""
+ + "ENTRY { title } { } { label }"
+ + "FUNCTION {presort} { cite$ 'sort.key$ := } ITERATE { presort } SORT FUNCTION {test} { type$ } ITERATE { test }");
+
+ Vector v = new Vector();
+ v.add(bibtexString2BibtexEntry("@article{a, author=\"AAA\"}"));
+ v.add(bibtexString2BibtexEntry("@book{b, author=\"BBB\"}"));
+ v.add(bibtexString2BibtexEntry("@misc{c, author=\"CCC\"}"));
+ v.add(bibtexString2BibtexEntry("@inproceedings{d, author=\"DDD\"}"));
+ vm.run(v);
+
+ assertEquals(4, vm.getStack().size());
+ assertEquals("Inproceedings", vm.getStack().pop());
+ assertEquals("Misc", vm.getStack().pop());
+ assertEquals("Book", vm.getStack().pop());
+ assertEquals("Article", vm.getStack().pop());
+ }
+
+ public void testMissing() throws RecognitionException, IOException {
+
+ VM vm = new VM( //
+ "ENTRY { title } { } { label } " + //
+ "FUNCTION {presort} { cite$ 'sort.key$ := } " + //
+ "ITERATE {presort} " + //
+ "READ SORT " + //
+ "FUNCTION {test}{ title missing$ cite$ } " + //
+ "ITERATE { test }");
+
+ Vector v = new Vector();
+ v.add(t1BibtexEntry());
+ v.add(bibtexString2BibtexEntry("@article{test, author=\"No title\"}"));
+ vm.run(v);
+
+ assertEquals(4, vm.getStack().size());
+
+ assertEquals("test", vm.getStack().pop());
+ assertEquals(new Integer(1), vm.getStack().pop());
+ assertEquals("canh05", vm.getStack().pop());
+ assertEquals(new Integer(0), vm.getStack().pop());
+ }
+
+ public void testFormatName() throws RecognitionException, IOException {
+ {
+ VM vm = new VM(
+ "FUNCTION {format}{ \"Charles Louis Xavier Joseph de la Vall{\\'e}e Poussin\" #1 \"{vv~}{ll}{, jj}{, f}?\" format.name$ }"
+ + "EXECUTE {format}");
+
+ Vector v = new Vector();
+ vm.run(v);
+ assertEquals("de~la Vall{\\'e}e~Poussin, C.~L. X.~J?", (String) vm.getStack().pop());
+ assertEquals(0, vm.getStack().size());
+ }
+ {
+ VM vm = new VM("ENTRY { author } { } { label } "
+ + "FUNCTION {presort} { cite$ 'sort.key$ := } " + "ITERATE { presort } " + "READ "
+ + "SORT " + "FUNCTION {format}{ author #2 \"{vv~}{ll}{, jj}{, f}?\" format.name$ }"
+ + "ITERATE {format}");
+
+ Vector v = new Vector();
+ v.add(t1BibtexEntry());
+ v
+ .add(bibtexString2BibtexEntry("@book{test, author=\"Jonathan Meyer and Charles Louis Xavier Joseph de la Vall{\\'e}e Poussin\"}"));
+ vm.run(v);
+ assertEquals("de~la Vall{\\'e}e~Poussin, C.~L. X.~J?", vm.getStack().pop());
+ assertEquals("Annabi, H?", vm.getStack().pop());
+ assertEquals(0, vm.getStack().size());
+ }
+ }
+
+ public void testCallType() throws RecognitionException, IOException {
+
+ VM vm = new VM(
+ "ENTRY { title } { } { label } FUNCTION {presort} { cite$ 'sort.key$ := } ITERATE { presort } READ SORT "
+ + "FUNCTION {inproceedings}{ \"InProceedings called on \" title * } "
+ + "FUNCTION {book}{ \"Book called on \" title * } " + " ITERATE { call.type$ }");
+
+ Vector v = new Vector();
+ v.add(t1BibtexEntry());
+ v.add(bibtexString2BibtexEntry("@book{test, title=\"Test\"}"));
+ vm.run(v);
+
+ assertEquals(2, vm.getStack().size());
+
+ assertEquals("Book called on Test", vm.getStack().pop());
+ assertEquals(
+ "InProceedings called on Effective work practices for floss development: A model and propositions",
+ vm.getStack().pop());
+ assertEquals(0, vm.getStack().size());
+ }
+
+ public void testIterate() throws RecognitionException, IOException {
+
+ VM vm = new VM("" + "ENTRY { " + " address " + " author " + " title " + " type "
+ + "} {} { label } " + "FUNCTION {test}{ cite$ } " + "READ " + "ITERATE { test }");
+
+ Vector v = new Vector();
+ v.add(t1BibtexEntry());
+
+ v.add(bibtexString2BibtexEntry("@article{test, title=\"BLA\"}"));
+
+ vm.run(v);
+
+ assertEquals(2, vm.getStack().size());
+
+ String s1 = (String) vm.getStack().pop();
+ String s2 = (String) vm.getStack().pop();
+
+ if (s1.equals("canh05")) {
+ assertEquals("test", s2);
+ } else {
+ assertEquals("canh05", s2);
+ assertEquals("test", s1);
+ }
+ }
+
+ public void testWidth() throws RecognitionException, IOException {
+
+ VM vm = new VM("ENTRY { " + " address " + " author " + " title " + " type "
+ + "} {} { label } " + //
+ "STRINGS { longest.label } " + //
+ "INTEGERS { number.label longest.label.width } " + //
+ "FUNCTION {initialize.longest.label} " + //
+ "{ \"\" 'longest.label := " + //
+ " #1 'number.label := " + //
+ " #0 'longest.label.width := " + //
+ "} " + //
+ " " + //
+ " FUNCTION {longest.label.pass} " + //
+ " { number.label int.to.str$ 'label := " + //
+ " number.label #1 + 'number.label := " + //
+ " label width$ longest.label.width > " + //
+ " { label 'longest.label := " + //
+ " label width$ 'longest.label.width := " + //
+ " } " + //
+ " 'skip$ " + //
+ " if$ " + //
+ " } " + //
+ " " + //
+ " EXECUTE {initialize.longest.label} " + //
+ " " + //
+ " ITERATE {longest.label.pass} " + //
+ "FUNCTION {begin.bib} " + //
+ "{ preamble$ empty$" + //
+ " 'skip$" + //
+ " { preamble$ write$ newline$ }" + //
+ " if$" + //
+ " \"\\begin{thebibliography}{\" longest.label * \"}\" *" + //
+ "}" + //
+ "EXECUTE {begin.bib}" + //
+ "");//
+
+ Vector v = new Vector();
+ v.add(t1BibtexEntry());
+
+ vm.run(v);
+
+ assertTrue(vm.getIntegers().containsKey("longest.label.width"));
+ assertEquals("\\begin{thebibliography}{1}", vm.getStack().pop());
+ }
+
+ public void testVMSwap() throws RecognitionException, IOException {
+
+ VM vm = new VM("FUNCTION {a}{ #3 \"Hallo\" swap$ } EXECUTE { a }");
+
+ Vector v = new Vector();
+ vm.run(v);
+
+ assertEquals(2, vm.getStack().size());
+ assertEquals(new Integer(3), vm.getStack().pop());
+ assertEquals("Hallo", vm.getStack().pop());
+ }
+
+ public static BibtexEntry bibtexString2BibtexEntry(String s) throws IOException {
+ ParserResult result = BibtexParser.parse(new StringReader(s));
+ Collection c = result.getDatabase().getEntries();
+ assertEquals(1, c.size());
+ return (BibtexEntry) c.iterator().next();
+ }
+
+ public static String bibtexEntry2BibtexString(BibtexEntry e) throws IOException {
+ StringWriter sw = new StringWriter();
+ e.write(sw, new net.sf.jabref.export.LatexFieldFormatter(), false);
+ return sw.getBuffer().toString();
+ }
+
+ /* TEST DATA */
+ public String t1BibtexString() {
+ return "@inproceedings{canh05,\n"
+ + " author = {Crowston, K. and Annabi, H. and Howison, J. and Masango, C.},\n"
+ + " title = {Effective work practices for floss development: A model and propositions},\n"
+ + " booktitle = {Hawaii International Conference On System Sciences (HICSS)},\n"
+ + " year = {2005},\n" + " owner = {oezbek},\n" + " timestamp = {2006.05.29},\n"
+ + " url = {http://james.howison.name/publications.html}}\n";
+ }
+
+ public void testHypthenatedName() throws RecognitionException, IOException {
+ VM vm = new VM(new File("src/tests/net/sf/jabref/bst/abbrv.bst"));
+ Vector v = new Vector();
+ v.add(bibtexString2BibtexEntry("@article{canh05, author = \"Jean-Paul Sartre\" }"));
+ assertTrue(vm.run(v).indexOf("J.-P. Sartre") != -1);
+ }
+
+ public BibtexEntry t1BibtexEntry() throws IOException {
+ return bibtexString2BibtexEntry(t1BibtexString());
+ }
+
+}
diff --git a/src/java/tests/net/sf/jabref/bst/TextPrefixFunctionTest.java b/src/java/tests/net/sf/jabref/bst/TextPrefixFunctionTest.java
new file mode 100644
index 0000000..a8d0153
--- /dev/null
+++ b/src/java/tests/net/sf/jabref/bst/TextPrefixFunctionTest.java
@@ -0,0 +1,29 @@
+package tests.net.sf.jabref.bst;
+
+import net.sf.jabref.bst.BibtexTextPrefix;
+import net.sf.jabref.bst.Warn;
+import junit.framework.TestCase;
+
+public class TextPrefixFunctionTest extends TestCase {
+
+ public void testPrefix(){
+ assertPrefix("i", "i");
+ assertPrefix("0I~ ", "0I~ ");
+ assertPrefix("Hi Hi", "Hi Hi ");
+ assertPrefix("{\\oe}", "{\\oe}");
+ assertPrefix("Hi {\\oe }H", "Hi {\\oe }Hi ");
+ assertPrefix("Jonat", "Jonathan Meyer and Charles Louis Xavier Joseph de la Vall{\\'e}e Poussin");
+ assertPrefix("{\\'e}", "{\\'e}");
+ assertPrefix("{\\'{E}}doua", "{\\'{E}}douard Masterly");
+ assertPrefix("Ulric", "Ulrich {\\\"{U}}nderwood and Ned {\\~N}et and Paul {\\={P}}ot");
+ }
+
+ private void assertPrefix(final String string, final String string2) {
+ assertEquals(string, BibtexTextPrefix.textPrefix(5, string2, new Warn() {
+ public void warn(String s) {
+ fail("Should not Warn! text.prefix$ should be " + string + " for (5) " + string2);
+ }
+ }));
+ }
+
+}
diff --git a/src/java/tests/net/sf/jabref/export/layout/AllTests.java b/src/java/tests/net/sf/jabref/export/layout/AllTests.java
new file mode 100644
index 0000000..4e4225e
--- /dev/null
+++ b/src/java/tests/net/sf/jabref/export/layout/AllTests.java
@@ -0,0 +1,17 @@
+package tests.net.sf.jabref.export.layout;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+public class AllTests {
+
+ public static Test suite() {
+ TestSuite suite = new TestSuite("Test for test.net.sf.jabref.layout");
+ //$JUnit-BEGIN$
+ suite.addTestSuite(LayoutTest.class);
+ suite.addTestSuite(RTFCharsTest.class);
+ //$JUnit-END$
+ return suite;
+ }
+
+}
diff --git a/src/java/tests/net/sf/jabref/export/layout/LayoutTest.java b/src/java/tests/net/sf/jabref/export/layout/LayoutTest.java
new file mode 100644
index 0000000..55ce9d7
--- /dev/null
+++ b/src/java/tests/net/sf/jabref/export/layout/LayoutTest.java
@@ -0,0 +1,100 @@
+package tests.net.sf.jabref.export.layout;
+
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.Collection;
+
+import junit.framework.TestCase;
+import net.sf.jabref.BibtexEntry;
+import net.sf.jabref.Globals;
+import net.sf.jabref.export.layout.Layout;
+import net.sf.jabref.export.layout.LayoutHelper;
+import net.sf.jabref.imports.BibtexParser;
+import net.sf.jabref.imports.ParserResult;
+
+public class LayoutTest extends TestCase {
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ /* TEST DATA */
+ public String t1BibtexString() {
+ return "@article{canh05,\n"
+ + " author = {This\nis\na\ntext},\n"
+ + " title = {Effective work practices for floss development: A model and propositions},\n"
+ + " booktitle = {Hawaii International Conference On System Sciences (HICSS)},\n"
+ + " year = {2005},\n" + " owner = {oezbek},\n" + " timestamp = {2006.05.29},\n"
+ + " url = {http://james.howison.name/publications.html},\n" + " abstract = {\\~{n}\n"
+ + "\\~n\n" + "\\'i\n" + "\\i\n" + "\\i}\n" + "}\n";
+ }
+
+ public BibtexEntry t1BibtexEntry() throws IOException {
+ return bibtexString2BibtexEntry(t1BibtexString());
+ }
+
+ public static BibtexEntry bibtexString2BibtexEntry(String s) throws IOException {
+ ParserResult result = BibtexParser.parse(new StringReader(s));
+ Collection c = result.getDatabase().getEntries();
+ assertEquals(1, c.size());
+ return (BibtexEntry) c.iterator().next();
+ }
+
+ public String layout(String layoutFile, String entry) throws Exception {
+
+ BibtexEntry be = bibtexString2BibtexEntry(entry);
+ StringReader sr = new StringReader(layoutFile.replaceAll("__NEWLINE__", "\n"));
+ Layout layout = new LayoutHelper(sr).getLayoutFromText(Globals.FORMATTER_PACKAGE);
+ StringBuffer sb = new StringBuffer();
+ sb.append(layout.doLayout(be, null));
+
+ return sb.toString();
+ }
+
+ public void testHTMLChar() throws Exception {
+ String layoutText = layout("\\begin{author}\\format[HTMLChars]{\\author}\\end{author} ",
+ "@other{bla, author={This\nis\na\ntext}}");
+
+ assertEquals("This is a text ", layoutText);
+
+ // This fails!
+
+ layoutText = layout("\\begin{author}\\format[HTMLChars]{\\author}\\end{author}",
+ "@other{bla, author={This\nis\na\ntext}}");
+
+ assertEquals("This is a text", layoutText);
+
+ layoutText = layout("\\begin{author}\\format[HTMLChars]{\\author}\\end{author} ",
+ "@other{bla, author={This\nis\na\n\ntext}}");
+
+ assertEquals("This is a<p>text ", layoutText);
+
+ }
+
+ /**
+ * [ 1495181 ] Dotless i and tilde not handled in preview
+ *
+ * @throws Exception
+ */
+ public void testLayout() throws Exception {
+
+ String layoutFile = "<font face=\"arial\">\\begin{abstract}<BR><BR><b>Abstract: </b> \\format[HTMLChars]{\\abstract} \\end{abstract}</font>";
+
+ StringReader sr = new StringReader(layoutFile.replaceAll("__NEWLINE__", "\n"));
+ Layout layout = new LayoutHelper(sr).getLayoutFromText(Globals.FORMATTER_PACKAGE);
+
+ StringBuffer sb = new StringBuffer();
+ sb.append(layout.doLayout(t1BibtexEntry(), null));
+ String layoutText = sb.toString();
+
+ assertEquals(
+ "<font face=\"arial\"><BR><BR><b>Abstract: </b> ñ ñ í ı ı</font>",
+ layoutText);
+
+ }
+
+}
diff --git a/src/java/tests/net/sf/jabref/export/layout/RTFCharsTest.java b/src/java/tests/net/sf/jabref/export/layout/RTFCharsTest.java
new file mode 100644
index 0000000..867e912
--- /dev/null
+++ b/src/java/tests/net/sf/jabref/export/layout/RTFCharsTest.java
@@ -0,0 +1,85 @@
+package tests.net.sf.jabref.export.layout;
+
+import junit.framework.TestCase;
+import net.sf.jabref.export.layout.LayoutFormatter;
+import net.sf.jabref.export.layout.format.RTFChars;
+
+public class RTFCharsTest extends TestCase {
+
+ public void testBasicFormat() {
+
+ LayoutFormatter layout = new RTFChars();
+
+ assertEquals("", layout.format(""));
+
+ assertEquals("hallo", layout.format("hallo"));
+
+ // We should be able to replace the ? with e
+ assertEquals("R\\u233?flexions sur le timing de la quantit\\u233?", layout.format("R�flexions sur le timing de la quantit�"));
+
+ assertEquals("h\\u225allo", layout.format("h\\'allo"));
+ }
+
+ public void testLaTeXHighlighting(){
+
+ LayoutFormatter layout = new RTFChars();
+
+ assertEquals("{\\i hallo}", layout.format("\\emph{hallo}"));
+ assertEquals("{\\i hallo}", layout.format("{\\emph hallo}"));
+
+ assertEquals("{\\i hallo}", layout.format("\\textit{hallo}"));
+ assertEquals("{\\i hallo}", layout.format("{\\textit hallo}"));
+
+ assertEquals("{\\b hallo}", layout.format("\\textbf{hallo}"));
+ assertEquals("{\\b hallo}", layout.format("{\\textbf hallo}"));
+ }
+
+ public void testComplicated() {
+ LayoutFormatter layout = new RTFChars();
+
+ assertEquals("R\\u233eflexions sur le timing de la quantit\\u233e \\u230ae should be \\u230ae", layout.format("R�flexions sur le timing de la quantit� \\ae should be �"));
+
+ assertEquals("h\\u225all{\\uc2\\u339oe}", layout.format("h\\'all\\oe "));
+ }
+
+ public void testSpecialCharacters() {
+
+ LayoutFormatter layout = new RTFChars();
+
+ assertEquals("\\u243o", layout.format("\\'{o}")); // �
+ assertEquals("\\'f2", layout.format("\\`{o}")); // �
+ assertEquals("\\'f4", layout.format("\\^{o}")); // �
+ assertEquals("\\'f6", layout.format("\\\"{o}")); // �
+ assertEquals("\\u245o", layout.format("\\~{o}")); // �
+ assertEquals("\\u333o", layout.format("\\={o}"));
+ assertEquals("\\u334O", layout.format("\\u{o}"));
+ assertEquals("\\u231c", layout.format("\\c{c}")); // �
+ assertEquals("{\\uc2\\u339oe}", layout.format("\\oe"));
+ assertEquals("{\\uc2\\u338OE}", layout.format("\\OE"));
+ assertEquals("{\\uc2\\u230ae}", layout.format("\\ae")); // �
+ assertEquals("{\\uc2\\u198AE}", layout.format("\\AE")); // �
+
+ assertEquals("", layout.format("\\.{o}")); // ???
+ assertEquals("", layout.format("\\v{o}")); // ???
+ assertEquals("", layout.format("\\H{a}")); // � // ???
+ assertEquals("", layout.format("\\t{oo}"));
+ assertEquals("", layout.format("\\d{o}")); // ???
+ assertEquals("", layout.format("\\b{o}")); // ???
+ assertEquals("", layout.format("\\aa")); // �
+ assertEquals("", layout.format("\\AA")); // �
+ assertEquals("", layout.format("\\o")); // �
+ assertEquals("", layout.format("\\O")); // �
+ assertEquals("", layout.format("\\l"));
+ assertEquals("", layout.format("\\L"));
+ assertEquals("", layout.format("\\ss")); // �
+ assertEquals("", layout.format("?`")); // �
+ assertEquals("", layout.format("!`")); // �
+
+ assertEquals("", layout.format("\\dag"));
+ assertEquals("", layout.format("\\ddag"));
+ assertEquals("", layout.format("\\S")); // �
+ assertEquals("", layout.format("\\P")); // �
+ assertEquals("", layout.format("\\copyright")); // �
+ assertEquals("", layout.format("\\pounds")); // �
+ }
+}
diff --git a/src/java/tests/net/sf/jabref/export/layout/format/AllTests.java b/src/java/tests/net/sf/jabref/export/layout/format/AllTests.java
new file mode 100644
index 0000000..258b14f
--- /dev/null
+++ b/src/java/tests/net/sf/jabref/export/layout/format/AllTests.java
@@ -0,0 +1,36 @@
+package tests.net.sf.jabref.export.layout.format;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+public class AllTests {
+
+ public static Test suite() {
+ TestSuite suite = new TestSuite("Test for test.net.sf.jabref");
+ //$JUnit-BEGIN$
+ suite.addTestSuite(AuthorFirstAbbrLastOxfordCommasTest.class);
+ suite.addTestSuite(AuthorFirstLastCommasTest.class);
+ suite.addTestSuite(AuthorLastFirstAbbreviatorTester.class);
+ suite.addTestSuite(AuthorLastFirstTest.class);
+ suite.addTestSuite(AuthorAndsCommaReplacerTest.class);
+ suite.addTestSuite(AuthorFirstFirstTest.class);
+ suite.addTestSuite(AuthorFirstLastOxfordCommasTest.class);
+ suite.addTestSuite(BibtexNameLayoutFormatterTest.class);
+ suite.addTestSuite(AuthorOrgSciTest.class);
+ suite.addTestSuite(AuthorAbbreviatorTest.class);
+ suite.addTestSuite(CompositeFormatTest.class);
+ suite.addTestSuite(ResolvePDFTest.class);
+ suite.addTestSuite(AuthorAndsReplacerTest.class);
+ suite.addTestSuite(AuthorLastFirstAbbrCommasTest.class);
+ suite.addTestSuite(HTMLParagraphsTest.class);
+ suite.addTestSuite(AuthorLastFirstOxfordCommasTest.class);
+ suite.addTestSuite(AuthorFirstAbbrLastCommasTest.class);
+ suite.addTestSuite(AuthorLastFirstCommasTest.class);
+ suite.addTestSuite(DOICheckTest.class);
+ suite.addTestSuite(AuthorLastFirstAbbrOxfordCommasTest.class);
+ suite.addTestSuite(NoSpaceBetweenAbbreviationsTest.class);
+ //$JUnit-END$
+ return suite;
+ }
+
+}
diff --git a/src/java/tests/net/sf/jabref/export/layout/format/AuthorAbbreviatorTest.java b/src/java/tests/net/sf/jabref/export/layout/format/AuthorAbbreviatorTest.java
new file mode 100644
index 0000000..f9fd39a
--- /dev/null
+++ b/src/java/tests/net/sf/jabref/export/layout/format/AuthorAbbreviatorTest.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2006 Jabref-Team
+ *
+ * All programs in this directory and subdirectories are published under the GNU
+ * General Public License as described below.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Further information about the GNU GPL is available at:
+ * http://www.gnu.org/copyleft/gpl.ja.html
+ *
+ */
+package tests.net.sf.jabref.export.layout.format;
+
+import junit.framework.TestCase;
+import net.sf.jabref.export.layout.LayoutFormatter;
+import net.sf.jabref.export.layout.format.AuthorAbbreviator;
+import net.sf.jabref.export.layout.format.AuthorLastFirstAbbreviator;
+
+/**
+ *
+ * Is the save as the AuthorLastFirstAbbreviator.
+ *
+ * @author $Author: coezbek $
+ * @version $Revision: 1.1 $ ($Date: 2006/08/12 15:36:45 $)
+ *
+ */
+public class AuthorAbbreviatorTest extends TestCase {
+
+ public void testFormat() {
+
+ LayoutFormatter a = new AuthorLastFirstAbbreviator();
+ LayoutFormatter b = new AuthorAbbreviator();
+
+ assertEquals(b.format(""), a.format(""));
+ assertEquals(b.format("Someone, Van Something"), a.format("Someone, Van Something"));
+ assertEquals(b.format("Smith, John"), a.format("Smith, John"));
+ assertEquals(b.format("von Neumann, John and Smith, John and Black Brown, Peter"), a
+ .format("von Neumann, John and Smith, John and Black Brown, Peter"));
+
+ }
+
+}
diff --git a/src/java/tests/net/sf/jabref/export/layout/format/AuthorAndsCommaReplacerTest.java b/src/java/tests/net/sf/jabref/export/layout/format/AuthorAndsCommaReplacerTest.java
new file mode 100644
index 0000000..29189eb
--- /dev/null
+++ b/src/java/tests/net/sf/jabref/export/layout/format/AuthorAndsCommaReplacerTest.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2006 Jabref-Team
+ *
+ * All programs in this directory and subdirectories are published under the GNU
+ * General Public License as described below.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Further information about the GNU GPL is available at:
+ * http://www.gnu.org/copyleft/gpl.ja.html
+ *
+ */
+package tests.net.sf.jabref.export.layout.format;
+
+import junit.framework.TestCase;
+import net.sf.jabref.export.layout.LayoutFormatter;
+import net.sf.jabref.export.layout.format.AuthorAndsCommaReplacer;
+
+/**
+ *
+ * @author $Author: coezbek $
+ * @version $Revision: 1.1 $ ($Date: 2006/08/12 15:36:45 $)
+ *
+ */
+public class AuthorAndsCommaReplacerTest extends TestCase {
+
+ /**
+ * Test method for
+ * {@link net.sf.jabref.export.layout.format.AuthorAndsCommaReplacer#format(java.lang.String)}.
+ */
+ public void testFormat() {
+
+ LayoutFormatter a = new AuthorAndsCommaReplacer();
+
+ // Empty case
+ assertEquals("", a.format(""));
+
+ // Single Names don't change
+ assertEquals("Someone, Van Something", a.format("Someone, Van Something"));
+
+ // Two names just an &
+ assertEquals("John von Neumann & Peter Black Brown",
+ a.format("John von Neumann and Peter Black Brown"));
+
+ // Three names put a comma:
+ assertEquals("von Neumann, John, Smith, John & Black Brown, Peter",
+ a.format("von Neumann, John and Smith, John and Black Brown, Peter"));
+ }
+}
diff --git a/src/java/tests/net/sf/jabref/export/layout/format/AuthorAndsReplacerTest.java b/src/java/tests/net/sf/jabref/export/layout/format/AuthorAndsReplacerTest.java
new file mode 100644
index 0000000..7ee2eaf
--- /dev/null
+++ b/src/java/tests/net/sf/jabref/export/layout/format/AuthorAndsReplacerTest.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2006 Jabref-Team
+ *
+ * All programs in this directory and subdirectories are published under the GNU
+ * General Public License as described below.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Further information about the GNU GPL is available at:
+ * http://www.gnu.org/copyleft/gpl.ja.html
+ *
+ */
+package tests.net.sf.jabref.export.layout.format;
+
+import junit.framework.TestCase;
+import net.sf.jabref.export.layout.LayoutFormatter;
+import net.sf.jabref.export.layout.format.AuthorAndsReplacer;
+
+/**
+ *
+ * @author $Author: coezbek $
+ * @version $Revision: 1.2 $ ($Date: 2006/08/12 15:36:45 $)
+ *
+ */
+public class AuthorAndsReplacerTest extends TestCase {
+
+ /**
+ * Test method for
+ * {@link net.sf.jabref.export.layout.format.AuthorAndsReplacer#format(java.lang.String)}.
+ */
+ public void testFormat() {
+ LayoutFormatter a = new AuthorAndsReplacer();
+
+ // Empty case
+ assertEquals("", a.format(""));
+
+ // Single Names don't change
+ assertEquals("Someone, Van Something", a.format("Someone, Van Something"));
+
+ // Two names just an &
+ assertEquals("John Smith & Black Brown, Peter", a
+ .format("John Smith and Black Brown, Peter"));
+
+ // Three names put a comma:
+ assertEquals("von Neumann, John; Smith, John & Black Brown, Peter", a
+ .format("von Neumann, John and Smith, John and Black Brown, Peter"));
+
+ assertEquals("John von Neumann; John Smith & Peter Black Brown", a
+ .format("John von Neumann and John Smith and Peter Black Brown"));
+ }
+
+}
diff --git a/src/java/tests/net/sf/jabref/export/layout/format/AuthorFirstAbbrLastCommasTest.java b/src/java/tests/net/sf/jabref/export/layout/format/AuthorFirstAbbrLastCommasTest.java
new file mode 100644
index 0000000..a0f86c6
--- /dev/null
+++ b/src/java/tests/net/sf/jabref/export/layout/format/AuthorFirstAbbrLastCommasTest.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2006 Jabref-Team
+ * 2003 Morten O. Alver, Nizar N. Batada
+ *
+ * All programs in this directory and subdirectories are published under the GNU
+ * General Public License as described below.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Further information about the GNU GPL is available at:
+ * http://www.gnu.org/copyleft/gpl.ja.html
+ *
+ */
+package tests.net.sf.jabref.export.layout.format;
+
+import junit.framework.TestCase;
+import net.sf.jabref.export.layout.LayoutFormatter;
+import net.sf.jabref.export.layout.format.AuthorFirstAbbrLastCommas;
+
+/**
+ *
+ * @author $Author: coezbek $
+ * @version $Revision: 1.1 $ ($Date: 2006/08/12 15:36:45 $)
+ *
+ */
+public class AuthorFirstAbbrLastCommasTest extends TestCase {
+
+ public void testFormat() {
+ LayoutFormatter a = new AuthorFirstAbbrLastCommas();
+
+ // Empty case
+ assertEquals("", a.format(""));
+
+ // Single Names
+ assertEquals("V. S. Someone", a.format("Someone, Van Something"));
+
+ // Two names
+ assertEquals("J. von Neumann and P. Black Brown", a
+ .format("John von Neumann and Black Brown, Peter"));
+
+ // Three names
+ assertEquals("J. von Neumann, J. Smith and P. Black Brown", a
+ .format("von Neumann, John and Smith, John and Black Brown, Peter"));
+
+ assertEquals("J. von Neumann, J. Smith and P. Black Brown", a
+ .format("John von Neumann and John Smith and Black Brown, Peter"));
+ }
+
+}
diff --git a/src/java/tests/net/sf/jabref/export/layout/format/AuthorFirstAbbrLastOxfordCommasTest.java b/src/java/tests/net/sf/jabref/export/layout/format/AuthorFirstAbbrLastOxfordCommasTest.java
new file mode 100644
index 0000000..041c99f
--- /dev/null
+++ b/src/java/tests/net/sf/jabref/export/layout/format/AuthorFirstAbbrLastOxfordCommasTest.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2006 Jabref-Team
+ *
+ * All programs in this directory and subdirectories are published under the GNU
+ * General Public License as described below.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Further information about the GNU GPL is available at:
+ * http://www.gnu.org/copyleft/gpl.ja.html
+ *
+ */
+package tests.net.sf.jabref.export.layout.format;
+
+import junit.framework.TestCase;
+import net.sf.jabref.export.layout.LayoutFormatter;
+import net.sf.jabref.export.layout.format.AuthorFirstAbbrLastOxfordCommas;
+
+/**
+ *
+ * @author $Author: coezbek $
+ * @version $Revision: 1.1 $ ($Date: 2006/08/12 15:36:45 $)
+ *
+ */
+public class AuthorFirstAbbrLastOxfordCommasTest extends TestCase {
+
+ /**
+ * Test method for {@link net.sf.jabref.export.layout.format.AuthorFirstAbbrLastOxfordCommas#format(java.lang.String)}.
+ */
+ public void testFormat() {
+ LayoutFormatter a = new AuthorFirstAbbrLastOxfordCommas();
+
+ // Empty case
+ assertEquals("", a.format(""));
+
+ // Single Names
+ assertEquals("V. S. Someone", a.format("Someone, Van Something"));
+
+ // Two names
+ assertEquals("J. von Neumann and P. Black Brown", a
+ .format("John von Neumann and Black Brown, Peter"));
+
+ // Three names
+ assertEquals("J. von Neumann, J. Smith, and P. Black Brown", a
+ .format("von Neumann, John and Smith, John and Black Brown, Peter"));
+
+ assertEquals("J. von Neumann, J. Smith, and P. Black Brown", a
+ .format("John von Neumann and John Smith and Black Brown, Peter"));
+ }
+
+}
diff --git a/src/java/tests/net/sf/jabref/export/layout/format/AuthorFirstFirstTest.java b/src/java/tests/net/sf/jabref/export/layout/format/AuthorFirstFirstTest.java
new file mode 100644
index 0000000..5407197
--- /dev/null
+++ b/src/java/tests/net/sf/jabref/export/layout/format/AuthorFirstFirstTest.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2006 Jabref-Team
+ *
+ * All programs in this directory and subdirectories are published under the GNU
+ * General Public License as described below.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Further information about the GNU GPL is available at:
+ * http://www.gnu.org/copyleft/gpl.ja.html
+ *
+ */
+package tests.net.sf.jabref.export.layout.format;
+
+import junit.framework.TestCase;
+import net.sf.jabref.export.layout.format.AuthorFirstFirst;
+
+/**
+ *
+ * @author $Author: coezbek $
+ * @version $Revision: 1.1 $ ($Date: 2006/08/12 15:36:45 $)
+ *
+ */
+public class AuthorFirstFirstTest extends TestCase {
+
+ /**
+ * Test method for
+ * {@link net.sf.jabref.export.layout.format.AuthorFirstFirst#format(java.lang.String)}.
+ */
+ public void testFormat() {
+ assertEquals("John von Neumann and John Smith and Peter Black Brown, Jr",
+ new AuthorFirstFirst()
+ .format("von Neumann,,John and John Smith and Black Brown, Jr, Peter"));
+ }
+
+}
diff --git a/src/java/tests/net/sf/jabref/export/layout/format/AuthorFirstLastCommasTest.java b/src/java/tests/net/sf/jabref/export/layout/format/AuthorFirstLastCommasTest.java
new file mode 100644
index 0000000..35d741d
--- /dev/null
+++ b/src/java/tests/net/sf/jabref/export/layout/format/AuthorFirstLastCommasTest.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2006 Jabref-Team
+ *
+ * All programs in this directory and subdirectories are published under the GNU
+ * General Public License as described below.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Further information about the GNU GPL is available at:
+ * http://www.gnu.org/copyleft/gpl.ja.html
+ *
+ */
+package tests.net.sf.jabref.export.layout.format;
+
+import junit.framework.TestCase;
+import net.sf.jabref.export.layout.LayoutFormatter;
+import net.sf.jabref.export.layout.format.AuthorFirstLastCommas;
+
+/**
+ *
+ * @author $Author: coezbek $
+ * @version $Revision: 1.1 $ ($Date: 2006/08/12 15:36:45 $)
+ *
+ */
+public class AuthorFirstLastCommasTest extends TestCase {
+
+ /**
+ * Test method for {@link net.sf.jabref.export.layout.format.AuthorFirstLastCommas#format(java.lang.String)}.
+ */
+ public void testFormat() {
+ LayoutFormatter a = new AuthorFirstLastCommas();
+
+ // Empty case
+ assertEquals("", a.format(""));
+
+ // Single Names
+ assertEquals("Van Something Someone", a.format("Someone, Van Something"));
+
+ // Two names
+ assertEquals("John von Neumann and Peter Black Brown", a
+ .format("John von Neumann and Peter Black Brown"));
+
+ // Three names
+ assertEquals("John von Neumann, John Smith and Peter Black Brown", a
+ .format("von Neumann, John and Smith, John and Black Brown, Peter"));
+
+ assertEquals("John von Neumann, John Smith and Peter Black Brown", a
+ .format("John von Neumann and John Smith and Black Brown, Peter"));
+ }
+
+}
diff --git a/src/java/tests/net/sf/jabref/export/layout/format/AuthorFirstLastOxfordCommasTest.java b/src/java/tests/net/sf/jabref/export/layout/format/AuthorFirstLastOxfordCommasTest.java
new file mode 100644
index 0000000..89be3fc
--- /dev/null
+++ b/src/java/tests/net/sf/jabref/export/layout/format/AuthorFirstLastOxfordCommasTest.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2006 Jabref-Team
+ *
+ * All programs in this directory and subdirectories are published under the GNU
+ * General Public License as described below.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Further information about the GNU GPL is available at:
+ * http://www.gnu.org/copyleft/gpl.ja.html
+ *
+ */
+package tests.net.sf.jabref.export.layout.format;
+
+import junit.framework.TestCase;
+import net.sf.jabref.export.layout.LayoutFormatter;
+import net.sf.jabref.export.layout.format.AuthorFirstLastOxfordCommas;
+
+/**
+ *
+ * @author $Author: coezbek $
+ * @version $Revision: 1.1 $ ($Date: 2006/08/12 15:36:45 $)
+ *
+ */
+public class AuthorFirstLastOxfordCommasTest extends TestCase {
+
+ /**
+ * Test method for {@link net.sf.jabref.export.layout.format.AuthorFirstLastOxfordCommas#format(java.lang.String)}.
+ */
+ public void testFormat() {
+ LayoutFormatter a = new AuthorFirstLastOxfordCommas();
+
+ // Empty case
+ assertEquals("", a.format(""));
+
+ // Single Names
+ assertEquals("Van Something Someone", a.format("Someone, Van Something"));
+
+ // Two names
+ assertEquals("John von Neumann and Peter Black Brown", a
+ .format("John von Neumann and Peter Black Brown"));
+
+ // Three names
+ assertEquals("John von Neumann, John Smith, and Peter Black Brown", a
+ .format("von Neumann, John and Smith, John and Black Brown, Peter"));
+
+ assertEquals("John von Neumann, John Smith, and Peter Black Brown", a
+ .format("John von Neumann and John Smith and Black Brown, Peter"));
+ }
+
+
+}
diff --git a/src/java/tests/net/sf/jabref/export/layout/format/AuthorLastFirstAbbrCommasTest.java b/src/java/tests/net/sf/jabref/export/layout/format/AuthorLastFirstAbbrCommasTest.java
new file mode 100644
index 0000000..3188df4
--- /dev/null
+++ b/src/java/tests/net/sf/jabref/export/layout/format/AuthorLastFirstAbbrCommasTest.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2006 Jabref-Team
+ *
+ * All programs in this directory and subdirectories are published under the GNU
+ * General Public License as described below.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Further information about the GNU GPL is available at:
+ * http://www.gnu.org/copyleft/gpl.ja.html
+ *
+ */
+package tests.net.sf.jabref.export.layout.format;
+
+import junit.framework.TestCase;
+import net.sf.jabref.export.layout.LayoutFormatter;
+import net.sf.jabref.export.layout.format.AuthorLastFirstAbbrCommas;
+
+/**
+ *
+ * @author $Author: coezbek $
+ * @version $Revision: 1.1 $ ($Date: 2006/08/12 15:36:45 $)
+ *
+ */
+public class AuthorLastFirstAbbrCommasTest extends TestCase {
+
+ /**
+ * Test method for {@link net.sf.jabref.export.layout.format.AuthorLastFirstAbbrCommas#format(java.lang.String)}.
+ */
+ public void testFormat() {
+ LayoutFormatter a = new AuthorLastFirstAbbrCommas();
+
+ // Empty case
+ assertEquals("", a.format(""));
+
+ // Single Names
+ assertEquals("Someone, V. S.", a.format("Van Something Someone"));
+
+ // Two names
+ assertEquals("von Neumann, J. and Black Brown, P.", a
+ .format("John von Neumann and Black Brown, Peter"));
+
+ // Three names
+ assertEquals("von Neumann, J., Smith, J. and Black Brown, P.", a
+ .format("von Neumann, John and Smith, John and Black Brown, Peter"));
+
+ assertEquals("von Neumann, J., Smith, J. and Black Brown, P.", a
+ .format("John von Neumann and John Smith and Black Brown, Peter"));
+
+ }
+
+}
diff --git a/src/java/tests/net/sf/jabref/export/layout/format/AuthorLastFirstAbbrOxfordCommasTest.java b/src/java/tests/net/sf/jabref/export/layout/format/AuthorLastFirstAbbrOxfordCommasTest.java
new file mode 100644
index 0000000..83682e7
--- /dev/null
+++ b/src/java/tests/net/sf/jabref/export/layout/format/AuthorLastFirstAbbrOxfordCommasTest.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2006 Jabref-Team
+ *
+ * All programs in this directory and subdirectories are published under the GNU
+ * General Public License as described below.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Further information about the GNU GPL is available at:
+ * http://www.gnu.org/copyleft/gpl.ja.html
+ *
+ */
+package tests.net.sf.jabref.export.layout.format;
+
+import junit.framework.TestCase;
+import net.sf.jabref.export.layout.LayoutFormatter;
+import net.sf.jabref.export.layout.format.AuthorLastFirstAbbrOxfordCommas;
+
+/**
+ *
+ * @author $Author: coezbek $
+ * @version $Revision: 1.1 $ ($Date: 2006/08/12 15:36:45 $)
+ *
+ */
+public class AuthorLastFirstAbbrOxfordCommasTest extends TestCase {
+
+ /**
+ * Test method for {@link net.sf.jabref.export.layout.format.AuthorLastFirstAbbrOxfordCommas#format(java.lang.String)}.
+ */
+ public void testFormat() {
+ LayoutFormatter a = new AuthorLastFirstAbbrOxfordCommas();
+
+ // Empty case
+ assertEquals("", a.format(""));
+
+ // Single Names
+ assertEquals("Someone, V. S.", a.format("Van Something Someone"));
+
+ // Two names
+ assertEquals("von Neumann, J. and Black Brown, P.", a
+ .format("John von Neumann and Black Brown, Peter"));
+
+ // Three names
+ assertEquals("von Neumann, J., Smith, J., and Black Brown, P.", a
+ .format("von Neumann, John and Smith, John and Black Brown, Peter"));
+
+ assertEquals("von Neumann, J., Smith, J., and Black Brown, P.", a
+ .format("John von Neumann and John Smith and Black Brown, Peter"));
+ }
+
+}
diff --git a/src/java/tests/net/sf/jabref/export/layout/format/AuthorLastFirstAbbreviatorTester.java b/src/java/tests/net/sf/jabref/export/layout/format/AuthorLastFirstAbbreviatorTester.java
index 8d0e61b..f6863a7 100644
--- a/src/java/tests/net/sf/jabref/export/layout/format/AuthorLastFirstAbbreviatorTester.java
+++ b/src/java/tests/net/sf/jabref/export/layout/format/AuthorLastFirstAbbreviatorTester.java
@@ -1,8 +1,9 @@
package tests.net.sf.jabref.export.layout.format;
-import net.sf.jabref.export.layout.format.AuthorLastFirstAbbreviator;
import junit.framework.Assert;
import junit.framework.TestCase;
+import net.sf.jabref.export.layout.LayoutFormatter;
+import net.sf.jabref.export.layout.format.AuthorLastFirstAbbreviator;
/**
* Test case that verifies the functionalities of the
@@ -45,7 +46,7 @@ public class AuthorLastFirstAbbreviatorTester extends TestCase {
String result = ab.format(name);
//Expected Results:
- String expectedResult = "Lastname, N.M.";
+ String expectedResult = "Lastname, N. M.";
//Verifies the functionality:
Assert.assertEquals("Abbreviator Test", result, expectedResult);
@@ -64,7 +65,7 @@ public class AuthorLastFirstAbbreviatorTester extends TestCase {
String result = ab.format(name);
//Expected Results:
- String expectedResult = "Lastname, N.M. and Sobrenome, N.N.";
+ String expectedResult = "Lastname, N. M. and Sobrenome, N. N.";
//Verifies the functionality:
Assert.assertEquals("Abbreviator Test", result, expectedResult);
@@ -77,11 +78,10 @@ public class AuthorLastFirstAbbreviatorTester extends TestCase {
* Ex: Lastname, Name Middlename
*/
public void testTwoAuthorsBadFormating() {
- // String name = new String("Lastname, Name Middlename and Nome Nomedomeio Sobrenome");
+ String name = new String("Lastname, Name Middlename and Nome Nomedomeio Sobrenome");
- fail();
- // @TODO: How should a Formatter fail?
- // assertEquals("Author names must be formatted \"Last, First\" or \"Last, Jr., First\" before formatting with AuthorLastFirstAbbreviator", abbreviate(name));
+ // Formatters should not fail but return the given string (if they can).
+ assertEquals(name, abbreviate(name));
}
/**
@@ -90,9 +90,21 @@ public class AuthorLastFirstAbbreviatorTester extends TestCase {
*/
public void testJrAuthor(){
String name = "Other, Jr., Anthony N.";
- assertEquals("Other, A.N.", abbreviate(name));
+ assertEquals("Other, A. N.", abbreviate(name));
}
+ public void testFormat() {
+
+ LayoutFormatter a = new AuthorLastFirstAbbreviator();
+
+ assertEquals("", a.format(""));
+ assertEquals("Someone, V. S.", a.format("Someone, Van Something"));
+ assertEquals("Smith, J.", a.format("Smith, John"));
+ assertEquals("von Neumann, J. and Smith, J. and Black Brown, P.",
+ a.format("von Neumann, John and Smith, John and Black Brown, Peter"));
+
+ }
+
protected String abbreviate(String name) {
return (new AuthorLastFirstAbbreviator()).format(name);
}
diff --git a/src/java/tests/net/sf/jabref/export/layout/format/AuthorLastFirstCommasTest.java b/src/java/tests/net/sf/jabref/export/layout/format/AuthorLastFirstCommasTest.java
new file mode 100644
index 0000000..6a88ef0
--- /dev/null
+++ b/src/java/tests/net/sf/jabref/export/layout/format/AuthorLastFirstCommasTest.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2006 Jabref-Team
+ *
+ * All programs in this directory and subdirectories are published under the GNU
+ * General Public License as described below.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Further information about the GNU GPL is available at:
+ * http://www.gnu.org/copyleft/gpl.ja.html
+ *
+ */
+package tests.net.sf.jabref.export.layout.format;
+
+import junit.framework.TestCase;
+import net.sf.jabref.export.layout.LayoutFormatter;
+import net.sf.jabref.export.layout.format.AuthorLastFirstCommas;
+
+/**
+ *
+ * @author $Author: coezbek $
+ * @version $Revision: 1.1 $ ($Date: 2006/08/12 15:36:45 $)
+ *
+ */
+public class AuthorLastFirstCommasTest extends TestCase {
+
+ /**
+ * Test method for
+ * {@link net.sf.jabref.export.layout.format.AuthorLastFirstCommas#format(java.lang.String)}.
+ */
+ public void testFormat() {
+
+ LayoutFormatter a = new AuthorLastFirstCommas();
+
+ // Empty case
+ assertEquals("", a.format(""));
+
+ // Single Names
+ assertEquals("Someone, Van Something", a.format("Van Something Someone"));
+
+ // Two names
+ assertEquals("von Neumann, John and Black Brown, Peter", a
+ .format("John von Neumann and Black Brown, Peter"));
+
+ // Three names
+ assertEquals("von Neumann, John, Smith, John and Black Brown, Peter", a
+ .format("von Neumann, John and Smith, John and Black Brown, Peter"));
+
+ assertEquals("von Neumann, John, Smith, John and Black Brown, Peter", a
+ .format("John von Neumann and John Smith and Black Brown, Peter"));
+ }
+
+}
diff --git a/src/java/tests/net/sf/jabref/export/layout/format/AuthorLastFirstOxfordCommasTest.java b/src/java/tests/net/sf/jabref/export/layout/format/AuthorLastFirstOxfordCommasTest.java
new file mode 100644
index 0000000..f9bf854
--- /dev/null
+++ b/src/java/tests/net/sf/jabref/export/layout/format/AuthorLastFirstOxfordCommasTest.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2006 Jabref-Team
+ *
+ * All programs in this directory and subdirectories are published under the GNU
+ * General Public License as described below.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Further information about the GNU GPL is available at:
+ * http://www.gnu.org/copyleft/gpl.ja.html
+ *
+ */
+package tests.net.sf.jabref.export.layout.format;
+
+import junit.framework.TestCase;
+import net.sf.jabref.export.layout.LayoutFormatter;
+import net.sf.jabref.export.layout.format.AuthorLastFirstOxfordCommas;
+
+/**
+ *
+ * @author $Author: coezbek $
+ * @version $Revision: 1.1 $ ($Date: 2006/08/12 15:36:45 $)
+ *
+ */
+public class AuthorLastFirstOxfordCommasTest extends TestCase {
+
+ /**
+ * Test method for {@link net.sf.jabref.export.layout.format.AuthorLastFirstOxfordCommas#format(java.lang.String)}.
+ */
+ public void testFormat() {
+ LayoutFormatter a = new AuthorLastFirstOxfordCommas();
+
+ // Empty case
+ assertEquals("", a.format(""));
+
+ // Single Names
+ assertEquals("Someone, Van Something", a.format("Van Something Someone"));
+
+ // Two names
+ assertEquals("von Neumann, John and Black Brown, Peter", a
+ .format("John von Neumann and Black Brown, Peter"));
+
+ // Three names
+ assertEquals("von Neumann, John, Smith, John, and Black Brown, Peter", a
+ .format("von Neumann, John and Smith, John and Black Brown, Peter"));
+
+ assertEquals("von Neumann, John, Smith, John, and Black Brown, Peter", a
+ .format("John von Neumann and John Smith and Black Brown, Peter"));
+ }
+
+}
diff --git a/src/java/tests/net/sf/jabref/export/layout/format/AuthorLastFirstTest.java b/src/java/tests/net/sf/jabref/export/layout/format/AuthorLastFirstTest.java
new file mode 100644
index 0000000..102c0d2
--- /dev/null
+++ b/src/java/tests/net/sf/jabref/export/layout/format/AuthorLastFirstTest.java
@@ -0,0 +1,30 @@
+package tests.net.sf.jabref.export.layout.format;
+
+import junit.framework.TestCase;
+import net.sf.jabref.export.layout.LayoutFormatter;
+import net.sf.jabref.export.layout.format.AuthorLastFirst;
+
+public class AuthorLastFirstTest extends TestCase {
+
+ public void testFormat() {
+ LayoutFormatter a = new AuthorLastFirst();
+
+ // Empty case
+ assertEquals("", a.format(""));
+
+ // Single Names
+ assertEquals("Someone, Van Something", a.format("Van Something Someone"));
+
+ // Two names
+ assertEquals("von Neumann, John and Black Brown, Peter", a
+ .format("John von Neumann and Black Brown, Peter"));
+
+ // Three names
+ assertEquals("von Neumann, John and Smith, John and Black Brown, Peter", a
+ .format("von Neumann, John and Smith, John and Black Brown, Peter"));
+
+ assertEquals("von Neumann, John and Smith, John and Black Brown, Peter", a
+ .format("John von Neumann and John Smith and Black Brown, Peter"));
+ }
+
+}
diff --git a/src/java/tests/net/sf/jabref/export/layout/format/AuthorOrgSciTest.java b/src/java/tests/net/sf/jabref/export/layout/format/AuthorOrgSciTest.java
new file mode 100644
index 0000000..dd6b1b6
--- /dev/null
+++ b/src/java/tests/net/sf/jabref/export/layout/format/AuthorOrgSciTest.java
@@ -0,0 +1,33 @@
+package tests.net.sf.jabref.export.layout.format;
+
+import junit.framework.TestCase;
+import net.sf.jabref.export.layout.LayoutFormatter;
+import net.sf.jabref.export.layout.format.AuthorOrgSci;
+import net.sf.jabref.export.layout.format.CompositeFormat;
+import net.sf.jabref.export.layout.format.NoSpaceBetweenAbbreviations;
+
+public class AuthorOrgSciTest extends TestCase {
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ public void testOrgSci(){
+ LayoutFormatter f = new AuthorOrgSci();
+
+ assertEquals("Flynn, J., S. Gartska", f.format("John Flynn and Sabine Gartska"));
+ assertEquals("Garvin, D. A.", f.format("David A. Garvin"));
+ assertEquals("Makridakis, S., S. C. Wheelwright, V. E. McGee", f.format("Sa Makridakis and Sa Ca Wheelwright and Va Ea McGee"));
+
+ }
+ public void testOrgSciPlusAbbreviation(){
+ LayoutFormatter f = new CompositeFormat(new AuthorOrgSci(), new NoSpaceBetweenAbbreviations());
+ assertEquals("Flynn, J., S. Gartska", f.format("John Flynn and Sabine Gartska"));
+ assertEquals("Garvin, D.A.", f.format("David A. Garvin"));
+ assertEquals("Makridakis, S., S.C. Wheelwright, V.E. McGee", f.format("Sa Makridakis and Sa Ca Wheelwright and Va Ea McGee"));
+ }
+}
diff --git a/src/java/tests/net/sf/jabref/export/layout/format/BibtexNameLayoutFormatterTest.java b/src/java/tests/net/sf/jabref/export/layout/format/BibtexNameLayoutFormatterTest.java
new file mode 100644
index 0000000..8cc0d0f
--- /dev/null
+++ b/src/java/tests/net/sf/jabref/export/layout/format/BibtexNameLayoutFormatterTest.java
@@ -0,0 +1,61 @@
+package tests.net.sf.jabref.export.layout.format;
+
+import junit.framework.TestCase;
+import net.sf.jabref.export.layout.LayoutFormatter;
+import net.sf.jabref.export.layout.format.AuthorLastFirstCommas;
+import net.sf.jabref.export.layout.format.NameFormat;
+
+public class BibtexNameLayoutFormatterTest extends TestCase {
+
+ public void testFormatStringStringBibtexEntry() {
+
+ NameFormat l = new NameFormat();
+
+ assertEquals("Doe", l.format("Joe Doe", "1@*@{ll}", null));
+
+ assertEquals("moremoremoremore", l.format("Joe Doe and Mary Jane and Bruce Bar and Arthur Kay",
+ "1@*@{ll}@@2 at 1..1@{ff}{ll}@2..2@ and {ff}{last}@@*@*@more", null));
+
+ assertEquals("Doe", l.format("Joe Doe",
+ "1@*@{ll}@@2 at 1..1@{ff}{ll}@2..2@ and {ff}{last}@@*@*@more", null));
+
+ assertEquals("JoeDoe and MaryJ", l.format("Joe Doe and Mary Jane",
+ "1@*@{ll}@@2 at 1..1@{ff}{ll}@2..2@ and {ff}{l}@@*@*@more", null));
+
+ assertEquals("Doe, Joe and Jane, M. and Kamp, J.~A.", l.format("Joe Doe and Mary Jane and John Arthur van Kamp",
+ "1@*@{ll}, {ff}@@*@1@{ll}, {ff}@2..-1@ and {ll}, {f}.", null));
+
+ assertEquals("Doe Joe and Jane, M. and Kamp, J.~A.", l.format("Joe Doe and Mary Jane and John Arthur van Kamp",
+ "1@*@{ll}, {ff}@@*@1@{ll} {ff}@2..-1@ and {ll}, {f}.", null));
+
+ }
+
+ public void testFormat() {
+
+ NameFormat a = new NameFormat();
+
+ // Empty case
+ assertEquals("", a.format(""));
+
+ String formatString = "1 at 1@{vv }{ll}{ ff}@@2 at 1@{vv }{ll}{ ff}@2@ and {vv }{ll}{, ff}@@*@1@{vv }{ll}{ ff}@2..-2@, {vv }{ll}{, ff}@-1@ and {vv }{ll}{, ff}";
+
+ // Single Names
+ assertEquals("Vandekamp Mary~Ann", a.format("Mary Ann Vandekamp", formatString, null));
+
+ // Two names
+ assertEquals("von Neumann John and Black~Brown, Peter", a
+ .format("John von Neumann and Black Brown, Peter",formatString, null));
+
+ // Three names
+ assertEquals("von Neumann John, Smith, John and Black~Brown, Peter", a
+ .format("von Neumann, John and Smith, John and Black Brown, Peter", formatString, null));
+
+ assertEquals("von Neumann John, Smith, John and Black~Brown, Peter", a
+ .format("John von Neumann and John Smith and Black Brown, Peter", formatString, null));
+
+ // Four names
+ assertEquals("von Neumann John, Smith, John, Vandekamp, Mary~Ann and Black~Brown, Peter", a
+ .format("von Neumann, John and Smith, John and Vandekamp, Mary Ann and Black Brown, Peter", formatString, null));
+ }
+
+}
diff --git a/src/java/tests/net/sf/jabref/export/layout/format/CompositeFormatTest.java b/src/java/tests/net/sf/jabref/export/layout/format/CompositeFormatTest.java
new file mode 100644
index 0000000..e4ca920
--- /dev/null
+++ b/src/java/tests/net/sf/jabref/export/layout/format/CompositeFormatTest.java
@@ -0,0 +1,60 @@
+package tests.net.sf.jabref.export.layout.format;
+
+import junit.framework.TestCase;
+import net.sf.jabref.export.layout.LayoutFormatter;
+import net.sf.jabref.export.layout.format.AuthorOrgSci;
+import net.sf.jabref.export.layout.format.CompositeFormat;
+import net.sf.jabref.export.layout.format.NoSpaceBetweenAbbreviations;
+
+public class CompositeFormatTest extends TestCase {
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ public void testComposite() {
+
+ {
+ LayoutFormatter f = new CompositeFormat();
+ assertEquals("No Change", f.format("No Change"));
+ }
+ {
+ LayoutFormatter f = new CompositeFormat(new LayoutFormatter[]{new LayoutFormatter(){
+
+ public String format(String fieldText) {
+ return fieldText + fieldText;
+ }
+
+ }, new LayoutFormatter(){
+
+ public String format(String fieldText) {
+ return "A" + fieldText;
+ }
+
+ }, new LayoutFormatter(){
+
+ public String format(String fieldText) {
+ return "B" + fieldText;
+ }
+
+ }});
+
+ assertEquals("BAff", f.format("f"));
+ }
+
+ {
+ LayoutFormatter f = new CompositeFormat(new AuthorOrgSci(),
+ new NoSpaceBetweenAbbreviations());
+ LayoutFormatter first = new AuthorOrgSci();
+ LayoutFormatter second = new NoSpaceBetweenAbbreviations();
+
+ assertEquals(second.format(first.format("John Flynn and Sabine Gartska")), f.format("John Flynn and Sabine Gartska"));
+ assertEquals(second.format(first.format("Sa Makridakis and Sa Ca Wheelwright and Va Ea McGee")), f.format("Sa Makridakis and Sa Ca Wheelwright and Va Ea McGee"));
+ }
+ }
+
+}
diff --git a/src/java/tests/net/sf/jabref/export/layout/format/DOICheckTest.java b/src/java/tests/net/sf/jabref/export/layout/format/DOICheckTest.java
new file mode 100644
index 0000000..dceb88c
--- /dev/null
+++ b/src/java/tests/net/sf/jabref/export/layout/format/DOICheckTest.java
@@ -0,0 +1,37 @@
+package tests.net.sf.jabref.export.layout.format;
+
+import junit.framework.TestCase;
+import net.sf.jabref.export.layout.LayoutFormatter;
+import net.sf.jabref.export.layout.format.DOICheck;
+
+public class DOICheckTest extends TestCase {
+
+ public void testFormat() {
+ LayoutFormatter lf = new DOICheck();
+
+ assertEquals("", lf.format(""));
+ assertEquals(null, lf.format(null));
+
+ assertEquals("http://dx.doi.org/10.1000/ISBN1-900512-44-0", lf
+ .format("10.1000/ISBN1-900512-44-0"));
+ assertEquals("http://dx.doi.org/10.1000/ISBN1-900512-44-0", lf
+ .format("http://dx.doi.org/10.1000/ISBN1-900512-44-0"));
+
+ assertEquals("http://doi.acm.org/10.1000/ISBN1-900512-44-0", lf
+ .format("http://doi.acm.org/10.1000/ISBN1-900512-44-0"));
+
+ assertEquals("http://doi.acm.org/10.1145/354401.354407", lf
+ .format("http://doi.acm.org/10.1145/354401.354407"));
+ assertEquals("http://dx.doi.org/10.1145/354401.354407", lf.format("10.1145/354401.354407"));
+
+ // Does not work if the string does not start with a 10
+ assertEquals("/10.1145/354401.354407", lf.format("/10.1145/354401.354407"));
+
+ // Obviously a wrong doi, but we still accept it.
+ assertEquals("http://dx.doi.org/10", lf.format("10"));
+
+ // Obviously a wrong doi, but we still accept it.
+ assertEquals("1", lf.format("1"));
+ }
+
+}
diff --git a/src/java/tests/net/sf/jabref/export/layout/format/HTMLParagraphsTest.java b/src/java/tests/net/sf/jabref/export/layout/format/HTMLParagraphsTest.java
new file mode 100644
index 0000000..f639774
--- /dev/null
+++ b/src/java/tests/net/sf/jabref/export/layout/format/HTMLParagraphsTest.java
@@ -0,0 +1,21 @@
+package tests.net.sf.jabref.export.layout.format;
+
+import junit.framework.TestCase;
+import net.sf.jabref.export.layout.LayoutFormatter;
+import net.sf.jabref.export.layout.format.HTMLParagraphs;
+
+public class HTMLParagraphsTest extends TestCase {
+
+ public void testFormat() {
+
+ LayoutFormatter f = new HTMLParagraphs();
+
+ assertEquals("", f.format(""));
+ assertEquals("<p>\nHello\n</p>", f.format("Hello"));
+ assertEquals("<p>\nHello\nWorld\n</p>", f.format("Hello\nWorld"));
+ assertEquals("<p>\nHello World\n</p>\n<p>\nWhat a lovely day\n</p>", f.format("Hello World\n \nWhat a lovely day\n"));
+ assertEquals("<p>\nHello World\n</p>\n<p>\nCould not be any better\n</p>\n<p>\nWhat a lovely day\n</p>", f.format("Hello World\n \n\nCould not be any better\n\nWhat a lovely day\n"));
+
+ }
+
+}
diff --git a/src/java/tests/net/sf/jabref/export/layout/format/NoSpaceBetweenAbbreviationsTest.java b/src/java/tests/net/sf/jabref/export/layout/format/NoSpaceBetweenAbbreviationsTest.java
new file mode 100644
index 0000000..27db88f
--- /dev/null
+++ b/src/java/tests/net/sf/jabref/export/layout/format/NoSpaceBetweenAbbreviationsTest.java
@@ -0,0 +1,26 @@
+package tests.net.sf.jabref.export.layout.format;
+
+import junit.framework.TestCase;
+import net.sf.jabref.export.layout.LayoutFormatter;
+import net.sf.jabref.export.layout.format.NoSpaceBetweenAbbreviations;
+
+public class NoSpaceBetweenAbbreviationsTest extends TestCase {
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ public void testFormat() {
+ LayoutFormatter f = new NoSpaceBetweenAbbreviations();
+ assertEquals("", f.format(""));
+ assertEquals("John Meier", f.format("John Meier"));
+ assertEquals("J.F. Kennedy", f.format("J. F. Kennedy"));
+ assertEquals("J.R.R. Tolkien", f.format("J. R. R. Tolkien"));
+ assertEquals("J.R.R. Tolkien and J.F. Kennedy", f.format("J. R. R. Tolkien and J. F. Kennedy"));
+ }
+
+}
diff --git a/src/java/tests/net/sf/jabref/export/layout/format/ResolvePDFTest.java b/src/java/tests/net/sf/jabref/export/layout/format/ResolvePDFTest.java
new file mode 100644
index 0000000..b3ce0e1
--- /dev/null
+++ b/src/java/tests/net/sf/jabref/export/layout/format/ResolvePDFTest.java
@@ -0,0 +1,52 @@
+package tests.net.sf.jabref.export.layout.format;
+
+import java.io.File;
+import java.net.URI;
+import java.net.URISyntaxException;
+
+import net.sf.jabref.export.layout.LayoutFormatter;
+import net.sf.jabref.export.layout.format.ResolvePDF;
+import tests.net.sf.jabref.FileBasedTestCase;
+
+/**
+ * Testing the PDF resolver.
+ *
+ * @author $Author: coezbek $
+ * @version $Revision: 1.1 $ ($Date: 2006/08/27 21:04:27 $)
+ *
+ */
+public class ResolvePDFTest extends FileBasedTestCase {
+
+ public void setUp() throws Exception {
+ super.setUp();
+ }
+
+ public void tearDown() {
+ super.tearDown();
+ }
+
+ public void testFormat() throws URISyntaxException {
+ LayoutFormatter pdf = new ResolvePDF();
+
+ assertEquals("", pdf.format(""));
+
+ /*
+ * Check one that will be found
+ */
+ String result = pdf.format("Organization Science\\HipKro03 - Hello.pdf");
+ assertTrue(result.startsWith("file:/"));
+
+ assertTrue(result.endsWith("/Organization%20Science/HipKro03%20-%20Hello.pdf"));
+
+ // Should not contain a backslash:
+ assertEquals(-1, result.indexOf('\\'));
+
+ assertTrue(new File(new URI(result)).exists());
+
+ /*
+ * And one that is not to be found
+ */
+ result = pdf.format("Organization Science/Does not exist.pdf");
+ assertEquals("Organization Science/Does not exist.pdf", result);
+ }
+}
diff --git a/src/java/tests/net/sf/jabref/imports/AllTests.java b/src/java/tests/net/sf/jabref/imports/AllTests.java
new file mode 100644
index 0000000..01fa995
--- /dev/null
+++ b/src/java/tests/net/sf/jabref/imports/AllTests.java
@@ -0,0 +1,19 @@
+package tests.net.sf.jabref.imports;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+public class AllTests {
+
+ public static Test suite() {
+ TestSuite suite = new TestSuite("Test for tests.net.sf.jabref.imports");
+ //$JUnit-BEGIN$
+ suite.addTestSuite(IsiImporterTest.class);
+ suite.addTestSuite(AutoImportTest.class);
+ suite.addTestSuite(BibtexParserTest.class);
+ suite.addTestSuite(OAI2ImportTest.class);
+ //$JUnit-END$
+ return suite;
+ }
+
+}
diff --git a/src/java/tests/net/sf/jabref/imports/AutoImportTest.java b/src/java/tests/net/sf/jabref/imports/AutoImportTest.java
new file mode 100644
index 0000000..97e87fb
--- /dev/null
+++ b/src/java/tests/net/sf/jabref/imports/AutoImportTest.java
@@ -0,0 +1,11 @@
+package tests.net.sf.jabref.imports;
+
+import junit.framework.TestCase;
+
+public class AutoImportTest extends TestCase {
+
+ public void testAutoImport(){
+ fail();
+ }
+
+}
diff --git a/src/java/tests/net/sf/jabref/imports/BibtexParserTest.java b/src/java/tests/net/sf/jabref/imports/BibtexParserTest.java
new file mode 100644
index 0000000..f3aeb9f
--- /dev/null
+++ b/src/java/tests/net/sf/jabref/imports/BibtexParserTest.java
@@ -0,0 +1,216 @@
+package tests.net.sf.jabref.imports;
+
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.Collection;
+
+import junit.framework.TestCase;
+import net.sf.jabref.BibtexEntry;
+import net.sf.jabref.BibtexEntryType;
+import net.sf.jabref.KeyCollisionException;
+import net.sf.jabref.imports.BibtexParser;
+import net.sf.jabref.imports.ParserResult;
+
+/**
+ * Test the BibtexParser
+ *
+ * @version $revision: 1.1$ $date: $
+ *
+ * @author Christopher Oezbek <oezi at oezi.de>
+ */
+public class BibtexParserTest extends TestCase {
+
+ public void testParseReader() throws IOException {
+
+ ParserResult result = BibtexParser.parse(new StringReader(
+ "@article{test,author={Ed von Test}}"));
+
+ Collection c = result.getDatabase().getEntries();
+ assertEquals(1, c.size());
+
+ BibtexEntry e = (BibtexEntry) c.iterator().next();
+ assertEquals("test", e.getCiteKey());
+ assertEquals(2, e.getAllFields().length);
+ Object[] o = e.getAllFields();
+ assertTrue(o[0].toString().equals("author") || o[1].toString().equals("author"));
+ assertEquals("Ed von Test", e.getField("author"));
+ }
+
+ public void testBibtexParser() {
+ try {
+ BibtexParser p = new BibtexParser(null);
+ fail("Should not accept null.");
+ } catch (NullPointerException npe) {
+
+ }
+ }
+
+ public void testIsRecognizedFormat() throws IOException {
+ assertTrue(BibtexParser
+ .isRecognizedFormat(new StringReader(
+ "This file was created with JabRef 2.1 beta 2."
+ + "\n"
+ + "Encoding: Cp1252"
+ + "\n"
+ + ""
+ + "\n"
+ + "@INPROCEEDINGS{CroAnnHow05,"
+ + "\n"
+ + " author = {Crowston, K. and Annabi, H. and Howison, J. and Masango, C.},"
+ + "\n"
+ + " title = {Effective work practices for floss development: A model and propositions},"
+ + "\n"
+ + " booktitle = {Hawaii International Conference On System Sciences (HICSS)},"
+ + "\n" + " year = {2005}," + "\n" + " owner = {oezbek}," + "\n"
+ + " timestamp = {2006.05.29}," + "\n"
+ + " url = {http://james.howison.name/publications.html}" + "\n" + "}))")));
+
+ assertTrue(BibtexParser.isRecognizedFormat(new StringReader(
+ "This file was created with JabRef 2.1 beta 2." + "\n" + "Encoding: Cp1252" + "\n")));
+
+ assertTrue(BibtexParser
+ .isRecognizedFormat(new StringReader(
+ "@INPROCEEDINGS{CroAnnHow05,"
+ + "\n"
+ + " author = {Crowston, K. and Annabi, H. and Howison, J. and Masango, C.},"
+ + "\n"
+ + " title = {Effective work practices for floss development: A model and propositions},"
+ + "\n"
+ + " booktitle = {Hawaii International Conference On System Sciences (HICSS)},"
+ + "\n" + " year = {2005}," + "\n" + " owner = {oezbek}," + "\n"
+ + " timestamp = {2006.05.29}," + "\n"
+ + " url = {http://james.howison.name/publications.html}" + "\n" + "}))")));
+
+ assertFalse(BibtexParser
+ .isRecognizedFormat(new StringReader(
+ " author = {Crowston, K. and Annabi, H. and Howison, J. and Masango, C.},"
+ + "\n"
+ + " title = {Effective work practices for floss development: A model and propositions},"
+ + "\n"
+ + " booktitle = {Hawaii International Conference On System Sciences (HICSS)},"
+ + "\n" + " year = {2005}," + "\n" + " owner = {oezbek}," + "\n"
+ + " timestamp = {2006.05.29}," + "\n"
+ + " url = {http://james.howison.name/publications.html}" + "\n" + "}))")));
+
+ assertFalse(BibtexParser.isRecognizedFormat(new StringReader(
+ "This was created with JabRef 2.1 beta 2." + "\n" + "Encoding: Cp1252" + "\n")));
+ }
+
+ public void testParse() throws IOException {
+
+ // Test Standard parsing
+ BibtexParser parser = new BibtexParser(new StringReader(
+ "@article{test,author={Ed von Test}}"));
+ ParserResult result = parser.parse();
+
+ Collection c = result.getDatabase().getEntries();
+ assertEquals(1, c.size());
+
+ BibtexEntry e = (BibtexEntry) c.iterator().next();
+ assertEquals("test", e.getCiteKey());
+ assertEquals(2, e.getAllFields().length);
+ Object[] o = e.getAllFields();
+ assertTrue(o[0].toString().equals("author") || o[1].toString().equals("author"));
+ assertEquals("Ed von Test", e.getField("author"));
+
+ // Calling parse again will return the same result
+ assertEquals(result, parser.parse());
+ }
+
+ public void testParse2() throws IOException {
+
+ BibtexParser parser = new BibtexParser(new StringReader(
+ "@article{test,author={Ed von Test}}"));
+ ParserResult result = parser.parse();
+
+ BibtexEntry e = new BibtexEntry("", BibtexEntryType.ARTICLE);
+ e.setField("author", "Ed von Test");
+ e.setField("bibtexkey", "test");
+
+ Collection c = result.getDatabase().getEntries();
+ assertEquals(1, c.size());
+
+ BibtexEntry e2 = (BibtexEntry) c.iterator().next();
+
+ assertNotSame(e.getId(), e2.getId());
+
+ Object[] o = e.getAllFields();
+ for (int i = 0; i < o.length; i++){
+ if (!e.getField(o[i].toString()).equals(e2.getField(o[i].toString()))){
+ fail("e and e2 differ in field " + o[i].toString());
+ }
+ }
+ }
+
+
+ /**
+ * Test for [ 1594123 ] Failure to import big numbers
+ *
+ * Issue Reported by Ulf Martin.
+ *
+ * @throws IOException
+ */
+ public void testBigNumbers() throws IOException {
+
+ ParserResult result = BibtexParser.parse(new StringReader("@article{canh05,"
+ + "isbn = 1234567890123456789,\n"
+ + "isbn2 = {1234567890123456789},\n"
+ + "small = 1234,\n"
+ + "}"));
+
+ Collection c = result.getDatabase().getEntries();
+ BibtexEntry e = (BibtexEntry) c.iterator().next();
+
+ assertEquals("1234567890123456789", (String)e.getField("isbn"));
+ assertEquals("1234567890123456789", (String)e.getField("isbn2"));
+ assertEquals("1234", (String)e.getField("small"));
+ }
+
+ public void testBigNumbers2() throws IOException {
+
+
+ ParserResult result = BibtexParser.parse(new StringReader("" +
+ "@string{bourdieu = {Bourdieu, Pierre}}" +
+ "@book{bourdieu-2002-questions-sociologie, " +
+ " Address = {Paris}," +
+ " Author = bourdieu," +
+ " Isbn = 2707318256," +
+ " Publisher = {Minuit}," +
+ " Title = {Questions de sociologie}," +
+ " Year = 2002" +
+ "}"));
+
+ Collection c = result.getDatabase().getEntries();
+ assertEquals(1, c.size());
+
+ BibtexEntry e = (BibtexEntry) c.iterator().next();
+
+ assertEquals("bourdieu-2002-questions-sociologie", e.getCiteKey());
+ assertEquals(BibtexEntryType.BOOK, e.getType());
+ assertEquals("2707318256", (String)e.getField("isbn"));
+ assertEquals("Paris", (String)e.getField("address"));
+ assertEquals("Minuit", (String)e.getField("publisher"));
+ assertEquals("Questions de sociologie", (String)e.getField("Title"));
+ assertEquals("#bourdieu#", (String)e.getField("Author"));
+ assertEquals("2002", (String)e.getField("Year"));
+ }
+
+ public void testNewlineHandling() throws IOException {
+
+ ParserResult result = BibtexParser.parse(new StringReader("@article{canh05,"
+ + "title = {\nHallo \nWorld \nthis \n is\n\nnot \n\nan \n\n exercise \n \n.\n \n\n},\n"
+ + "tabs = {\nHallo \tWorld \tthis \t is\t\tnot \t\tan \t\n exercise \t \n.\t \n\t},\n"
+ + "}"));
+
+ Collection c = result.getDatabase().getEntries();
+ assertEquals(1, c.size());
+
+ BibtexEntry e = (BibtexEntry) c.iterator().next();
+
+ assertEquals("canh05", e.getCiteKey());
+ assertEquals(BibtexEntryType.ARTICLE, e.getType());
+
+ assertEquals("Hallo World this is not an exercise .", (String)e.getField("title"));
+ assertEquals("Hallo World this is not an exercise .", (String)e.getField("tabs"));
+ }
+}
\ No newline at end of file
diff --git a/src/java/tests/net/sf/jabref/imports/IEEEImport1.txt b/src/java/tests/net/sf/jabref/imports/IEEEImport1.txt
new file mode 100644
index 0000000..81599a3
--- /dev/null
+++ b/src/java/tests/net/sf/jabref/imports/IEEEImport1.txt
@@ -0,0 +1,60 @@
+TY - JOUR
+
+JO - Geoscience and Remote Sensing Letters, IEEE
+
+TI - Improving Urban Road Extraction in High-Resolution
+Images Exploiting Directional Filtering, Perceptual
+Grouping, and Simple Topological Concepts
+
+IS - 3
+
+SN - 1545-598X
+
+SP - 387
+
+EP - 391
+
+AU - Gamba, P.
+
+AU - Dell'Acqua, F.
+
+AU - Lisini, G.
+
+PY - 2006
+
+KW - Perceptual grouping
+
+KW - street extraction
+
+KW - urban remote sensing
+
+KW - Perceptual grouping
+
+KW - street extraction
+
+KW - urban remote sensing
+
+VL - 4
+
+JA - Geoscience and Remote Sensing Letters, IEEE
+
+AB - In this letter, the problem of detecting urban road
+networks from high-resolution optical/synthetic aperture
+radar (SAR) images is addressed. To this end, this letter
+exploits a priori knowledge about road direction
+distribution in urban areas. In particular, this letter
+presents an adaptive filtering procedure able to capture the
+predominant directions of these roads and enhance the
+extraction results. After road element extraction, to both
+discard redundant segments and avoid gaps, a special
+perceptual grouping algorithm is devised, exploiting
+colinearity as well as proximity concepts. Finally, the road
+network topology is considered, checking for road
+intersections and regularizing the overall patterns using
+these focal points. The proposed procedure was tested on a
+pair of very high resolution images, one from an optical
+sensor and one from a SAR sensor. The experiments show an
+increase in both the completeness and the quality indexes
+for the extracted road network.
+
+ER -
\ No newline at end of file
diff --git a/src/java/tests/net/sf/jabref/imports/IsiImporterTest.java b/src/java/tests/net/sf/jabref/imports/IsiImporterTest.java
new file mode 100644
index 0000000..ceba558
--- /dev/null
+++ b/src/java/tests/net/sf/jabref/imports/IsiImporterTest.java
@@ -0,0 +1,370 @@
+package tests.net.sf.jabref.imports;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.regex.Pattern;
+
+import junit.framework.TestCase;
+import net.sf.jabref.BibtexEntry;
+import net.sf.jabref.BibtexEntryType;
+import net.sf.jabref.Globals;
+import net.sf.jabref.JabRefPreferences;
+import net.sf.jabref.imports.IsiImporter;
+
+/**
+ * Test cases for the IsiImporter
+ *
+ * @author $Author: mortenalver $
+ * @version $Revision: 1.6 $ ($Date: 2006/09/26 21:01:39 $)
+ *
+ */
+public class IsiImporterTest extends TestCase {
+
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ if (Globals.prefs == null) {
+ Globals.prefs = JabRefPreferences.getInstance();
+ }
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ public void testIsRecognizedFormat() throws IOException {
+
+ IsiImporter importer = new IsiImporter();
+ assertTrue(importer.isRecognizedFormat(IsiImporterTest.class
+ .getResourceAsStream("IsiImporterTest1.isi")));
+
+ assertTrue(importer.isRecognizedFormat(IsiImporterTest.class
+ .getResourceAsStream("IsiImporterTestINSPEC.isi")));
+
+ assertTrue(importer.isRecognizedFormat(IsiImporterTest.class
+ .getResourceAsStream("IsiImporterTestWOS.isi")));
+
+ assertTrue(importer.isRecognizedFormat(IsiImporterTest.class
+ .getResourceAsStream("IsiImporterTestMedline.isi")));
+ }
+
+ public void testProcessSubSup() {
+
+ HashMap hm = new HashMap();
+ hm.put("title", "/sub 3/");
+ IsiImporter.processSubSup(hm);
+ assertEquals("$_3$", hm.get("title"));
+
+ hm.put("title", "/sub 3 /");
+ IsiImporter.processSubSup(hm);
+ assertEquals("$_3$", hm.get("title"));
+
+ hm.put("title", "/sub 31/");
+ IsiImporter.processSubSup(hm);
+ assertEquals("$_{31}$", hm.get("title"));
+
+ hm.put("abstract", "/sub 3/");
+ IsiImporter.processSubSup(hm);
+ assertEquals("$_3$", hm.get("abstract"));
+
+ hm.put("review", "/sub 31/");
+ IsiImporter.processSubSup(hm);
+ assertEquals("$_{31}$", hm.get("review"));
+
+ hm.put("title", "/sup 3/");
+ IsiImporter.processSubSup(hm);
+ assertEquals("$^3$", hm.get("title"));
+
+ hm.put("title", "/sup 31/");
+ IsiImporter.processSubSup(hm);
+ assertEquals("$^{31}$", hm.get("title"));
+
+ hm.put("abstract", "/sup 3/");
+ IsiImporter.processSubSup(hm);
+ assertEquals("$^3$", hm.get("abstract"));
+
+ hm.put("review", "/sup 31/");
+ IsiImporter.processSubSup(hm);
+ assertEquals("$^{31}$", hm.get("review"));
+
+ hm.put("title", "/sub $Hello/");
+ IsiImporter.processSubSup(hm);
+ assertEquals("$_{\\$Hello}$", hm.get("title"));
+ }
+
+ public void testImportEntries() throws IOException {
+ IsiImporter importer = new IsiImporter();
+
+ List entries = importer.importEntries(IsiImporterTest.class
+ .getResourceAsStream("IsiImporterTest1.isi"));
+ assertEquals(1, entries.size());
+ BibtexEntry entry = (BibtexEntry) entries.get(0);
+ assertEquals("Optical properties of MgO doped LiNbO$_3$ single crystals", entry
+ .getField("title"));
+ assertEquals(
+ "James Brown and James Marc Brown and Brown, J. M. and Brown, J. and Brown, J. M. and Brown, J.",
+ entry.getField("author"));
+
+ assertEquals(BibtexEntryType.ARTICLE, entry.getType());
+ assertEquals("Optical Materials", entry.getField("journal"));
+ assertEquals("2006", entry.getField("year"));
+ assertEquals("28", entry.getField("volume"));
+ assertEquals("5", entry.getField("number"));
+ assertEquals("467--72", entry.getField("pages"));
+
+ // What todo with PD and UT?
+ }
+
+ public void testImportEntriesINSPEC() throws IOException {
+ IsiImporter importer = new IsiImporter();
+
+ List entries = importer.importEntries(IsiImporterTest.class
+ .getResourceAsStream("IsiImporterTestInspec.isi"));
+
+ assertEquals(2, entries.size());
+ BibtexEntry a = (BibtexEntry) entries.get(0);
+ BibtexEntry b = (BibtexEntry) entries.get(1);
+
+ if (a.getField("title").equals(
+ "Optical and photoelectric spectroscopy of photorefractive Sn$_2$P$_2$S$_6$ crystals")) {
+ BibtexEntry tmp = a;
+ a = b;
+ b = tmp;
+ }
+
+ // Check a
+ assertEquals(
+ "Second harmonic generation of continuous wave ultraviolet light and production of beta -BaB$_2$O$_4$ optical waveguides",
+ a.getField("title"));
+ assertEquals(BibtexEntryType.ARTICLE, a.getType());
+
+ assertEquals("Degl'Innocenti, R. and Guarino, A. and Poberaj, G. and Gunter, P.", a
+ .getField("author"));
+ assertEquals("Applied Physics Letters", a.getField("journal"));
+ assertEquals("2006", a.getField("year"));
+ assertEquals("#jul#", a.getField("month"));
+ assertEquals("89", a.getField("volume"));
+ assertEquals("4", a.getField("number"));
+
+ // JI Appl. Phys. Lett. (USA)
+
+ // BP 41103-1
+ // EP 41103-41103-3
+ // PS 41103-1-3
+ // assertEquals("41103-1-3", a.getField("pages"));
+
+ // LA English
+ assertEquals("We report on the generation of continuous-wave (cw) ultraviolet"
+ + " (UV) laser light at lambda =278 nm by optical frequency doubling of"
+ + " visible light in beta -BaB$_2$O$_4$ waveguides. Ridge-type "
+ + "waveguides were produced by He$^+$ implantation, photolithography"
+ + " masking, and plasma etching. The final waveguides have core dimension"
+ + " of a few mu m$^2$ and show transmission losses of 5 dB/cm at 532 nm "
+ + "and less than 10 dB/cm at 266 nm. In our first experiments, a second "
+ + "harmonic power of 24 mu W has been generated at 278 nm in an 8 mm long "
+ + "waveguide pumped by 153 mW at 556 nm.".replaceFirst("266", "\n"), a.getField(
+ "abstract").toString());
+ /*
+ * DE Experimental/ barium compounds; ion implantation; optical harmonic
+ * generation; optical losses; optical pumping; photolithography; solid
+ * lasers; sputter etching; ultraviolet sources; waveguide lasers/
+ * second harmonic generation; continuous-wave light; beta -BaB/sub
+ * 2/O/sub 4/ optical waveguides; UV laser light; optical frequency
+ * doubling; visible light; ridge-type waveguides; He/sup +/
+ * implantation; photolithography masking; plasma etching; transmission
+ * losses; optical pumping; 278 nm; 532 nm; 266 nm; 24 muW; 8 mm; 153
+ * mW; 556 nm; BaB/sub 2/O/sub 4// A4265K Optical harmonic generation,
+ * frequency conversion, parametric oscillation and amplification A4255R
+ * Lasing action in other solids A4260B Design of specific laser systems
+ * B4340K Optical harmonic generation, frequency conversion, parametric
+ * oscillation and amplification B4320G Solid lasers/ wavelength
+ * 2.78E-07 m; wavelength 5.32E-07 m; wavelength 2.66E-07 m; power
+ * 2.4E-05 W; size 8.0E-03 m; power 1.53E-01 W; wavelength 5.56E-07 m/
+ * BaB2O4/ss B2/ss Ba/ss O4/ss B/ss O/ss C1 Degl'Innocenti, R.; Guarino,
+ * A.; Poberaj, G.; Gunter, P.; Nonlinear Opt. Lab., Inst. of Quantum
+ * Electron., Zurich, Switzerland
+ */
+ assertEquals("Aip", a.getField("publisher"));
+ // PV USA
+ // NR 11
+ // CO APPLAB
+ // SN 0003-6951
+ // ID
+ // 0003-6951/2006/89(4)/041103-1(3)/$23.00],[0003-6951(20060724)89:4L.41103:SHGC;1-T],[S0003-6951(06)22430-6],[10.1063/1.2234275]
+ // UT INSPEC:9027814
+
+ // Check B
+ assertEquals(
+ "Optical and photoelectric spectroscopy of photorefractive Sn$_2$P$_2$S$_6$ crystals",
+ b.getField("title").toString());
+ assertEquals(BibtexEntryType.ARTICLE, b.getType());
+ }
+
+ public void testImportEntriesWOS() throws IOException {
+ IsiImporter importer = new IsiImporter();
+
+ List entries = importer.importEntries(IsiImporterTest.class
+ .getResourceAsStream("IsiImporterTestWOS.isi"));
+
+ assertEquals(2, entries.size());
+ BibtexEntry a = (BibtexEntry) entries.get(0);
+ BibtexEntry b = (BibtexEntry) entries.get(1);
+
+ if (a.getField("title").equals(
+ "Optical waveguides in Sn2P2S6 by low fluence MeV He+ ion implantation")) {
+ BibtexEntry tmp = a;
+ a = b;
+ b = tmp;
+ }
+
+ assertEquals("Optical and photoelectric spectroscopy of photorefractive Sn2P2S6 crystals",
+ a.getField("title"));
+ assertEquals("Optical waveguides in Sn2P2S6 by low fluence MeV He+ ion implantation", b
+ .getField("title"));
+
+ assertEquals("Journal Of Physics-Condensed Matter", a.getField("journal"));
+ }
+
+ public void testIsiAuthorsConvert() {
+ assertEquals(
+ "James Brown and James Marc Brown and Brown, J. M. and Brown, J. and Brown, J. M. and Brown, J.",
+ IsiImporter
+ .isiAuthorsConvert("James Brown and James Marc Brown and Brown, J.M. and Brown, J. and Brown, J.M. and Brown, J."));
+
+ assertEquals(
+ "Joffe, Hadine and Hall, Janet E. and Gruber, Staci and Sarmiento, Ingrid A. and Cohen, Lee S. and Yurgelun-Todd, Deborah and Martin, Kathryn A.",
+ IsiImporter
+ .isiAuthorsConvert("Joffe, Hadine; Hall, Janet E; Gruber, Staci; Sarmiento, Ingrid A; Cohen, Lee S; Yurgelun-Todd, Deborah; Martin, Kathryn A"));
+
+ }
+
+ public void testMonthConvert(){
+
+ assertEquals("#jun#", IsiImporter.parseMonth("06"));
+ assertEquals("#jun#", IsiImporter.parseMonth("JUN"));
+ assertEquals("#jun#", IsiImporter.parseMonth("jUn"));
+ assertEquals("#may#", IsiImporter.parseMonth("MAY-JUN"));
+ assertEquals("#jun#", IsiImporter.parseMonth("2006 06"));
+ assertEquals("#jun#", IsiImporter.parseMonth("2006 06-07"));
+ assertEquals("#jul#", IsiImporter.parseMonth("2006 07 03"));
+ assertEquals("#may#", IsiImporter.parseMonth("2006 May-Jun"));
+ }
+
+ public void testIsiAuthorConvert() {
+ assertEquals("James Brown", IsiImporter.isiAuthorConvert("James Brown"));
+ assertEquals("James Marc Brown", IsiImporter.isiAuthorConvert("James Marc Brown"));
+ assertEquals("Brown, J. M.", IsiImporter.isiAuthorConvert("Brown, J.M."));
+ assertEquals("Brown, J.", IsiImporter.isiAuthorConvert("Brown, J."));
+ assertEquals("Brown, J. M.", IsiImporter.isiAuthorConvert("Brown, JM"));
+ assertEquals("Brown, J.", IsiImporter.isiAuthorConvert("Brown, J"));
+ assertEquals("Brown, James", IsiImporter.isiAuthorConvert("Brown, James"));
+ assertEquals("Hall, Janet E.", IsiImporter.isiAuthorConvert("Hall, Janet E"));
+ assertEquals("", IsiImporter.isiAuthorConvert(""));
+ }
+
+ public void testGetExtensions() {
+ // new IsiImporter().getExtensions();
+ }
+
+ public void testGetIsCustomImporter() {
+ IsiImporter importer = new IsiImporter();
+ assertEquals(false, importer.getIsCustomImporter());
+ }
+
+ public void testImportIEEEExport() throws IOException {
+ IsiImporter importer = new IsiImporter();
+
+ List entries = importer.importEntries(IsiImporterTest.class
+ .getResourceAsStream("IEEEImport1.txt"));
+
+ assertEquals(1, entries.size());
+ BibtexEntry a = (BibtexEntry) entries.get(0);
+
+ assertEquals(a.getType().getName(), BibtexEntryType.ARTICLE, a.getType());
+ assertEquals("Geoscience and Remote Sensing Letters, IEEE", a.getField("journal"));
+ assertEquals(
+ "Improving Urban Road Extraction in High-Resolution " +
+ "Images Exploiting Directional Filtering, Perceptual " +
+ "Grouping, and Simple Topological Concepts",
+ a.getField("title"));
+
+ assertEquals("4", a.getField("volume"));
+ assertEquals("3", a.getField("number"));
+
+ assertEquals("1545-598X", a.getField("SN"));
+
+ assertEquals("387--391", a.getField("pages"));
+
+ assertEquals("Gamba, P. and Dell'Acqua, F. and Lisini, G.", (String) a.getField("author"));
+
+ assertEquals("2006", a.getField("year"));
+
+ assertEquals("Perceptual grouping, street extraction, urban remote sensing", (String)a.getField("keywords"));
+
+ assertEquals("In this letter, the problem of detecting urban road " +
+ "networks from high-resolution optical/synthetic aperture " +
+ "radar (SAR) images is addressed. To this end, this letter " +
+ "exploits a priori knowledge about road direction " +
+ "distribution in urban areas. In particular, this letter " +
+ "presents an adaptive filtering procedure able to capture the " +
+ "predominant directions of these roads and enhance the " +
+ "extraction results. After road element extraction, to both " +
+ "discard redundant segments and avoid gaps, a special " +
+ "perceptual grouping algorithm is devised, exploiting " +
+ "colinearity as well as proximity concepts. Finally, the road " +
+ "network topology is considered, checking for road " +
+ "intersections and regularizing the overall patterns using " +
+ "these focal points. The proposed procedure was tested on a " +
+ "pair of very high resolution images, one from an optical " +
+ "sensor and one from a SAR sensor. The experiments show an " +
+ "increase in both the completeness and the quality indexes " +
+ "for the extracted road network.", (String)a.getField("abstract"));
+
+ }
+
+ public void testImportEntriesMedline() throws IOException {
+ IsiImporter importer = new IsiImporter();
+
+ List entries = importer.importEntries(IsiImporterTest.class
+ .getResourceAsStream("IsiImporterTestMedline.isi"));
+
+ assertEquals(2, entries.size());
+ BibtexEntry a = (BibtexEntry) entries.get(0);
+ BibtexEntry b = (BibtexEntry) entries.get(1);
+
+ if (((String) a.getField("title")).startsWith("Estrogen")) {
+ BibtexEntry tmp = a;
+ a = b;
+ b = tmp;
+ }
+
+ // Check A
+ assertEquals(
+ "Effects of modafinil on cognitive performance and alertness during sleep deprivation.",
+ a.getField("title"));
+
+ assertEquals("Wesensten, Nancy J.", (String) a.getField("author"));
+ assertEquals("Curr Pharm Des", a.getField("journal"));
+ assertEquals("2006", a.getField("year"));
+ assertEquals(null, a.getField("month"));
+ assertEquals("12", a.getField("volume"));
+ assertEquals("20", a.getField("number"));
+ assertEquals("2457--71", a.getField("pages"));
+ assertEquals(BibtexEntryType.ARTICLE, a.getType());
+
+ // Check B
+ assertEquals(
+ "Estrogen therapy selectively enhances prefrontal cognitive processes: a randomized, double-blind, placebo-controlled study with functional magnetic resonance imaging in perimenopausal and recently postmenopausal women.",
+ b.getField("title").toString());
+ assertEquals(
+ "Joffe, Hadine and Hall, Janet E. and Gruber, Staci and Sarmiento, Ingrid A. and Cohen, Lee S. and Yurgelun-Todd, Deborah and Martin, Kathryn A.",
+ (String) b.getField("author"));
+ assertEquals("2006", b.getField("year"));
+ assertEquals("#may#", b.getField("month"));
+ assertEquals("13", b.getField("volume"));
+ assertEquals("3", b.getField("number"));
+ assertEquals("411--22", b.getField("pages"));
+ assertEquals(BibtexEntryType.ARTICLE, b.getType());
+ }
+}
diff --git a/src/java/tests/net/sf/jabref/imports/IsiImporterTest1.isi b/src/java/tests/net/sf/jabref/imports/IsiImporterTest1.isi
new file mode 100644
index 0000000..49fe70b
--- /dev/null
+++ b/src/java/tests/net/sf/jabref/imports/IsiImporterTest1.isi
@@ -0,0 +1,25 @@
+FN ISI Export Format
+VR 1.0
+
+PT J
+TI Optical properties of MgO doped LiNbO/sub 3/ single
+ crystals
+AU James Brown
+ James Marc Brown
+ Brown, JM
+ Brown, J
+ Brown, J.M.
+ Brown, J.
+SO Optical Materials
+PY 2006
+PD 04 2006
+VL 28
+IS 5
+JI Opt. Mater. (Netherlands)
+BP 467
+EP 472
+PS 467-72
+UT INSPEC:8863438
+ER
+
+EF
\ No newline at end of file
diff --git a/src/java/tests/net/sf/jabref/imports/IsiImporterTestInspec.isi b/src/java/tests/net/sf/jabref/imports/IsiImporterTestInspec.isi
new file mode 100644
index 0000000..09ceb92
--- /dev/null
+++ b/src/java/tests/net/sf/jabref/imports/IsiImporterTestInspec.isi
@@ -0,0 +1,122 @@
+FN ISI Export Format
+VR 1.0
+PT J
+AN 9027814
+DT Journal Paper
+TI Second harmonic generation of continuous wave ultraviolet light and
+ production of beta -BaB/sub 2/O/sub 4/ optical waveguides
+AU Degl'Innocenti, R.
+ Guarino, A.
+ Poberaj, G.
+ Gunter, P.
+SO Applied Physics Letters
+PY 2006
+PD 07 2006
+VL 89
+IS 4
+JI Appl. Phys. Lett. (USA)
+BP 41103-1
+EP 41103-41103-3
+PS 41103-1-3
+LA English
+AB We report on the generation of continuous-wave (cw) ultraviolet (UV)
+ laser light at lambda =278 nm by optical frequency doubling of visible
+ light in beta -BaB/sub 2/O/sub 4/ waveguides. Ridge-type waveguides
+ were produced by He/sup +/ implantation, photolithography masking, and
+ plasma etching. The final waveguides have core dimension of a few mu
+ m/sup 2/ and show transmission losses of 5 dB/cm at 532 nm and less
+ than 10 dB/cm at 266 nm. In our first experiments, a second harmonic
+ power of 24 mu W has been generated at 278 nm in an 8 mm long waveguide
+ pumped by 153 mW at 556 nm.
+DE Experimental/ barium compounds; ion implantation; optical harmonic generation;
+ optical losses; optical pumping; photolithography; solid lasers;
+ sputter etching; ultraviolet sources; waveguide lasers/ second harmonic generation; continuous-wave light; beta -BaB/sub
+ 2/O/sub 4/ optical waveguides; UV laser light; optical frequency
+ doubling; visible light; ridge-type waveguides; He/sup +/ implantation;
+ photolithography masking; plasma etching; transmission losses; optical
+ pumping; 278 nm; 532 nm; 266 nm; 24 muW; 8 mm; 153 mW; 556 nm; BaB/sub
+ 2/O/sub 4// A4265K Optical harmonic generation, frequency conversion, parametric
+ oscillation and amplification
+ A4255R Lasing action in other solids
+ A4260B Design of specific laser systems
+ B4340K Optical harmonic generation, frequency conversion, parametric
+ oscillation and amplification
+ B4320G Solid lasers/ wavelength 2.78E-07 m; wavelength 5.32E-07 m; wavelength 2.66E-07 m;
+ power 2.4E-05 W; size 8.0E-03 m; power 1.53E-01 W; wavelength 5.56E-07 m/ BaB2O4/ss B2/ss Ba/ss O4/ss B/ss O/ss
+C1 Degl'Innocenti, R.; Guarino, A.; Poberaj, G.; Gunter, P.; Nonlinear
+ Opt. Lab., Inst. of Quantum Electron., Zurich, Switzerland
+PU AIP
+PV USA
+NR 11
+CO APPLAB
+SN 0003-6951
+ID 0003-6951/2006/89(4)/041103-1(3)/$23.00],[0003-6951(20060724)89:4L.41103:SHGC;1-T],[S0003-6951(06)22430-6],[10.1063/1.2234275]
+UT INSPEC:9027814
+ER
+
+PT J
+AN 9023788
+DT Journal Paper
+TI Optical and photoelectric spectroscopy of photorefractive Sn/sub 2
+ /P/sub 2/S/sub 6/ crystals
+AU Gamernyk, R.V.
+ Gnatenko, Yu.P.
+ Bukivskij, P.M.
+ Skubenko, P.A.
+ Slivka, V.Y.
+SO Journal of Physics: Condensed Matter
+PY 2006
+PD 06 2006
+VL 18
+IS 23
+JI J. Phys., Condens. Matter. (UK)
+BP 5323
+EP 5331
+PS 5323-31
+LA English
+AB Low-temperature studies of the absorption, photoluminescence,
+ photodiffusion and photoconductivity spectra of Sn/sub 2/P/sub 2 /S/sub
+ 6/ crystals were carried out in the wide spectral range 0.8-3.5 eV. The
+ position of defect energy levels relative to the crystal energy bands
+ has been determined. It was shown that the photoionization transitions
+ from the valence band to the level with the energy E/sub v /+1.35 eV
+ are caused by the presence of the hole metastable state. In the optical
+ and photoelectric spectra several bands were revealed with energy
+ greater than the band gap of the crystal (E/sub g/ = 2.5 eV). It was
+ established that these bands are caused by the optical transitions
+ between the valence band and upper conduction bands. It was shown that
+ the electron-hole recombination, caused by the band-to-band transitions
+ with the participation of the upper conduction subbands, is fast and
+ corresponds to the nanosecond region. The combined scheme of the defect
+ energy level and the band-to-band electronic phototransitions in Sn/sub
+ 2/P/sub 2/S/sub 6/ crystals was constructed. A mechanism for the
+ photorefractive effect in these crystals is proposed.
+DE Experimental/ conduction bands; defect states; electron-hole recombination; infrared
+ spectra; metastable states; photoconductivity; photoionisation;
+ photoluminescence; photorefractive effect; ternary semiconductors; tin
+ compounds; ultraviolet spectra; valence bands; visible spectra/ photoelectric spectroscopy; optical spectroscopy; photorefractive
+ Sn/sub 2/P/sub 2/S/sub 6/ crystals; low-temperature studies; absorption
+ spectra; photoluminescence spectra; photodiffusion; photoconductivity
+ spectra; defect energy levels; crystal energy bands; photoionization
+ transitions; valency band; hole metastable state; photoelectric
+ spectra; band gap; optical transitions; conduction bands; electron-hole
+ recombination; band-to-band transitions; upper conduction subbands;
+ nanosecond region; defect energy-level; band-to-band electronic
+ phototransitions; mechanism; photorefractive effect; 0.8 to 3.5 eV;
+ Sn/sub 2/P/sub 2/S/sub 6// A7820W Other optical properties of condensed matter
+ A7855H Photoluminescence in other inorganic materials
+ A7240 Photoconduction and photovoltaic effects; photodielectric effects
+ A7155H Impurity and defect levels in other nonmetals
+ A7830G Infrared and Raman spectra in inorganic crystals
+ A7840H Visible and ultraviolet spectra of other nonmetals/ electron volt energy 8.0E-01 to 3.5E+00 eV/ Sn2P2S6/ss Sn2/ss P2/ss S6/ss Sn/ss P/ss S/ss
+C1 Gamernyk, R.V.; Lviv Nat. Univ., Ukraine
+PU IOP Publishing
+PV UK
+NR 18
+CO JCOMEL
+SN 0953-8984
+ID 0953-8984/06/235323+09$30.00],[0953-8984(20060614)18:23L.5323:OPSP;1-Y],[S0953-8984(06)16823-X],[10.1088/0953-8984/18/23/006]
+UT INSPEC:9023788
+ER
+
+EF
\ No newline at end of file
diff --git a/src/java/tests/net/sf/jabref/imports/IsiImporterTestMedline.isi b/src/java/tests/net/sf/jabref/imports/IsiImporterTestMedline.isi
new file mode 100644
index 0000000..e19fb54
--- /dev/null
+++ b/src/java/tests/net/sf/jabref/imports/IsiImporterTestMedline.isi
@@ -0,0 +1,27 @@
+FN ISI Export Format
+VR 1.0
+PT J
+TI Effects of modafinil on cognitive performance and alertness during sleep deprivation.
+AU Wesensten, Nancy J
+SO Curr Pharm Des
+VL 12
+IS 20
+PS 2457-71
+PY 2006
+PD 2006
+UT MEDLINE:16842170
+ER
+
+PT J
+TI Estrogen therapy selectively enhances prefrontal cognitive processes: a randomized, double-blind, placebo-controlled study with functional magnetic resonance imaging in perimenopausal and recently postmenopausal women.
+AU Joffe, Hadine; Hall, Janet E; Gruber, Staci; Sarmiento, Ingrid A; Cohen, Lee S; Yurgelun-Todd, Deborah; Martin, Kathryn A
+SO Menopause
+VL 13
+IS 3
+PS 411-22
+PY 2006
+PD 2006 May-Jun
+UT MEDLINE:16735938
+ER
+
+EF
\ No newline at end of file
diff --git a/src/java/tests/net/sf/jabref/imports/IsiImporterTestWOS.isi b/src/java/tests/net/sf/jabref/imports/IsiImporterTestWOS.isi
new file mode 100644
index 0000000..ee5dec9
--- /dev/null
+++ b/src/java/tests/net/sf/jabref/imports/IsiImporterTestWOS.isi
@@ -0,0 +1,135 @@
+FN ISI Export Format
+VR 1.0
+PT J
+AU Gamernyk, RV
+ Gnatenko, YP
+ Bukivskij, PM
+ Skubenko, PA
+ Slivka, VY
+TI Optical and photoelectric spectroscopy of photorefractive Sn2P2S6
+ crystals
+SO JOURNAL OF PHYSICS-CONDENSED MATTER
+LA English
+DT Article
+ID ELECTRIC-FIELD
+AB Low-temperature studies of the absorption, photoluminescence,
+ photodiffusion and photoconductivity spectra of Sn2P2S6 crystals were
+ carried out in the wide spectral range 0.8-3.5 eV. The position of
+ defect energy levels relative to the crystal energy bands has been
+ determined. It was shown that the photoionization transitions from the
+ valence band to the level with the energy E-v + 1.35 eV are caused by
+ the presence of the hole metastable state. In the optical and
+ photoelectric spectra several bands were revealed with energy greater
+ than the band gap of the crystal (E-g = 2.5 eV). It was established
+ that these bands are caused by the optical transitions between the
+ valence band and upper conduction bands. It was shown that the
+ electron-hole recombination, caused by the band-to-band transitions
+ with the participation of the upper conduction subbands, is fast and
+ corresponds to the nanosecond region. The combined scheme of the defect
+ energy level and the band-to-band electronic phototransitions in
+ Sn2P2S6 crystals was constructed. A mechanism for the photorefractive
+ effect in these crystals is proposed.
+C1 NAS Ukraine, Inst Phys, UA-03028 Kiev, Ukraine.
+ Lviv Natl Univ, UA-29005 Lvov, Ukraine.
+RP Gnatenko, YP, NAS Ukraine, Inst Phys, 46 Prospect Nauky, UA-03028 Kiev,
+ Ukraine.
+EM gnatenko at iop.kiev.ua
+CR BERCHA DM, 1997, FIZ TVERD TELA, V39, P1219
+ BRAVINA SL, 1997, FERROELECTRICS, V192, P197
+ CARPENTIER CD, 1974, MAT RES B, V9, P401
+ ENJALBERT R, 1999, EUR PHYS J B, V8, P169
+ FENCHAK VY, 1997, FERROELECTRICS, V192, P129
+ GNATENKO YP, 2003, J APPL PHYS, V94, P4896
+ GRABAR AA, 1997, FERROELECTRICS, V192, P155
+ GRABAR AA, 2001, OPT COMMUN, V188, P187
+ HLINKA J, 2002, PHYS REV B, V65
+ KEDYULICH VM, 2001, FERROELECTRICS, V254, P243
+ KITYK IV, 1995, FIZ TEKH POLUPROV, V29, P697
+ KUEPPER E, 2003, PHYS REV B, V67
+ LUPASCU DC, 2006, J AM CERAM SOC, V89, P224
+ ODOULOV SG, 1996, J OPT SOC AM B, V13, P2352
+ PETROV MP, 1990, J APPL PHYS, V68, P2216
+ RUEDIGER A, 2001, OPT MATER, V18, P123
+ SHUMELYUK A, 2001, APPL PHYS B-LASERS O, V72, P707
+NR 17
+TC 0
+PU IOP PUBLISHING LTD
+PI BRISTOL
+PA DIRAC HOUSE, TEMPLE BACK, BRISTOL BS1 6BE, ENGLAND
+SN 0953-8984
+J9 J PHYS-CONDENS MATTER
+JI J. Phys.-Condes. Matter
+PD JUN 14
+PY 2006
+VL 18
+IS 23
+BP 5323
+EP 5331
+PG 9
+SC Physics, Condensed Matter
+GA 057JR
+UT ISI:000238592600006
+ER
+
+PT J
+AU Guarino, A
+ Jazbinsek, M
+ Herzog, C
+ Degl'Innocenti, R
+ Poberaj, G
+ Gunter, P
+TI Optical waveguides in Sn2P2S6 by low fluence MeV He+ ion implantation
+SO OPTICS EXPRESS
+LA English
+DT Article
+ID REFRACTIVE-INDEX PROFILES; INFRARED WAVELENGTHS; PHASE-CONJUGATION;
+ KNBO3; MODES
+AB Planar waveguides in nonlinear optical crystals of Sn2P2S6 have been
+ produced by He+ ion implantation. The effective indices of the
+ waveguide have been determined and refractive index profiles have been
+ evaluated for the indices along all three principal axes of the optical
+ indicatrix. The depth of the induced optical barrier is. Delta n(1) = -
+ 0.07, Delta n(2) = - 0.07 and Delta n(3) = - 0.09 lambda = 0.633 mu m
+ for a fluence Phi = 0.5 x 10(15) ions/cm(2). Propagation losses for
+ hybrid-n(1) modes are alpha similar or equal to 10dB/cm. (c) 2006
+ Optical Society of America.
+C1 ETH, Inst Quantum Elect, Nonlinear Opt Lab, CH-8093 Zurich, Switzerland.
+RP Guarino, A, ETH, Inst Quantum Elect, Nonlinear Opt Lab, CH-8093 Zurich,
+ Switzerland.
+EM guarino at phys.ethz.ch
+CR BACH T, 2005, OPT EXPRESS, V13, P9890
+ CHANDLER PJ, 1986, OPT ACTA, V33, P127
+ CHIANG KS, 1985, J LIGHTWAVE TECHNOL, V3, P385
+ DEROSSI A, 2005, J APPL PHYS, V97
+ FLUCK D, 1992, FERROELECTRICS, V128, P79
+ FLUCK D, 1993, J APPL PHYS, V74, P6023
+ GUARINO A, 2005, OPT LETT, V18, P2412
+ HAERTLE D, 2005, OPT EXPRESS, V13, P2047
+ HAERTLE D, 2005, OPT EXPRESS, V13, P3765
+ JAZBINSEK M, 2005, J OPT SOC AM B, V22, P2459
+ MALDONADO TA, 1996, J LIGHTWAVE TECHNOL, V14, P486
+ MARCUSE D, 1978, IEEE J QUANTUM ELECT, V14, P736
+ TOWNSEND PD, 1994, OPTICAL EFFECTS ION
+ YARIV A, 1984, OPTICAL WAVES CRYSTA
+ ZHA M, 1993, OPT LETT, V18, P577
+NR 15
+TC 0
+PU OPTICAL SOC AMER
+PI WASHINGTON
+PA 2010 MASSACHUSETTS AVE NW, WASHINGTON, DC 20036 USA
+SN 1094-4087
+J9 OPT EXPRESS
+JI Opt. Express
+PD MAR 20
+PY 2006
+VL 14
+IS 6
+BP 2344
+EP 2358
+PG 15
+SC Optics
+GA 024NR
+UT ISI:000236202800037
+ER
+
+EF
\ No newline at end of file
diff --git a/src/java/tests/net/sf/jabref/imports/OAI2ImportTest.java b/src/java/tests/net/sf/jabref/imports/OAI2ImportTest.java
new file mode 100644
index 0000000..fa6c4b2
--- /dev/null
+++ b/src/java/tests/net/sf/jabref/imports/OAI2ImportTest.java
@@ -0,0 +1,99 @@
+package tests.net.sf.jabref.imports;
+
+import java.io.File;
+
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+
+import junit.framework.TestCase;
+import net.sf.jabref.BibtexEntry;
+import net.sf.jabref.BibtexEntryType;
+import net.sf.jabref.Util;
+import net.sf.jabref.imports.*;
+
+
+/**
+ * Test for OAI2-Handler and Fetcher.
+ *
+ * @author Ulrich Stärk
+ * @author Christian Kopf
+ *
+ * @version $Revision: 1.1 $ ($Date: 2006/11/24 15:29:11 $)
+ *
+ */
+public class OAI2ImportTest extends TestCase {
+
+ OAI2Handler handler;
+ BibtexEntry be;
+ File fis;
+ File fis2;
+ protected SAXParserFactory parserFactory;
+ protected SAXParser saxParser;
+
+ protected void setUp() throws Exception {
+ parserFactory = SAXParserFactory.newInstance();
+ saxParser = parserFactory.newSAXParser();
+ be = new BibtexEntry(Util.createNeutralId(), BibtexEntryType.getType("article"));
+ handler = new OAI2Handler(be);
+ fis = new File("src/java/tests/net/sf/jabref/imports/oai2.xml");
+ fis2 = new File("src/java/tests/net/sf/jabref/imports/oai22.xml");
+ }
+
+ public void testParse() {
+ try {
+ saxParser.parse(fis,handler);
+ } catch (Exception e) {
+ fail("Exception");
+ }
+ }
+
+ public void testOai2xml() {
+ try {
+ saxParser.parse(fis,handler);
+ assertEquals("hep-ph/0408155",(String)be.getField("eprint"));
+ assertEquals("G. F. Giudice and A. Riotto and A. Zaffaroni",(String)be.getField("author"));
+ assertEquals("Nucl.Phys. B",(String)be.getField("journal"));
+ assertEquals("710",(String)be.getField("volume"));
+ assertEquals("2005",(String)be.getField("year"));
+ assertEquals("511-525",(String)be.getField("pages"));
+ assertEquals("GiuRioZaf05",be.getCiteKey());
+ assertEquals("Heavy Particles from Inflation",(String)be.getField("title"));
+ assertNotNull((String)be.getField("abstract"));
+ assertEquals("23 pages",(String)be.getField("comments"));
+ assertEquals("CERN-PH-TH/2004-151",(String)be.getField("reportno"));
+ } catch (Exception e) {
+ fail("Exception");
+ }
+ }
+
+ public void testOai22xml() {
+ try {
+ saxParser.parse(fis2,handler);
+ assertEquals("GiuRioZaf05",be.getCiteKey());
+ assertEquals("2005",(String)be.getField("year"));
+ } catch (Exception e) {
+ fail("Exception");
+ }
+ }
+
+ public void testUrlConstructor() {
+ OAI2Fetcher fetcher = new OAI2Fetcher();
+ be.setField(OAI2Fetcher.OAI2_IDENTIFIER_FIELD, "hep-ph/0408155");
+ assertEquals("http://arxiv.org/oai2?verb=GetRecord&identifier=oai%3AarXiv.org%3Ahep-ph%2F0408155&metadataPrefix=arXiv",fetcher.constructUrl(be));
+ }
+
+ /*
+ public void testOnline() {
+ try {
+ OAI2Fetcher fetcher = new OAI2Fetcher();
+ be.setField(OAI2Fetcher.OAI2_IDENTIFIER_FIELD, "hep-ph/0408155");
+
+ fetcher.importOai2Entry(be);
+
+ assertEquals("hep-ph/0408155",(String)be.getField("eprint"));
+ } catch (Exception e) {
+ //fail("Exception");
+ e.printStackTrace();
+ }
+ }*/
+}
diff --git a/src/java/tests/net/sf/jabref/imports/RisTest.ris b/src/java/tests/net/sf/jabref/imports/RisTest.ris
new file mode 100644
index 0000000..c80bd41
--- /dev/null
+++ b/src/java/tests/net/sf/jabref/imports/RisTest.ris
@@ -0,0 +1,18 @@
+
+
+
+
+TY - JOUR
+A1 - Stottrup,J G
+T1 - The elusive copepods: their production and suitability in marine aquaculture
+Y1 - 2000
+JF - Aquaculture Research
+JO - Aquaculture Research
+SP - 703
+EP - 711
+VL - 31
+IS - 8-9
+M3 - doi:10.1046/j.1365-2109.2000.00488.x
+UR - http://www.blackwell-synergy.com/doi/abs/10.1046/j.1365-2109.2000.00488.x
+N2 - Abstract Despite the fact that the suitability of copepods as live prey for marine fish larvae is now well established, their use in aquaculture remains sporadic. Although of lower nutritional value, the relative ease of production of rotifers (Brachionus spp.) and Artemia nauplii continues to ensure their predominance. Studies in the literature have highlighted differences in the levels and ratios of fatty acids, lipid classes and pigments between copepods and traditional live pre [...]
+ER -
diff --git a/src/java/tests/net/sf/jabref/imports/oai2.xml b/src/java/tests/net/sf/jabref/imports/oai2.xml
new file mode 100644
index 0000000..82768fa
--- /dev/null
+++ b/src/java/tests/net/sf/jabref/imports/oai2.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<OAI-PMH xmlns="http://www.openarchives.org/OAI/2.0/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.openarchives.org/OAI/2.0/ http://www.openarchives.org/OAI/2.0/OAI-PMH.xsd">
+<responseDate>2006-11-17T15:29:52Z</responseDate>
+<request verb="GetRecord" identifier="oai:arXiv.org:hep-ph/0408155" metadataPrefix="arXiv">http://arXiv.org/oai2</request>
+<GetRecord>
+<record>
+<header>
+ <identifier>oai:arXiv.org:hep-ph/0408155</identifier>
+ <datestamp>2005-09-18</datestamp>
+ <setSpec>physics:astro-ph</setSpec>
+ <setSpec>physics:hep-ph</setSpec>
+ <setSpec>physics:hep-th</setSpec>
+</header>
+<metadata>
+ <arXiv xmlns="http://arxiv.org/OAI/arXiv/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://arxiv.org/OAI/arXiv/ http://arXiv.org/OAI/arXiv.xsd">
+ <id>hep-ph/0408155</id><authors><author><keyname>Giudice</keyname><forenames>G. F.</forenames></author><author><keyname>Riotto</keyname><forenames>A.</forenames></author><author><keyname>Zaffaroni</keyname><forenames>A.</forenames></author></authors><title>Heavy Particles from Inflation</title><categories>hep-ph astro-ph hep-th</categories><comments>23 pages</comments><report-no>CERN-PH-TH/2004-151</report-no><journal-ref>Nucl.Phys. B710 (2005) 511-525</journal-ref><doi>10.1016/j.nuclph [...]
+are copiously created from a primordial inflationary epoch. It works for scalar
+fields which are massless or very light during inflation and acquire a large
+mass right after the end of inflation. Such particles can exist in realistic
+scenarios, as we illustrate with several examples in the context of both field
+and string theory. Long-wavelength fluctuations of these fields are generated
+during inflation with an almost scale-invariant spectrum and may give the
+dominant contribution to the energy density of the heavy fields at late times.
+Applications of our results to superheavy dark matter and leptogenesis are
+discussed.
+</abstract></arXiv>
+</metadata>
+</record>
+</GetRecord>
+</OAI-PMH>
diff --git a/src/java/tests/net/sf/jabref/imports/oai22.xml b/src/java/tests/net/sf/jabref/imports/oai22.xml
new file mode 100644
index 0000000..4eec30b
--- /dev/null
+++ b/src/java/tests/net/sf/jabref/imports/oai22.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<OAI-PMH xmlns="http://www.openarchives.org/OAI/2.0/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.openarchives.org/OAI/2.0/ http://www.openarchives.org/OAI/2.0/OAI-PMH.xsd">
+<responseDate>2006-11-17T15:29:52Z</responseDate>
+<request verb="GetRecord" identifier="oai:arXiv.org:hep-ph/0408155" metadataPrefix="arXiv">http://arXiv.org/oai2</request>
+<GetRecord>
+<record>
+<header>
+ <identifier>oai:arXiv.org:hep-ph/0408155</identifier>
+ <datestamp>2005-09-18</datestamp>
+ <setSpec>physics:astro-ph</setSpec>
+ <setSpec>physics:hep-ph</setSpec>
+ <setSpec>physics:hep-th</setSpec>
+</header>
+<metadata>
+ <arXiv xmlns="http://arxiv.org/OAI/arXiv/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://arxiv.org/OAI/arXiv/ http://arXiv.org/OAI/arXiv.xsd">
+ <id>hep-ph/0408155</id><authors><author><keyname>Giudice</keyname><forenames>G. F.</forenames></author><author><keyname>Riotto</keyname><forenames>A.</forenames></author><author><keyname>Zaffaroni</keyname><forenames>A.</forenames></author></authors><title>Heavy Particles from Inflation</title><categories>hep-ph astro-ph hep-th</categories><comments>23 pages</comments><report-no>CERN-PH-TH/2004-151</report-no><doi>10.1016/j.nuclphysb.2004.12.037</doi><abstract> We describe a simple and [...]
+are copiously created from a primordial inflationary epoch. It works for scalar
+fields which are massless or very light during inflation and acquire a large
+mass right after the end of inflation. Such particles can exist in realistic
+scenarios, as we illustrate with several examples in the context of both field
+and string theory. Long-wavelength fluctuations of these fields are generated
+during inflation with an almost scale-invariant spectrum and may give the
+dominant contribution to the energy density of the heavy fields at late times.
+Applications of our results to superheavy dark matter and leptogenesis are
+discussed.
+</abstract></arXiv>
+</metadata>
+</record>
+</GetRecord>
+</OAI-PMH>
\ No newline at end of file
diff --git a/src/java/tests/net/sf/jabref/search/AllTests.java b/src/java/tests/net/sf/jabref/search/AllTests.java
new file mode 100644
index 0000000..9908d1c
--- /dev/null
+++ b/src/java/tests/net/sf/jabref/search/AllTests.java
@@ -0,0 +1,16 @@
+package tests.net.sf.jabref.search;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+public class AllTests {
+
+ public static Test suite() {
+ TestSuite suite = new TestSuite("Test for tests.net.sf.jabref.search");
+ //$JUnit-BEGIN$
+ suite.addTestSuite(BasicSearchTest.class);
+ //$JUnit-END$
+ return suite;
+ }
+
+}
diff --git a/src/java/tests/net/sf/jabref/search/BasicSearchTest.java b/src/java/tests/net/sf/jabref/search/BasicSearchTest.java
new file mode 100644
index 0000000..3e5f079
--- /dev/null
+++ b/src/java/tests/net/sf/jabref/search/BasicSearchTest.java
@@ -0,0 +1,60 @@
+package tests.net.sf.jabref.search;
+
+import junit.framework.TestCase;
+import net.sf.jabref.BibtexEntry;
+import net.sf.jabref.Util;
+import net.sf.jabref.BibtexEntryType;
+import net.sf.jabref.search.BasicSearch;
+
+import java.util.ArrayList;
+
+/**
+ * Test case for BasicSearch.
+ */
+public class BasicSearchTest extends TestCase {
+
+ public void testBasicSearchParsing() {
+
+ BibtexEntry be = makeBibtexEntry();
+ BasicSearch bsCaseSensitive = new BasicSearch(true, false);
+ BasicSearch bsCaseInsensitive = new BasicSearch(false, false);
+ BasicSearch bsCaseSensitiveRegexp = new BasicSearch(true, true);
+ BasicSearch bsCaseInsensitiveRegexp = new BasicSearch(false, true);
+
+ String query = "marine 2001 shields";
+
+ assertEquals(0, bsCaseSensitive.applyRule(query, be));
+ assertEquals(1, bsCaseInsensitive.applyRule(query, be));
+ assertEquals(0, bsCaseSensitiveRegexp.applyRule(query, be));
+ assertEquals(1, bsCaseInsensitiveRegexp.applyRule(query, be));
+
+ query = "\"marine larviculture\"";
+
+ assertEquals(0, bsCaseSensitive.applyRule(query, be));
+ assertEquals(0, bsCaseInsensitive.applyRule(query, be));
+ assertEquals(0, bsCaseSensitiveRegexp.applyRule(query, be));
+ assertEquals(0, bsCaseInsensitiveRegexp.applyRule(query, be));
+
+ query = "\"marine [A-Za-z]* larviculture\"";
+
+ assertEquals(0, bsCaseSensitive.applyRule(query, be));
+ assertEquals(0, bsCaseInsensitive.applyRule(query, be));
+ assertEquals(0, bsCaseSensitiveRegexp.applyRule(query, be));
+ assertEquals(1, bsCaseInsensitiveRegexp.applyRule(query, be));
+
+
+ }
+
+ public BibtexEntry makeBibtexEntry() {
+ BibtexEntry e = new BibtexEntry(Util.createNeutralId(), BibtexEntryType.INCOLLECTION);
+ e.setField("title", "Marine finfish larviculture in Europe");
+ e.setField("bibtexkey", "shields01");
+ e.setField("year", "2001");
+ e
+ .setField(
+ "author",
+ "Kevin Shields");
+ return e;
+ }
+}
+
diff --git a/src/java/tests/net/sf/jabref/util/AllTests.java b/src/java/tests/net/sf/jabref/util/AllTests.java
new file mode 100644
index 0000000..41847ce
--- /dev/null
+++ b/src/java/tests/net/sf/jabref/util/AllTests.java
@@ -0,0 +1,18 @@
+package tests.net.sf.jabref.util;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+public class AllTests {
+
+ public static Test suite() {
+ TestSuite suite = new TestSuite("Test for tests.net.sf.jabref.util");
+ //$JUnit-BEGIN$
+ suite.addTestSuite(CaseChangerTest.class);
+ suite.addTestSuite(XMPUtilTest.class);
+ suite.addTestSuite(XMPSchemaBibtexTest.class);
+ //$JUnit-END$
+ return suite;
+ }
+
+}
diff --git a/src/java/tests/net/sf/jabref/util/CaseChangerTest.java b/src/java/tests/net/sf/jabref/util/CaseChangerTest.java
new file mode 100644
index 0000000..49a4101
--- /dev/null
+++ b/src/java/tests/net/sf/jabref/util/CaseChangerTest.java
@@ -0,0 +1,58 @@
+package tests.net.sf.jabref.util;
+
+import junit.framework.TestCase;
+import net.sf.jabref.util.CaseChanger;
+
+public class CaseChangerTest extends TestCase {
+
+ public void testNumberOfModes() {
+
+ // If this fails we know there are new modes
+ assertEquals(4, CaseChanger.getNumModes());
+ assertEquals(4, CaseChanger.getModeNames().length);
+
+ String[] modeNames = CaseChanger.getModeNames();
+ for (int i = 0; i < CaseChanger.getNumModes(); i++){
+ assertEquals(CaseChanger.getModeName(i), modeNames[i]);
+ }
+ assertEquals("lower", CaseChanger.getModeName(0));
+ assertEquals("UPPER", CaseChanger.getModeName(1));
+ assertEquals("Upper first", CaseChanger.getModeName(2));
+ assertEquals("Upper Each First", CaseChanger.getModeName(3));
+ }
+
+ public void testChangeCaseStringArrayInt() {
+ String[] s = new String[0];
+ assertEquals(0, CaseChanger.changeCase(s, 0).length);
+
+ s = new String[]{"UPPER", "UPdownUPdown", "Mary has a little Lamb"};
+
+ s = CaseChanger.changeCase(s,0);
+ assertEquals(3, s.length);
+ assertEquals("upper", s[0]);
+ assertEquals("updownupdown", s[1]);
+ assertEquals("mary has a little lamb", s[2]);
+ }
+
+ public void testChangeCaseStringInt() {
+
+ assertEquals("", CaseChanger.changeCase("", 0));
+ assertEquals("", CaseChanger.changeCase("", 1));
+ assertEquals("", CaseChanger.changeCase("", 2));
+ assertEquals("", CaseChanger.changeCase("", 3));
+
+ assertEquals("lower", CaseChanger.changeCase("LOWER", 0));
+ assertEquals("LOWER", CaseChanger.changeCase("LOWER", 1));
+ assertEquals("UPPER", CaseChanger.changeCase("upper", 1));
+ assertEquals("UPPER", CaseChanger.changeCase("UPPER", 1));
+
+ assertEquals("Upper first", CaseChanger.changeCase("upper First", 2));
+
+ assertEquals("Upper Each First", CaseChanger.changeCase("upper each First", 3));
+ }
+
+ public void testPreserveBrackets(){
+
+
+ }
+}
diff --git a/src/java/tests/net/sf/jabref/util/XMPSchemaBibtexTest.java b/src/java/tests/net/sf/jabref/util/XMPSchemaBibtexTest.java
new file mode 100644
index 0000000..7ea7d28
--- /dev/null
+++ b/src/java/tests/net/sf/jabref/util/XMPSchemaBibtexTest.java
@@ -0,0 +1,245 @@
+package tests.net.sf.jabref.util;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+import net.sf.jabref.BibtexEntry;
+import net.sf.jabref.util.XMPSchemaBibtex;
+
+import org.jempbox.impl.XMLUtil;
+import org.jempbox.xmp.XMPMetadata;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+
+import tests.net.sf.jabref.FileBasedTestCase;
+import tests.net.sf.jabref.JabRefTestCase;
+
+public class XMPSchemaBibtexTest extends JabRefTestCase {
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ public void testXMPSchemaBibtexXMPMetadata() throws IOException {
+
+ XMPMetadata xmp = new XMPMetadata();
+ XMPSchemaBibtex bibtex = new XMPSchemaBibtex(xmp);
+
+ assertNotNull(bibtex.getElement());
+ assertEquals("rdf:Description", bibtex.getElement().getTagName());
+
+ }
+
+ public void testXMPSchemaBibtexElement() throws ParserConfigurationException {
+ DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
+ DocumentBuilder builder = builderFactory.newDocumentBuilder();
+ Element e = builder.newDocument().createElement("rdf:Description");
+
+ XMPSchemaBibtex bibtex = new XMPSchemaBibtex(e);
+
+ assertEquals(e, bibtex.getElement());
+ assertEquals("rdf:Description", bibtex.getElement().getTagName());
+ }
+
+ public void testGetSetPersonList() throws IOException {
+ XMPMetadata xmp = new XMPMetadata();
+ XMPSchemaBibtex bibtex = new XMPSchemaBibtex(xmp);
+
+ bibtex.setPersonList("author", "Tom DeMarco and Kent Beck");
+
+ Element e = bibtex.getElement();
+
+ NodeList l1 = e.getElementsByTagName("bibtex:author");
+ assertEquals(1, l1.getLength());
+
+ NodeList l = e.getElementsByTagName("rdf:li");
+
+ assertEquals(2, l.getLength());
+
+ assertEquals("Tom DeMarco", XMLUtil.getStringValue(((Element) l.item(0))));
+ assertEquals("Kent Beck", XMLUtil.getStringValue(((Element) l.item(1))));
+
+ List authors = bibtex.getPersonList("author");
+ assertEquals(2, authors.size());
+
+ assertEquals("Tom DeMarco", authors.get(0));
+ assertEquals("Kent Beck", authors.get(1));
+ }
+
+ public void testSetGetTextPropertyString() throws IOException {
+ XMPMetadata xmp = new XMPMetadata();
+ XMPSchemaBibtex bibtex = new XMPSchemaBibtex(xmp);
+
+ bibtex.setTextProperty("title", "The advanced Flux-Compensation for Delawney-Separation");
+
+ Element e = bibtex.getElement();
+ assertEquals("The advanced Flux-Compensation for Delawney-Separation", e
+ .getAttribute("bibtex:title"));
+
+ assertEquals("The advanced Flux-Compensation for Delawney-Separation", bibtex
+ .getTextProperty("title"));
+
+ bibtex.setTextProperty("title", "The advanced Flux-Correlation for Delawney-Separation");
+
+ e = bibtex.getElement();
+ assertEquals("The advanced Flux-Correlation for Delawney-Separation", e
+ .getAttribute("bibtex:title"));
+
+ assertEquals("The advanced Flux-Correlation for Delawney-Separation", bibtex
+ .getTextProperty("title"));
+
+ bibtex.setTextProperty("abstract", " The abstract\n can go \n \n on several \n lines with \n many \n\n empty ones in \n between.");
+ assertEquals(" The abstract\n can go \n \n on several \n lines with \n many \n\n empty ones in \n between.", bibtex.getTextProperty("abstract"));
+ }
+
+ public void testSetGetBagListString() throws IOException {
+
+ XMPMetadata xmp = new XMPMetadata();
+ XMPSchemaBibtex bibtex = new XMPSchemaBibtex(xmp);
+
+ bibtex.addBagValue("author", "Tom DeMarco");
+ bibtex.addBagValue("author", "Kent Beck");
+ {
+
+ List l = bibtex.getBagList("author");
+
+ assertEquals(2, l.size());
+
+ assertTrue(l.get(0).equals("Tom DeMarco") || l.get(1).equals("Tom DeMarco"));
+ assertTrue(l.get(0).equals("Kent Beck") || l.get(1).equals("Kent Beck"));
+ }
+ {
+ bibtex.removeBagValue("author", "Kent Beck");
+ List l = bibtex.getBagList("author");
+ assertEquals(1, l.size());
+ assertTrue(l.get(0).equals("Tom DeMarco"));
+ }
+ { // Already removed
+ bibtex.removeBagValue("author", "Kent Beck");
+ List l = bibtex.getBagList("author");
+ assertEquals(1, l.size());
+ assertTrue(l.get(0).equals("Tom DeMarco"));
+ }
+ { // Duplicates allowed!
+ bibtex.addBagValue("author", "Tom DeMarco");
+ List l = bibtex.getBagList("author");
+ assertEquals(2, l.size());
+ assertTrue(l.get(0).equals("Tom DeMarco"));
+ assertTrue(l.get(1).equals("Tom DeMarco"));
+ }
+ { // Removes both
+ bibtex.removeBagValue("author", "Tom DeMarco");
+ List l = bibtex.getBagList("author");
+ assertEquals(0, l.size());
+ }
+ }
+
+ public void testGetSequenceListString() throws IOException {
+
+ XMPMetadata xmp = new XMPMetadata();
+ XMPSchemaBibtex bibtex = new XMPSchemaBibtex(xmp);
+
+ bibtex.addSequenceValue("author", "Tom DeMarco");
+ bibtex.addSequenceValue("author", "Kent Beck");
+ {
+
+ List l = bibtex.getSequenceList("author");
+
+ assertEquals(2, l.size());
+
+ assertEquals("Tom DeMarco", l.get(0));
+ assertEquals("Kent Beck", l.get(1));
+ }
+ {
+ bibtex.removeSequenceValue("author", "Tom DeMarco");
+ List l = bibtex.getSequenceList("author");
+ assertEquals(1, l.size());
+ assertTrue(l.get(0).equals("Kent Beck"));
+ }
+ { // Already removed
+ bibtex.removeSequenceValue("author", "Tom DeMarco");
+ List l = bibtex.getSequenceList("author");
+ assertEquals(1, l.size());
+ assertTrue(l.get(0).equals("Kent Beck"));
+ }
+ { // Duplicates allowed!
+ bibtex.addSequenceValue("author", "Kent Beck");
+ List l = bibtex.getSequenceList("author");
+ assertEquals(2, l.size());
+ assertTrue(l.get(0).equals("Kent Beck"));
+ assertTrue(l.get(1).equals("Kent Beck"));
+ }
+ { // Remvoes all
+ bibtex.removeSequenceValue("author", "Kent Beck");
+ List l = bibtex.getSequenceList("author");
+ assertEquals(0, l.size());
+ }
+ }
+
+ public void testSetRemoveGetSequenceDateListString() {
+ // We don't use this...
+ }
+
+ public void testGetAllProperties() throws IOException {
+ XMPMetadata xmp = new XMPMetadata();
+ XMPSchemaBibtex bibtex = new XMPSchemaBibtex(xmp);
+
+ bibtex.setTextProperty("title", "BlaBla Ta Ta\nHello World");
+ bibtex.setTextProperty("abstract", "BlaBla Ta Ta\nHello World");
+ bibtex.setTextProperty("review", "BlaBla Ta Ta\nHello World");
+ bibtex.setTextProperty("note", "BlaBla Ta Ta\nHello World");
+ bibtex.setPersonList("author", "Mouse, Mickey and Bond, James");
+
+ Map s = bibtex.getAllProperties();
+
+ assertEquals(5, s.size());
+ assertTrue(s.containsKey("title"));
+ assertTrue(s.containsKey("author"));
+
+ assertEquals("BlaBla Ta Ta Hello World", s.get("title"));
+ assertEquals("BlaBla Ta Ta\nHello World", s.get("abstract"));
+ assertEquals("BlaBla Ta Ta\nHello World", s.get("review"));
+ assertEquals("BlaBla Ta Ta\nHello World", s.get("note"));
+ assertEquals("Mickey Mouse and James Bond", s.get("author"));
+ }
+
+ public void testSetBibtexEntry() throws IOException {
+
+ XMPMetadata xmp = new XMPMetadata();
+ XMPSchemaBibtex bibtex = new XMPSchemaBibtex(xmp);
+
+ BibtexEntry e = FileBasedTestCase.getBibtexEntry();
+ bibtex.setBibtexEntry(e);
+
+ BibtexEntry e2 = bibtex.getBibtexEntry();
+
+ assertEquals(e, e2);
+ }
+
+ public void testGetTextContent() throws IOException {
+ String bibtexString = "<bibtex:year>2003</bibtex:year>\n"
+ + "<bibtex:title>\n " +
+ "Beach sand convolution by surf-wave optimzation\n" +
+ "</bibtex:title>\n"
+ + "<bibtex:bibtexkey>OezbekC06</bibtex:bibtexkey>\n";
+
+ bibtexString = XMPUtilTest.bibtexXPacket(XMPUtilTest.bibtexDescription(bibtexString));
+
+ Document d = XMLUtil.parse(new ByteArrayInputStream(bibtexString.getBytes()));
+
+ assertEquals("Beach sand convolution by surf-wave optimzation", XMPSchemaBibtex.getTextContent(d.getElementsByTagName("bibtex:title").item(0)).trim());
+
+ }
+
+}
diff --git a/src/java/tests/net/sf/jabref/util/XMPUtilTest.java b/src/java/tests/net/sf/jabref/util/XMPUtilTest.java
new file mode 100644
index 0000000..7067c07
--- /dev/null
+++ b/src/java/tests/net/sf/jabref/util/XMPUtilTest.java
@@ -0,0 +1,1122 @@
+package tests.net.sf.jabref.util;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.io.PrintStream;
+import java.io.Reader;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.util.Calendar;
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.TimeZone;
+
+import javax.xml.transform.TransformerException;
+
+import junit.framework.TestCase;
+import net.sf.jabref.BibtexEntry;
+import net.sf.jabref.BibtexEntryType;
+import net.sf.jabref.Globals;
+import net.sf.jabref.JabRefPreferences;
+import net.sf.jabref.Util;
+import net.sf.jabref.imports.BibtexParser;
+import net.sf.jabref.imports.ParserResult;
+import net.sf.jabref.util.EncryptionNotSupportedException;
+import net.sf.jabref.util.XMPSchemaBibtex;
+import net.sf.jabref.util.XMPUtil;
+
+import org.jempbox.xmp.XMPMetadata;
+import org.jempbox.xmp.XMPSchemaBasic;
+import org.jempbox.xmp.XMPSchemaDublinCore;
+import org.jempbox.xmp.XMPSchemaMediaManagement;
+import org.pdfbox.exceptions.COSVisitorException;
+import org.pdfbox.pdmodel.PDDocument;
+import org.pdfbox.pdmodel.PDDocumentCatalog;
+import org.pdfbox.pdmodel.PDPage;
+import org.pdfbox.pdmodel.common.PDMetadata;
+import org.pdfbox.util.XMLUtil;
+
+/**
+ *
+ * Limitations: The test suite only handles UTF8. Not UTF16.
+ *
+ * @author Christopher Oezbek <oezi at oezi.de>
+ */
+public class XMPUtilTest extends TestCase {
+
+ /**
+ * Wrap bibtex-data (<bibtex:author>...) into an rdf:Description.
+ *
+ * @param bibtex
+ * @return
+ */
+ public static String bibtexDescription(String bibtex) {
+ return " <rdf:Description rdf:about='' xmlns:bibtex='http://jabref.sourceforge.net/bibteXMP/'>\n"
+ + bibtex + "\n" + " </rdf:Description>\n";
+ }
+
+ /**
+ * Wrap bibtex-descriptions (rdf:Description) into the xpacket header.
+ *
+ * @param bibtexDescriptions
+ * @return
+ */
+ public static String bibtexXPacket(String bibtexDescriptions) {
+
+ StringBuffer xmp = new StringBuffer();
+
+ xmp.append("<?xpacket begin='' id='W5M0MpCehiHzreSzNTczkc9d'?>\n");
+ xmp.append(" <x:xmpmeta xmlns:x='adobe:ns:meta/'>\n");
+ xmp
+ .append(" <rdf:RDF xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#' xmlns:iX='http://ns.adobe.com/iX/1.0/' xmlns:rdfs='http://www.w3.org/2000/01/rdf-schema#'>\n");
+
+ xmp.append(bibtexDescriptions);
+
+ xmp.append(" </rdf:RDF>\n");
+ xmp.append(" </x:xmpmeta>\n");
+ xmp.append("<?xpacket end='r'?>");
+
+ return xmp.toString();
+ }
+
+ /**
+ * Write a manually constructed xmp-string to file
+ *
+ * @param xmpString
+ * @throws Exception
+ */
+ public void writeManually(File tempFile, String xmpString) throws Exception {
+
+ PDDocument document = null;
+
+ try {
+ document = PDDocument.load(tempFile.getAbsoluteFile());
+ if (document.isEncrypted()) {
+ System.err.println("Error: Cannot add metadata to encrypted document.");
+ System.exit(1);
+ }
+ PDDocumentCatalog catalog = document.getDocumentCatalog();
+ PDMetadata meta = catalog.getMetadata();
+
+ // Convert to UTF8 and make available for metadata.
+ ByteArrayOutputStream bs = new ByteArrayOutputStream();
+ OutputStreamWriter os = new OutputStreamWriter(bs, "UTF8");
+ os.write(xmpString);
+ os.close();
+ ByteArrayInputStream in = new ByteArrayInputStream(bs.toByteArray());
+
+ PDMetadata metadataStream = new PDMetadata(document, in, false);
+ catalog.setMetadata(metadataStream);
+
+ document.save(tempFile.getAbsolutePath());
+
+ } finally {
+ if (document != null)
+ document.close();
+ }
+ }
+
+ public static BibtexEntry bibtexString2BibtexEntry(String s) throws IOException {
+ ParserResult result = BibtexParser.parse(new StringReader(s));
+ Collection c = result.getDatabase().getEntries();
+ assertEquals(1, c.size());
+ return (BibtexEntry) c.iterator().next();
+ }
+
+ public static String bibtexEntry2BibtexString(BibtexEntry e) throws IOException {
+ StringWriter sw = new StringWriter();
+ e.write(sw, new net.sf.jabref.export.LatexFieldFormatter(), false);
+ return sw.getBuffer().toString();
+ }
+
+ /* TEST DATA */
+ public String t1BibtexString() {
+ return "@article{canh05,\n"
+ + " author = {Crowston, K. and Annabi, H. and Howison, J. and Masango, C.},\n"
+ + " title = {Effective work practices for floss development: A model and propositions},\n"
+ + " booktitle = {Hawaii International Conference On System Sciences (HICSS)},\n"
+ + " year = {2005},\n" + " owner = {oezbek},\n" + " timestamp = {2006.05.29},\n"
+ + " url = {http://james.howison.name/publications.html}}\n";
+ }
+
+ public BibtexEntry t1BibtexEntry() throws IOException {
+ return bibtexString2BibtexEntry(t1BibtexString());
+ }
+
+ public String t2XMP() {
+ return "<rdf:Description rdf:about='' xmlns:bibtex='http://jabref.sourceforge.net/bibteXMP/' "
+ + "bibtex:title='�pt�mz�t��n' "
+ + "bibtex:bibtexkey='OezbekC06' "
+ + "bibtex:entrytype='INCOLLECTION' "
+ + "bibtex:year='2003' "
+ + "bibtex:booktitle='Proceedings of the of the 25th International Conference on \n Software-Engineering (Portland, Oregon)' "
+ + ">\n" + "<bibtex:pdf>YeKis03 - Towards.pdf</bibtex:pdf>\n" + "</rdf:Description>\n";
+ }
+
+ public String t2BibtexString() throws IOException {
+ return bibtexEntry2BibtexString(t2BibtexEntry());
+ }
+
+ public BibtexEntry t2BibtexEntry() {
+ BibtexEntry e = new BibtexEntry(Util.createNeutralId(), BibtexEntryType.INCOLLECTION);
+ e.setField("title", "�pt�mz�t��n");
+ e.setField("bibtexkey", "OezbekC06");
+ e.setField("year", "2003");
+ e
+ .setField(
+ "booktitle",
+ "Proceedings of the of the 25th International Conference on Software-Engineering (Portland, Oregon)");
+ e.setField("pdf", "YeKis03 - Towards.pdf");
+ return e;
+ }
+
+ public BibtexEntry t3BibtexEntry() {
+ BibtexEntry e = new BibtexEntry(Util.createNeutralId(), BibtexEntryType.OTHER);
+ e.setField("title", "Hypersonic ultra-sound");
+ e.setField("bibtexkey", "Clarkson06");
+ e.setField("author", "Kelly Clarkson and Ozzy Osbourne");
+ e.setField("editor", "Huey Duck and Dewey Duck and Louie Duck");
+ e.setField("pdf", "YeKis03 - Towards.pdf");
+ return e;
+ }
+
+ public String t3BibtexString() throws IOException {
+ return bibtexEntry2BibtexString(t3BibtexEntry());
+ }
+
+ public String t3XMP() {
+ return bibtexDescription("<bibtex:title>Hypersonic ultra-sound</bibtex:title>\n"
+ + "<bibtex:author><rdf:Seq>\n" + " <rdf:li>Kelly Clarkson</rdf:li>"
+ + " <rdf:li>Ozzy Osbourne</rdf:li>" + "</rdf:Seq></bibtex:author>"
+ + "<bibtex:editor><rdf:Seq>" + " <rdf:li>Huey Duck</rdf:li>"
+ + " <rdf:li>Dewey Duck</rdf:li>" + " <rdf:li>Louie Duck</rdf:li>"
+ + "</rdf:Seq></bibtex:editor>" + "<bibtex:bibtexkey>Clarkson06</bibtex:bibtexkey>");
+ }
+
+ /**
+ * The PDF file that basically all operations are done upon.
+ */
+ File pdfFile;
+
+ /**
+ * Create a temporary PDF-file with a single empty page.
+ */
+ public void setUp() throws IOException, COSVisitorException {
+
+ pdfFile = File.createTempFile("JabRef", ".pdf");
+
+ PDDocument pdf = null;
+ try {
+ pdf = new PDDocument();
+ pdf.addPage(new PDPage()); // Need page to open in Acrobat
+ pdf.save(pdfFile.getAbsolutePath());
+ } finally {
+ if (pdf != null)
+ pdf.close();
+ }
+
+ // Don't forget to initialize the preferences
+ if (Globals.prefs == null) {
+ Globals.prefs = JabRefPreferences.getInstance();
+ }
+
+ }
+
+ /**
+ * Delete the temporary file.
+ */
+ public void tearDown() {
+ pdfFile.delete();
+ }
+
+ /**
+ * Most basic test for reading.
+ *
+ * @throws Exception
+ */
+ public void testReadXMPSimple() throws Exception {
+
+ String bibtex = "<bibtex:year>2003</bibtex:year>\n"
+ + "<bibtex:title>Beach sand convolution by surf-wave optimzation</bibtex:title>\n"
+ + "<bibtex:bibtexkey>OezbekC06</bibtex:bibtexkey>\n";
+
+ writeManually(pdfFile, bibtexXPacket(bibtexDescription(bibtex)));
+
+ List l = XMPUtil.readXMP(pdfFile.getAbsoluteFile());
+ assertEquals(1, l.size());
+ BibtexEntry e = (BibtexEntry) l.get(0);
+
+ assertNotNull(e);
+ assertEquals("OezbekC06", e.getCiteKey());
+ assertEquals("2003", e.getField("year"));
+ assertEquals("Beach sand convolution by surf-wave optimzation", e.getField("title"));
+ assertEquals(BibtexEntryType.OTHER, e.getType());
+
+ }
+
+ /**
+ * Is UTF8 handling working? This is because Java by default uses the
+ * platform encoding or a special UTF-kind.
+ *
+ * @throws Exception
+ */
+ public void testReadXMPUTF8() throws Exception {
+
+ String bibtex = "<bibtex:year>2003</bibtex:year>\n"
+ + "<bibtex:title>�pt�mz�t��n</bibtex:title>\n"
+ + "<bibtex:bibtexkey>OezbekC06</bibtex:bibtexkey>\n";
+
+ writeManually(pdfFile, bibtexXPacket(bibtexDescription(bibtex)));
+
+ List l = XMPUtil.readXMP(pdfFile.getAbsoluteFile());
+ assertEquals(1, l.size());
+ BibtexEntry e = (BibtexEntry) l.get(0);
+
+ assertNotNull(e);
+ assertEquals("OezbekC06", e.getCiteKey());
+ assertEquals("2003", e.getField("year"));
+ assertEquals("�pt�mz�t��n", e.getField("title"));
+ assertEquals(BibtexEntryType.OTHER, e.getType());
+ }
+
+ /**
+ * Are authors and editors correctly read?
+ *
+ * @throws Exception
+ */
+ public void testReadXMPSeq() throws Exception {
+
+ String bibtex = "<bibtex:author><rdf:Seq>\n" + " <rdf:li>Kelly Clarkson</rdf:li>"
+ + " <rdf:li>Ozzy Osbourne</rdf:li>" + "</rdf:Seq></bibtex:author>"
+ + "<bibtex:editor><rdf:Seq>" + " <rdf:li>Huey Duck</rdf:li>"
+ + " <rdf:li>Dewey Duck</rdf:li>" + " <rdf:li>Louie Duck</rdf:li>"
+ + "</rdf:Seq></bibtex:editor>" + "<bibtex:bibtexkey>Clarkson06</bibtex:bibtexkey>";
+
+ writeManually(pdfFile, bibtexXPacket(bibtexDescription(bibtex)));
+
+ List l = XMPUtil.readXMP(pdfFile.getAbsoluteFile());
+ assertEquals(1, l.size());
+ BibtexEntry e = (BibtexEntry) l.get(0);
+
+ assertNotNull(e);
+ assertEquals("Clarkson06", e.getCiteKey());
+ assertEquals("Kelly Clarkson and Ozzy Osbourne", e.getField("author"));
+ assertEquals("Huey Duck and Dewey Duck and Louie Duck", e.getField("editor"));
+ assertEquals(BibtexEntryType.OTHER, e.getType());
+ }
+
+ /**
+ * Is the XMPEntryType correctly set?
+ *
+ * @throws Exception
+ */
+ public void testReadXMPEntryType() throws Exception {
+
+ String bibtex = "<bibtex:entrytype>ARticle</bibtex:entrytype>";
+
+ writeManually(pdfFile, bibtexXPacket(bibtexDescription(bibtex)));
+
+ List l = XMPUtil.readXMP(pdfFile.getAbsoluteFile());
+ assertEquals(1, l.size());
+ BibtexEntry e = (BibtexEntry) l.get(0);
+
+ assertNotNull(e);
+ assertEquals(BibtexEntryType.ARTICLE, e.getType());
+ }
+
+ public static String readManually(File tempFile) throws IOException {
+
+ PDDocument document = null;
+
+ try {
+ document = PDDocument.load(tempFile.getAbsoluteFile());
+ if (document.isEncrypted()) {
+ System.err.println("Error: Cannot add metadata to encrypted document.");
+ System.exit(1);
+ }
+ PDDocumentCatalog catalog = document.getDocumentCatalog();
+ PDMetadata meta = catalog.getMetadata();
+
+ if (meta == null) {
+ return null;
+ } else {
+ // PDMetadata.getInputStreamAsString() does not work
+
+ // Convert to UTF8 and make available for metadata.
+ InputStreamReader is = new InputStreamReader(meta.createInputStream(), "UTF8");
+ return slurp(is).trim(); // Trim to kill padding end-newline.
+ }
+ } finally {
+ if (document != null)
+ document.close();
+ }
+ }
+
+ /**
+ * Test whether the helper function work correctly.
+ *
+ * @throws Exception
+ */
+ public void testWriteReadManually() throws Exception {
+
+ String bibtex = "<bibtex:year>2003</bibtex:year>\n"
+ + "<bibtex:title>�pt�mz�t��n</bibtex:title>\n"
+ + "<bibtex:bibtexkey>OezbekC06</bibtex:bibtexkey>\n";
+
+ writeManually(pdfFile, bibtexXPacket(bibtexDescription(bibtex)));
+ assertEquals(bibtexXPacket(bibtexDescription(bibtex)), readManually(pdfFile));
+
+ bibtex = "<bibtex:author><rdf:Seq>\n" + " <rdf:li>Kelly Clarkson</rdf:li>"
+ + " <rdf:li>Ozzy Osbourne</rdf:li>" + "</rdf:Seq></bibtex:author>"
+ + "<bibtex:editor><rdf:Seq>" + " <rdf:li>Huey Duck</rdf:li>"
+ + " <rdf:li>Dewey Duck</rdf:li>" + " <rdf:li>Louie Duck</rdf:li>"
+ + "</rdf:Seq></bibtex:editor>" + "<bibtex:bibtexkey>Clarkson06</bibtex:bibtexkey>";
+
+ writeManually(pdfFile, bibtexXPacket(bibtexDescription(bibtex)));
+ assertEquals(bibtexXPacket(bibtexDescription(bibtex)), readManually(pdfFile));
+ }
+
+ /**
+ * Test that readXMP and writeXMP work together.
+ *
+ * @throws Exception
+ */
+ public void testReadWriteXMP() throws Exception {
+ ParserResult result = BibtexParser
+ .parse(new StringReader(
+ "@article{canh05,"
+ + " author = {Crowston, K. and Annabi, H. and Howison, J. and Masango, C.},"
+ + "\n"
+ + " title = {Effective work practices for floss development: A model and propositions},"
+ + "\n"
+ + " booktitle = {Hawaii International Conference On System Sciences (HICSS)},"
+ + "\n" + " year = {2005}," + "\n" + " owner = {oezbek}," + "\n"
+ + " timestamp = {2006.05.29}," + "\n"
+ + " url = {http://james.howison.name/publications.html}" + "\n" + "}"));
+
+ Collection c = result.getDatabase().getEntries();
+ assertEquals(1, c.size());
+
+ BibtexEntry e = (BibtexEntry) c.iterator().next();
+
+ XMPUtil.writeXMP(pdfFile, e);
+
+ List l = XMPUtil.readXMP(pdfFile.getAbsoluteFile());
+ assertEquals(1, l.size());
+ BibtexEntry x = (BibtexEntry) l.get(0);
+
+ assertEquals(e.getCiteKey(), x.getCiteKey());
+ assertEquals(e.getType(), x.getType());
+
+ Object[] o = e.getAllFields();
+
+ for (int i = 0; i < o.length; i++) {
+ assertEquals(e.getField(o.toString()), x.getField(o.toString()));
+ }
+ }
+
+ /**
+ * Are newlines in the XML processed correctly?
+ *
+ * @throws Exception
+ */
+ public void testNewlineHandling() throws Exception {
+
+ {
+ String bibtex = "<bibtex:title>\nHallo\nWorld \nthis \n is\n\nnot \n\nan \n\n exercise \n \n.\n \n\n</bibtex:title>\n"
+ + "<bibtex:tabs>\nHallo\tWorld \tthis \t is\t\tnot \t\tan \t\n exercise \t \n.\t \n\t</bibtex:tabs>\n" +
+ "<bibtex:abstract>\n\nAbstract preserve\n\t Whitespace\n\n</bibtex:abstract>";
+
+ writeManually(pdfFile, bibtexXPacket(bibtexDescription(bibtex)));
+
+ List l = XMPUtil.readXMP(pdfFile.getAbsoluteFile());
+ assertEquals(1, l.size());
+ BibtexEntry e = (BibtexEntry) l.get(0);
+
+ assertNotNull(e);
+ assertEquals("Hallo World this is not an exercise .", e.getField("title"));
+ assertEquals("Hallo World this is not an exercise .", e.getField("tabs"));
+ assertEquals("\n\nAbstract preserve\n\t Whitespace\n\n", e.getField("abstract"));
+ }
+ }
+
+ /**
+ * Test whether XMP.readFile can deal with text-properties that are not
+ * element-nodes, but attribute-nodes
+ *
+ * @throws Exception
+ */
+ public void testAttributeRead() throws Exception {
+
+ // test 1 has attributes
+ String bibtex = t2XMP();
+
+ writeManually(pdfFile, bibtexXPacket(bibtex));
+
+ List l = XMPUtil.readXMP(pdfFile.getAbsoluteFile());
+ assertEquals(1, l.size());
+ BibtexEntry e = (BibtexEntry) l.get(0);
+
+ assertEquals(t2BibtexEntry(), e);
+ }
+
+ public void testEmpty() throws Exception {
+
+ assertEquals(null, XMPUtil.readXMP(pdfFile));
+
+ }
+
+ /**
+ * Tests whether writing BibTex.xmp will preserve existing XMP-descriptions.
+ *
+ * @throws Exception
+ * (indicating an failure)
+ */
+ public void testSimpleUpdate() throws Exception {
+
+ String s = " <rdf:Description rdf:about=''" + " xmlns:xmp='http://ns.adobe.com/xap/1.0/'>"
+ + " <xmp:CreatorTool>Acrobat PDFMaker 7.0.7</xmp:CreatorTool>"
+ + " <xmp:ModifyDate>2006-08-07T18:50:24+02:00</xmp:ModifyDate>"
+ + " <xmp:CreateDate>2006-08-07T14:44:24+02:00</xmp:CreateDate>"
+ + " <xmp:MetadataDate>2006-08-07T18:50:24+02:00</xmp:MetadataDate>"
+ + " </rdf:Description>" + "" + " <rdf:Description rdf:about=''"
+ + " xmlns:xapMM='http://ns.adobe.com/xap/1.0/mm/'>"
+ + " <xapMM:DocumentID>uuid:843cd67d-495e-4c1e-a4cd-64178f6b3299</xapMM:DocumentID>"
+ + " <xapMM:InstanceID>uuid:1e56b4c0-6782-440d-ba76-d2b3d87547d1</xapMM:InstanceID>"
+ + " <xapMM:VersionID>" + " <rdf:Seq>" + " <rdf:li>17</rdf:li>" + " </rdf:Seq>"
+ + " </xapMM:VersionID>" + " </rdf:Description>" + ""
+ + " <rdf:Description rdf:about=''" + " xmlns:dc='http://purl.org/dc/elements/1.1/'>"
+ + " <dc:format>application/pdf</dc:format>" + " <dc:title>" + " <rdf:Alt>"
+ + " <rdf:li xml:lang='x-default'>Questionnaire.pdf</rdf:li>" + " </rdf:Alt>"
+ + " </dc:title>" + "" + "</rdf:Description>";
+
+ writeManually(pdfFile, bibtexXPacket(s));
+
+ // Nothing there yet, but should not crash
+ assertEquals(0, XMPUtil.readXMP(pdfFile).size());
+
+ {
+ // Now write new packet and check if it was correctly written
+ XMPUtil.writeXMP(pdfFile, t1BibtexEntry());
+
+ List l = XMPUtil.readXMP(pdfFile.getAbsoluteFile());
+ assertEquals(1, l.size());
+ BibtexEntry e = (BibtexEntry) l.get(0);
+
+ assertEquals(t1BibtexEntry(), e);
+
+ // This is what we really want to test: Is the rest of the
+ // descriptions still there?
+
+ PDDocument document = null;
+ try {
+ document = PDDocument.load(pdfFile.getAbsoluteFile());
+ if (document.isEncrypted()) {
+ throw new IOException("Error: Cannot read metadata from encrypted document.");
+ }
+ PDDocumentCatalog catalog = document.getDocumentCatalog();
+ PDMetadata metaRaw = catalog.getMetadata();
+
+ XMPMetadata meta;
+ if (metaRaw != null) {
+ meta = new XMPMetadata(XMLUtil.parse(metaRaw.createInputStream()));
+ } else {
+ meta = new XMPMetadata();
+ }
+ meta.addXMLNSMapping(XMPSchemaBibtex.NAMESPACE, XMPSchemaBibtex.class);
+
+ List schemas = meta.getSchemas();
+
+ assertEquals(4, schemas.size());
+
+ schemas = meta.getSchemasByNamespaceURI(XMPSchemaBibtex.NAMESPACE);
+ assertEquals(1, schemas.size());
+
+ schemas = meta.getSchemasByNamespaceURI(XMPSchemaDublinCore.NAMESPACE);
+ assertEquals(1, schemas.size());
+ XMPSchemaDublinCore dc = (XMPSchemaDublinCore) schemas.get(0);
+ assertEquals("application/pdf", dc.getFormat());
+
+ schemas = meta.getSchemasByNamespaceURI(XMPSchemaBasic.NAMESPACE);
+ assertEquals(1, schemas.size());
+ XMPSchemaBasic bs = (XMPSchemaBasic) schemas.get(0);
+ assertEquals("Acrobat PDFMaker 7.0.7", bs.getCreatorTool());
+
+ Calendar c = Calendar.getInstance();
+ c.clear();
+ c.set(Calendar.YEAR, 2006);
+ c.set(Calendar.MONTH, 8);
+ c.set(Calendar.DATE, 7);
+ c.set(Calendar.HOUR, 14);
+ c.set(Calendar.MINUTE, 44);
+ c.set(Calendar.SECOND, 24);
+ c.setTimeZone(TimeZone.getTimeZone("GMT+2"));
+
+ Calendar other = bs.getCreateDate();
+
+ assertEquals(c.get(Calendar.YEAR), other.get(Calendar.YEAR));
+ assertEquals(c.get(Calendar.MONTH), other.get(Calendar.MONTH));
+ assertEquals(c.get(Calendar.DATE), other.get(Calendar.DATE));
+ assertEquals(c.get(Calendar.HOUR), other.get(Calendar.HOUR));
+ assertEquals(c.get(Calendar.MINUTE), other.get(Calendar.MINUTE));
+ assertEquals(c.get(Calendar.SECOND), other.get(Calendar.SECOND));
+ assertTrue(c.getTimeZone().hasSameRules(other.getTimeZone()));
+
+ schemas = meta.getSchemasByNamespaceURI(XMPSchemaMediaManagement.NAMESPACE);
+ assertEquals(1, schemas.size());
+ XMPSchemaMediaManagement mm = (XMPSchemaMediaManagement) schemas.get(0);
+ assertEquals("17", mm.getSequenceList("xapMM:VersionID").get(0));
+
+ } finally {
+ if (document != null) {
+ document.close();
+ }
+ }
+ }
+
+ { // Now alter the Bibtex entry, write it and do all the checks again
+ BibtexEntry toSet = t1BibtexEntry();
+ toSet.setField("author", "Pokemon!");
+
+ XMPUtil.writeXMP(pdfFile, toSet);
+
+ List l = XMPUtil.readXMP(pdfFile.getAbsoluteFile());
+ assertEquals(1, l.size());
+ BibtexEntry e = (BibtexEntry) l.get(0);
+
+ assertEquals(toSet, e);
+
+ // This is what we really want to test: Is the rest of the
+ // descriptions still there?
+
+ PDDocument document = null;
+ try {
+ document = PDDocument.load(pdfFile.getAbsoluteFile());
+ if (document.isEncrypted()) {
+ throw new IOException("Error: Cannot read metadata from encrypted document.");
+ }
+ PDDocumentCatalog catalog = document.getDocumentCatalog();
+ PDMetadata metaRaw = catalog.getMetadata();
+
+ XMPMetadata meta;
+ if (metaRaw != null) {
+ meta = new XMPMetadata(XMLUtil.parse(metaRaw.createInputStream()));
+ } else {
+ meta = new XMPMetadata();
+ }
+ meta.addXMLNSMapping(XMPSchemaBibtex.NAMESPACE, XMPSchemaBibtex.class);
+
+ List schemas = meta.getSchemas();
+
+ assertEquals(4, schemas.size());
+
+ schemas = meta.getSchemasByNamespaceURI(XMPSchemaBibtex.NAMESPACE);
+ assertEquals(1, schemas.size());
+
+ schemas = meta.getSchemasByNamespaceURI(XMPSchemaDublinCore.NAMESPACE);
+ assertEquals(1, schemas.size());
+ XMPSchemaDublinCore dc = (XMPSchemaDublinCore) schemas.get(0);
+ assertEquals("application/pdf", dc.getFormat());
+
+ schemas = meta.getSchemasByNamespaceURI(XMPSchemaBasic.NAMESPACE);
+ assertEquals(1, schemas.size());
+ XMPSchemaBasic bs = (XMPSchemaBasic) schemas.get(0);
+ assertEquals("Acrobat PDFMaker 7.0.7", bs.getCreatorTool());
+
+ Calendar c = Calendar.getInstance();
+ c.clear();
+ c.set(Calendar.YEAR, 2006);
+ c.set(Calendar.MONTH, 8);
+ c.set(Calendar.DATE, 7);
+ c.set(Calendar.HOUR, 14);
+ c.set(Calendar.MINUTE, 44);
+ c.set(Calendar.SECOND, 24);
+ c.setTimeZone(TimeZone.getTimeZone("GMT+2"));
+
+ Calendar other = bs.getCreateDate();
+
+ assertEquals(c.get(Calendar.YEAR), other.get(Calendar.YEAR));
+ assertEquals(c.get(Calendar.MONTH), other.get(Calendar.MONTH));
+ assertEquals(c.get(Calendar.DATE), other.get(Calendar.DATE));
+ assertEquals(c.get(Calendar.HOUR), other.get(Calendar.HOUR));
+ assertEquals(c.get(Calendar.MINUTE), other.get(Calendar.MINUTE));
+ assertEquals(c.get(Calendar.SECOND), other.get(Calendar.SECOND));
+ assertTrue(c.getTimeZone().hasSameRules(other.getTimeZone()));
+
+ schemas = meta.getSchemasByNamespaceURI(XMPSchemaMediaManagement.NAMESPACE);
+ assertEquals(1, schemas.size());
+ XMPSchemaMediaManagement mm = (XMPSchemaMediaManagement) schemas.get(0);
+ assertEquals("17", mm.getSequenceList("xapMM:VersionID").get(0));
+
+ } finally {
+ if (document != null) {
+ document.close();
+ }
+ }
+ }
+ }
+
+ /**
+ * Is XML in text properties properly escaped?
+ *
+ * @throws Exception
+ *
+ */
+ public void testXMLEscape() throws Exception {
+ ParserResult result = BibtexParser
+ .parse(new StringReader(
+ "@article{canh05,"
+ + " author = {Crowston, K. and Annabi, H. and Howison, J. and Masango, C.},"
+ + "\n"
+ + " title = {</bibtex:title> \" bla \" '' '' && & for floss development: A model and propositions},"
+ + "\n" + " booktitle = {<randomXML>}," + "\n" + " year = {2005}," + "\n"
+ + " owner = {oezbek}," + "\n" + " timestamp = {2006.05.29}," + "\n"
+ + " url = {http://james.howison.name/publications.html}" + "\n" + "}"));
+
+ Collection c = result.getDatabase().getEntries();
+ assertEquals(1, c.size());
+
+ BibtexEntry e = (BibtexEntry) c.iterator().next();
+
+ XMPUtil.writeXMP(pdfFile, e);
+
+ List l = XMPUtil.readXMP(pdfFile.getAbsoluteFile());
+ assertEquals(1, l.size());
+ BibtexEntry x = (BibtexEntry) l.get(0);
+
+ assertEquals(e, x);
+ }
+
+ public void assertEquals(BibtexEntry expected, BibtexEntry actual) {
+ assertEquals(expected.getCiteKey(), actual.getCiteKey());
+ assertEquals(expected.getType(), actual.getType());
+
+ Object[] o = expected.getAllFields();
+
+ for (int i = 0; i < o.length; i++) {
+ assertEquals(expected.getField(o.toString()), actual.getField(o.toString()));
+ }
+ }
+
+ /**
+ *
+ * @depends XMPUtilTest.testReadMultiple()
+ */
+ public void testXMPreadString() throws Exception {
+
+ ParserResult result = BibtexParser.parse(new StringReader("@article{canh05,"
+ + " author = {Crowston, K. and Annabi, H.},\n" + " title = {Title A}}\n"
+ + "@inProceedings{foo," + " author={Norton Bar}}"));
+
+ Collection c = result.getDatabase().getEntries();
+ assertEquals(2, c.size());
+
+ String xmp = XMPUtil.toXMP(c);
+
+ /* Test minimal syntaxical completeness */
+ assertTrue(0 < xmp.indexOf("xpacket"));
+ assertTrue(0 < xmp.indexOf("adobe:ns:meta"));
+ assertTrue(0 < xmp.indexOf("<bibtex:bibtexkey>canh05</bibtex:bibtexkey>")
+ || 0 < xmp.indexOf("bibtex:bibtexkey="));
+ assertTrue(0 < xmp.indexOf("<rdf:li>Norton Bar</rdf:li>"));
+ assertTrue(0 < xmp.indexOf("id='W5M0MpCehiHzreSzNTczkc9d'?>")
+ || 0 < xmp.indexOf("id=\"W5M0MpCehiHzreSzNTczkc9d\"?>"));
+ assertTrue(0 < xmp.indexOf("xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#'")
+ || 0 < xmp.indexOf("xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\""));
+ assertTrue(0 < xmp.indexOf("<rdf:Description"));
+ assertTrue(0 < xmp.indexOf("<?xpacket end='w'?>") || 0 < xmp.indexOf("<?xpacket end=\"w\"?>"));
+
+ /* Test contents of string */
+ writeManually(pdfFile, xmp);
+
+ List l = XMPUtil.readXMP(pdfFile);
+
+ assertEquals(2, l.size());
+
+ BibtexEntry a = (BibtexEntry) l.get(0);
+ BibtexEntry b = (BibtexEntry) l.get(1);
+
+ if (a.getCiteKey().equals("foo")) {
+ BibtexEntry tmp = a;
+ a = b;
+ b = tmp;
+ }
+
+ assertEquals("canh05", a.getCiteKey());
+ assertEquals("K. Crowston and H. Annabi", a.getField("author"));
+ assertEquals("Title A", a.getField("title"));
+ assertEquals(BibtexEntryType.ARTICLE, a.getType());
+
+ assertEquals("foo", b.getCiteKey());
+ assertEquals("Norton Bar", b.getField("author"));
+ assertEquals(BibtexEntryType.INPROCEEDINGS, b.getType());
+ }
+
+ /**
+ * Tests whether it is possible to read several BibtexEntries
+ *
+ * @throws Exception
+ *
+ */
+ public void testReadMultiple() throws Exception {
+
+ String bibtex = t2XMP() + t3XMP();
+ writeManually(pdfFile, bibtexXPacket(bibtex));
+
+ // Read from file
+ List l = XMPUtil.readXMP(pdfFile);
+
+ assertEquals(2, l.size());
+
+ BibtexEntry a = (BibtexEntry) l.get(0);
+ BibtexEntry b = (BibtexEntry) l.get(1);
+
+ if (a.getCiteKey().equals("Clarkson06")) {
+ BibtexEntry tmp = a;
+ a = b;
+ b = tmp;
+ }
+
+ assertEquals(t2BibtexEntry(), a);
+ assertEquals(t3BibtexEntry(), b);
+ }
+
+ /**
+ * Tests whether it is possible to write several Bibtexentries
+ *
+ * @throws TransformerException
+ * @throws IOException
+ *
+ */
+ public void testWriteMultiple() throws IOException, TransformerException {
+ List l = new LinkedList();
+ l.add(t2BibtexEntry());
+ l.add(t3BibtexEntry());
+
+ XMPUtil.writeXMP(pdfFile, l);
+
+ l = XMPUtil.readXMP(pdfFile);
+
+ assertEquals(2, l.size());
+
+ BibtexEntry a = (BibtexEntry) l.get(0);
+ BibtexEntry b = (BibtexEntry) l.get(1);
+
+ if (a.getCiteKey().equals("Clarkson06")) {
+ BibtexEntry tmp = a;
+ a = b;
+ b = tmp;
+ }
+
+ assertEquals(t2BibtexEntry(), a);
+ assertEquals(t3BibtexEntry(), b);
+ }
+
+ public void testReadRawXMP() throws Exception {
+
+ ParserResult result = BibtexParser
+ .parse(new StringReader(
+ "@article{canh05,"
+ + " author = {Crowston, K. and Annabi, H. and Howison, J. and Masango, C.},\n"
+ + " title = {Effective work practices for floss development: A model and propositions},\n"
+ + " booktitle = {Hawaii International Conference On System Sciences (HICSS)},\n"
+ + " year = {2005},\n" + " owner = {oezbek},\n"
+ + " timestamp = {2006.05.29},\n"
+ + " url = {http://james.howison.name/publications.html}}"));
+
+ Collection c = result.getDatabase().getEntries();
+ assertEquals(1, c.size());
+
+ BibtexEntry e = (BibtexEntry) c.iterator().next();
+
+ XMPUtil.writeXMP(pdfFile, e);
+
+ XMPMetadata metadata = XMPUtil.readRawXMP(pdfFile);
+
+ List schemas = metadata.getSchemas();
+ assertEquals(1, schemas.size());
+ schemas = metadata.getSchemasByNamespaceURI(XMPSchemaBibtex.NAMESPACE);
+ assertEquals(1, schemas.size());
+ XMPSchemaBibtex bib = (XMPSchemaBibtex) schemas.get(0);
+
+ List authors = bib.getSequenceList("author");
+ assertEquals(4, authors.size());
+ assertEquals("K. Crowston", authors.get(0));
+ assertEquals("H. Annabi", authors.get(1));
+ assertEquals("J. Howison", authors.get(2));
+ assertEquals("C. Masango", authors.get(3));
+
+ assertEquals("Article", bib.getTextProperty("entrytype"));
+ assertEquals("Effective work practices for floss development: A model and propositions",
+ bib.getTextProperty("title"));
+ assertEquals("Hawaii International Conference On System Sciences (HICSS)", bib
+ .getTextProperty("booktitle"));
+ assertEquals("2005", bib.getTextProperty("year"));
+ assertEquals("oezbek", bib.getTextProperty("owner"));
+ assertEquals("http://james.howison.name/publications.html", bib.getTextProperty("url"));
+
+ }
+
+ /**
+ * Test whether the command-line client works correctly with writing a
+ * single entry
+ *
+ * @throws Exception
+ *
+ */
+ public void testCommandLineSingleBib() throws Exception {
+
+ // First check conversion from .bib to .xmp
+ File tempBib = File.createTempFile("JabRef", ".bib");
+ FileWriter fileWriter = null;
+ try {
+ fileWriter = new FileWriter(tempBib);
+ fileWriter.write(t1BibtexString());
+ fileWriter.close();
+
+ ByteArrayOutputStream s = new ByteArrayOutputStream();
+ PrintStream oldOut = System.out;
+ System.setOut(new PrintStream(s));
+ XMPUtil.main(new String[] { tempBib.getAbsolutePath() });
+ System.setOut(oldOut);
+ s.close();
+ String xmp = s.toString();
+
+ writeManually(pdfFile, xmp);
+
+ List l = XMPUtil.readXMP(pdfFile);
+ assertEquals(1, l.size());
+ assertEquals(t1BibtexEntry(), (BibtexEntry) l.get(0));
+
+ } finally {
+ if (fileWriter != null)
+ fileWriter.close();
+ if (tempBib != null)
+ tempBib.delete();
+ }
+ }
+
+ /**
+ *
+ *
+ * @depends XMPUtil.writeXMP
+ *
+ */
+ public void testCommandLineSinglePdf() throws Exception {
+ {
+ // Write XMP to file
+
+ BibtexEntry e = t1BibtexEntry();
+
+ XMPUtil.writeXMP(pdfFile, e);
+
+ ByteArrayOutputStream s = new ByteArrayOutputStream();
+ PrintStream oldOut = System.out;
+ System.setOut(new PrintStream(s));
+ XMPUtil.main(new String[] { pdfFile.getAbsolutePath() });
+ System.setOut(oldOut);
+ s.close();
+ String bibtex = s.toString();
+
+ ParserResult result = BibtexParser.parse(new StringReader(bibtex));
+ Collection c = result.getDatabase().getEntries();
+ assertEquals(1, c.size());
+ BibtexEntry x = (BibtexEntry) c.iterator().next();
+
+ assertEquals(e, x);
+ }
+ {
+ // Write XMP to file
+ BibtexEntry e = t1BibtexEntry();
+
+ XMPUtil.writeXMP(pdfFile, e);
+
+ ByteArrayOutputStream s = new ByteArrayOutputStream();
+ PrintStream oldOut = System.out;
+ System.setOut(new PrintStream(s));
+ XMPUtil.main(new String[] { "-x", pdfFile.getAbsolutePath() });
+ System.setOut(oldOut);
+ s.close();
+ String xmp = s.toString();
+
+ /* Test minimal syntaxical completeness */
+ assertTrue(0 < xmp.indexOf("xpacket"));
+ assertTrue(0 < xmp.indexOf("adobe:ns:meta"));
+ assertTrue(0 < xmp.indexOf("<bibtex:bibtexkey>canh05</bibtex:bibtexkey>")
+ || 0 < xmp.indexOf("bibtex:bibtexkey="));
+ assertTrue(0 < xmp.indexOf("<rdf:li>K. Crowston</rdf:li>"));
+ assertTrue(0 < xmp.indexOf("id='W5M0MpCehiHzreSzNTczkc9d'?>")
+ || 0 < xmp.indexOf("id=\"W5M0MpCehiHzreSzNTczkc9d\"?>"));
+ assertTrue(0 < xmp.indexOf("xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#'")
+ || 0 < xmp.indexOf("xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\""));
+ assertTrue(0 < xmp.indexOf("<rdf:Description"));
+ assertTrue(0 < xmp.indexOf("<?xpacket end='w'?>") || 0 < xmp.indexOf("<?xpacket end=\"w\"?>"));
+
+ /* Test contents of string */
+ writeManually(pdfFile, xmp);
+ List l = XMPUtil.readXMP(pdfFile);
+ assertEquals(1, l.size());
+
+ assertEquals(t1BibtexEntry(), (BibtexEntry)l.get(0));
+ }
+ }
+
+ /**
+ * Test whether the command-line client can pick one of several entries from
+ * a bibtex file
+ *
+ * @throws Exception
+ *
+ */
+ public void testCommandLineByKey() throws Exception {
+
+ File tempBib = File.createTempFile("JabRef", ".bib");
+ FileWriter fileWriter = null;
+ try {
+ fileWriter = new FileWriter(tempBib);
+ fileWriter.write(t1BibtexString());
+ fileWriter.write(t2BibtexString());
+ fileWriter.close();
+
+ { // First try canh05
+ ByteArrayOutputStream s = new ByteArrayOutputStream();
+ PrintStream oldOut = System.out;
+ System.setOut(new PrintStream(s));
+ XMPUtil.main(new String[] { "canh05", tempBib.getAbsolutePath(),
+ pdfFile.getAbsolutePath() });
+ System.setOut(oldOut);
+ s.close();
+
+ // PDF should be annotated:
+ List l = XMPUtil.readXMP(pdfFile);
+ assertEquals(1, l.size());
+ assertEquals(t1BibtexEntry(), (BibtexEntry) l.get(0));
+ }
+ { // Now try OezbekC06
+ ByteArrayOutputStream s = new ByteArrayOutputStream();
+ PrintStream oldOut = System.out;
+ System.setOut(new PrintStream(s));
+ XMPUtil.main(new String[] { "OezbekC06", tempBib.getAbsolutePath(),
+ pdfFile.getAbsolutePath() });
+ System.setOut(oldOut);
+ s.close();
+ // PDF should be annotated:
+ List l = XMPUtil.readXMP(pdfFile);
+ assertEquals(1, l.size());
+ assertEquals(t2BibtexEntry(), (BibtexEntry) l.get(0));
+ }
+ } finally {
+ if (fileWriter != null)
+ fileWriter.close();
+
+ if (tempBib != null)
+ tempBib.delete();
+ }
+ }
+
+ /**
+ * Test whether the command-line client can deal with several bibtex
+ * entries.
+ *
+ */
+ public void testCommandLineSeveral() throws Exception {
+
+ File tempBib = File.createTempFile("JabRef", ".bib");
+ FileWriter fileWriter = null;
+ try {
+ fileWriter = new FileWriter(tempBib);
+ fileWriter.write(t1BibtexString());
+ fileWriter.write(t3BibtexString());
+ fileWriter.close();
+
+ ByteArrayOutputStream s = new ByteArrayOutputStream();
+ PrintStream oldOut = System.out;
+ System.setOut(new PrintStream(s));
+ XMPUtil.main(new String[] { tempBib.getAbsolutePath(), pdfFile.getAbsolutePath() });
+ System.setOut(oldOut);
+ s.close();
+
+ List l = XMPUtil.readXMP(pdfFile);
+
+ assertEquals(2, l.size());
+
+ BibtexEntry a = (BibtexEntry) l.get(0);
+ BibtexEntry b = (BibtexEntry) l.get(1);
+
+ if (a.getCiteKey().equals("Clarkson06")) {
+ BibtexEntry tmp = a;
+ a = b;
+ b = tmp;
+ }
+
+ assertEquals(t1BibtexEntry(), a);
+ assertEquals(t3BibtexEntry(), b);
+
+ } finally {
+ if (fileWriter != null)
+ fileWriter.close();
+
+ if (tempBib != null)
+ tempBib.delete();
+ }
+ }
+
+ /**
+ * Test that we cannot use encrypted PDFs.
+ */
+ public void testEncryption() throws Exception {
+
+ // // PDF was created using:
+ //
+ // PDDocument pdf = null;
+ // try {
+ // pdf = new PDDocument();
+ // pdf.addPage(new PDPage()); // Need page to open in Acrobat
+ // pdf.encrypt("hello", "world");
+ // pdf.save("d:/download/encrypted.pdf");
+ // } finally {
+ // if (pdf != null)
+ // pdf.close();
+ // }
+ //
+
+ try {
+ XMPUtil.readXMP("src/tests/encrypted.pdf");
+ fail();
+ } catch (EncryptionNotSupportedException e) {
+ }
+
+ try {
+ XMPUtil.writeXMP("src/tests/encrypted.pdf", t1BibtexEntry());
+ fail();
+ } catch (EncryptionNotSupportedException e) {
+ }
+ }
+
+ /**
+ * Read the contents of a reader as one string
+ *
+ * @param reader
+ * @return
+ * @throws IOException
+ */
+ public static String slurp(Reader reader) throws IOException {
+ char[] chars = new char[4092];
+ StringBuffer totalBuffer = new StringBuffer();
+ int bytesRead;
+ while ((bytesRead = reader.read(chars)) != -1) {
+ if (bytesRead == 4092) {
+ totalBuffer.append(chars);
+ } else {
+ totalBuffer.append(new String(chars, 0, bytesRead));
+ }
+ }
+ return totalBuffer.toString();
+ }
+}
diff --git a/src/resource/IntegrityMessage_du.properties b/src/resource/IntegrityMessage_du.properties
new file mode 100644
index 0000000..6be22c6
--- /dev/null
+++ b/src/resource/IntegrityMessage_du.properties
@@ -0,0 +1,11 @@
+#! created/edited by Gert Renckens, Dutch translation v0.12, last update: 20061102 (e-mail: gert (dot) renckens (at) student (dot) uhasselt (dot) be)
+
+ITEXT_1=Er zijn hints
+ITEXT_1001=Waarschuwing
+ITEXT_2001=Mislukking!
+ITEXT_1010=Begin van $FIELD veld
+ITEXT_1011=Verkeerd einde ($FIELD veld)
+ITEXT_1012=Er kan iets mis zijn in het $FIELD veld
+ITEXT_10=Er zijn hoofdletters zonder een {} masker in het $FIELD veld
+ITEXT_11=$FIELD veld moet een getal bestaande uit 4 cijfers bevatten
+ITEXT_2010=onverwachte sluitings } in het $FIELD veld
diff --git a/src/resource/JabRef_de.properties b/src/resource/JabRef_de.properties
index 8487e74..9c0bd26 100644
--- a/src/resource/JabRef_de.properties
+++ b/src/resource/JabRef_de.properties
@@ -2104,4 +2104,70 @@ Override_default_font_settings=Standardschrifteinstellungen_\u00FCberschreiben
Mac_file_dialog=Mac_Dateidialog
-Use_native_file_dialog=Plattformabh\u00E4ngigen_Dateidialog_verwenden
\ No newline at end of file
+Use_native_file_dialog=Plattformabh\u00E4ngigen_Dateidialog_verwenden
+
+XMP-annotated_PDF=PDF_mit_XMP-Anmerkungen
+PDF_and_PS_links=PDF_und_PS-Links
+Use_Regular_Expression_Search=Suche_mit_Regul\u00e4rem_Ausdruck_benutzen
+Help_on_Regular_Expression_Search=Hilfe_zur_Suche_mit_Regul\u00e4rem_Ausdruck
+writeXMP=XMP_schreiben
+Will_write_XMP-metadata_to_the_PDFs_linked_from_selected_entries.=Schreibe_XMP-Metadaten_in_die_PDFs,_die_mit_den_ausgew\u00e4hlten_Eintr\u00e4gen_verlinkt_sind.
+Select_external_application=Externe_Anwendung_ausw\u00e4hlen
+Show_last_names_only=Zeige_nur_Nachnamen
+Help_on_Preview_Settings=Hilfe_zu_den_Einstellungen_der_Vorschau
+Writing_XMP_metadata...=XMP-Metadaten_werden_geschrieben...
+Writing_XMP_metadata_for_selected_entries...=XMP-Metadaten_f\u00fcr_ausgew\u00e4hlte_Eintr\u00e4ge_werden_geschrieben...
+Skipped_-_No_PDF_linked=\u00dcbersprungen_-_Kein_PDF_verlinkt
+Finished_writing_XMP_for_%0_file_(%1_skipped,_%2_errors).=Schreiben_der_XMP-Metadaten_f\u00fcr_Datei_%0_beendet_(%1_\u00fcbersprungen,_%2_Fehler).
+Grouping_may_not_work_for_this_entry.=Gruppierung_f\u00fcr_diesen_Eintrag_evtl._nicht_m\u00f6glich.
+Write_BibtexEntry_as_XMP-metadata_to_PDF.=BibTeX-Eintrag_als_XMP-Metadaten_ins_PDF_schreiben.
+write_XMP=schreibe_XMP
+New_field_value=Neuer_Feldwert
+Overwrite_existing_field_values=Bestehende_Feldwerte_\u00fcberschreiben
+Include_entries=Eintr\u00e4ge_einschlie\u00dfen
+Selected_entries=Ausgew\u00e4hlte_Eintr\u00e4ge
+
+Fetch_CiteSeer_by_ID=CiteSeer_mittels_ID_abrufen
+Push_entries_to_external_application_(%0)=Eintr\u00e4ge_in_externe_Anwendung_einf\u00fcgen_(%0)
+Write_XMP=XMP_schreiben
+
+Writing_XMP=Schreibe_XMP
+
+HTML_table=HTML-Tabelle
+
+Set/clear_fields=Felder_setzen/l\u00f6schen
+
+Clear_fields=Felder_l\u00f6schen
+Set_fields=Felder_setzen
+
+HTML_table_(with_Abstract_&_BibTeX)=HTML-Tabelle_(mit_Abstract_&_BibTeX)
+
+OpenOffice_Calc=OpenOffice_Calc
+OpenDocument_Spreadsheet=OpenDocument-Tabelle
+
+Skipped_entry.=Eintrag_\u00fcbersprungen.
+Error_occured_when_parsing_entry=Fehler_beim_Analysieren_des_Eintrags
+Operation_canceled.\n=Vorgang_abgebrochen.\n
+Error_while_writing=Fehler_beim_Schreiben
+Skipped_-_PDF_does_not_exist=\u00dcbersprungen_-_PDF_exisitert_nicht
+Use_custom_icon_theme=Angepasstes_Icon-Theme_verwenden
+Custom_icon_theme=Pers\u00f6nliches_Icon-Theme
+Custom_icon_theme_file=Datei_des_pers\u00f6nlichen_Icon-Themes
+Unable_to_read_icon_theme_file=Datei_des_pers\u00f6nlichen_Icon-Themes_nicht_lesbar
+Unable_to_read_default_icon_theme.=Datei_des_Standard-Icon-Themes_nicht_lesbar.
+Could_not_find_image_file=Bilddatei_nicht_gefunden.
+Set_field=Setze_Feld
+No_entries_selected.=Keine_Eintr\u00e4ge_ausgew\u00e4hlt.
+Link_from_new_entries.=Link_von_neuen_Eintr\u00e4gen.
+Link_from_new_entry=Link_von_neuem_Eintrag.
+Link_from_entries.=Link_von_Eintr\u00e4gen.
+Link_from_entry=Link_von_Eintrag.
+exists.Overwrite?=ist_vorhanden._\u00dcberschreiben?
+File_exists=Datei_ist_vorhanden
+No_file_associated=Keine_Datei_zugeordnet
+Exported_%0_entries_to_file=%0_Eintr\u00e4ge_wurden_exportiert_in_die_Datei
+Formatter_Name=
+Format_String=
+Help_on_Name_Formatting=
+Special_Name_Formatters=
+Name_formatter=
diff --git a/src/resource/JabRef_du.properties b/src/resource/JabRef_du.properties
new file mode 100644
index 0000000..fc3a557
--- /dev/null
+++ b/src/resource/JabRef_du.properties
@@ -0,0 +1,2171 @@
+#!
+#! created/edited by Gert Renckens, Dutch translation v0.12, last update: 20061102 (e-mail: gert (dot) renckens (at) student (dot) uhasselt (dot) be)
+#! encoding:ISO-8859-1
+
+!This_is_a_simple_copy_and_paste_dialog._First_load_or_paste_some_text_into_the_text_input_area._After_that,_you_can_mark_text_and_assign_it_to_a_bibtex_field.=Dit_is_een_eenvoudige_kopieer_en_plak_dialoog._Laad_of_plak_eerst_wat_tekst_in_het_invoerveld._Hierna,_kan_u_tekst_markeren_en_deze_toekennen_aan_een_bibtex_veld.
+
+%0_contains_the_Regular_Expression_<b>%1</b>=%0_bevat_de_regular_expression_<b>%1</b>
+
+%0_contains_the_term_<b>%1</b>=%0_bevat_de_term_<b>%1</b>
+
+%0_doesn't_contain_the_Regular_Expression_<b>%1</b>=%0_bevat_de_regular_expression_<b>%1</b>_niet
+
+%0_doesn't_contain_the_term_<b>%1</b>=%0_bevat_de_term_<b>%1</b>_niet
+
+%0_doesn't_match_the_Regular_Expression_<b>%1</b>=%0_komt_niet_overeen_met_de_regular_expression_<b>%1</b>
+
+%0_doesn't_match_the_term_<b>%1</b>=%0_komt_niet_overeen_met_de_term_<b>%1</b>
+
+%0_field_set=%0-veld_ingesteld
+
+%0_import_cancelled.=%0_importeer-operatie_geannuleerd
+
+%0_matches_the_Regular_Expression_<b>%1</b>=%0_komt_overeen_met_de_regular_expression_<b>%1</b>
+
+%0_matches_the_term_<b>%1</b>=%0_komt_overeen_met_de_term_<b>%1</b>
+
+<field_name>=<veldnaam>
+
+<HTML>Unpack_the_zip_file_containing_import/export_filters_for_Endnote,<BR>for_optimal_interoperability_with_JabRef</HTML>=<HTML>Pak_het_zip_bestand_dat_de_import/export_filters_voor_Endnote_bevat_uit<BR>voor_optimale_samenwerking_met_JabRef</HTML>
+
+<no_field>=<geen_veld>
+
+<select>=<selecteer>
+
+<select_word>=<selecteer_woord>
+
+_on_entry_number_=_op_entry_nummber
+
+A_CiteSeer_fetch_operation_is_currently_in_progress.=Een_CiteSeer_ophaal-operatie_is_momenteel_in_werking.
+
+A_CiteSeer_import_operation_is_currently_in_progress.=Een_CiteSeer_importeer-operatie_is_momenteel_in_werking.
+
+A_string_with_that_label_already_exists=Een_constante_met_dat_label_bestaat_al
+
+Abbreviate_journal_names_of_the_selected_entries_(ISO_abbreviation)=Kort_tijdschriftennamen_met_de_geselecteerde_entries_af_(ISO_afkorting)
+
+Abbreviate_journal_names_of_the_selected_entries_(MEDLINE_abbreviation)=Kort_tijdschriftennamen_met_de_geselecteerde_entries_af_(MEDLINE_afkorting)
+
+Abbreviate_names=Namen_afkorten
+
+Abbreviation=Afkorting
+
+About_JabRef=Over_JabRef
+
+Abstract=Abstract
+
+Accept=Aanvaarden
+
+Accept_change=Veranderingen_aanvaarden
+
+Action=Actie
+
+Add=Toevoegen
+
+Add_a_(compiled)_custom_ImportFormat_class_from_a_class_path._\nThe_path_need_not_be_on_the_classpath_of_JabRef.=Voeg_een_(gecompileerde)_externe_ImportFormat_klasse_van_een_class_path_toe._\nHet_pad_moet_niet_in_het_classpath_van_JabRef_staan.
+
+Add_a_(compiled)_custom_ImportFormat_class_from_a_Zip-archive.\nThe_Zip-archive_need_not_be_on_the_classpath_of_JabRef.=Voeg_een_(gecompileerde)_externe_ImportFormat_klasse_van_een_Zip-archief_toe._\nHet_pad_moet_niet_in_het_classpath_van_JabRef_staan.
+
+add_entries_to_group=voeg_entries_toe_aan_groep
+
+Add_entry_selection_to_this_group=Voeg_entry_selectie_toe_aan_deze_groep
+
+Add_from_folder=Voeg_toe_uit_map
+
+Add_from_jar=_Voeg_toe_uit_jar
+
+add_group=groep_toevoegen
+
+Add_Group=Groep_toevoegen
+
+Add_new=Voeg_nieuw_toe
+
+Add_Subgroup=Voeg_subgroep_toe
+
+Add_to_group=Voeg_toe_aan_groep
+
+Added_entry=Toegevoegde_entry
+
+Added_group=Toegevoegde_groep
+
+Added_group_"%0".=Toegevoegde_groep_"%0".
+
+Added_new=Nieuwe_toegevoegd
+
+Added_string=Toegevoegde_constante
+
+Additionally,_entries_whose_<b>%0</b>_field_does_not_contain_<b>%1</b>_can_be_assigned_manually_to_this_group_by_selecting_them_then_using_either_drag_and_drop_or_the_context_menu._This_process_adds_the_term_<b>%1</b>_to_each_entry's_<b>%0</b>_field._Entries_can_be_removed_manually_from_this_group_by_selecting_them_then_using_the_context_menu._This_process_removes_the_term_<b>%1</b>_from_each_entry's_<b>%0</b>_field.=Bijkomstig, entries_waarvan_het_<b>%0</b>_veld_niet_<b>%1</b>_bevatten_ [...]
+
+Advanced=Geavanceerd
+
+Advanced_options_for_setting...=Geavanceerde_opties_om_in_te_stellen...
+
+All_Entries=Alle_Entries
+
+All_entries=Alle_entries
+
+All_entries_of_this_type_will_be_declared_typeless._Continue?=Alle_entries_van_dit_type_zullen_zonder_type_gedeclareerd_worden._Verder_gaan?
+
+All_fields=Alle_velden
+
+All_subgroups_(recursively)=Alle_subgroepen_(recursief)
+
+Allow_editing_in_table_cells=Sta_aanpassingen_in_tabel_cellen_toe
+
+Always_save_database_ordered_by_author_name=Sla_database_altijd_op_geordend_op_auteursnaam
+
+and=en
+
+and_the_class_must_be_available_in_your_classpath_next_time_you_start_JabRef.=en_de_klasse_moet_beschikbaar_zijn_in_uw_classpath_de_volgende_keer_wanneer_u_JabRef_opstart
+
+any_field_that_matches_the_regular_expression_<b>%0</b>=elk_veld_dat_overeenkomt_met_de_regular_expression_<b>%0</b>
+
+Appearance=Uiterlijk
+
+Append=Bijvoegen
+
+Append_contents_from_a_BibTeX_database_into_the_currently_viewed_database=Voeg_de_inhoud_van_een_BibTeX_database_in_de_huidige_weergegeven_database_toe
+
+Append_database=Database_invoegen
+
+append_the_selected_text_to_bibtex_key=voeg_de_geselecteerde_tekst_toe_aan_BibTeX-sleutel
+
+Apply=Toepassen
+
+Arguments_passed_on_to_running_JabRef_instance._Shutting_down.=Argumenten_doorgegeven_aan_de_draaiende_JabRef_instantie._Wordt_nu_afgesloten.
+
+Assign_entries_based_on:=Entries_toekennen_gebaseerd_op:
+
+Assign_entry_selection_exclusively_to_this_group=Ken_entry_selectie_exclusief_aan_deze_groep_toe
+
+Assign_new_file=Ken_nieuw_bestand_toe
+
+Assign_the_original_group's_entries_to_this_group?=De_entries_van_de_originele_groep_aan_deze_groep_toekennen?
+
+Assigned_%0_entries_to_group_"%1".=%0_entries_aan_groep_"%1"_toegekend
+
+Assigned_1_entry_to_group_"%0".=1_entry_aan_groep_"%0"_toegekend
+
+Attach_%0_file=Voeg_%0_bestand_bij
+
+Attach_URL=URL_bijvoegen
+
+Attempt_to_autoset_%0_links_for_your_entries._Autoset_works_if_a_%0_file_in_your_%0_directory_or_a_subdirectory<BR>is_named_identically_to_an_entry's_BibTeX_key,_plus_extension.=Poging_om_%0_snelkoppelingen_voor_jouw_entries_automatisch_in_te_stellen._Automatisch_instellen_werkt_als_een_%0_bestand_in_jouw_%0_map_of_een_submap<BR>een_identieke_naam_heeft_als_een_BibTeX-sleutel_van_een_entry,_plus_extensie.
+
+Auto=Auto
+
+Autodetect_format=Formaat_automatisch_detecteren
+
+Autogenerate_BibTeX_key=BibTeX-sleutel_automatisch_genereren
+
+Autogenerate_BibTeX_keys=BibTeX-sleutels_automatisch_genereren
+
+Autogenerate_groups=Groepen_automatisch_genereren
+
+autogenerate_keys=BibTeX-sleutels_automatisch_genereren
+
+Automatically_create_groups=Groepen_automatisch_aanmaken
+
+Automatically_create_groups_for_database.=Automatisch_groepen_voor_database_aanmaken
+
+Automatically_created_groups=Automatisch_aangemaakte_groepen
+
+Automatically_hide_groups_interface_when_switching_to_a_database_that_contains_no_groups=Verberg_automatisch_het_groepenvenster_bij_overgang_naar_een_database_die_geen_groepen_bevat
+
+Automatically_show_groups_interface_when_switching_to_a_database_that_contains_groups=Toon_automatisch_het_groepenvenster_bij_overgang_naar_een_database_die_groepen_bevat
+
+Autoset=Automatisch_instellen
+
+Autoset_%0_field=Automatisch_het_%0_veld_instellen
+
+Autoset_%0_links._Allow_overwriting_existing_links.=Automatisch_%0_snelkoppelingen_instellen._Overschrijven_van_bestaande_snelkoppelingen_toestaan.
+
+Autoset_%0_links._Do_not_overwrite_existing_links.=Automatisch_%0_snelkoppelingen_instellen._Overschrijven_van_bestaande_snelkoppelingen_niet_toestaan.
+
+Autosetting_%0_field...=%0_veld_automatisch_aan_het_instellen...
+
+AUX_File_import=AUX_Bestand_importeren
+
+AUX_file_import=AUX_bestand_importeren
+
+Available_export_formats=Beschikbare_exporteer_formaten
+
+Available_fields=Beschikbare_velden
+
+Available_import_formats=Beschikbare_importeer_formaten
+
+Background_color_for_marked_entries=Achtergrondkleur_voor_gemarkeerde_entries
+
+Background_color_for_optional_fields=Achtergrondkleur_voor_optionele_velden
+
+Background_color_for_required_fields=Achtergrondkleur_voor_vereiste_velden
+
+Backup_old_file_when_saving=Maak_reservekopie_van_oud_bestand_bij_het_opslaan
+
+Bibkey_to_filename_conversion=BibTeX-sleutel_naar_bestandsnaam_conversie
+
+Biblioscape_Tag_file=Biblioscape_Tag_bestand
+
+BibTeX=BibTeX
+
+BibTeX_key=BibTeX-sleutel
+
+BibTeX_key_is_unique.=BibTeX-sleutel_is_uniek
+
+BibTeX_key_not_set._Enter_a_name_for_the_downloaded_file=BibTeX-sleutel_is_niet_ingesteld._Geef_een_naam_voor_het_gedownloade_bestand
+
+BibTeX_source=BibTeX-broncode
+
+BibTeXML=BibTeXML
+
+BibTeXML_File=BibTeXML_Bestand
+
+Binding=Binding
+
+Broken_link=Foutieve_snelkoppeling
+
+Browse=Bladeren
+
+by=door
+
+Calling_external_viewer...=Externe_viewer_opgeroepen...
+
+Cancel=Annuleren
+
+Cannot_add_entries_to_group_without_generating_keys._Generate_keys_now?=Kan_entries_niet_aan_de_groep_toevoegen_zonder_sleutels_te_genereren._Sleutels_nu_genereren?
+
+Cannot_merge_this_change=Kan_deze_verandering_niet_samenvoegen
+
+Cannot_move_group=Kan_groep_niet_verplaatsen
+
+Cannot_move_group_"%0"_down.=Kan_groep_"%0"_niet_naar_beneden_verplaatsen
+
+Cannot_move_group_"%0"_left.=Kan_groep_"%0"_niet_naar_links_verplaatsen
+
+Cannot_move_group_"%0"_right.=Kan_groep_"%0"_niet_naar_rechts_verplaatsen
+
+Cannot_move_group_"%0"_up.=Kan_groep_"%0"_niet_naar_boven_verplaatsen
+
+case_insensitive=hoofdletter_ongevoelig
+
+case_sensitive=hoofdletter_gevoelig
+
+Case_sensitive=Hoofdletter_gevoelig
+
+change_assignment_of_entries=verandering_toekenning_van_entries
+
+# The following are for case change in right-click menu in entry editor. The last four
+# illustrate the four variations of capitalization
+Change_case=Verander_geval
+
+Change_entry_type=Wijzig_entry_type
+
+change_key=wijzig_sleutel
+
+Change_of_Grouping_Method=Wijzig_groepering_methode
+
+change_preamble=wijzig_inleiding
+
+change_string_content=wijzig_constante_inhoud
+
+change_string_name=wijzig_constante_naam
+
+change_type=wijzig_type
+
+changed_=gewijzigd_
+
+Changed_font_settings=Gewijzigde_lettertypeinstellingen
+
+Changed_language_settings=Gewijzigde_taal_instellingen
+
+Changed_look_and_feel_settings=Gewijzigde_"Look_and_Feel"-instellingen
+
+Changed_preamble=Gewijzigde_inleiding
+
+Changed_type_to=Type_gewijzigd_naar
+
+Characters_to_ignore=Tekens_die_genegeerd_worden
+
+Check_existing_%0_links=Controleer_bestaande_%0_snelkoppelingen
+
+Check_links=Controleer_snelkoppelingen
+
+Choose_the_URL_to_download._The_default_value_points_to_a_list_provided_by_the_JabRef_developers.=Kies_de_URL_om_te_downloaden._De_standaard_waarde_wijst_naar_een_lijst_voorzien_door_de_JabRef_ontwikkelaars.
+
+Citation_import_from_CiteSeer_failed.=Citaat_van_CiteSeer_importeren_is_mislukt.
+
+Cite_command_(for_Emacs/WinEdt)=Cite-commando_(voor_Emacs/WinEdt)
+
+CiteSeer_Error=CiteSeer_Foutmelding
+
+CiteSeer_Fetch_Error=CiteSeer_Ophaal_Foutmelding
+
+CiteSeer_import_entries=CiteSeer_importeer_entries
+
+CiteSeer_Import_Error=CiteSeer_Importeer_foutmelding
+
+CiteSeer_Import_Fields=CiteSeer_Importeer_Velden
+
+CiteSeer_Transfer=CiteSeer_Overdracht
+
+CiteSeer_Warning=CiteSeer_Waarschuwing
+
+Class_name=Klassenaam
+
+Clear=Wissen
+
+clear_all_groups=Wis_alle_groepen
+
+Clear_field=Wis_velden
+
+Clear_highlight=Wis_selectie
+
+Clear_highlighted=Wis_geselecteerde
+
+Clear_highlighted_groups=Wis_geselecteerde_groepen
+
+Clear_inputarea=Wis_invoergebied
+
+Clear_search=Wis_zoek
+
+Close=Sluiten
+
+Close_database=Sluit_database
+
+Close_dialog=Sluit_dialoog
+
+# The following lines correspond to names of key bindings:
+Close_entry_editor=Sluit_entry_editor
+
+Close_preamble_editor=Sluit_inleiding_editor
+
+Close_the_current_database=Sluit_de_huidige_database
+
+Close_the_help_window=Sluit_het_help_venster
+
+Close_window=Sluit_venster
+
+Closed_database=Sluit_database
+
+Collapse_subtree=Subboom_in_mekaar_klappen
+
+Color_codes_for_required_and_optional_fields=Kleurcodes_voor_vereiste_en_optionele_velden
+
+Color_for_marking_incomplete_entries=Kleur_om_onvolledige_entries_te_markeren
+
+Column_width=Kolombreedte
+
+Command_line_id=Commandoregel_id
+
+Complete_record=Vervolledig_record
+
+Completed_citation_import_from_CiteSeer.=Citaten_importeer-actie_van_CiteSeer_voltooid.
+
+Completed_Import_Fields_from_CiteSeer.=Velden_importeer-actie_van_CiteSeer_voltooid.
+
+Completed_import_from_CiteSeer.=Importeer-actie_van_CiteSeer_voltooid.
+
+Contained_in=bevat_in
+
+Content=Inhoud
+
+Copied=Gekopieerd
+
+Copied_cell_contents=Gekopieerde_cel_inhoud
+
+Copied_key=Gekopieerde_BibTeX-sleutel
+
+Copied_keys=Gekopieerde_BibTeX-sleutels
+
+Copy=Kopi\u00ebren
+
+Copy_\cite{BibTeX_key}=Kopieer_\cite{BibTeX-sleutel}
+
+Copy_BibTeX_key=Kopieer_BibTeX-sleutel
+
+Copy_to_clipboard=Kopieer_naar_klembord
+
+Could_not_call_executable=Kon_executable_niet_oproepen
+
+Could_not_connect_to_a_running_gnuserv_process._Make_sure_that_Emacs_or_XEmacs_is_running,<BR>and_that_the_server_has_been_started_(by_running_the_command_'gnuserv-start').=Kon_geen_verbinding_maken_met_een_draaiend_gnuserv_proces._Zorg_ervoor_dat_Emacs_of_XEmacs_draait,<BR>en_dat_de_server_gestart_is_(door_het_commando_'gnuserv-start'_te_draaien).
+
+Could_not_connect_to_host=Kon_geen_verbinding_maken_met_de_host
+
+# I have reformulated the following lines, because the 1st person form is not suitable:
+Could_not_connect_to_host_=Kon_geen_verbinding_maken_met_de_host
+
+Could_not_export_entry_types=Kon_entry_types_niet_exporteren
+
+Could_not_export_file=Kon_bestand_niet_exporteren
+
+Could_not_export_preferences=Kon_instellingen_niet_exporteren
+
+Could_not_find_a_suitable_import_format.=Kon_geen_geschikt_importeer_formaat_vinden.
+
+Could_not_find_layout_file=Kon_layout_bestand_niet_vinden
+
+Could_not_import_entry_types=Kon_entry_types_niet_importeren
+
+Could_not_import_preferences=Kon_instellingen_niet_importeren
+
+Could_not_instantiate_%0_%1=Kon_geen_instantie_van_%0_%1_aanmaken
+
+Could_not_instantiate_%0_%1._Have_you_chosen_the_correct_package_path?=Kon_geen_instantie_van_%0_%1_aanmaken._Heeft_u_het_correcte_pakket_pad_gekozen?
+
+Could_not_parse_number_of_hits=Kon_het_aantal_hits_niet_ontleden
+
+Could_not_resolve_import_format=Kon_het_importeer_formaat_niet_beslissen
+
+#####Switches_between_full_and_abbreviated_journal_name=Schakelt_tussen_volledige_en_afgekorte_tijdschriftnamen
+#####if_the_journal_name_is_known._Go_to_(...............)=als_het_tijdschrift_gekend_is._Ga_naar_(...............)
+Could_not_run_the_'gnuclient'_program._Make_sure_you_have_the_gnuserv/gnuclient_programs_installed.=Kon_het_'gnuclient'_programma_niet_uitvoeren._Zorg_ervoor_dat_u_de_gnuserv/gnuclient_programma's_ge\u00efnstalleerd_hebt.
+
+Could_not_save_file=Kon_het_bestand_niet_opslaan
+
+Couldn't_find_an_entry_associated_with_this_URL=Kon_geen_entry_geassocieerd_met_deze_URL_vinden
+
+Couldn't_parse_the_'citeseerurl'_field_of_the_following_entries=Kon_het_'citeseerurl'_veld_van_de_volgende_entries_niet_ontleden
+
+Create_group=Groep_aanmaken
+
+Created_group=Groep_aangemaakt
+
+Created_group_"%0".=Groep_"%0"_aangemaakte.
+
+Created_groups.=Groepen_aangemaakt.
+
+Curly_braces_{_and_}_must_be_balanced.=Gekrulde_haakjes_{_and_}_moeten_uitgebalanceerd_zijn.
+
+Current_content=Huidige_inhoud
+
+Current_value=Huidige_waarde
+
+Custom_entry_types=Externe_entry_types
+
+Custom_entry_types_found_in_file=Externe_entry_types_gevonden_in_bestand
+
+Custom_export=Externe_exportfilter
+
+Custom_importers=Externe_importfilter
+
+Customize_entry_types=Entry_types_aanpassen
+
+Customize_key_bindings=Toetsentoekenningen_aanpassen
+
+Cut=Knippen
+
+cut_entries=entries_knippen
+
+cut_entry=entry_knippen
+
+Cut_pr=Knippen_pr
+
+Database_encoding=Database_encodering
+
+Database_has_changed._Do_you_want_to_save_before_closing?=De_database_is_gewijzigd._Wilt_u_opslaan_alvorens_af_te_sluiten?
+
+Database_properties=Database_eigenschappen
+
+Date_format=Datum_formaat
+
+Default=Standaard
+
+Default_encoding=Standaard_encodering
+
+Default_grouping_field=Standaard_groeperingsveld
+
+Default_look_and_feel=Standaard_"look_and_feel"
+
+Default_owner=Standaard_eigenaar
+
+Default_pattern=Standaard_patroon
+
+Default_sort_criteria=Standaard_sorteercriteria
+
+defined.=gedefinieerd.
+
+Delete=Verwijderen
+
+Delete_custom=Verwijder_aangepast
+
+Delete_custom_format=Verwijder_aangepast_formaat
+
+# I have reformulated the following lines, because the 1st person form is not suitable:
+# (Folgende_URL_konnte_nicht_analysiert_werden)
+delete_entries=verwijder_entries
+
+Delete_entry=Verwijder_entry
+
+delete_entry=verwijder_entry
+
+Delete_multiple_entries=Verwijder_meerdere_entries
+
+Delete_rows=Verwijder_rijen
+
+Delete_strings=Verwijder_constanten
+
+Deleted=Verwijderd
+
+Deleted_entry=Verwijderde_entry
+
+Delimit_fields_with_semicolon,_ex.=Scheid_velden_met_puntkomma,_bv.
+
+Descending=Afdalend
+
+Description=Beschrijving
+
+Deselect_all=Alle_selecties_ongedaan_maken
+
+Details=Details
+
+Disable_entry_editor_when_multiple_entries_are_selected=Maak_entry_editor_onbeschikbaar_wanneer_meerdere_entries_geselecteerd_zijn
+
+Disable_this_confirmation_dialog=Maak_deze_bevestigingsdialoog_onbeschikbaar
+
+Disable_this_warning_dialog=Maak_deze_waarschuwingsdialoog_onbeschikbaar
+
+Display_all_entries_belonging_to_one_or_more_of_the_selected_groups.=Toon_alle_entries_die_bij_een_of_meerdere_van_de_geselecteerde_groepen_behoren.
+
+Display_all_error_messages=Toon_alle_foutmeldingen
+
+Display_help_on_command_line_options=Toon_help_over_commandline_opties
+
+Display_imported_entries_in_an_inspection_window_before_they_are_added.=Toon_ge\u00efmporteerde_entries_in_een_onderzoeksvenster_voordat_ze_toegevoegd_worden
+
+Display_only_entries_belonging_to_all_selected_groups.=Toon_alleen_entries_die_tot_alle_geselecteerde_groepen_behoren.
+
+Displaying_no_groups=Geen_groepen_tonend
+
+Do_not_abbreviate_names=Namen_niet_afkorten
+
+Do_not_autoset=Niet_automatisch_instellen
+
+Do_not_import_entry=Entry_niet_importeren
+
+Do_not_open_any_files_at_startup=Geen_bestanden_openen_bij_het_opstarten
+
+Do_not_overwrite_existing_keys=Bestaande_BibTeX-sleutels_niet_overschrijven
+
+Do_not_wrap_the_following_fields_when_saving=De_volgende_velden_niet_bij_het_opslaan_afbreken
+
+Docbook=Docbook
+
+Done=Klaar
+
+Down=Omlaag
+
+Download=Download
+
+Download_completed=Download_voltooid
+
+Download_file=Download_bestand
+
+Downloading...=Downloading...
+
+Due_to_the_duplicate_BibTeX_key,_the_groups_assignment(s)_for_this_entryncannot_be_restored_correctly_when_reopening_this_database._It_is_recommendednthat_you_have_JabRef_generate_a_unique_key_now_to_prevent_this_problem.=Omwille_van_een_dubbele_BibTex-sleutel,_kan_de_groepen_toekenning(en)_for_deze_entry_niet_hersteld_worden_bij_het_opnieuw_openen_van_deze_database._Het_is_aangeraden_JabRef_nu_een_unieke_sleutel_te_laten_genereren_om_dit_probleem_te_voorkomen.
+
+dummy=dummy
+
+Duplicate_BibTeX_key=Dubbele_BibTeX-sleutel
+
+duplicate_BibTeX_key=dubbele_BibTeX-sleutel
+
+Duplicate_BibTeX_key.=Dubbele_BibTeX-sleutel.
+
+duplicate_BibTeX_key.=dubbele_BibTeX-sleutel.
+
+Duplicate_BibTeX_key._Grouping_may_not_work_for_this_entry.=Dubbele_BibTeX-sleutel._Groepering_kan_misschien_niet_werken_voor_deze_entry.
+
+Duplicate_Key_Warning=Waarschuwing:_dubbele_BibTeX-sleutel
+
+Duplicate_pairs_found=Dubbele_paren_gevonden
+
+duplicate_removal=dubbels_verwijderen
+
+Duplicate_string_name=Dubbele_constante_naam
+
+Duplicates_found=Dubbels_gevonden
+
+Duplicates_removed=Dubbels_verwijderd
+
+Dynamic_groups=Dynamische_groepen
+
+Dynamically_group_entries_by_a_free-form_search_expression=Dynamisch_entries_groeperen_door_een_"free-form"_zoek_expressie
+
+Dynamically_group_entries_by_searching_a_field_for_a_keyword=Dynamisch_entries_groeperen_door_een_veld_te_zoeken_via_een_sleutelwoord
+
+Each_line_must_be_on_the_following_form=Elke_regel_moet_in_de_volgende_vorm_zijn
+
+Edit=Bewerken
+
+Edit_custom_export=Externe_exportfilter_bewerken
+
+Edit_entry=Entry_bewerken
+
+Edit_group=Groep_bewerken
+
+Edit_journal=Tijdschrift_bewerken
+
+Edit_preamble=Inleiding_bewerken
+
+Edit_strings=Constanten_bewerken
+
+empty_BibTeX_key=lege_BibTeX-sleutel
+
+Empty_BibTeX_key.=Lege_BibTeX-sleutel.
+
+Empty_BibTeX_key._Grouping_may_not_work_for_this_entry.=Lege_BibTeX-sleutel._Groepering_kan_misschien_niet_werken_voor_deze_entry.
+
+Empty_database=Lege_database
+
+empty_database=lege_database
+
+Enable_source_editing=Broncode_aanpassing_mogelijk_maken
+
+Endnote=Endnote
+
+Enter_URL=URL_ingeven
+
+Enter_URL_to_download=Geef_URL_om_te_downloaden_in
+
+entries=entries
+
+Entries_cannot_be_manually_assigned_to_or_removed_from_this_group.=Entries_kunnen_niet_manueel_toegekend_of_verwijderd_worden_van_deze_groep.
+
+Entries_exported_to_clipboard=Entries_ge\u00ebxporteerd_naar_het_klembord
+
+entries_have_undefined_BibTeX_key=entries_hebben_een_ongedefinieerde_BibTeX-sleutel
+
+entries_into_new_database=entries_in_nieuwe_database
+
+entry=entry
+
+Entry_editor=Entry_editor
+
+# The following lines correspond to names of key bindings:
+Entry_editor,_next_entry=Entry_editor,_volgende_entry
+
+Entry_editor,_next_panel=Entry_editor,_volgend_paneel
+
+Entry_editor,_previous_entry=Entry_editor,_vorige_entry
+
+Entry_editor,_previous_panel=Entry_editor,_vorige_paneel
+
+Entry_editor,_store_field=Entry_editor,_veld_opslaan
+
+Entry_in_current_database=Entry_in_huidige_database
+
+Entry_in_import=Entry_in_importering
+
+Entry_is_incomplete=Entry_is_onvolledig
+
+Entry_preview=Entry_voorbeeld
+
+Entry_table=Entry_tabel
+
+Entry_table_columns=Entry_tabelkolommen
+
+Entry_type=Entry_type
+
+Entry_type_names_are_not_allowed_to_contain_white_space_or_the_following_characters=Entry_typenamen_mogen_geen_witruimtes_of_de_volgende_tekens_bevatten
+
+Entry_types=Entrytypes
+
+EOF_in_mid-string=EOF_in_mid-string
+
+Error=Foutmelding
+
+##Error:_check_your_External_viewer_settings_in_Preferences=Foutmelding:_controleer_uw_Externe_viewer_instellingen_in_Instellingen
+Error_in_field=Fout_in_veld
+
+Error_in_line=Fout_in_regel
+
+Error_messages=Foutmeldingen
+
+Error_opening_file=Foutmelding_bij_het_openen_van_het_bestand
+
+Error_setting_field=Foutmelding_bij_het_instellen_van_het_veld
+
+Existing_file=Bestaande_bestand
+
+exists._Overwrite?=bestaat_reeds._Overschrijven?
+
+exists._Overwrite_file?=bestaat_reeds._Bestand_overschrijven?
+
+Exit=Afsluiten
+
+Expand_subtree=Subboom_uitklappen
+
+Explicit=Expliciet
+
+Export=Exporteren
+
+Export_entry_types=Entry_types_exporteren
+
+Export_name=Naam_exporteren
+
+Export_preferences=Instellingen_exporteren
+
+Export_preferences_to_file=Instellingen_exporteren_naar_bestand
+
+Export_properties=Eigenschappen_exporteren
+
+Export_selected_to_clipboard=Exporteer_geselecteerde_naar_klembord
+
+Export_to_clipboard=Exporteer_naar_klembord
+
+Exported_database_to_file=Exporteer_database_naar_bestand
+
+Exporting=Exporteren...
+
+External_changes=Externe_wijzigingen
+
+External_files=Externe_bestanden
+
+External_programs=Externe_programma's
+
+External_viewer_called=Externe_viewer_opgeroepen
+
+Failed_to_read_groups_data_(unsupported_version:_%0)=Lezen_van_groepen_data_mislukt_(niet_ondersteunde_versie:_%0)
+
+Fetch=Ophalen
+
+Fetch_Articles_Citing_your_Database=Haal_Artikels_Geciteerd_in_de_Database_op
+
+Fetch_Citations_from_CiteSeer=Haal_Citaten_van_CiteSeer_op
+
+Fetch_citations_from_CiteSeer=Haal_citaten_van_CiteSeer_op
+
+Fetch_CiteSeer=Ophalen_van_CiteSeer
+
+Fetch_Medline=Ophalen_van_Medline
+
+fetch_Medline=ophalen_van_Medline
+
+Fetch_Medline_by_author=Ophalen_van_Medline_op_auteur
+
+Fetch_Medline_by_ID=Ophalen_van_Medline_op_ID
+
+Fetched_all_citations_from_target_database.=Haal_alle_citaten_op_van_doeldatabase
+
+Fetching_Citations=Citaten_aan_het_Ophalen
+
+Fetching_Identifiers=Identificatienummers_aan_het_Ophalen
+
+Fetching_Medline...=Aan_het_Ophalen_van_Medline...
+
+Fetching_Medline_by_ID...=Aan_het_Ophalen_van_Medline_op_ID...
+
+Fetching_Medline_by_id_...=Aan_het_Ophalen_van_Medline_op_id...
+
+Fetching_Medline_by_term_...=Aan_het_Ophalen_van_Medline_op_term...
+
+Field=Veld
+
+field=veld
+
+# Integrity check is a process that checks for indications of wrongly filled out bibtex fields. "Scan" is the button that starts the check.
+Field_content=Veld_inhoud
+
+Field_name=Veldnaam
+
+Field_names_are_not_allowed_to_contain_white_space_or_the_following_characters=Veldnamen_mogen_geen_witruimtes_of_de_volgende_tekens_bevatten
+
+Field_sizes=Veld_groottes
+
+Field_to_group_by=Veld_te_groeperen_op
+
+Field_to_search=Veld_te_zoeken
+
+Fields=Velden
+
+File=Bestand
+
+file=vestand
+
+File_'%0'_not_found=Bestand_'%0'_niet_gevonden
+
+File_changed=Bestand_veranderd
+
+File_extension=Bestandsextensie
+
+File_has_been_updated_externally._Are_you_sure_you_want_to_save?=Het_bestand_is_extern_geupdate._Verdergaan_met_opslaan?
+
+File_not_found=Bestand_niet_gevonden
+
+File_updated_externally=Bestand_extern_geupdate
+
+filename=bestandsnaam
+
+Files_opened=Bestanden_geopend
+
+Filter=Filter
+
+Find_duplicates=Dubbels_vinden
+
+Finished_autosetting_%0_field._Entries_changed:_%1.=Automatisch_instellen_van_%0_velden_voltooid._Aantal_veranderde_entries:_%1.
+
+Finished_synchronizing_%0_links._Entries_changed%c_%1.=Synchroniseren_van_%0_snelkoppelingen_voltooid._Aantal_veranderde_entries%c_%1.
+
+First_select_the_entries_you_want_keys_to_be_generated_for.=Selecteer_eerst_de_entries_waarvoor_u_sleutels_wilt_genereren.
+
+Fit_table_horizontally_on_screen=Pas_tabel_horizontaal_aan_op_het_scherm
+
+Float=Float
+
+Font_Family=Lettertype_Type
+
+Font_Preview=Lettertype_Voorbeeld
+
+Font_Size=Lettertype_Grootte
+
+Font_Style=Lettertype_Stijl
+
+FontSelector=Lettertype_selecteren
+
+for=voor
+
+Format_of_author_and_editor_names=Formaat_van_de_auteur-_en_editornamen
+
+Format_used=Formaat_gebruikt
+
+Formatter_not_found=Formateerder_niet_gevonden
+
+found=gevonden
+
+found_in_aux_file=gevonden_in_aux_bestand
+
+Full_name=Volledige_naam
+
+General=Algemeen
+
+General_fields=Algemene_velden
+
+Generate=Genereren
+
+Generate_BibTeX_key=Genereer_BibTeX-sleutel
+
+Generate_keys=Genereer_sleutels
+
+Generate_keys_before_saving_(for_entries_without_a_key)=Genereer_sleutels_voor_het_opslaan_(voor_entries_zonder_een_sleutel)
+
+Generate_now=Genereer_nu
+
+Generated_BibTeX_key_for=Gegenereerde_BibTeX-sleutel_voor
+
+Generating_BibTeX_key_for=BibTeX-sleutel_aan_het_genereren_voor
+
+Grab=Neem
+
+Gray_out_entries_not_in_group_selection=Maak_entries_die_niet_in_de_groep_selectie_zitten_grijs
+
+Gray_out_non-hits=Maak_niet_gevonden_items_grijs
+
+Gray_out_non-matching_entries=Maak_entries_die_niet_overeenkomen_grijs
+
+Group_definitions_have_been_converted_to_JabRef_1.7_format.=De_groep_definities_zijn_geconverteerd_naar_het_JabRef_1.7_formaat.
+
+Group_name=Groepnaam
+
+Group_properties=Groepeigenschappen
+
+Groups=Groepen
+
+Harvard_RTF=Harvard_RTF
+
+Have_you_chosen_the_correct_package_path?=Heeft_u_het_correcte_pakket_pad_gekozen?
+
+Help=Help
+
+Help_contents=Help_inhoud
+
+Help_on_groups=Help_over_groepen
+
+Help_on_key_patterns=Help_over_sleutelpatronen
+
+Hide_non-hits=Verberg_niet_gevonden_objecten
+
+Hide_non-matching_entries=Verberg_entries_die_niet_overeenkomen
+
+Hierarchical_context=Hi\u00ebrarchische_context
+
+Highlight=Markeren
+
+Highlight_groups_matching_all_selected_entries=Markeer_groepen_die_overeenkomen_met_alle_geselecteerde_entries
+
+Highlight_groups_matching_any_selected_entry=Markeer_groepen_die_overeenkomen_met_elke_geselecteerde_entry
+
+Highlight_groups_that_contain_entries_contained_in_any_currently_selected_group=Markeer_groepen_die_entries_bevatten_die_zich_bevinden_in_elke_huidige_geselecteerde_groep
+
+Highlight_overlapping_groups=Markeer_overlappende_groepen
+
+Hint%c_To_search_specific_fields_only,_enter_for_example%c<p><tt>author%esmith_and_title%eelectrical</tt>=Hint%c_Om_specifieke_velden_alleen_te_zoeken,_geef_bijvoorbeeld_in%c<p><tt>auteur%esmith_en_titel%eelectrical</tt>
+
+HTML=HTML
+
+Ignore=Negeren
+
+Illegal_type_name=Verkeerde_typenaam
+
+Immediate_subgroups=Directe_subgroepen
+
+Import=Importeren
+
+Import_and_append=Importeren_en_bijvoegen
+
+Import_and_keep_old_entry=Importeren_en_oude_entry_behouden
+
+Import_and_remove_old_entry=Importeren_en_oude_entry_verwijderen
+
+Import_cancelled.=Importering_geannuleerd
+
+Import_Data_from_CiteSeer=Importeer_Data_van_CiteSeer
+
+Import_Data_from_CiteSeer_Database=Importeer_Data_van_CiteSeer_Database
+
+Import_database=Importeer_database
+
+Import_entries=Importeer_entries
+
+Import_entry_types=Importeer_entry_types
+
+Import_failed=Importering_mislukt
+
+Import_Fields_from_CiteSeer=Importeer_Velden_van_CiteSeer
+
+Import_fields_from_CiteSeer=Importeer_velden_van_CiteSeer
+
+Import_fields_from_CiteSeer_Database=Importeer_velden_van_CiteSeer_Database
+
+Import_Fields_from_CiteSeer_Database=Importeer_Velden_van_CiteSeer_Database
+
+Import_file=Importeer_bestand
+
+Import_group_definitions=Importeer_groep_definities
+
+Import_name=Importeer_naam
+
+Import_plain_text=Importeer_onopgemaakte_tekst
+
+Import_preferences=Instellingen_importeren
+
+Import_preferences_from_file=Importeer_instellingen_van_bestand
+
+Import_strings=Importeer_constanten
+
+Import_to_open_tab=Importeer_naar_open_tabblad
+
+Import_word_selector_definitions=Importeer_woordselecteerder_definities
+
+Imported_database=Ge\u00efmporteerde_database
+
+Imported_entries=Ge\u00efmporteerde_entries
+
+Imported_entry_types=Ge\u00efmporteerde_entry_types
+
+Imported_file=Ge\u00efmporteerd_bestand
+
+Imported_from_database=Ge\u00efmporteerd_van_database
+
+ImportFormat_class=ImportFormat_Klasse
+
+Importing=Aan_het_importeren
+
+Importing_file=Bestand_aan_het_Importeren
+
+Importing_in_unknown_format=Aan_het_Importeren_in_onbekend_formaat
+
+In_JabRef,_use_pairs_of_#_characters_to_indicate_a_string.=In_JabRef,_gebruik_paren_van_#_tekens_om_een_constante_aan_te_duiden.
+
+Include_abstracts=Abstracts_insluiten
+
+Include_subgroups=Subgroepen_insluiten
+
+Include_subgroups\:_When_selected,_view_entries_contained_in_this_group_or_its_subgroups=Subgroepen_insluiten\:_Wanneer_geselecteerd,_toon_entries_in_deze_groep_of_in_zijn_subgroepen
+
+Incremental=Incrementeel
+
+Incremental_search=Incrementeel_zoeken
+
+Incremental_search_failed._Repeat_to_search_from_top.=Incrementeel_zoeken_mislukt._Herhaal_om_te_zoeken_vanaf_het_begin.
+
+Independent=Onafhankelijk
+
+Independent_group\:_When_selected,_view_only_this_group's_entries=Onafhankelijke_groep\:_Wanneer_geselecteerd,_toon_enkel_de_entries_van_deze_groep
+
+Initially_show_groups_tree_expanded=Initieel,_toon_alle_bomen_van_de_groepen_uitgeklapt
+
+Input=Invoer
+
+Input_error=Invoer_foutmelding
+
+Insert=Invoegen
+
+Insert_rows=Rijen_invoegen
+
+Insert_selected_citations_into_LyX/Kile=Voeg_geselecteerde_citaten_in_LyX/Kile
+
+Insert_selected_citations_into_WinEdt=Voeg_geselecteerde_citaten_in_WinEdt
+
+insert_string_=voeg_constante_in_
+
+Insert_URL=voeg_URL_in
+
+INSPEC=INSPEC
+
+integrity=integriteit
+
+# Integrity check is a process that checks for indications of wrongly filled out bibtex fields. "Scan" is the button that starts the check.
+Integrity_check=Integriteitscontrole
+
+Intersection=Doorsnede
+
+Intersection_with_supergroups=Doorsnede_met_subgroepen
+
+Invalid_BibTeX_key=Ongeldige_BibTeX-sleutel
+
+Invalid_date_format=Ongeldig_datumformaat
+
+Invalid_URL=Ongeldige_URL
+
+Inverted=Ge\u00efnverteerd
+
+is_a_standard_type.=is_een_standaard_type.
+
+ISI=ISI
+
+ISO_abbreviation=ISO_afkorting
+
+Item_list_for_field=Item_lijst_voor_veld
+
+JabRef_help=JabRef_Help
+
+JabRef_preferences=JabRef_instellingen
+
+Journal_abbreviations=Tijdschrift_afkortingen
+
+Journal_list_preview=Tijdschriftenlijst_voorbeeld
+
+Journal_name=Tijdschrift_naam
+
+Journal_names=Tijdschrift_namen
+
+JStor_file=JStor_bestand
+
+Keep=Behouden
+
+Keep_both=Beide_behouden
+
+Keep_lower=Onderste_behouden
+
+Keep_upper=Bovenste_behouden
+
+Key_bindings=Sleutel_koppelingen
+
+Key_bindings_changed=Sleutel_koppelingen_gewijzigd
+
+Key_generator_settings=Sleutelgenerator_instellingen
+
+Key_pattern=Sleutelpatroon
+
+keys_in_database=sleutels_in_database
+
+Keyword=Sleutelwoord
+
+Label=Label
+
+Language=Taal
+
+Last_modified=Laatst_gewijzigd
+
+Latex_AUX_file=LateX_AUX_bestand
+
+LaTeX_AUX_file=LaTeX_AUX-bestand
+
+Left=Links
+
+License=Licentie
+
+Limit_to_fields=De_volgende_velden_begrenzen
+
+Limit_to_selected_entries=De_volgende_geselecteerde_entries_begrenzen
+
+Listen_for_remote_operation_on_port=Luister_naar_operatie_vanop_afstand_op_poort
+
+Load_session=Sessie_laden
+
+Loading_session...=Sessie_aan_het_laden...
+
+Look_and_feel="Look_and_feel"
+
+lower=lager
+
+Main_layout_file=Hoofd_layoutbestand
+
+Main_PDF_directory=Hoofd_PDF-map
+
+Main_PS_directory=Hoofd_PS-map
+
+Manage=Beheren
+
+Manage_content_selectors=Beheer_inhoud_selectors
+
+Manage_custom_exports=Beheer_externe_exportfilters
+
+Manage_custom_imports=Beheer_externe_importfilters
+
+Manage_journal_abbreviations=Beheer_tijdschrift_afkortingen
+
+Mark_entries=Markeer_entries
+
+Mark_entry=Markeer_entry
+
+Mark_new_entries_with_addition_date=Markeer_nieuwe_entries_met_datum_van_toevoeging
+
+Mark_new_entries_with_owner_name=Markeer_nieuwe_entries_met_naam_van_eigenaar
+
+# These are status line messages when marking/unmarking entries:
+Marked_selected=Markering_geselecteerd
+
+Medline_entries_fetched=Medline_entries_opgehaald
+
+Medline_XML=Medline_XML
+
+Medline_XML_File=Medline_XML_Bestand
+
+Menu_and_label_font_size=Menu_en_label_lettertypegrootte
+
+Merged_external_changes=Voeg_externe_veranderingen_samen
+
+messages=berichten
+
+Messages=Berichten
+
+Messages_and_Hints=berichten_en_hints
+
+Miscellaneous=Varia
+
+Modification_of_field=Wijziging_van_veld
+
+Modified_group_"%0".=Gewijzigde_groep_"%0".
+
+Modified_groups=Gewijzigde_groepen
+
+Modified_groups_tree=Gewijzigde_groep_boom
+
+Modified_string=Gewijzigde_constante
+
+Modify=Wijzigen
+
+modify_group=wijzig_groep
+
+MODS=MODS
+
+Move=Verplaats
+
+Move_down=Verplaats_naar_beneden
+
+Move_entries_in_group_selection_to_the_top=Verplaats_entries_in_de_groep_selectie_naar_de_top
+
+move_group=verplaats_groep
+
+Move_matching_entries_to_the_top=Verplaats_overeenkomstige_entries_naar_de_top
+
+Move_string_down=Verplaats_constante_naar_beneden
+
+Move_string_up=Verplaats_constante_naar_boven
+
+Move_up=Verplaats_naar_boven
+
+Moved_Group=Verplaatste_Groep
+
+Moved_group_"%0".=Verplaatste_Groep_"%0".
+
+Name=Naam
+
+Natbib_style=Natbib_stijl
+
+nested_aux_files=geneste_aux_bestanden
+
+New=Nieuw
+
+new=nieuw
+
+New_article=Nieuwe_entry_'article'
+
+New_BibTeX_database=Nieuwe_BibTeX-database
+
+New_BibTeX_entry=Nieuwe_BibTeX-entry
+
+New_BibTeX_subdatabase=Nieuwe_BibTeX_subdatabase
+
+New_book=Nieuwe_entry_'book'
+
+New_content=Nieuwe_inhoud
+
+New_database=Nieuwe_database
+
+New_database_created.=Nieuwe_database_aangemaakt.
+
+New_entry=Nieuwe_entry
+
+New_entry...=Nieuwe_entry...
+
+New_entry_from_plain_text=Nieuwe_entry_van_onopgemaakte_tekst
+
+New_file=Nieuw_bestand
+
+New_group=Nieuwe_groep
+
+New_inbook=Nieuwe_entry_'inbook'
+
+New_mastersthesis=Nieuwe_entry_'masterthesis'
+
+New_phdthesis=Nieuwe_entry_'phdthesis'
+
+New_proceedings=Nieuwe_entry_'proceedings'
+
+New_string=Nieuwe_constante
+
+New_subdatabase=Nieuwe_subdatabase
+
+New_subdatabase_based_on_AUX_file=Nieuwe_subdatabase_gebaseerd_op_AUX_bestand
+
+New_unpublished=Nieuwe_entry_'unpublished'
+
+Next_entry=Volgende_entry
+
+Next_tab=Volgend_tabblad
+
+No_%0_found=Geen_%0_gevonden
+
+No_actual_changes_found.=Geen_actuele_veranderingen_gevonden.
+
+no_base-bibtex-file_specified=Geen_basis_BibTeX-bestand_gespecifieerd
+
+No_custom_imports_registered_yet.=Geen_externe_importfilters_geregistreerd.
+
+no_database_generated=Geen_database_gegenereerd
+
+No_duplicates_found=Geen_dubbels_gevonden
+
+No_entries_found._Please_make_sure_you_are_using_the_correct_import_filter.=Geen_entries_gevonden._Zorg_er_a.u.b._voor_dat_u_de_juiste_importfilter_gebruikt.
+
+No_entries_imported.=Geen_entries_ge\u00efmporteerd.
+
+No_entries_or_multiple_entries_selected.=Geen_entries_of_meerdere_entries_geselecteerd.
+
+No_entries_selected=Geen_entries_geselecteerd
+
+No_exceptions_have_ocurred.=Geen_uitzonderingen_zijn_voorgekomen.
+
+No_file_extension._Could_not_find_viewer_for_file.=Geen_bestandsextensie._Kon_geen_viewer_voor_het_bestand_vinden.
+
+No_GUI._Only_process_command_line_options.=Geen_GUI._Alleen_proces_commandoregel_opties.
+
+No_journal_names_could_be_abbreviated.=Er_konden_geen_tijdschrift_namen_afgekort_worden.
+
+No_journal_names_could_be_unabbreviated.=Geen_afkortingen_van_tijdschrift_namen_konden_ongedaan_gemaakt_worden.
+
+No_Medline_entries_found.=Geen_Medline_entries_gevonden.
+
+No_pdf_or_ps_defined,_and_no_file_matching_Bibtex_key_found=Geen_PDF_of_PS_gedefinieerd,_en_geen_BibTeX-sleutel_die_overeenkomt_met_een_bestand_gevonden
+
+No_references_found=Geen_referenties_gevonden
+
+No_saved_session_found.=Geen_opgeslagen_sessie_gevonden.
+
+No_url_defined=Geen_URL_gedefinieerd
+
+non-Mac_only=enkel_niet-Mac
+
+Normal=Normaal
+
+not=niet
+
+not_found=niet_gevonden
+
+Not_saved_(empty_session)=Niet_opgeslagen
+
+Note_that_the_entry_causing_the_problem_has_been_selected.=Merk_op_dat_de_entry_die_het_probleem_veroorzaakt_geselecteerd_werd.
+
+Note_that_the_new_definitions_will_not_be_compatible_with_previous_JabRef_versions.=Merk_op_dat_de_nieuwe_definities_niet_compatibel_zijn_met_voorgaande_JabRef_versies.
+
+Note_that_you_must_specify_the_fully_qualified_class_name_for_the_look_and_feel,=Merk_op_dat_u_de_volledig_gekwalificeerde_klassenaam_voor_de_"look_and_feel"_moet_specificeren,
+
+Nothing_to_redo=Niets_om_te_herstellen
+
+Nothing_to_undo=Niets_om_ongedaan_te_maken
+
+# The next is used like in "References found: 1 Number of references to fetch?"
+Number_of_references_to_fetch?=Aantal_referenties_om_op_te_halen?
+
+occurences=voorkomens
+
+OK=OK
+
+Ok=OK
+
+One_or_more_keys_will_be_overwritten._Continue?=E\u00e9n_of_meerdere_sleutels_zullen_overschreven_worden._Verder_gaan?
+
+Open=Openen
+
+open=openen
+
+Open_BibTeX_database=Open_BibTeX-database
+
+Open_database=Open_database
+
+Open_editor_when_a_new_entry_is_created=Open_editor_wanneer_een_nieuwe_entry_aangemaakt_werd
+
+Open_file=Open_bestand
+
+Open_last_edited_databases_at_startup=Open_laatst_aangepaste_databases_bij_het_opstarten
+
+Open_PDF_or_PS=Open_PDF_of_PS
+
+Open_right-click_menu_with_Ctrl+left_button=Open_rechtsklik-menu_met_Ctrl_+_linkse_muisknop
+
+Open_URL_or_DOI=Open_URL_of_DOI
+
+Opened_database=Geopende_database
+
+Opening=Aan_het_openen
+
+Opening_preferences...=Instellingen_aan_het_openen
+
+Optional_fields=Optionele_velden
+
+Options=Opties
+
+or=of
+
+out_of=van
+
+Output_or_export_file=Geef_uitvoer_of_exporteer_bestand
+
+Overlapping_groups=Overlappende_groepen
+
+Override=Wijzigen
+
+Override_default_file_directories=Wijzig_standaard_bestandsmappen
+
+override_the_bibtex_key_by_the_selected_text=wijzig_de_BibTeX-sleutel_door_de_geselecteerde_tekst
+
+Overwrite_keys=Overschrijf_sleutels
+
+Ovid=Ovid
+
+pairs_processed=paren_verwerkt
+
+Paste=Plakken
+
+paste_entries=plak_entries
+
+paste_entry=plak_entry
+
+Paste_from_clipboard=plak_vanuit_klembord
+
+Pasted=Geplakt
+
+Path_to_HTML_viewer=Pad_naar_HTML-viewer
+
+Path_to_LyX_pipe=Pad_naar_LyX-pipe
+
+Path_to_PDF_viewer=Pad_naar_PDF-viewer
+
+Path_to_PS_viewer=Pad_naar_PS-viewer
+
+Path_to_WinEdt.exe=Pad_naar_WinEdt.exe
+
+Paths_to_external_programs=Paden_naar_externe_programma's
+
+PDF_directory=PDF_map
+
+PDF_links=PDF_snelkoppelingen
+
+Personal_journal_list=Persoonlijke_tijdschriften_lijst
+
+Pick_titles=Kies_titels
+
+Plain_right_menu="Plain_rechtse_menu
+
+Plain_text=Onopgemaakte_tekst
+
+Plain_text_import=Onopgemaakte_tekst_importeren
+
+Please_check_your_network_connection_to_this_machine.=Controleer_uw_netwerkverbinding_naar_deze_machine.
+
+Please_define_BibTeX_key_first=Definieer_de_BibTeX-sleutel_eerst_a.u.b.
+
+Please_enter_a_name_for_the_group.=Geef_a.u.b._een_naam_voor_de_groep.
+
+Please_enter_a_search_term._For_example,_to_search_all_fields_for_<b>Smith</b>,_enter%c<p><tt>smith</tt><p>To_search_the_field_<b>Author</b>_for_<b>Smith</b>_and_the_field_<b>Title</b>_for_<b>electrical</b>,_enter%c<p><tt>author%esmith_and_title%eelectrical</tt>=Geef_a.u.b._een_zoekterm._Bijvoorbeeld,_om_alle_velden_te_doorzoeken_naar_<b>Smith</b>,_geef_in:%c<p><tt>smith</tt><p>Om_het_veld_<b>Author</b>_te_doorzoeken_naar_<b>Smith</b>_en_het_veld_<b>Title</b>_naar_<b>electrical</b>,_geef [...]
+
+Please_enter_a_semicolon_or_comma_separated_list_of_Medline_IDs_(numbers).=Geef_a.u.b._een_Medline_IDs_(getallen)_lijst_in,_gescheiden_door_een_puntkomma_of_komma.
+
+Please_enter_the_field_to_search_(e.g._<b>keywords</b>)_and_the_keyword_to_search_it_for_(e.g._<b>electrical</b>).=Geef_a.u.b._het_veld_om_te_doorzoeken_(bv._<b>keywords</b>)_en_het_sleutelword_om_naar_te_zoeken_(bv._<b>electrical</b>).
+
+Please_enter_the_string's_label=Geef_a.u.b._het_label_van_de_constante_in
+
+Please_refer_to_the_JabRef_help_manual_on_using_the_CiteSeer_tools.=Kijk_a.u.b._in_JabRef's_help_handleiding_voor_het_gebruik_van_CiteSeer_tools.
+
+Please_select_an_importer=Selecteer_a.u.b._een_importer
+
+Please_select_an_importer.=Selecteer_a.u.b._een_importer.
+
+Please_select_exactly_one_group_to_move.=Selecteer_a.u.b._exact_\u00e9\u00e9n_groep_om_te_verplaatsen.
+
+Please_wait_until_it_has_finished.=Even_geduld_a.u.b._tot_de_operatie_voltooid_is.
+
+Possible_duplicate_entries=Mogelijke_dubbele_entries
+
+Possible_duplicate_of_existing_entry._Click_to_resolve.=Mogelijk_duplicaat_van_bestaande_entry.
+
+Preamble=Inleiding
+
+Preamble_editor,_store_changes=Inleiding_editor,_sla_veranderingen_op
+
+Preferences=Instellingen
+
+Preferences_recorded=Instellingen_opgeslagen
+
+Preferences_recorded.=Instellingen_opgeslagen.
+
+Preserve_formatting_of_non-BibTeX_fields=Behoud_formattering_van_niet-BibTeX_velden
+
+Preview=Voorbeeld
+
+Previous_entry=Vorige_entry
+
+Previous_tab=Vorige_tabblad
+
+Primary_sort_criterion=Primair_sorteercriterium
+
+Problem_with_parsing_entry=Probleem_met_entry_ontleding
+
+PS_directory=PS_map
+
+PS_links=PS_snelkoppelingen
+
+Push_selection_to_Emacs=Stuur_selectie_naar_Emacs
+
+push_selection_to_lyx=Stuur_selectie_naar_lyx
+
+Push_selection_to_LyX/Kile=Stuur_selectie_naar_LyX/Kile
+
+Push_selection_to_WinEdt=Stuur_selectie_naar_WinEdt
+
+Push_to_LatexEditor=Stuur_selectie_naar_LaTeXEditor
+
+Push_to_LyX=Stuur_selectie_naar_LyX
+
+Push_to_WinEdt=Stuur_selectie_naar_WinEdt
+
+Pushed_citations_to_Emacs=Citaten_naar_Emacs_gestuurd
+
+Pushed_citations_to_WinEdt=Citaten_naar_WinEdt_gestuurd
+
+Pushed_the_citations_for_the_following_rows_to=De_citaten_voor_de_volgende_rijen_gestuurd_naar
+
+Query_author(s)=Vraag_stellen_over_auteur(s)
+
+Quit=Afsluiten
+
+Quit_JabRef=JabRef_afsluiten
+
+Quit_synchronization=Synchronisatie_afsluiten
+
+Raw_source=Ruwe_bron
+
+Really_delete_the_selected=Bent_u_zeker_over_het_verwijderen_van_deze
+
+Rearrange_tabs_alphabetically_by_title=Rangschik_tabbladen_alfabetisch_op_titel
+
+Recent_files=Recente_bestanden
+
+Redo=Herstellen
+
+Refer/Endnote=Refer/Endnote
+
+Reference_database=Referentie_database
+
+# The next two lines are used like in "References found: 1 Number of references to fetch?"
+References_found=Referenties_gevonden
+
+Refine_supergroup\:_When_selected,_view_entries_contained_in_both_this_group_and_its_supergroup=Verfijn_supergroep\:_Wanneer_geselecteerd,_toon_de_entries_die_in_deze_groep_en_zijn_supergroep_zitten
+
+Refresh_view=Beeld_verversen
+
+Regexp=Regexp
+
+Regular_Expression=Regular_Expression
+
+Remember_these_entry_types?=Deze_entry_types_behouden?
+
+Remote_operation=Externe_operatie
+
+Remote_server_port=Externe_server_poort
+
+Remove=Verwijderen
+
+Remove_all?=Alles_verwijderen?
+
+Remove_all_subgroups=Verwijder_alle_subgroepen
+
+Remove_all_subgroups_of_"%0"?=Alle_subgroepen_van_"%0"_verwijderen?
+
+Remove_double_braces_around_BibTeX_fields_when_loading.=Verwijder_dubbele_haakjes_rond_BibTeX-velden_bij_het_laden
+
+Remove_duplicates=Verwijder_dubbels
+
+Remove_entry_from_import=Verwijder_entry_uit_importering
+
+Remove_entry_selection_from_this_group=Verwijder_entry_selectie_van_deze_groep
+
+Remove_entry_type=Verwijder_entry_type
+
+remove_from_group=verwijder_uit_groep
+
+Remove_from_group=Verwijder_uit_groep
+
+Remove_group=Verwijder_groep
+
+Remove_group,_keep_subgroups=Verwijder_groep,_behoud_subgroepen
+
+Remove_group_"%0"?=Verwijder_groep_"%0"?
+
+Remove_group_"%0"_and_its_subgroups?=Verwijder_groep_"%0"_en_zijn_subgroepen?
+
+remove_group_(keep_subgroups)=verwijder_groep_(behoud_subgroepen)
+
+remove_group_and_subgroups=verwijder_groep_en_subgroepen
+
+Remove_group_and_subgroups=Verwijder_groep_en_subgroepen
+
+Remove_old_entry=Verwijder_oude_entry
+
+Remove_selected_strings=Verwijder_geselecteerde_entries
+
+remove_string=verwijder_constante
+
+remove_string_=verwijder_constante_
+
+Removed_entry_type.=Entry_type_verwijderd
+
+Removed_group=Groep_verwijderd
+
+Removed_group_"%0".=Groep_"%0"_verwijderd.
+
+Removed_group_"%0"_and_its_subgroups.=Groep_"%0"_en_zijn_subgroepen_verwijderd.
+
+Removed_string=Constante_verwijderd
+
+Renamed_string=Constante_hernoemd
+
+Repeat_incremental_search=Herhaal_incrementele_zoekopdracht
+
+Replace=Vervangen
+
+Replace_(regular_expression)=Vervang_(regular_expression)
+
+Replace_string=Tekst_vervangen
+
+Replace_with=Vervang_door
+
+Replaced=Vervangen
+
+Required_fields=Vereiste_velden
+
+Reset_all=Herstel_alles
+
+resolved=opgelost
+
+Results=Resultaten
+
+Revert_to_original_source=Herstel_naar_originele_bron
+
+Review=Recensie
+
+Review_changes=Bekijk_veranderingen
+
+Right=Rechts
+
+RIS=RIS
+
+Save=Opslaan
+
+Save_before_closing=Opslaan_voor_afsluiten
+
+Save_database=Database_opslaan
+
+Save_database_as_...=Database_opslaan_als_...
+
+Save_entries_in_their_original_order=Sla_entries_in_hun_originele_volgorde_op
+
+Save_failed=Opslaan_mislukt
+
+Save_failed_during_backup_creation=Opslaan_mislukt_tijdens_creatie_van_backup
+
+Save_failed_while_committing_changes=Opslaan_mislukt_bij_het_vastleggen_van_veranderingen
+
+Save_in_default_table_sort_order=Sla_in_standaard_tabel_sorteervolgorde_op
+
+Save_ordered_by_author/editor/year=Sla_gesorteerd_op_auteur/editor/jaar_op
+
+Save_selected_as_...=Sla_geselecteerde_op_als_...
+
+Save_session=Sessie_opslaan
+
+Saved_database=Database_opgeslagen
+
+Saved_selected_to=Geselecteerde_opgeslagen_naar
+
+Saved_session=Sessie_opgeslagen
+
+Saving=Aan_het_opslaan
+
+Saving_database=Database_aan_het_opslaan
+
+Scan=Doorzoeken
+
+SciFinder=SciFinder
+
+Search=Zoeken
+
+Search_All_Fields=Zoek_in_Alle_Velden
+
+Search_all_fields=Zoek_in_alle_velden
+
+Search_error=Zoek_foutmelding
+
+Search_expression=Zoek_expressie
+
+Search_for=Zoek_naar
+
+Search_General_Fields=Zoek_Algemene_Velden
+
+Search_general_fields=Zoek_algemene_velden
+
+Search_IEEEXplore=Zoek_IEEEXplore
+
+Search_Optional_Fields=Zoek_Optionele_Velden
+
+Search_optional_fields=Zoek_optionele_velden
+
+Search_Required_Fields=Zoek_Vereiste_Velden
+
+Search_required_fields=Zoek_vereiste_velden
+
+Search_Specified_Field(s)=Zoek_Gespecifieerde_Veld(en)
+
+Search_term=Zoek_term
+
+Searched_database._Global_number_of_hits=Database_doorzocht._Globaal_aantal_gevonden_resultaten
+
+Searched_database._Number_of_hits=Database_doorzocht._Aantal_gevonden_resultaten
+
+Searching_for_%0_file=Aan_het_zoeken_naar_%0_bestand
+
+Searching_for_duplicates...=Aan_het_zoeken_naar_dubbels
+
+Secondary_sort_criterion=Secundair_sorteercriterium
+
+Select=Selecteer
+
+Select_a_Zip-archive=Selecteer_een_ZIP-archief
+
+Select_action=Selecteer_actie
+
+Select_all=Alles_selecteren
+
+Select_Classpath_of_New_Importer=Selecteer_Classpath_van_Nieuwe_Importer
+
+Select_encoding=Selecteer_encodering
+
+Select_entries_in_group_selection=Selecteer_entries_in_groep_selectie
+
+Select_entry_type=Selecteer_entry_type
+
+Select_file_from_ZIP-archive=Selecteer_bestand_van_ZIP-archief
+
+Select_format=Selecteer_formaat
+
+Select_matches=Selecteer_overeenkomsten
+
+Select_matching_entries=Selecteer_overeenkomstige_entries
+
+Select_new_ImportFormat_Subclass=Selecteer_nieuw_ImportFormat_Subklasse
+
+Select_the_tree_nodes_to_view_and_accept_or_reject_changes=Selecteer_de_boom_knopen_om_veranderingen_te_tonen_en_te_accepteren_of_afwijzen
+
+Selector_enabled_fields=Selecteer_velden_die_in_werking_zijn
+
+Set_general_fields=Algemene_velden_instellen
+
+Set_table_font=Tabel_lettertype_instellen
+
+Set_up_general_fields=Algemene_velden_instellen
+
+Settings=Instellingen
+
+Setup_selectors=Selectors_instellen
+
+Short_form=Korte_vorm
+
+Shortcut=Snelkoppeling
+
+Show/edit_BibTeX_source=Toon/bewerk_BibTeX-broncode
+
+Show_'Firstname_Lastname'=Toon_'Voornaam_Familienaam'
+
+Show_'Lastname,_Firstname'=Toon_'Familienaam,_Voornaam'
+
+Show_abstract=Toon_abstract
+
+Show_BibTeX_source_by_default=Toon_standaard_BibTeX-broncode
+
+Show_BibTeX_source_panel=Toon_BibTeX-bronpaneel
+
+Show_CiteSeer_column=Toon_CiteSeer-kolom
+
+Show_confirmation_dialog_when_deleting_entries=Toon_bevestigingsdialoog_bij_verwijderen_van_entries
+
+Show_description=Toon_beschrijving
+
+Show_dynamic_groups_in_<i>italics</i>=Toon_dynamische_groepen_<i>cursief</i>
+
+Show_entries_*not*_in_group_selection=Toon_entries_die_zich_*niet*_in_de_groep_selectie_bevinden
+
+Show_general_fields=Toon_algemene_velden
+
+Show_groups_matching_all=Toon_groepen_die_overeenkomen_met_alle
+
+Show_groups_matching_any=Toon_groepen_die_overeenkomen_met_elke
+
+Show_icons_for_groups=Toon_iconen_voor_groepen
+
+Show_names_unchanged=Toon_namen_onveranderd
+
+Show_one_less_rows=Toon_\u00e9\u00e9n_rij_minder
+
+Show_one_more_row=Toon_\u00e9\u00e9n_rij_meer
+
+Show_optional_fields=Toon_optionele_velden
+
+Show_overlapping_groups=Toon_overlappende_groepen
+
+Show_PDF/PS_column=Toon_PDF/PS-kolom
+
+Show_required_fields=Toon_vereiste_velden
+
+Show_URL/DOI_column=Toon_URL/DOI-kolom
+
+Show_warning_dialog_when_a_duplicate_BibTeX_key_is_entered=Toon_waarschuwingsdialoog_wanneer_een_dubbele_BibTeX-sleutel_ingegeven_wordt
+
+Show_warning_dialog_when_an_empty_BibTeX_key_is_entered=Toon_waarschuwingsdialoog_wanneer_een_lege_BibTeX-sleutel_ingegeven_wordt
+
+Simple_HTML=Eenvoudige_HTML
+
+Sixpack=Sixpack
+
+Size=Grootte
+
+Size_of_groups_interface_(rows)=Grootte_van_groepenvenster_(rijen)
+
+Skip=Overslaan
+
+Sort_alphabetically=Alphabetisch_sorteren
+
+Sort_Automatically=Automatisch_sorteren
+
+Sort_options=Sorteer_opties
+
+sort_subgroups=subgroepen_sorteren
+
+Sorted_all_subgroups_recursively=Alle_subgroepen_recursief_gesorteerd
+
+Sorted_all_subgroups_recursively.=Alle_subgroepen_recursief_gesorteerd.
+
+Sorted_immediate_subgroups=Onmiddellijke_subgroepen_sorteren
+
+Sorted_immediate_subgroups.=Onmiddellijke_subgroepen_sorteren.
+
+source_edit=broncode_aanpassen
+
+Special_table_columns=Speciale_tabelkolommen
+
+Start=Starten
+
+Start_incremental_search=Start_incrementele_zoekopdracht
+
+Start_search=Start_zoeken
+
+Statically_group_entries_by_manual_assignment=Groepeer_entries_statisch_door_manuele_toekenning
+
+Status=Status
+
+Stop=Stop
+
+Store=Opslaan
+
+Store_fields_with_double_braces,_and_remove_extra_braces_when_loading.<BR>Double_braces_signal_that_BibTeX_should_preserve_character_case.=Sla_velden_met_dubbele_haakjes_op,_en_verwijder_extra_haakjes_bij_het_laden.<BR>Dubbele_haakjes_wijzen_erop_dat_BibTeX_de_grootte_van_de_tekens_moet_behouden.
+
+Store_journal_abbreviations=Tijdschrift_afkortingen_opslaan
+
+Store_string=Constante_opslaan
+
+Store_the_following_fields_with_braces_around_capital_letters=Volgende_velden_met_haakjes_rond_hoofdletters_opslaan
+
+Stored_definition_for_type=Definitie_voor_type_opslaan
+
+Stored_entry=Entry_opgeslagen
+
+Stored_entry.=Entry_opgeslagen.
+
+Strings=Constanten
+
+Strings_for_database=Constanten_voor_database
+
+subdatabase_from_aux=subdatabase_van_aux
+
+Subdatabase_from_aux=Subdatabase_van_aux
+
+Suggest=Voorstellen
+
+Switch_preview_layout=Toon_voorbeeld_layout
+
+#### These lines were changed:
+Switches_between_full_and_abbreviated_journal_name_if_the_journal_name_is_known.=Schakelt_tussen_volledige_en_afgekorte_tijdschriftnaam_als_het_tijdschrift_gekend_is.
+
+Synchronize_%0_links=Synchroniseer_%0_snelkoppelingen
+
+Synchronizing_%0_links...=%0_snelkoppelingen_aan_het_synchroniseren
+
+Table=Tabel
+
+Table_appearance=Tabel_uiterlijk
+
+Table_background_color=Tabel_achtergrondkleur
+
+Table_grid_color=Tabel_roosterkleur
+
+Table_text_color=Tabel_tekstkleur
+
+Tabname=Tabblad_naam
+
+Tertiary_sort_criterion=Tertiair_sorteercriterium
+
+Test=Test
+
+Text_Input_Area=Tekst_Invoer_Gebied
+
+The_#_character_is_not_allowed_in_BibTeX_fields=Het_#_teken_is_niet_toegestand_in_BibTeX-velden
+
+The_chosen_date_format_for_new_entries_is_not_valid=Het_gekozen_datumformaat_voor_nieuwe_entries_is_niet_geldig
+
+The_CiteSeer_fetch_operation_returned_zero_results.=De_CiteSeer_ophaaloperatie_gaf_nul_resultaten_terug.
+
+the_field_<b>%0</b>=het_veld_<b>%0</b>
+
+The_file<BR>'%0'<BR>has_been_modified<BR>externally!=Het_bestand<BR>'%0'<BR>werd_extern_gewijzigd!
+
+The_group_"%0"_already_contains_the_selection.=De_groep_"%0"_bevat_reeds_de_selectie.
+
+The_group_"%0"_does_not_support_the_adding_of_entries.=De_groep_"%0"_ondersteunt_het_toevoegen_van_entries_niet.
+
+The_group_"%0"_does_not_support_the_removal_of_entries.=De_groep_"%0"_ondersteunt_het_verwijderen_van_entries_niet.
+
+The_label_of_the_string_can_not_be_a_number.=Het_label_van_een_constante_mag_geen_nummer_zijn.
+
+The_label_of_the_string_can_not_contain_spaces.=Het_label_van_een_constante_mag_geen_spaties_bevatten.
+
+The_label_of_the_string_can_not_contain_the_'#'_character.=Het_label_van_een_constante_mag_het_'#'_teken_niet_bevatten.
+
+The_output_option_depends_on_a_valid_import_option.=De_uitvoeroptie_is_afhankelijk_van_een_geldige_importeeroptie.
+
+The_regular_expression_<b>%0</b>_is_invalid%c=De_regular_expression_<b>%0</b>_is_ongeldig%c
+
+The_search_is_case_insensitive.=De_zoekopdracht_is_hoofdletterongevoelig.
+
+The_search_is_case_sensitive.=De_zoekopdracht_is_hoofdlettergevoelig.
+
+The_string_has_been_removed_locally=De_constante_werd_lokaal_verwijderd
+
+The_type_name_can_not_contain_spaces.=De_typenaam_mag_geen_spaties_bevatten.
+
+The_URL_field_appears_to_be_empty_on_entry_number_=Het_URL_veld_blijkt_leeg_te_zijn_voor_het_entry_nummer
+
+There_are_possible_duplicates_(marked_with_a_'D'_icon)_that_haven't_been_resolved._Continue?=Er_zijn_mogelijke_dubbels_(aangeduid_met_een_'D'_icoon)_die_nog_niet_opgelost_werden._Verdergaan?
+
+There_is_no_entry_type=Er_is_geen_entry_type
+
+This_action_will_modify_the_"%0"_field_of_your_entries.nThis_could_cause_undesired_changes_to_your_entries,_so_itnis_recommended_that_you_change_the_field_in_your_groupndefinition_to_"keywords"_or_a_non-standard_name.nnDo_you_still_want_to_continue?=Deze_actie_zal_het_"%0"_veld_van_uw_entries_veranderen._Dit_kan_ongewenste_wijzigingen_aan_uw_entries_veroorzaken,_dus_is_het_aangeraden_dat_u_het_veld_in_uw_groepdefinitie_naar_"keywords"_of_een_niet-standaard_naam_verandert._Wilt_u_nog_stee [...]
+
+this_button_will_update=deze_knop_zal_update_uitvoeren
+
+this_button_will_update_the_column_width_settings<BR>to_match_the_current_widths_in_your_table=deze_knop_zal_een_update_uitvoeren_van_de_kolombreedte_instellingen<BR>om_overeen_te_komen_met_de_huidige_breedtes_in_uw_tabel
+
+This_entry_is_incomplete=Deze_entry_is_onvolledig
+
+This_entry_type_cannot_be_removed.=Dit_entry_type_kan_niet_verwijderd_worden.
+
+This_group_contains_entries_based_on_manual_assignment._Entries_can_be_assigned_to_this_group_by_selecting_them_then_using_either_drag_and_drop_or_the_context_menu._Entries_can_be_removed_from_this_group_by_selecting_them_then_using_the_context_menu._Every_entry_assigned_to_this_group_must_have_a_unique_key._The_key_may_be_changed_at_any_time_as_long_as_it_remains_unique.=Deze_groep_bevat_entries_gebaseerd_op_manuele_toekenning._Entries_kunnen_aan_deze_groep_toegekend_worden_door_ze_te_s [...]
+
+This_group_contains_entries_in_which=Deze_groep_bevat_entries_waarin
+
+This_group_contains_entries_in_which_any_field_contains_the_regular_expression_<b>%0</b>=Deze_groep_bevat_entries_waarin_elk_veld_de_regular_expression_<b>%0</b>_bevat
+
+This_group_contains_entries_in_which_any_field_contains_the_term_<b>%0</b>=Deze_groep_bevat_entries_waarin_elk_veld_de_term_<b>%0</b>_bevat
+
+This_group_contains_entries_whose_<b>%0</b>_field_contains_the_keyword_<b>%1</b>=Deze_groep_bevat_entries_waarin_het_<b>%0</b>_veld_het_sleutelwoord_<b>%1</b>_bevat
+
+This_group_contains_entries_whose_<b>%0</b>_field_contains_the_regular_expression_<b>%1</b>=Deze_groep_bevat_entries_waarin_het_<b>%0</b>_veld_de_regular_expression_<b>%1</b>_bevat
+
+This_is_a_simple_copy_and_paste_dialog._First_load_or_paste_some_text_into_the_text_input_area._After_that,_you_can_mark_text_and_assign_it_to_a_bibtex_field.=Dit_is_een_simpele_kopieer_en_plak_dialoog._Laad_of_plak_eerst_wat_tekst_in_het_tekst_invoerveld._Hierna,_kan_u_tekst_markeren_en_deze_toekennen_aan_een_BibTeX-veld.
+
+This_is_a_simple_copy_and_paste_dialog_for_import_some_fields_from_normal_text.=Dit_is_een_simpele_kopieer_en_plak_dialoog_om_enkele_velden_vanuit_normale_tekst_te_importeren.
+
+This_makes_JabRef_look_up_each_%0_link_and_check_if_the_file_exists._If_not,_you_will_be_given_options<BR>to_resolve_the_problem.=Dit_zorgt_ervoor_dat_JabRef_elke_%0_snelkoppeling_op_zoekt_en_controleert_of_het_bestand_bestaat._Indien_dit_niet_het_geval_is,_zullen_u_opties_gegeven_worden<BR>om_het_probleem_op_te_lossen.
+
+This_operation_cannot_work_on_multiple_rows.=Deze_operatie_kan_niet_werken_op_meerdere_rijen.
+
+This_operation_requires_all_selected_entries_to_have_BibTex_keys_defined.=Deze_operatie_vereist_dat_alle_geselecteerde_entries_BibTeX-sleutels_gedefinieerd_hebben.
+
+This_operation_requires_one_or_more_entries_to_be_selected.=Deze_operatie_vereist_dat_een_of_meer_entries_geselecteerd_zijn.
+
+To_set_up,_go_to_<B>Tools_->_Manage_journal_abbreviations</B>=Om_in_te_stellen,_ga_naar_<B>Opties_->_Beheer_tijdschrift_afkortingen</B>
+
+Toggle_abbreviation=Toon_afkorting
+
+Toggle_entry_preview=Toon_entry_voorbeeld
+
+Toggle_groups_interface=Toon_groepenvenster
+
+Toggle_search_panel=Toon_zoekpaneel
+
+Tools=Extra's
+
+Try_different_encoding=Probeer_een_andere_encodering
+
+Type=Type
+
+Type_set_to_'other'=Type_ingesteld_als_'other'
+
+Unabbreviate_journal_names_of_the_selected_entries=Maak_afkortingen_van_tijdschriftnamen_van_geselecteerde_entries_ongedaan
+
+unable_to_access_LyX-pipe=kan_geen_toegang_krijgen_tot_LyX-pipe
+
+Unable_to_create_graphical_interface=kan_grafische_interface_niet_aanmaken
+
+Unable_to_parse_clipboard_text_as_Bibtex_entries.=kan_klembord_tekst_niet_ontleden_als_BibTeX-entries
+
+Unable_to_parse_the_following_URL=De_volgende_URL_kan_niet_ontleed_worden
+
+unable_to_write_to=kan_niet_schrijven_naar
+
+Undo=Ongedaan_maken
+
+Union=Unie
+
+unknown_bibtex_entries=onbekende_BibTeX-entries
+
+Unknown_bibtex_entries=Onbekende_BibTeX-entries
+
+unknown_edit=onbekende_aanpassing
+
+unknown_entry_type=onbekend_entry_type
+
+Unknown_export_format=Onbekend_exporteerformaat
+
+Unmark_all=Alle_markeringen_ongedaan_maken
+
+Unmark_entries=Alle_markeringen_van_entries_ongedaan_maken
+
+Unmark_entry=Markering_van_entry_ongedaan_maken
+
+Unmarked_selected=Markering_van_geselecteerde_ongedaan_maken
+
+Unpack_EndNote_filter_set=EndNote_filter_set_uitpakken
+
+Unpacked_file=Uitgepakt_bestand
+
+Unpacked_file.=Uitgepakt_bestand.
+
+Unsupported_version_of_class_%0:_%1=Niet_ondersteunde_versie_van_klasse_%0:_%1
+
+untitled=naamloos
+
+Up=Omhoog
+
+Update_to_current_column_widths=Update_naar_huidige_kolombreedtes
+
+Updated_group_selection=Groep_selectie_geupdate
+
+Updating_entries...=Entries_aan_het_updaten...
+
+UPPER=BOVENSTE
+
+Upper_Each_First=Elke_Eerste_Bovenste
+
+Upper_first=Bovenste_eerst
+
+usage=gebruik
+
+Use_antialiasing_font=Gebruik_antialiasing_lettertype
+
+Use_antialiasing_font_in_table=Gebruik_antialiasing_lettertype_in_tabel
+
+Use_inspection_window_also_when_a_single_entry_is_imported.=Gebruik_inspectievenster_ook_wanneer_een_enkele_entry_ge\u00efmporteerd_wordt
+
+Use_other_look_and_feel=Gebruik_andere_"look_and_feel"
+
+Use_regular_expressions=Gebruik_regular_expressions
+
+Use_the_following_delimiter=Gebruik_het_volgend_scheidingsteken
+
+Use_the_following_delimiter_character(s)=Gebruik_volgende_teken(s)_als_scheidingsteken
+
+Uses_default_application=Gebruikt_standaard_applicatie
+
+Value_cleared_externally=Waarde_extern_gewist
+
+Value_set_externally=Waarde_extern_ingesteld
+
+verify_that_LyX_is_running_and_that_the_lyxpipe_is_valid=verifieer_dat_LyX_draait_en_dat_de_lyxpipe_geldig_is
+
+View=Beeld
+
+Visible_fields=Zichtbare_velden
+
+Warn_about_unresolved_duplicates_when_closing_inspection_window=Waarschuw_bij_onopgeloste_dubbels_bij_het_sluiten_van_het_inspectievenster
+
+Warn_before_overwriting_existing_keys=Waarschuwing_v\u00f3\u00f3r_het_overschrijven_van_bestaande_sleutels
+
+Warning=Waarschuwing
+
+Warning_there_is_a_duplicate_key=Waarschuwing!_Er_is_een_dubbele_sleutel
+
+Warnings=Waarschuwingen
+
+web_link=web-link
+
+What_do_you_want_to_do?=Wat_wilt_u_doen?
+
+When_adding/removing_keywords,_separate_them_by=Wanneer_u_sleutelwoorden_toevoegt/verwijdert,_scheid_ze_dan_door
+
+with=met
+
+Word=Woord
+
+Wrong_file_format=Verkeerd_bestandsformaat
+
+You_have_changed_the_language_setting._You_must_restart_JabRef_for_this_to_come_into_effect.=U_heeft_de_taalinstelling_veranderd._U_moet_JabRef_herstarten_om_dit_toe_te_passen.
+
+You_have_cleared_this_field._Original_value=U_heeft_dit_veld_gewist._Originele_waarde
+
+You_must_choose_a_file_name_to_store_journal_abbreviations=U_moet_een_bestandsnaam_kiezen_om_tijdschrift_afkortingen_op_te_slaan
+
+You_must_enter_an_integer_value_in_the_text_field_for=U_moet_een_gehele_waarde_in_het_tekstveld_ingeven_voor
+
+You_must_fill_in_a_name_for_the_entry_type.=U_moet_een_naam_invullen_voor_het_entry_type.
+
+You_must_provide_a_name,_a_search_string_and_a_field_name_for_this_group.=U_moet_een_naam_geven,_een_zoek_waarde_en_een_veldnaam_voor_deze_groep.
+
+You_must_restart_JabRef_for_the_new_key_bindings_to_work_properly.=U_moet_JabRef_herstarten_zodat_de_nieuwe_sneltoetsen_correct_kunnen_werken.
+
+You_must_select_a_row_to_perform_this_operation.=U_moet_een_rij_selecteren_om_deze_operatie_uit_te_voeren.
+
+You_must_select_at_least_one_row_to_perform_this_operation.=U_moet_minstens_\u00e9\u00e9n_rij_selecteren_om_deze_operatie_uit_te_voeren.
+
+You_must_set_both_BibTeX_key_and_%0_directory=U_moet_de_BibTeX-sleutel_en_%0_map_instellen
+
+You_must_set_both_bibtex_key_and_PDF_directory=U_moet_de_BibTeX-sleutel_en_PDF_map_instellen
+
+Your_new_key_bindings_have_been_stored.=Uw_nieuwe_sneltoetsen_zijn_opgeslagen.
+
+Float_marked_entries=Gemarkeerde_entries_bovenaan_tonen
+
+Starting_import=Importeren_aan_het_starten
+
+Output=Uitvoer
+
+Exceptions=Uitzonderingen
+
+Program_output=Programma_uitvoer
+
+grouping_may_not_work_for_this_entry=groepering_werkt_misschien_niet_voor_deze_entry
+
+crossreferenced_entries_included=inclusief_kruisgerefereerde_entries
+
+Display_version=Display_versie
+
+Override_default_font_settings=Wijzig_standaard_lettertypeinstellingen
+
+Mac_file_dialog=Mac_bestandsdialoog
+
+Use_native_file_dialog=Gebruik_"native_bestandsdialoog
+
+XMP-annotated_PDF=XMP_geannoteerde_PDF
+PDF_and_PS_links=PDF_en_PS_snelkoppelingen
+Use_Regular_Expression_Search=Gebruik_Regular_Expression_Zoekopdracht
+Help_on_Regular_Expression_Search=Help_over_Regular_Expression_Zoekopdracht
+writeXMP=schrijfXMP
+Will_write_XMP-metadata_to_the_PDFs_linked_from_selected_entries.=Zal_XPM_metadata_naar_de_PDFs_gelinkt_vanuit_geselecteerde_entries_schrijven.
+Select_external_application=Selecteer_externe_applicatie
+Show_last_names_only=Toon_enkel_laatste_namen
+Help_on_Preview_Settings=Help_over_Voorbeeld_Instellingen
+Writing_XMP_metadata...=XPM_metadata_aan_het_schrijven...
+Writing_XMP_metadata_for_selected_entries...=XPM_metadata_voor_geselecteerde_entries_aan_het_schrijven...
+Skipped_-_No_PDF_linked=Overgeslagen_-_Geen_PDF_gelinkt
+Finished_writing_XMP_for_%0_file_(%1_skipped,_%2_errors).=XPM_schrijven_voor_%0_bestand_voltooid_(%1_overgeslagen,_%2_fouten).
+Grouping_may_not_work_for_this_entry.=Groepering_kan_misschien_niet_werken_voor_deze_entry.
+Write_BibtexEntry_as_XMP-metadata_to_PDF.=Schrijf_BibTeX-entry_als_XMP-metadata_naar_PDF.
+write_XMP=schrijf_XMP
+New_field_value=Nieuwe_veld_waarde
+Overwrite_existing_field_values=Overschrijf_bestaande_veld_waarden
+Include_entries=Entries_insluiten
+Selected_entries=Geselecteerde_entries
+
+Fetch_CiteSeer_by_ID=Ophalen_van_CiteSeer_op_ID
+Push_entries_to_external_application_(%0)=Stuur_entries_naar_externe_applicatie_(%0)
+Write_XMP=Schrijf_XMP
+
+Writing_XMP=XMP_aan_het_schrijven
+
+HTML_table=HTML_tabel
+
+Set/clear_fields=Velden_instellen/wissen
+
+Clear_fields=Velden_wissen
+Set_fields=Velden_instellen
+
+HTML_table_(with_Abstract_&_BibTeX)=HTML_tabel_(met_Abstract_&_BibTeX)
+OpenOffice_Calc=OpenOffice_Calc
+OpenDocument_Spreadsheet=OpenDocument_Spreadsheet
+Skipped_entry.=Overgeslagen_entry.
+Error_occured_when_parsing_entry=Foutmelding_bij_het_ontleden_van_de_entry
+Operation_canceled.\n=Operatie_geannuleerd.\n
+Error_while_writing=Foutmelding_bij_het_schrijven
+Skipped_-_PDF_does_not_exist=Overgeslagen_-_PDF_bestaat_niet
+Use_custom_icon_theme=Gebruik_extern_icoonthema
+Custom_icon_theme=Extern_icoonthema
+Custom_icon_theme_file=Extern_icoonthema_bestaan
+Unable_to_read_icon_theme_file=Kan_icoonthema_bestand_niet_lezen
+Unable_to_read_default_icon_theme.=Kan_standaard_icoonthema_niet_lezen.
+Could_not_find_image_file=Kan_fotobestand_niet_vinden
+Set_field=Veld_instellen
+No_entries_selected.=Geen_entries_geselecteerd.
+Link_from_new_entries.=Snelkoppeling_van_nieuwe_entries.
+Link_from_new_entry=Snelkoppeling_van_nieuwe_entry
+Link_from_entries.=Snelkoppeling_van_entries.
+Link_from_entry=Snelkoppeling_van_entry
+exists.Overwrite?=bestaat._Overschrijven?
+File_exists=Bestand_bestaat
+No_file_associated=Geen_bestand_geassocieerd
+Exported_%0_entries_to_file=
+Formatter_Name=
+Format_String=
+Help_on_Name_Formatting=
+Special_Name_Formatters=
+Name_formatter=
diff --git a/src/resource/JabRef_en.properties b/src/resource/JabRef_en.properties
index 6df36fd..e21da45 100644
--- a/src/resource/JabRef_en.properties
+++ b/src/resource/JabRef_en.properties
@@ -2091,3 +2091,70 @@ crossreferenced_entries_included=crossreferenced_entries_included
Display_version=Display_version
Override_default_font_settings=Override_default_font_settings
+
+Mac_file_dialog=Mac_file_dialog
+Use_native_file_dialog=Use_native_file_dialog
+
+XMP-annotated_PDF=XMP-annotated_PDF
+PDF_and_PS_links=PDF_and_PS_links
+Use_Regular_Expression_Search=Use_Regular_Expression_Search
+Help_on_Regular_Expression_Search=Help_on_Regular_Expression_Search
+writeXMP=writeXMP
+Will_write_XMP-metadata_to_the_PDFs_linked_from_selected_entries.=Will_write_XMP-metadata_to_the_PDFs_linked_from_selected_entries.
+Select_external_application=Select_external_application
+Show_last_names_only=Show_last_names_only
+Help_on_Preview_Settings=Help_on_Preview_Settings
+Writing_XMP_metadata...=Writing_XMP_metadata...
+Writing_XMP_metadata_for_selected_entries...=Writing_XMP_metadata_for_selected_entries...
+Skipped_-_No_PDF_linked=Skipped_-_No_PDF_linked
+Finished_writing_XMP_for_%0_file_(%1_skipped,_%2_errors).=Finished_writing_XMP_for_%0_file_(%1_skipped,_%2_errors).
+
+Grouping_may_not_work_for_this_entry.=Grouping_may_not_work_for_this_entry.
+Write_BibtexEntry_as_XMP-metadata_to_PDF.=Write_BibtexEntry_as_XMP-metadata_to_PDF.
+write_XMP=write_XMP
+New_field_value=New_field_value
+Overwrite_existing_field_values=Overwrite_existing_field_values
+Include_entries=Include_entries
+Selected_entries=Selected_entries
+
+Write_XMP=Write_XMP
+Fetch_CiteSeer_by_ID=Fetch_CiteSeer_by_ID
+Push_entries_to_external_application_(%0)=Push_entries_to_external_application_(%0)
+Writing_XMP=Writing_XMP
+HTML_table=HTML_table
+HTML_table_(with_Abstract_&_BibTeX)=HTML_table_(with_Abstract_&_BibTeX)
+Set/clear_fields=Set/clear_fields
+Set_fields=Set_fields
+Clear_fields=Clear_fields
+
+Exported_%0_entries_to_file=Exported_%0_entries_to_file
+
+OpenOffice_Calc=OpenOffice_Calc
+OpenDocument_Spreadsheet=OpenDocument_Spreadsheet
+
+Skipped_entry.=Skipped_entry.
+Error_occured_when_parsing_entry=Error_occurred_when_parsing_entry
+Operation_canceled.\n=Operation_canceled.\n
+Error_while_writing=Error_while_writing
+Skipped_-_PDF_does_not_exist=Skipped_-_PDF_does_not_exist
+Use_custom_icon_theme=Use_custom_icon_theme
+Custom_icon_theme=Custom_icon_theme
+Custom_icon_theme_file=Custom_icon_theme_file
+Unable_to_read_icon_theme_file=Unable_to_read_icon_theme_file
+Unable_to_read_default_icon_theme.=Unable_to_read_default_icon_theme.
+Could_not_find_image_file=Could_not_find_image_file
+Set_field=Set_field
+No_entries_selected.=No_entries_selected.
+Link_from_new_entries.=Link_from_new_entries.
+Link_from_new_entry=Link_from_new_entry
+Link_from_entries.=Link_from_entries.
+Link_from_entry=Link_from_entry
+exists.Overwrite?=exists._Overwrite?
+File_exists=File_exists
+No_file_associated=No_file_associated
+Formatter_Name=Formatter_Name
+Format_String=Format_String
+Help_on_Name_Formatting=Help_on_Name_Formatting
+Special_Name_Formatters=Special_Name_Formatters
+Name_formatter=Name_formatter
+
diff --git a/src/resource/JabRef_fr.properties b/src/resource/JabRef_fr.properties
index 601e806..916619c 100644
--- a/src/resource/JabRef_fr.properties
+++ b/src/resource/JabRef_fr.properties
@@ -59,7 +59,7 @@ All_fields=Tous_les_champs
All_subgroups_(recursively)=Tous_les_sous-groupes_(r\u00e9cursivement)
Allow_editing_in_table_cells=Autoriser_l'\u00E9dition_dans_les_cellules_de_la_table
Always_save_database_ordered_by_author_name=Toujours_enregistrer_la_base_avec_l'ordre_auteur_nom
-and= et
+and=_et
and_the_class_must_be_available_in_your_classpath_next_time_you_start_JabRef.=et_la_classe_doit_\u00EAtre_disponible_dans_votre_chemin_de_classe_la_prochaine_fois_que_vous_d\u00E9marrez_JabRef.
any_field_that_matches_the_regular_expression_<b>%0</b>=tout_champ_qui_correspond_\u00e0_l'expression_r\u00e9guli\u00e8re_<b>%0</b>
Appearance=Aspect
@@ -346,8 +346,8 @@ Error_messages=Messages_d'erreur
Error_opening_file=Erreur_lors_de_l'ouverture_du_fichier
Error_setting_field=Erreur_de_configuration_du_champ
Existing_file=Fichier_existant
-exists._Overwrite?=existe._Ecraser_le_fichier ?
-exists._Overwrite_file?=existe._Ecraser_le_fichier ?
+exists._Overwrite?=existe._Ecraser_le_fichier_?
+exists._Overwrite_file?=existe._Ecraser_le_fichier_?
Exit=Quitter
Expand_subtree=D\u00e9velopper_le_sous-arbre
Explicit=Explicite
@@ -657,7 +657,7 @@ occurences=occurrences
OK=OK
Ok=Ok
One_or_more_keys_will_be_overwritten._Continue?=Une_ou_plusieurs_clefs_seront_\u00e9cras\u00e9es._Continuer_?
-Open=Ouvre
+Open=Cliquer_pour_ouvrir_le
open=ouvre
Open_BibTeX_database=Ouvrir_une_base_BibTeX
Open_database=Ouvrir_une_base
@@ -918,7 +918,7 @@ Stored_definition_for_type=D\u00E9finition_pour_le_type_enregistr\u00E9
Stored_entry=Entr\u00E9e_enregistr\u00E9e
Stored_entry.=Entr\u00E9e_stock\u00E9e.
Strings=Cha\u00EEne
-Strings_for_database=Cha\u00EEnes_pour_la_base :
+Strings_for_database=Cha\u00EEnes_pour_la_base
subdatabase_from_aux=BibTeX_\u00E0_partir_de_LaTex_aux
Subdatabase_from_aux=BibTeX_\u00E0_partir_de_LaTex_aux
Suggest=Sugg\u00E9rer
@@ -1002,7 +1002,7 @@ Unmarked_selected=D\u00E9s\u00E9tiquetage_de_la_s\u00E9lection
Unpack_EndNote_filter_set=D\u00E9compacter_la_s\u00E9rie_de_filtres_EndNote
Unpacked_file=Fichier_d\u00e9compact\u00e9
Unpacked_file.=Fichier_d\u00e9compact\u00e9.
-Unsupported_version_of_class_%0:_%1=Version_non_support\u00e9e_de_la_classe_%0 :_%1
+Unsupported_version_of_class_%0:_%1=Version_non_support\u00e9e_de_la_classe_%0_:_%1
untitled=sans_titre
Up=Haut
Update_to_current_column_widths=Figer_les_largeurs_des_colonnes_actuelles
@@ -1065,3 +1065,70 @@ Override_default_font_settings=Se_substituer_aux_param\u00e8tres_de_police_par_d
Mac_file_dialog=S\u00e9lectionneur_de_fichiers_Mac
Use_native_file_dialog=Utiliser_le_s\u00e9lectionneur_de_fichiers_natif
+
+XMP-annotated_PDF=PDF_avec_annotations_XMP
+PDF_and_PS_links=Liens_PDF_et_PS
+Use_Regular_Expression_Search=Rechercher_l'expression_r\u00e9guli\u00e8re
+Help_on_Regular_Expression_Search=Aide_sur_la_recherche_d'une_expression_r\u00e9guli\u00e8re
+
+writeXMP=Ecrire_XMP
+write_XMP=Ecrire_XMP
+Will_write_XMP-metadata_to_the_PDFs_linked_from_selected_entries.=Ecrit_les_m\u00e9tadonn\u00e9es_XMP_dans_les_PDFs_li\u00e9s_aux_entr\u00e9es_s\u00e9lectionn\u00e9es
+Select_external_application=S\u00e9lectionner_une_application_externe
+Show_last_names_only=Afficher_uniquement_les_noms_propres
+Help_on_Preview_Settings=Aide_sur_les_param\u00e8tres_de_l'aper\u00E7u
+Writing_XMP_metadata...=Ecriture_des_m\u00e9tadonn\u00e9es_XMP
+Writing_XMP_metadata_for_selected_entries...=Ecriture_des_m\u00e9tadonn\u00e9es_XMP_pour_les_entr\u00e9es_s\u00e9lectionn\u00e9es
+Skipped_-_No_PDF_linked=Saut\u00e9_-_Pas_de_PDF_li\u00e9
+Finished_writing_XMP_for_%0_file_(%1_skipped,_%2_errors).=Fin de l'\u00e9criture des XMP pour_%0_fichiers_(%1_pass\u00e9s,_%2_erreurs).
+
+Write_BibtexEntry_as_XMP-metadata_to_PDF.=Ecrire_l'entr\u00e9e_BibTeX_comme_des_m\u00e9tadonn\u00e9es_XMP_dans_un_PDF
+New_field_value=Nouvelle_valeur_du_champ
+Overwrite_existing_field_values=Ecraser_les_valeurs_existantes_du_champ
+Include_entries=Entr\u00e9es_affect\u00e9es
+Selected_entries=Les_entr\u00e9es_s\u00e9lectionn\u00e9es
+
+Fetch_CiteSeer_by_ID=Recherche_CiteSeer_par_ID
+Push_entries_to_external_application_(%0)=Envoyer_les_entr\u00e9es_vers_l'application_externe_(%0)
+Write_XMP=Ecrire_XMP
+
+Writing_XMP=Ecriture_XMP
+
+HTML_table=Tableau_HTML
+
+Set/clear_fields=Configurer/vider_les_champs
+
+Clear_fields=Vider_les_champs
+Set_fields=Configurer_les_champs
+
+HTML_table_(with_Abstract_&_BibTeX)=Tableau_HTML_(avec_R\u00e9sum\u00e9_&_BibTeX)
+
+OpenOffice_Calc=OpenOffice_Calc
+OpenDocument_Spreadsheet=Tableur_OpenDocument
+
+Skipped_entry.=Entr\u00e9e_omise
+Error_occured_when_parsing_entry=Une_erreur_est_survenue_pendant_le_traitement_de_l'entr\u00e9e
+Operation_canceled.\n=Op\u00e9ration_annul\u00e9e.\n
+Error_while_writing=Erreur_lors_de_l'\u00e9criture
+Skipped_-_PDF_does_not_exist=Omis_-_Le_PDF_n'existe_pas
+Use_custom_icon_theme=Utiliser_un_th\u00e8me_d'ic\u00f4nes_personnalis\u00e9
+Custom_icon_theme=Th\u00e8me_d'ic\u00f4nes_personnalis\u00e9
+Custom_icon_theme_file=Fichier_de_th\u00e8me_d'ic\u00f4nes_personnalis\u00e9
+Unable_to_read_icon_theme_file=Impossible_de_lire_le_fichier_de_th\u00e8me_d'ic\u00f4nes
+Unable_to_read_default_icon_theme.=Impossilbe_de_lire_le_th\u00e8me_d'ic\u00f4nes_par_d\u00e9faut
+Could_not_find_image_file=Le_fichier_image_n'a_pas_\u00e9t\u00e9_trouv\u00e9
+Set_field=Configurer_le_champ
+No_entries_selected.=Pas_d'entr\u00e9es_s\u00e9lectionn\u00e9es.
+Link_from_new_entries.=Lien_\u00e0_partir_de_nouvelles_entr\u00e9es
+Link_from_new_entry=Lien_\u00e0_partir_d'une_nouvelle_entr\u00e9e
+Link_from_entries.=Lien_\u00e0_partir_d'entr\u00e9es.
+Link_from_entry=Lien_\u00e0_partir_d'une_entr\u00e9e
+exists.Overwrite?=existe._Ecraser_?
+File_exists=Le_fichier_existe
+No_file_associated=Pas_de_fichier_associ\u00e9
+Exported_%0_entries_to_file=%0_entr\u00e9es_export\u00e9es_vers_le_fichier
+Formatter_Name=Nom_de_formateur
+Format_String=Cha\u00EEne_de_format
+Help_on_Name_Formatting=Aide_sur_le_formatage_des_noms
+Special_Name_Formatters=Formateurs_de_nom_sp\u00e9ciaux
+Name_formatter=Formateur_de_nom
diff --git a/src/resource/JabRef_it.properties b/src/resource/JabRef_it.properties
index d30263c..7feeb3a 100644
--- a/src/resource/JabRef_it.properties
+++ b/src/resource/JabRef_it.properties
@@ -1086,5 +1086,71 @@ Grouping_may_not_work_for_this_entry.=Il_raggruppamento_potrebbe_non_funzionare_
Display_version=Versione
Override_default_font_settings=Ignora_le_impostazioni_dei_font_predefinite
-Mac_file_dialog=
-Use_native_file_dialog=
+Mac_file_dialog=Finestra_di_dialogo_file_Mac
+Use_native_file_dialog=Usa_finestra_di_dialogo_File_nativa
+
+XMP-annotated_PDF=PDF_con_annotazioni_XMP
+PDF_and_PS_links=Collegamenti_PDF_e_PS
+Use_Regular_Expression_Search=Ricerca_l'espressione_regolare
+Help_on_Regular_Expression_Search=Aiuto_sulla_ricerca_di_un'espressione_regolare
+writeXMP=Scrivi_XMP
+Select_external_application=Seleziona_un'applicazione_esterna
+Show_last_names_only=Mostra_solo_i_cognomi
+Help_on_Preview_Settings=Aiuto_sui_parametri_di_anteprima
+Writing_XMP_metadata...=Scrittura_dei_metadati_XMP...
+Writing_XMP_metadata_for_selected_entries...=Scrittura_dei_metadati_XMP_per_le_voci_selezionate
+Skipped_-_No_PDF_linked=Saltato_-_Nessun_file_PDF_collegato
+Finished_writing_XMP_for_%0_file_(%1_skipped,_%2_errors).=Terminata_la_scrittura_di_metadati_XMP_per_%0_file_(%1_saltati,_%2_errori).
+Write_BibtexEntry_as_XMP-metadata_to_PDF.=Scrivi_voce_BibTeX_come_metadati_XMP_in_un_file_PDF.
+write_XMP=Scrivi_XMP
+Will_write_XMP-metadata_to_the_PDFs_linked_from_selected_entries.=Scrive_i_metadati_XMP_nei_file_PDF_collegati_alle_voci_selezionate
+New_field_value=Nuovo_valore_del_campo
+Overwrite_existing_field_values=Sovrascrivi_i_valori_esistenti_del_campo
+Include_entries=Includi_voci
+Selected_entries=Voci_selezionate
+
+Fetch_CiteSeer_by_ID=Ricerca_su_CiteSeer_per_ID
+Push_entries_to_external_application_(%0)=Invia_le_voci_selezionate_all'applicazione_esterna_(%0)
+Write_XMP=Scrivi_XMP
+
+Writing_XMP=Scrittura_XMP
+
+HTML_table=Tabella_HTML
+
+Set/clear_fields=Imposta/annulla_i_campi
+
+Clear_fields=Annulla_i_campi
+Set_fields=Imposta_i_campi
+
+HTML_table_(with_Abstract_&_BibTeX)=Tabella_HTML_(con_riassunto_e_BibTeX)
+
+
+OpenOffice_Calc=OpenOffice_Calc
+OpenDocument_Spreadsheet=Foglio_elettronico_OpenDocument
+
+Skipped_entry.=Voce_saltata
+Error_occured_when_parsing_entry=Errore_durante_l'elaborazione_della_voce
+Operation_canceled.\n=Operazione_annullata.\n
+Error_while_writing=Errore_durante_la_scrittura
+Skipped_-_PDF_does_not_exist=Saltato_-_Il_file_PDF_non_esiste
+Use_custom_icon_theme=Utilizza_un_tema_di_icone_personalizzato
+Custom_icon_theme=Tema_di_icone_personalizzato
+Custom_icon_theme_file=File_di_tema_di_icone_personalizzato
+Unable_to_read_icon_theme_file=Impossibile_leggere_il_file_di_tema_di_icone
+Unable_to_read_default_icon_theme.=Impossibile_leggere_il_file_di_tema_di_icone_predefinito
+Could_not_find_image_file=Il_file_di_immagini_non_\u00e8_stato_trovato
+Set_field=Imposta_il_campo
+No_entries_selected.=Nessuna_voce_selezionata
+Link_from_new_entries.=Collegamento_da_nuove_voci.
+Link_from_new_entry=Collegamento_da_nuova_voce
+Link_from_entries.=Collegamento_da_voci.
+Link_from_entry=Collegamento_da_voce
+exists.Overwrite?=esiste._Sovrascrivere?
+File_exists=Il_file_esiste
+No_file_associated=Nessun_file_associato
+Exported_%0_entries_to_file=
+Formatter_Name=
+Format_String=
+Help_on_Name_Formatting=
+Special_Name_Formatters=
+Name_formatter=
diff --git a/src/resource/JabRef_no.properties b/src/resource/JabRef_no.properties
index 814da71..86bfc73 100644
--- a/src/resource/JabRef_no.properties
+++ b/src/resource/JabRef_no.properties
@@ -1063,5 +1063,70 @@ Display_version=Vis_versjonsnummer
Override_default_font_settings=Overstyr_standardfonter
-Mac_file_dialog=
-Use_native_file_dialog=
+Mac_file_dialog=Mac-fildialog
+Use_native_file_dialog=Bruk_system-fildialog
+
+XMP-annotated_PDF=XMP-annotert_PDF
+PDF_and_PS_links=PDF-_og_PS-lenker
+Use_Regular_Expression_Search=
+Help_on_Regular_Expression_Search=
+writeXMP=skrivXMP
+Will_write_XMP-metadata_to_the_PDFs_linked_from_selected_entries.=
+Select_external_application=Velg_ekstern_applikasjon
+Show_last_names_only=Vis_bare_etternavn
+Help_on_Preview_Settings=
+Writing_XMP_metadata...=
+Writing_XMP_metadata_for_selected_entries...=
+Skipped_-_No_PDF_linked=
+Finished_writing_XMP_for_%0_file_(%1_skipped,_%2_errors).=
+Grouping_may_not_work_for_this_entry.=
+Write_BibtexEntry_as_XMP-metadata_to_PDF.=
+write_XMP=skriv_XMP
+New_field_value=Ny_verdi
+Overwrite_existing_field_values=Skriv_over_eksisterende_verdier
+Include_entries=Inkluder_enheter
+Selected_entries=Valgte_enheter
+
+Fetch_CiteSeer_by_ID=Hent_CiteSeer_ved_hjelp_av_ID
+Push_entries_to_external_application_(%0)=Send_enheter_til_eksternt_program_(%0)
+Write_XMP=Skriv_XMP
+
+Writing_XMP=Skriver_XMP
+
+HTML_table=HTML-tabell
+HTML_table_(with_Abstract_&_BibTeX)=HTML-tabell_(med_Abstract_&_BibTeX)
+
+Set/clear_fields=Sett/fjern_felter
+
+Clear_fields=Slett_felter
+Set_fields=Sett_felter
+
+OpenOffice_Calc=
+OpenDocument_Spreadsheet=
+
+Skipped_entry.=
+Error_occured_when_parsing_entry=
+Operation_canceled.\n=
+Error_while_writing=
+Skipped_-_PDF_does_not_exist=
+Use_custom_icon_theme=
+Custom_icon_theme=
+Custom_icon_theme_file=
+Unable_to_read_icon_theme_file=
+Unable_to_read_default_icon_theme.=
+Could_not_find_image_file=
+Set_field=
+No_entries_selected.=
+Link_from_new_entries.=
+Link_from_new_entry=
+Link_from_entries.=
+Link_from_entry=
+exists.Overwrite?=
+File_exists=
+No_file_associated=
+Exported_%0_entries_to_file=
+Formatter_Name=
+Format_String=
+Help_on_Name_Formatting=
+Special_Name_Formatters=
+Name_formatter=
diff --git a/src/resource/Menu_de.properties b/src/resource/Menu_de.properties
index 5be77a3..a01003e 100644
--- a/src/resource/Menu_de.properties
+++ b/src/resource/Menu_de.properties
@@ -183,8 +183,16 @@ Unmark_entries=Markierung_a&ufheben
Unpack_EndNote_filter_set=&EndNote_Filter-Set_entpacken
View=&Ansicht
-Web_search=
-Import_into_new_database=
-Import_into_current_database=
+Web_search=&Internet
+Import_into_new_database=Importieren_in_neue_Datenbank
+Import_into_current_database=Importieren_in_aktuelle_Datenbank
-Scan_database...=
\ No newline at end of file
+Scan_database...=Datenbank_durchsuchen
+
+Push_entries_to_external_application_(%0)=Eintr\u00e4ge_in_externe_Anwendung_einf\u00fcgen
+Write_XMP-metadata_to_PDFs=XMP-Metadaten_in_PDFs_schreiben
+
+
+Set/clear_fields=Felder_setzen/l\u00f6schen
+Export_selected_entries=Ausgew\u00e4hlte_Eintr\u00e4ge_exportieren
+Fetch_ArXiv.org=
diff --git a/src/resource/Menu_du.properties b/src/resource/Menu_du.properties
new file mode 100644
index 0000000..4db6620
--- /dev/null
+++ b/src/resource/Menu_du.properties
@@ -0,0 +1,203 @@
+#!
+#! created/edited by Gert Renckens, Dutch translation v0.12, last update: 20061102 (e-mail: gert (dot) renckens (at) student (dot) uhasselt (dot) be)
+#! encoding:ISO-8859-1
+
+Abbreviate_journal_names_(ISO)=Kort_namen_van_tijdschriften_af_(ISO)
+
+Abbreviate_journal_names_(MEDLINE)=Kort_namen_van_tijdschriften_af_(MEDLINE)
+
+About_JabRef=Over_JabRef
+
+Append_database=Database_bijvoegen
+
+Autogenerate_BibTeX_keys=Genereer_BibTeX-sleutels_automatisch
+
+BibTeX=BibTeX
+
+Close_database=Sluit_database
+
+Copy=Kopi�ren
+
+Copy_\\cite{BibTeX_key}=Kopieer_\\cite{BibTeX-sleutel}
+
+Copy_BibTeX_key=Kopieer_BibTeX-sleutel
+
+Custom_export=Externe_exportfilter
+
+Custom_importers=Externe_importfilter
+
+Customize_entry_types=Pas_entry_types_aan
+
+Cut=Knippen
+
+Database_properties=Database_eigenschappen
+
+Delete=Verwijderen
+
+Edit=Bewerken
+
+# Bibtex
+Edit_entry=Bewerk_entry
+
+Edit_preamble=Bewerk_inleiding
+
+Edit_strings=Bewerk_constanten
+
+Export=Exporteren
+
+Export_selected_entries_to_clipboard=Exporteer_geselecteerde_entries_naar_het_klembord
+
+Fetch_citations_from_CiteSeer=Haal_citaat_op_van_Citeseer
+
+Fetch_CiteSeer=Ophalen_van_Citeseer
+
+Fetch_Medline=Ophalen_van_Medline
+
+# Menu names
+File=Bestand
+
+Find_And_Fix=Zoeken_en_herstellen
+
+Find_and_remove_exact_duplicates=Zoek_en_verwijder_exacte_dubbels
+
+Find_duplicates=Zoek_dubbels
+
+Help=Help
+
+Help_contents=Help_inhoud
+
+Highlight_groups_matching_all_selected_entries=Markeer_groepen_die_overeenkomen_met_alle_geselecteerde_entries
+
+Highlight_groups_matching_any_selected_entry=Markeer_groepen_die_overeenkomen_met_elke_geselecteerde_entry
+
+Import_Fields_from_CiteSeer=Importeer_velden_van_CiteSeer
+
+Incremental_search=Incrementele_zoekopdracht
+
+Insert_selected_citations_into_Emacs=Voeg_geselecteerde_citaten_toe_aan_Emacs
+
+Insert_selected_citations_into_LatexEditor=Voeg_geselecteerde_citaten_toe_aan_LatexEditor
+
+Insert_selected_citations_into_LyX/Kile=Voeg_geselecteerde_citaten_toe_aan_LyX/Kile
+
+Insert_selected_citations_into_WinEdt=Voeg_geselecteerde_citaten_toe_aan_WinEdt
+
+Integrity_check=Integriteitscontrole
+
+# Help
+JabRef_help=JabRef_help
+
+Load_session=Sessie_laden
+
+Manage_content_selectors=Beheer_inhoud_selectors
+
+Manage_custom_exports=Beheer_externe_exportfilters
+
+Manage_custom_imports=Beheer_externe_importfilters
+
+Mark_entries=Markeer_entries
+
+# File menu
+New_database=Nieuwe_database
+
+# Menu BibTeX (BibTeX)
+New_entry=Nieuwe_entry
+
+New_entry...=Nieuwe_entry...
+
+New_entry_from_plain_text=Nieuwe_entry_van_onopgemaakte_tekst
+
+New_subdatabase_based_on_AUX_file=Nieuwe_subdatabase_gebaseerd_op_AUX_bestand
+
+# View
+Next_tab=Volgende_tabblad
+
+Open_database=Open_database
+
+Open_PDF_or_PS=Open_PDF_of_PS
+
+Open_URL_or_DOI=Open_URL_of_DOI
+
+Options=Opties
+
+Paste=Plakken
+
+# Options
+Preferences=Instellingen
+
+Previous_tab=Vorige_tabblad
+
+Quit=Afsluiten
+
+Recent_files=Recente_bestanden
+
+Redo=Herstellen
+
+Replace_string=Tekst_vervangen
+
+Save_database=Database_opslaan
+
+Save_database_as_...=Database_opslaan_als_...
+
+Save_selected_as_...=Geselecteerde_opslaan_als_...
+
+Save_session=Sessie_opslaan
+
+# Tools
+Search=Zoeken
+
+Search_IEEEXplore=Zoeken_op_IEEEXplore
+
+Select_all=Selecteer_alles
+
+Set_up_general_fields=Stel_algemene_velden_in
+
+Show_error_console=Toon_foutenconsole
+
+Sort_tabs=Tabbladen_sorteren
+
+Switch_preview_layout=Toon_voorbeeld_layout
+
+Synchronize_PDF_links=Synchroniseer_PDF_snelkoppelingen
+
+Synchronize_PS_links=Synchroniseer_PDF_snelkoppelingen
+
+# Export menu
+Tab-separated_file=Bestand_gescheiden_door_tabbladen
+
+Toggle_entry_preview=Toon_entry_voorbeeld
+
+Toggle_groups_interface=Toon_groepenvenster
+
+Tools=Extra's
+
+Unabbreviate_journal_names=Maak_afkorting_van_tijdschriftnamen_ongedaan
+
+# Edit
+Undo=Ongedaan_maken
+
+Unmark_all=Maak_alle_markeringen_ongedaan
+
+Unmark_entries=Maak_markeringen_van_entries_ongedaan
+
+Unpack_EndNote_filter_set=EndNote_filter_set_uitpakken
+
+View=Beeld
+
+Web_search=Zoeken_op_het_web
+
+Import_into_new_database=Importeer_in_nieuwe_database
+
+Import_into_current_database=Importeer_in_huidige_database
+
+Scan_database...=Database_doorzoeken
+
+Push_entries_to_external_application_(%0)=Stuur_entries_naar_externe_applicatie
+
+Write_XMP-metadata_to_PDFs=Schrijf_XMP_metadata_naar_PDFs
+
+Set/clear_fields=Instellen/verwijderen_velden
+
+Export_selected_entries=
+
+Fetch_ArXiv.org=
diff --git a/src/resource/Menu_en.properties b/src/resource/Menu_en.properties
index 10b4a56..ed564f4 100644
--- a/src/resource/Menu_en.properties
+++ b/src/resource/Menu_en.properties
@@ -104,4 +104,12 @@ Web_search=Web_search
Import_into_new_database=Import_into_new_database
Import_into_current_database=Import_into_current_database
-Scan_database...=S&can_database...
\ No newline at end of file
+Scan_database...=S&can_database...
+
+Push_entries_to_external_application_(%0)=Push_entries_to_external_application_(%0)
+Write_XMP-metadata_to_PDFs=Write_XMP-metadata_to_PDFs
+
+Set/clear_fields=Set/clear_fields
+
+Export_selected_entries=Export_selected_entries
+Fetch_ArXiv.org=Fetch_ArXiv.org
diff --git a/src/resource/Menu_fr.properties b/src/resource/Menu_fr.properties
index a56e1e6..c34a905 100644
--- a/src/resource/Menu_fr.properties
+++ b/src/resource/Menu_fr.properties
@@ -75,7 +75,7 @@ Select_all=&Tout_s\u00E9lectionner
Set_up_general_fields=Configurer_les_champs_&g\u00E9n\u00E9raux
Show_error_console=Afficher_la_console_d'erreur
Sort_tabs=Trier_les_onglets
-Switch_preview_layout=Pr\u00E9&visualiser_la_mise_en_page
+Switch_preview_layout=Aper\u00E7u_1/Aper\u00E7u_2
Synchronize_PDF_links=Synchroniser_les_liens_PD&F
Synchronize_PS_links=Synchroniser_les_liens_P&S
Tab-separated_file=Fichier_-_s\u00E9paration_par_&tabulation
@@ -93,3 +93,12 @@ Import_into_new_database=Importer_dans_une_nouvelle_base
Import_into_current_database=Importer_dans_la_base_courante
Scan_database...=Parcours_de_la_base_de_donn\u00E9es...
+
+Push_entries_to_external_application_(%0)=Envoyer_l'entr\u00e9e_vers_l'application_externe_(%0)
+Write_XMP-metadata_to_PDFs=Ecrire_les_m\u00e9tadonn\u00e9es_XMP_dans_les_PDFs
+
+Set/clear_fields=Configurer/vider_les_champs
+
+Export_selected_entries=Exporter_les_entr\u00E9es_s\u00E9lectionn\u00E9es
+
+Fetch_ArXiv.org=Recherche_ArXiv.org
diff --git a/src/resource/Menu_it.properties b/src/resource/Menu_it.properties
index d2ab839..3f57a4d 100644
--- a/src/resource/Menu_it.properties
+++ b/src/resource/Menu_it.properties
@@ -103,3 +103,10 @@ Web_search=&Internet
Import_into_new_database=Importa_in_un_nuo&vo_database
Import_into_current_database=Importa_nel_database_&corrente
Scan_database...=Scansione_del_database...
+
+Write_XMP-metadata_to_PDFs=Inserisci_metadati_XMP_nei_file_PDF
+Push_entries_to_external_application_(%0)=Invia_le_voci_all'applicazione_esterna_(%0)
+
+Set/clear_fields=Imposta/svuota_campi
+Export_selected_entries=Esporta_le_voci_selezionate
+Fetch_ArXiv.org=
diff --git a/src/resource/Menu_no.properties b/src/resource/Menu_no.properties
index 67b9dc1..c1ad53f 100644
--- a/src/resource/Menu_no.properties
+++ b/src/resource/Menu_no.properties
@@ -102,4 +102,11 @@ Web_search=
Import_into_new_database=
Import_into_current_database=
-Scan_database...=&Unders\u00F8k_database
\ No newline at end of file
+Scan_database...=&Unders\u00F8k_database
+
+Push_entries_to_external_application_(%0)=
+Write_XMP-metadata_to_PDFs=
+
+Set/clear_fields=Sett/fjern_felter
+Export_selected_entries=
+Fetch_ArXiv.org=
diff --git a/src/resource/build.properties b/src/resource/build.properties
index 1172524..5c6ef37 100644
--- a/src/resource/build.properties
+++ b/src/resource/build.properties
@@ -1,3 +1,3 @@
-builddate=August 9 2006
-build=569
-version=2.1
\ No newline at end of file
+builddate=November 26 2006
+build=340
+version=2.2b2
\ No newline at end of file
diff --git a/src/resource/fields/.cvsignore b/src/resource/fields/.cvsignore
new file mode 100644
index 0000000..167bfad
--- /dev/null
+++ b/src/resource/fields/.cvsignore
@@ -0,0 +1 @@
+fields.xml~
\ No newline at end of file
diff --git a/src/resource/journalList.txt b/src/resource/journalList.txt
new file mode 100644
index 0000000..3b7d81b
--- /dev/null
+++ b/src/resource/journalList.txt
@@ -0,0 +1,1556 @@
+#############################################################################
+##
+## Last update: December 4, 2005
+##
+## Journal abbreviations list readable by JabRef. JabRef versions
+## from 2.0 and upward can download and use this list for automatically
+## abbreviating and unabbreviating journal names. To access this function,
+## choose Tools -> Manage journal abbreviations.
+##
+#############################################################################
+Accounts of Chemical Research=Acc. Chem. Res.;ACHRE4;M
+ACS Symposium Series=ACS Symp. Ser.;ACSMC8;IRR
+Acta Biochimica Polonica=Acta Biochim. Pol.;ABPLAF;Q
+Acta Chimica Slovenica=Acta Chim. Slov.;ACSLE7;Q
+Acta Crystallographica, Section A: Foundations of Crystallography=Acta Crystallogr., Sect. A: Found. Crystallogr.;ACACEQ;BM
+Acta Crystallographica, Section B: Structural Science=Acta Crystallogr., Sect. B: Struct. Sci.;ASBSDK;BM
+Acta Crystallographica, Section C: Crystal Structure Communications=Acta Crystallogr., Sect. C: Cryst. Struct. Commun.;ACSCEE;M
+Acta Crystallographica, Section D: Biological Crystallography=Acta Crystallogr., Sect. D: Biol. Crystallogr.;ABCRE6;M
+Acta Crystallographica, Section E: Structure Reports Online=Acta Crystallogr., Sect. E: Struct. Rep. Online;ACSEBH;M
+Acta Crystallographica, Section F: Structural Biology and Crystallization Communications=Acta Crystallogr., Sect. F: Struct. Biol. Cryst. Commun.;ACSFCL;M
+Acta Hydrochimica et Hydrobiologica=Acta Hydrochim. Hydrobiol.;AHCBAU;BM
+Acta Materialia=Acta Mater.;ACMAFD;20/YR
+Acta Pharmaceutica (Zagreb, Croatia)=Acta Pharm. (Zagreb, Croatia);ACPHEE;Q
+Acta Pharmacologica Sinica=Acta Pharmacol. Sin.;APSCG5;M
+Acta Physica Polonica, A=Acta Phys. Pol., A;ATPLB6;M
+Acta Physica Polonica, B=Acta Phys. Pol., B;APOBBB;M
+Acta Physiologica Scandinavica=Acta Physiol. Scand.;APSCAX;M
+Adsorption=Adsorption;ADSOFO;Q
+Adsorption Science & Technology=Adsorpt. Sci. Technol.;ASTEEZ;10/YR
+Advanced Drug Delivery Reviews=Adv. Drug Delivery Rev.;ADDREP;15/YR
+Advanced Functional Materials=Adv. Funct. Mater.;AFMDC6;M
+Advanced Materials (Weinheim, Germany)=Adv. Mater. (Weinheim, Ger.);ADVMEW;SM
+Advanced Synthesis & Catalysis=Adv. Synth. Catal.;ASCAF7;15/YR
+Advances in Applied Ceramics=Adv. Appl. Ceram.;AACDCN;BM
+Advances in Atomic, Molecular, and Optical Physics=Adv. At., Mol., Opt. Phys.;AAMPE9;IRR
+Advances in Chemical Physics=Adv. Chem. Phys.;ADCPAA;IRR
+Advances in Chromatography (New York, NY, United States)=Adv. Chromatogr. (N. Y., NY, U. S.);ADCYA3;IRR
+Advances in Colloid and Interface Science=Adv. Colloid Interface Sci.;ACISB9;24/YR
+Advances in Electrochemical Science and Engineering=Adv. Electrochem. Sci. Eng.;AESEEY;IRR
+Advances in Inorganic Chemistry=Adv. Inorg. Chem.;AICHEP;IRR
+Advances in Polymer Science=Adv. Polym. Sci.;APSIDK;IRR
+Advances in Polymer Technology=Adv. Polym. Technol.;APTYD5;Q
+Advances in Quantum Chemistry=Adv. Quantum Chem.;AQCHA9;IRR
+Advances in X-Ray Analysis=Adv. X-Ray Anal.;AXRAAA;A
+Aerosol Science and Technology=Aerosol Sci. Technol.;ASTYDQ;M
+Afinidad=Afinidad;AFINAE;BM
+Aging Cell=Aging Cell;ACGECQ;BM
+AIChE Journal=AIChE J.;AICEAC;M
+American Ceramic Society Bulletin=Am. Ceram. Soc. Bull.;ACSBA7;M
+American Journal of Clinical Nutrition=Am. J. Clin. Nutr.;AJCNAC;M
+American Journal of Human Genetics=Am. J. Hum. Genet.;AJHGAG;M
+American Journal of Physiology=Am. J. Physiol.;AJPHAP;M
+American Journal of Respiratory Cell and Molecular Biology=Am. J. Respir. Cell Mol. Biol.;AJRBEL;M
+American Mineralogist=Am. Mineral.;AMMIAY;8/YR
+Amino Acids=Amino Acids;AACIE6;8/YR
+Analyst (Cambridge, United Kingdom)=Analyst (Cambridge, U. K.);ANALAO;M
+Analytica Chimica Acta=Anal. Chim. Acta;ACACAM;52/YR
+Analytical and Bioanalytical Chemistry=Anal. Bioanal. Chem.;ABCNBP;SM
+Analytical Biochemistry=Anal. Biochem.;ANBCA2;SM
+Analytical Chemistry=Anal. Chem.;ANCHAM;SM
+Analytical Letters=Anal. Lett.;ANALBP;15/YR
+Analytical Sciences=Anal. Sci.;ANSCEN;M
+Angewandte Chemie, International Edition=Angew. Chem., Int. Ed.;ACIEF5;W
+Animal Welfare=Anim. Welfare;ANWEEF;4/YR
+Animal Welfare Information Center Bulletin=Anim. Welfare Inf. Cent. Bull.;AWICAW;Q
+Annales de Chimie (Cachan, France)=Ann. Chim. (Cachan, Fr.);ANCPAC;6/YR
+Annales Pharmaceutiques Francaises=Ann. Pharm. Fr.;APFRAD;BM
+Annali di Chimica (Rome, Italy)=Ann. Chim. (Rome, Italy);ANCRAI;BM
+Annals of Nuclear Energy=Ann. Nucl. Energy;ANENDJ;18/YR
+Annals of Nutrition & Metabolism=Ann. Nutr. Metab.;ANUMDS;BM
+Annals of Physics (San Diego, CA, United States)=Ann. Phys. (San Diego, CA, U. S.);APNYA6;M
+Annexins=Annexins;ANNEC2;Q
+Annual Reports in Medicinal Chemistry=Annu. Rep. Med. Chem.;ARMCBI;A
+Annual Reports on NMR Spectroscopy=Annu. Rep. NMR Spectrosc.;NMRPAJ;IRR
+Annual Reports on the Progress of Chemistry, Section A: Inorganic Chemistry=Annu. Rep. Prog. Chem., Sect. A: Inorg. Chem.;APCCDO;A
+Annual Reports on the Progress of Chemistry, Section B: Organic Chemistry=Annu. Rep. Prog. Chem., Sect. B: Org. Chem.;CACBB4;A
+Annual Reports on the Progress of Chemistry, Section C: Physical Chemistry=Annu. Rep. Prog. Chem., Sect. C: Phys. Chem.;ACPCDW;A
+Annual Review of Biochemistry=Annu. Rev. Biochem.;ARBOAW;A
+Annual Review of Biomedical Engineering=Annu. Rev. Biomed. Eng.;ARBEF7;A
+Annual Review of Biophysics and Biomolecular Structure=Annu. Rev. Biophys. Biomol. Struct.;ABBSE4;A
+Annual Review of Cell and Developmental Biology=Annu. Rev. Cell Dev. Biol.;ARDBF8;A
+Annual Review of Earth and Planetary Sciences=Annu. Rev. Earth Planet. Sci.;AREPCI;A
+Annual Review of Entomology=Annu. Rev. Entomol.;ARENAA;A
+Annual Review of Genetics=Annu. Rev. Genet.;ARVGB7;A
+Annual Review of Genomics and Human Genetics=Annu. Rev. Genomics Hum. Genet.;ARGHC4;A
+Annual Review of Immunology=Annu. Rev. Immunol.;ARIMDU;A
+Annual Review of Materials Research=Annu. Rev. Mater. Res.;ARMRCU;A
+Annual Review of Medicine=Annu. Rev. Med.;ARMCAH;A
+Annual Review of Microbiology=Annu. Rev. Microbiol.;ARMIAZ;A
+Annual Review of Neuroscience=Annu. Rev. Neurosci.;ARNSD5;A
+Annual Review of Nuclear and Particle Science=Annu. Rev. Nucl. Part. Sci.;ARPSDF;A
+Annual Review of Nutrition=Annu. Rev. Nutr.;ARNTD8;A
+Annual Review of Pharmacology and Toxicology=Annu. Rev. Pharmacol. Toxicol.;ARPTDI;A
+Annual Review of Physical Chemistry=Annu. Rev. Phys. Chem.;ARPLAP;A
+Annual Review of Physiology=Annu. Rev. Physiol.;ARPHAD;A
+Annual Review of Phytopathology=Annu. Rev. Phytopathol.;APPYAG;A
+Annual Review of Plant Biology=Annu. Rev. Plant Biol.;ARPBDW;A
+Anti-Cancer Drugs=Anti-Cancer Drugs;ANTDEV;10/YR
+Antibiotiki i Khimioterapiya=Antibiot. Khimioter.;ANKHEW;M
+Antimicrobial Agents and Chemotherapy=Antimicrob. Agents Chemother.;AMACCQ;M
+Antioxidants & Redox Signaling=Antioxid. Redox Signaling;ARSIF2;BM
+Antiviral Chemistry & Chemotherapy=Antiviral Chem. Chemother.;ACCHEH;BM
+Antiviral Research=Antiviral Res.;ARSRDR;M
+Applied and Environmental Microbiology=Appl. Environ. Microbiol.;AEMIDF;M
+Applied Biochemistry and Biotechnology=Appl. Biochem. Biotechnol.;ABIBDL;24/YR
+Applied Biochemistry and Microbiology=Appl. Biochem. Microbiol.;APBMAC;BM
+Applied Catalysis, A: General=Appl. Catal., A;ACAGE4;36/YR
+Applied Catalysis, B: Environmental=Appl. Catal., B;ACBEE3;28/YR
+Applied Clay Science=Appl. Clay Sci.;ACLSER;BM
+Applied Geochemistry=Appl. Geochem.;APPGEY;M
+Applied Microbiology and Biotechnology=Appl. Microbiol. Biotechnol.;AMBIDG;18/YR
+Applied Organometallic Chemistry=Appl. Organomet. Chem.;AOCHEX;M
+Applied Physics A: Materials Science & Processing=Appl. Phys. A: Mater. Sci. Process.;APAMFC;16/YR
+Applied Physics B: Lasers and Optics=Appl. Phys. B: Lasers Opt.;APBOEM;16/YR
+Applied Physics Letters=Appl. Phys. Lett.;APPLAB;W
+Applied Radiation and Isotopes=Appl. Radiat. Isot.;ARISEF;M
+Applied Spectroscopy=Appl. Spectrosc.;APSPA4;M
+Applied Surface Science=Appl. Surf. Sci.;ASUSEE;19/YR
+Aquatic Toxicology=Aquat. Toxicol.;AQTODG;20/YR
+Archaea=Archaea;ARCHCI;IRR
+Archiv der Pharmazie (Weinheim, Germany)=Arch. Pharm. (Weinheim, Ger.);ARPMAS;M
+Archives of Biochemistry and Biophysics=Arch. Biochem. Biophys.;ABBIA4;SM
+Archives of Environmental Contamination and Toxicology=Arch. Environ. Contam. Toxicol.;AECTCV;8/YR
+Archives of Insect Biochemistry and Physiology=Arch. Insect Biochem. Physiol.;AIBPEA;M
+Archives of Microbiology=Arch. Microbiol.;AMICCW;M
+Archives of Pharmacal Research=Arch. Pharmacal Res.;APHRDQ;M
+Archives of Physiology and Biochemistry=Arch. Physiol. Biochem.;APBIF5;5/YR
+Archives of Toxicology=Arch. Toxicol.;ARTODN;12/YR
+Archives of Virology=Arch. Virol.;ARVIDF;12/YR
+Archivum Combustionis=Arch. Combust.;ACOMEO;Q
+ARKIVOC (Gainesville, FL, United States)=ARKIVOC (Gainesville, FL, U. S.);AGFUAR;IRR
+Arteriosclerosis, Thrombosis, and Vascular Biology=Arterioscler., Thromb., Vasc. Biol.;ATVBFA;M
+Arzneimittel Forschung=Arzneim. Forsch.;ARZNAD;M
+Asian Journal of Chemistry=Asian J. Chem.;AJCHEW;Q
+Assay and Drug Development Technologies=Assay Drug Dev. Technol.;ADDTAR;BM
+Atherosclerosis (Amsterdam, Netherlands)=Atherosclerosis (Amsterdam, Neth.);ATHSBL;M
+ATLA, Alternatives to Laboratory Animals=ATLA, Altern. Lab. Anim.;AALADQ;BM
+Atmospheric Chemistry and Physics=Atmos. Chem. Phys.;ACPTCE;12/YR
+Atmospheric Environment=Atmos. Environ.;AENVEQ;40/YR
+Atomic Energy (New York, NY, United States)=At. Energy (N. Y., NY, U. S.);AENYEZ;M
+Atomic Spectroscopy=At. Spectrosc.;ASPND7;BM
+Australian Journal of Chemistry=Aust. J. Chem.;AJCHAS;M
+Autonomic & Autacoid Pharmacology=Auton. Autacoid Pharmacol.;AAPUC3;Q
+Azerbaidzhanskii Khimicheskii Zhurnal=Azerb. Khim. Zh.;AZKZAU;Q
+Basic & Clinical Pharmacology & Toxicology=Basic Clin. Pharmacol. Toxicol.;BCPTBO;M
+Beilstein Journal of Organic Chemistry=Beilstein J. Org. Chem.;BJOCBH;IRR
+Biocatalysis and Biotransformation=Biocatal. Biotransform.;BOBOEQ;BM
+Biochemical and Biophysical Research Communications=Biochem. Biophys. Res. Commun.;BBRCA9;50/YR
+Biochemical Genetics=Biochem. Genet.;BIGEBA;BM
+Biochemical Journal=Biochem. J.;BIJOAK;SM
+Biochemical Pharmacology=Biochem. Pharmacol.;BCPCA6;SM
+Biochemical Society Transactions=Biochem. Soc. Trans.;BCSTB5;6/YR
+Biochemical Systematics and Ecology=Biochem. Syst. Ecol.;BSECBU;M
+Biochemistry=Biochemistry;BICHAW;W
+Biochemistry (Moscow)=Biochemistry (Moscow);BIORAK;M
+Biochemistry and Cell Biology=Biochem. Cell Biol.;BCBIEQ;BM
+Biochemistry and Molecular Biology Education=Biochem. Mol. Biol. Educ.;BMBECE;BM
+Biochimica et Biophysica Acta=Biochim. Biophys. Acta;BBACAQ;
+Biochimica et Biophysica Acta, Bioenergetics=Biochim. Biophys. Acta, Bioenerg.;BBBEB4;15/YR
+Biochimica et Biophysica Acta, Biomembranes=Biochim. Biophys. Acta, Biomembr.;BBBMBS;20/YR
+Biochimica et Biophysica Acta, Biophysics Including Photosynthesis=Biochim. Biophys. Acta, Biophys. Incl. Photosynth.;BBABER;
+Biochimica et Biophysica Acta, Enzymology=Biochim. Biophys. Acta, Enzymol.;BBEZAD;
+Biochimica et Biophysica Acta, Enzymology and Biological Oxidation=Biochim. Biophys. Acta, Enzymol. Biol. Oxid.;BBAECY;
+Biochimica et Biophysica Acta, Gene Structure and Expression=Biochim. Biophys. Acta, Gene Struct. Expression;BBGSD5;18/YR
+Biochimica et Biophysica Acta, General Subjects=Biochim. Biophys. Acta, Gen. Subj.;BBGSB3;18/YR
+Biochimica et Biophysica Acta, Lipids and Lipid Metabolism=Biochim. Biophys. Acta, Lipids Lipid Metab.;BBLLA6;18/YR
+Biochimica et Biophysica Acta, Molecular and Cell Biology of Lipids=Biochim. Biophys. Acta, Mol. Cell Biol. Lipids;BBMLFG;18/YR
+Biochimica et Biophysica Acta, Molecular Basis of Disease=Biochim. Biophys. Acta, Mol. Basis Dis.;BBADEX;9/YR
+Biochimica et Biophysica Acta, Molecular Cell Research=Biochim. Biophys. Acta, Mol. Cell Res.;BBAMCO;15/YR
+Biochimica et Biophysica Acta, Mucoproteins and Mucopolysaccharides=Biochim. Biophys. Acta, Mucoproteins Mucopolysaccharides;BBAMFR;
+Biochimica et Biophysica Acta, Protein Structure=Biochim. Biophys. Acta, Protein Struct.;BBPTBH;
+Biochimica et Biophysica Acta, Protein Structure and Molecular Enzymology=Biochim. Biophys. Acta, Protein Struct. Mol. Enzymol.;BBAEDZ;16/YR
+Biochimica et Biophysica Acta, Proteins and Proteomics=Biochim. Biophys. Acta, Proteins Proteomics;BBAPBW;16/YR
+Biochimica et Biophysica Acta, Reviews on Bioenergetics=Biochim. Biophys. Acta, Rev. Bioenerg.;BRBECF;
+Biochimica et Biophysica Acta, Reviews on Biomembranes=Biochim. Biophys. Acta, Rev. Biomembr.;BRBMC5;3/YR
+Biochimica et Biophysica Acta, Reviews on Cancer=Biochim. Biophys. Acta, Rev. Cancer;BBACEU;4/YR
+Biochimica et Biophysica Acta, Specialized Section on Biophysical Subjects=Biochim. Biophys. Acta, Spec. Sect. Biophys. Subj.;BBASEA;
+Biochimica et Biophysica Acta, Specialized Section on Enzymological Subjects=Biochim. Biophys. Acta, Spec. Sect. Enzymol. Subj.;BBASD9;
+Biochimica et Biophysica Acta, Specialized Section on Lipids and Related Subjects=Biochim. Biophys. Acta, Spec. Sect. Lipids Relat. Subj.;BBASC8;
+Mucopolysaccharides Biochimica et Biophysica Acta, Specialized Section on Mucoproteins and Mucopolysaccharides=Biochim. Biophys. Acta, Spec. Sect. Mucoproteins;BBASFB;
+Subj. Biochimica et Biophysica Acta, Specialized Section on Nucleic Acids and Related Subjects=Biochim. Biophys. Acta, Spec. Sect. Nucleic Acids Relat.;BBASB7;
+Biochimie=Biochimie;BICMBE;M
+Bioconjugate Chemistry=Bioconjugate Chem.;BCCHES;BM
+Bioelectrochemistry=Bioelectrochemistry;BIOEFK;6/YR
+BioFactors=BioFactors;BIFAEU;12/YR
+Biofizika=Biofizika;BIOFAI;BM
+Biogenic Amines=Biog. Amines;BIAME7;6/YR
+Bioinformatics=Bioinformatics;BOINFP;24/YR
+Bioinorganic Chemistry and Applications=Bioinorg. Chem. Appl.;BCAIAH;4/YR
+Biological & Pharmaceutical Bulletin=Biol. Pharm. Bull.;BPBLEO;M
+Biological Chemistry=Biol. Chem.;BICHF3;M
+Biological Trace Element Research=Biol. Trace Elem. Res.;BTERDG;18/YR
+Biologicheskie Membrany=Biol. Membr.;BIMEE9;BM
+Biology of Reproduction=Biol. Reprod.;BIREBV;13/YR
+Biomacromolecules=Biomacromolecules;BOMAF6;BM
+Biomarkers=Biomarkers;BIOMFA;BM
+Biomaterials=Biomaterials;BIMADU;36/YR
+Biomedical Chromatography=Biomed. Chromatogr.;BICHE2;8/YR
+Biomedical Research=Biomed. Res.;BRESD5;BM
+Biomeditsinskaya Khimiya=Biomed. Khim.;BKIHA8;BM
+BioMetals=BioMetals;BOMEEH;BM
+Biomolecular Engineering=Biomol. Eng.;BIENFV;6/YR
+Bioorganic & Medicinal Chemistry=Bioorg. Med. Chem.;BMECEP;SM
+Bioorganic & Medicinal Chemistry Letters=Bioorg. Med. Chem. Lett.;BMCLE8;SM
+Bioorganic Chemistry=Bioorg. Chem.;BOCMBM;BM
+Biopharmaceutics & Drug Disposition=Biopharm. Drug Dispos.;BDDID8;9/YR
+Biophysical Chemistry=Biophys. Chem.;BICIAZ;21/YR
+Biophysical Journal=Biophys. J.;BIOJAU;M
+Biopolymers=Biopolymers;BIPMAA;24/YR
+Bioprocess and Biosystems Engineering=Bioprocess Biosyst. Eng.;BBEIBV;6/YR
+Bioresource Technology=Bioresour. Technol.;BIRTEB;18/YR
+Bioscience Reports=Biosci. Rep.;BRPTDT;BM
+Bioscience, Biotechnology, and Biochemistry=Biosci., Biotechnol., Biochem.;BBBIEJ;M
+Biosensors & Bioelectronics=Biosens. Bioelectron.;BBIOE4;M
+BioTechniques=BioTechniques;BTNQDO;M
+Biotechnology and Applied Biochemistry=Biotechnol. Appl. Biochem.;BABIEC;BM
+Biotechnology and Bioengineering=Biotechnol. Bioeng.;BIBIAU;28/YR
+Biotechnology and Bioprocess Engineering=Biotechnol. Bioprocess Eng.;BBEIAU;BM
+Biotechnology Letters=Biotechnol. Lett.;BILED3;SM
+Biotechnology Progress=Biotechnol. Prog.;BIPRET;BM
+Birth Defects Research, Part A: Clinical and Molecular Teratology=Birth Defects Res., Part A;BDRPBT;M
+Birth Defects Research, Part B: Developmental and Reproductive Toxicology=Birth Defects Res., Part B;BDRPCU;BM
+Birth Defects Research, Part C: Embryo Today--Reviews=Birth Defects Res., Part C;BDRPDV;Q
+Bitamin=Bitamin;BTMNA7;M
+Blood=Blood;BLOOAW;25/YR
+Bopuxue Zazhi=Bopuxue Zazhi;BOZAE2;Q
+Brain Research=Brain Res.;BRREAP;72/YR
+British Journal of Nutrition=Br. J. Nutr.;BJNUAV;M
+British Journal of Pharmacology=Br. J. Pharmacol.;BJPCBM;SM
+Bulgarian Chemical Communications=Bulg. Chem. Commun.;BCHCE4;Q
+Bulletin of Electrochemistry=Bull. Electrochem.;BUELE6;M
+Bulletin of Environmental Contamination and Toxicology=Bull. Environ. Contam. Toxicol.;BECTA6;M
+Bulletin of Materials Science=Bull. Mater. Sci.;BUMSDW;BM
+Bulletin of the Chemical Society of Japan=Bull. Chem. Soc. Jpn.;BCSJA8;M
+Bulletin of the Korean Chemical Society=Bull. Korean Chem. Soc.;BKCSDE;M
+Bunseki Kagaku=Bunseki Kagaku;BNSKAK;M
+Cailiao Rechuli Xuebao=Cailiao Rechuli Xuebao;CRXAAK;BM
+Calcified Tissue International=Calcif. Tissue Int.;CTINDZ;M
+CALPHAD: Computer Coupling of Phase Diagrams and Thermochemistry=CALPHAD: Comput. Coupling Phase Diagrams Thermochem.;CCCTD6;Q
+Canadian Journal of Analytical Sciences and Spectroscopy=Can. J. Anal. Sci. Spectrosc.;CJASFA;BM
+Canadian Journal of Chemical Engineering=Can. J. Chem. Eng.;CJCEA7;BM
+Canadian Journal of Chemistry=Can. J. Chem.;CJCHAG;M
+Canadian Journal of Microbiology=Can. J. Microbiol.;CJMIAZ;M
+Canadian Journal of Physics=Can. J. Phys.;CJPHAD;M
+Canadian Journal of Physiology and Pharmacology=Can. J. Physiol. Pharmacol.;CJPPA3;M
+Canadian Metallurgical Quarterly=Can. Metall. Q.;CAMQAU;Q
+Canadian Mineralogist=Can. Mineral.;CAMIA6;BM
+Cancer Cell=Cancer Cell;CCAECI;M
+Cancer Gene Therapy=Cancer Gene Ther.;CGTHEG;M
+Cancer Genomics & Proteomics=Cancer Genomics Proteomics;CGPAC7;BM
+Cancer Letters (Amsterdam, Netherlands)=Cancer Lett. (Amsterdam, Neth.);CALEDQ;28/YR
+Cancer Research=Cancer Res.;CNREA8;SM
+Cancer Science=Cancer Sci.;CSACCM;M
+Carbohydrate Polymers=Carbohydr. Polym.;CAPOD8;16/YR
+Carbohydrate Research=Carbohydr. Res.;CRBRAT;18/YR
+Carbon=Carbon;CRBNAH;15/YR
+Carcinogenesis=Carcinogenesis;CRNGDP;M
+Cardiovascular Research=Cardiovasc. Res.;CVREAU;14/YR
+Catalysis Communications=Catal. Commun.;CCAOAC;M
+Catalysis Letters=Catal. Lett.;CALEER;28/YR
+Catalysis Reviews - Science and Engineering=Catal. Rev. - Sci. Eng.;CRSEC9;Q
+Catalysis Today=Catal. Today;CATTEA;44/YR
+Cell (Cambridge, MA, United States)=Cell (Cambridge, MA, U. S.);CELLB5;BW
+Cell Biochemistry and Biophysics=Cell Biochem. Biophys.;CBBIFV;6/YR
+Cell Biochemistry and Function=Cell Biochem. Funct.;CBFUDH;6/YR
+Cell Calcium=Cell Calcium;CECADV;M
+Cell Cycle=Cell Cycle;CCEYAS;M
+Cell Metabolism=Cell Metab.;CMEEB5;M
+Cellular and Molecular Biology (Paris, France, Online)=Cell. Mol. Biol. (Paris, Fr., Online);CMBPBN;IRR
+Cellular and Molecular Biology (Sarreguemines, France, Print)=Cell. Mol. Biol. (Sarreguemines, Fr., Print);CMOBEF;8/YR
+Cellular and Molecular Life Sciences=Cell. Mol. Life Sci.;CMLSFI;24/YR
+Cellular Immunology=Cell. Immunol.;CLIMB8;M
+Cellular Microbiology=Cell. Microbiol.;CEMIF5;M
+Cellular Physiology and Biochemistry=Cell. Physiol. Biochem.;CEPBEW;6/YR
+Cellular Polymers=Cell. Polym.;CELPDJ;BM
+Cellulose Chemistry and Technology=Cellul. Chem. Technol.;CECTAH;BM
+Cement & Concrete Composites=Cem. Concr. Compos.;CCOCEG;10/YR
+Cement and Concrete Research=Cem. Concr. Res.;CCNRAI;M
+Ceramics International=Ceram. Int.;CINNDH;8/YR
+Ceramics-Silikaty=Ceram.-Silik.;CERSEP;Q
+Cereal Chemistry=Cereal Chem.;CECHAF;BM
+Ceska a Slovenska Farmacie=Ceska Slov. Farm.;CSLFEK;BM
+ChemBioChem=ChemBioChem;CBCHFX;M
+Chemia Analityczna (Warsaw, Poland)=Chem. Anal. (Warsaw, Pol.);CANWAJ;BM
+Chemical & Pharmaceutical Bulletin=Chem. Pharm. Bull.;CPBTAL;M
+Chemical and Biochemical Engineering Quarterly=Chem. Biochem. Eng. Q.;CBEQEZ;Q
+Chemical Communications (Cambridge, United Kingdom)=Chem. Commun. (Cambridge, U. K.);CHCOFS;48/YR
+Chemical Engineering & Technology=Chem. Eng. Technol.;CETEER;M
+Chemical Engineering and Processing=Chem. Eng. Process.;CENPEU;M
+Chemical Engineering Communications=Chem. Eng. Commun.;CEGCAK;M
+Chemical Engineering Journal (Amsterdam, Netherlands)=Chem. Eng. J. (Amsterdam, Neth.);CMEJAJ;27/YR
+Chemical Engineering Progress=Chem. Eng. Prog.;CEPRA8;M
+Chemical Engineering Research and Design=Chem. Eng. Res. Des.;CERDEE;M
+Chemical Engineering Science=Chem. Eng. Sci.;CESCAC;SM
+Chemical Geology=Chem. Geol.;CHGEAD;44/YR
+Chemical Papers=Chem. Pap.;CHPAEG;6/YR
+Chemical Physics=Chem. Phys.;CMPHC2;33/YR
+Chemical Physics Letters=Chem. Phys. Lett.;CHPLBC;W
+Chemical Record=Chem. Rec.;CRHEAK;BM
+Chemical Research in Chinese Universities=Chem. Res. Chin. Univ.;CRCUED;BM
+Chemical Research in Toxicology=Chem. Res. Toxicol.;CRTOEC;M
+Chemical Reviews (Washington, DC, United States)=Chem. Rev. (Washington, DC, U. S.);CHREAY;M
+Chemical Society Reviews=Chem. Soc. Rev.;CSRVBR;12/YR
+Chemical Speciation and Bioavailability=Chem. Speciation Bioavailability;CHSBEY;Q
+Chemical Vapor Deposition=Chem. Vap. Deposition;CVDEFX;M
+Chemicke Listy=Chem. Listy;CHLSAC;M
+Chemico-Biological Interactions=Chem.-Biol. Interact.;CBINA8;18/YR
+Chemie der Erde=Chem. Erde;CERDAA;4/YR
+Chemie Ingenieur Technik=Chem. Ing. Tech.;CITEAH;M
+Chemija=Chemija;CHMJES;4/YR
+Chemistry & Biodiversity=Chem. Biodiversity;CBHIAM;M
+Chemistry & Biology (Cambridge, MA, United States)=Chem. Biol. (Cambridge, MA, U. S.);CBOLE2;M
+Chemistry & Industry (London, United Kingdom)=Chem. Ind. (London, U. K.);CHINAG;SM
+Chemistry and Physics of Lipids=Chem. Phys. Lipids;CPLIA4;M
+Chemistry and Technology of Fuels and Oils=Chem. Technol. Fuels Oils;CTFOAK;BM
+Chemistry Letters=Chem. Lett.;CMLTAG;M
+Chemistry of Heterocyclic Compounds (New York, NY, United States)=Chem. Heterocycl. Compd. (N. Y., NY, U. S.);CHCCAL;M
+Chemistry of Materials=Chem. Mater.;CMATEX;BW
+Chemistry of Natural Compounds=Chem. Nat. Compd.;CHNCA8;BM
+Chemistry--A European Journal=Chem.--Eur. J.;CEUJED;SM
+Chemometrics and Intelligent Laboratory Systems=Chemom. Intell. Lab. Syst.;CILSEN;9/YR
+Chemosphere=Chemosphere;CMSHAF;44/YR
+Chemotherapy (Basel, Switzerland)=Chemotherapy (Basel, Switz.);CHTHBK;BM
+ChemPhysChem=ChemPhysChem;CPCHFT;12/YR
+Chemtracts=Chemtracts;CHEMFW;12/YR
+Chimia=Chimia;CHIMAD;M
+Chimica e l'Industria (Milan, Italy)=Chim. Ind. (Milan, Italy);CINMAB;10/YR
+Chinese Chemical Letters=Chin. Chem. Lett.;CCLEE7;M
+Chinese Journal of Chemical Engineering=Chin. J. Chem. Eng.;CJCEEB;BM
+Chinese Journal of Chemistry=Chin. J. Chem.;CJOCEV;M
+Chinese Journal of Geochemistry=Chin. J. Geochem.;CJGEEV;Q
+Chinese Journal of Polymer Science=Chin. J. Polym. Sci.;CJPSEG;BM
+Chirality=Chirality;CHRLEP;10/YR
+Chromatographia=Chromatographia;CHRGB7;M
+Chromosome Research=Chromosome Res.;CRRSEE;8/YR
+Circulation Research=Circ. Res.;CIRUAL;SM
+Clay Minerals=Clay Miner.;CLMIAF;Q
+Clays and Clay Minerals=Clays Clay Miner.;CLCMAB;BM
+Clinica Chimica Acta=Clin. Chim. Acta;CCATAR;M
+Clinical and Diagnostic Laboratory Immunology=Clin. Diagn. Lab. Immunol.;CDIMEN;M
+Clinical and Experimental Pharmacology and Physiology=Clin. Exp. Pharmacol. Physiol.;CEXPB9;M
+Clinical Chemistry (Washington, DC, United States)=Clin. Chem. (Washington, DC, U. S.);CLCHAU;M
+Clinical Chemistry and Laboratory Medicine=Clin. Chem. Lab. Med.;CCLMFW;M
+Clinical Immunology (San Diego, CA, United States)=Clin. Immunol. (San Diego, CA, U. S.);CLIIFY;M
+Clinical Proteomics=Clin. Proteomics;CPLRCX;4/YR
+Cloning and Stem Cells=Cloning Stem Cells;CSCLBO;Q
+Coal Preparation (Philadelphia, PA, United States)=Coal Prep. (Philadelphia, PA, U. S.);COAPDY;6/YR
+Collection of Czechoslovak Chemical Communications=Collect. Czech. Chem. Commun.;CCCCAK;M
+Colloid and Polymer Science=Colloid Polym. Sci.;CPMSB6;M
+Colloid Journal=Colloid J.;CJRSEQ;BM
+Colloids and Surfaces, A: Physicochemical and Engineering Aspects=Colloids Surf., A;CPEAEH;24/YR
+Colloids and Surfaces, B: Biointerfaces=Colloids Surf., B;CSBBEQ;28/YR
+Coloration Technology=Color. Technol.;CTOEAZ;BM
+Combinatorial Chemistry and High Throughput Screening=Comb. Chem. High Throughput Screening;CCHSFU;8/YR
+Combustion and Flame=Combust. Flame;CBFMAO;M
+Combustion Science and Technology=Combust. Sci. Technol.;CBSTB9;M
+Comments on Inorganic Chemistry=Comments Inorg. Chem.;COICDZ;BM
+Communications in Soil Science and Plant Analysis=Commun. Soil Sci. Plant Anal.;CSOSA2;20/YR
+Comparative and Functional Genomics=Comp. Funct. Genomics;CFGOAT;8/YR
+Comparative Biochemistry and Physiology, Part A: Molecular & Integrative Physiology=Comp. Biochem. Physiol., Part A: Mol. Integr. Physiol.;CBPAB5;M
+Comparative Biochemistry and Physiology, Part B: Biochemistry & Molecular Biology=Comp. Biochem. Physiol., Part B: Biochem. Mol. Biol.;CBPBB8;M
+Comparative Biochemistry and Physiology, Part C: Toxicology & Pharmacology=Comp. Biochem. Physiol., Part C: Toxicol. Pharmacol.;CBPPFK;M
+Comparative Medicine=Comp. Med.;COMEFT;BM
+Comptes Rendus Chimie=C. R. Chim.;CRCOCR;M
+Comptes Rendus Physique=C. R. Phys.;CRPOBN;10/YR
+Computational Biology and Chemistry=Comput. Biol. Chem.;CBCOCH;BM
+Computer Physics Communications=Comput. Phys. Commun.;CPHCBZ;SM
+Computers & Chemical Engineering=Comput. Chem. Eng.;CCENDW;M
+Comunicaciones presentadas a las Jornadas del Comite Espanol de la Detergencia=Comun. Jorn. Com. Esp. Deterg.;CJCDD7;A
+Contemporary Topics in Laboratory Animal Science=Contemp. Top. Lab. Anim. Sci.;CTLAA8;BM
+Contributions to Mineralogy and Petrology=Contrib. Mineral. Petrol.;CMPEAP;M
+Coordination Chemistry Reviews=Coord. Chem. Rev.;CCHRAM;M
+Corrosion (Houston, TX, United States)=Corrosion (Houston, TX, U. S.);CORRAK;M
+Corrosion Engineering, Science and Technology=Corros. Eng., Sci. Technol.;CESTBU;Q
+Corrosion Reviews=Corros. Rev.;CORVE2;Q
+Corrosion Science=Corros. Sci.;CRRSAA;M
+Critical Reviews in Analytical Chemistry=Crit. Rev. Anal. Chem.;CCACBB;Q
+Critical Reviews in Solid State and Materials Sciences=Crit. Rev. Solid State Mater. Sci.;CCRSDA;Q
+Croatica Chemica Acta=Croat. Chem. Acta;CCACAA;Q
+Cryogenics=Cryogenics;CRYOAX;M
+Crystal Growth & Design=Cryst. Growth Des.;CGDEFU;BM
+Crystal Research and Technology=Cryst. Res. Technol.;CRTEDF;12/YR
+Crystallography Reports=Crystallogr. Rep.;CYSTE3;BM
+CrystEngComm=CrystEngComm;CRECF4;IRR
+Cuihua Xuebao=Cuihua Xuebao;THHPD3;M
+Current Alzheimer Research=Curr. Alzheimer Res.;CARUBY;5/YR
+Current Analytical Chemistry=Curr. Anal. Chem.;CACUBR;3/YR
+Current Biology=Curr. Biol.;CUBLE2;SM
+Current Cancer Drug Targets=Curr. Cancer Drug Targets;CCDTB9;8/YR
+Current Computer-Aided Drug Design=Curr. Comput.-Aided Drug Des.;CCDDAS;4/YR
+Current Drug Delivery=Curr. Drug Delivery;CDDUBJ;4/YR
+Current Drug Discovery Technologies=Curr. Drug Discovery Technol.;CDDTAF;4/YR
+Current Drug Metabolism=Curr. Drug Metab.;CDMUBU;BM
+Current Drug Targets=Curr. Drug Targets;CDTUAU;8/YR
+Current Drug Targets: Cardiovascular & Haematological Disorders=Curr. Drug Targets: Cardiovasc. & Haematol. Disord.;CDTCBB;6/YR
+Current Drug Targets: CNS & Neurological Disorders=Curr. Drug Targets: CNS Neurol. Disord.;CDTCCC;6/YR
+Current Drug Targets: Immune, Endocrine and Metabolic Disorders=Curr. Drug Targets: Immune, Endocr. Metab. Disord.;CDTIBT;4/YR
+Current Drug Targets: Infectious Disorders=Curr. Drug Targets: Infect. Disord.;CDTIAS;Q
+Current Drug Targets: Inflammation & Allergy=Curr. Drug Targets: Inflammation Allergy;CDTICU;BM
+Current Enzyme Inhibition=Curr. Enzyme Inhib.;CEIUAG;3/YR
+Current Gene Therapy=Curr. Gene Ther.;CGTUAH;6/YR
+Current Genetics=Curr. Genet.;CUGED5;M
+Current Genomics=Curr. Genomics;CGUEA8;8/YR
+Current HIV Research=Curr. HIV Res.;CHRUBF;4/YR
+Current Immunology Reviews=Curr. Immunol. Rev.;CIRUBM;3/YR
+Current Medicinal Chemistry=Curr. Med. Chem.;CMCHE7;26/YR
+Current Medicinal Chemistry: Anti-Cancer Agents=Curr. Med. Chem.: Anti-Cancer Agents;CMCACI;BM
+Current Medicinal Chemistry: Anti-Infective Agents=Curr. Med. Chem.: Anti-Infect. Agents;CMCAFL;4/YR
+Current Medicinal Chemistry: Anti-Inflammatory & Anti-Allergy Agents=Curr. Med. Chem.: Anti-Inflammatory Anti-Allergy Agents;CMCAGM;6/YR
+Current Medicinal Chemistry: Cardiovascular & Hematological Agents=Curr. Med. Chem.: Cardiovasc. Hematol. Agents;CMCCDP;4/YR
+Current Medicinal Chemistry: Central Nervous System Agents=Curr. Med. Chem.: Cent. Nerv. Syst. Agents;CMCCCO;Q
+Current Medicinal Chemistry: Immunology, Endocrine & Metabolic Agents=Curr. Med. Chem.: Immunol., Endocr. Metab. Agents;CMCIC8;6/YR
+Current Microbiology=Curr. Microbiol.;CUMIDD;M
+Current Molecular Medicine=Curr. Mol. Med.;CMMUBP;8/yr
+Current Neuropharmacology=Curr. Neuropharmacol.;CNUEAN;Q
+Current Opinion in Biotechnology=Curr. Opin. Biotechnol.;CUOBE3;BM
+Current Opinion in Cell Biology=Curr. Opin. Cell Biol.;COCBE3;BM
+Current Opinion in Chemical Biology=Curr. Opin. Chem. Biol.;COCBF4;BM
+Current Opinion in Colloid & Interface Science=Curr. Opin. Colloid Interface Sci.;COCSFL;BM
+Current Opinion in Drug Discovery & Development=Curr. Opin. Drug Discovery Dev.;CODDFF;BM
+Current Opinion in Genetics & Development=Curr. Opin. Genet. Dev.;COGDET;BM
+Current Opinion in Immunology=Curr. Opin. Immunol.;COPIEL;BM
+Current Opinion in Lipidology=Curr. Opin. Lipidol.;COPLEU;BM
+Current Opinion in Neurobiology=Curr. Opin. Neurobiol.;COPUEN;BM
+Current Opinion in Pharmacology=Curr. Opin. Pharmacol.;COPUBK;BM
+Current Opinion in Structural Biology=Curr. Opin. Struct. Biol.;COSBEF;BM
+Current Organic Chemistry=Curr. Org. Chem.;CORCFE;18/YR
+Current Organic Synthesis=Curr. Org. Synth.;COSUC2;4/YR
+Current Pharmaceutical Analysis=Curr. Pharm. Anal.;CPAUBK;3/YR
+Current Pharmaceutical Biotechnology=Curr. Pharm. Biotechnol.;CPBUBP;BM
+Current Pharmaceutical Design=Curr. Pharm. Des.;CPDEFP;32/YR
+Current Pharmacogenomics=Curr. Pharmacogenomics;CPUHAC;Q
+Current Protein and Peptide Science=Curr. Protein Pept. Sci.;CPPSCM;BM
+Current Proteomics=Curr. Proteomics;CPURCA;4/YR
+Current Separations=Curr. Sep.;CUSEEW;IRR
+Current Topics in Medicinal Chemistry (Sharjah, United Arab Emirates)=Curr. Top. Med. Chem. (Sharjah, United Arab Emirates);CTMCCL;16/YR
+Current Vascular Pharmacology=Curr. Vasc. Pharmacol.;CVPUAY;4/YR
+Cytokine & Growth Factor Reviews=Cytokine Growth Factor Rev.;CGFRFB;BM
+Cytokine+=Cytokine+;CYTIE9;24/YR
+Dalton Transactions=Dalton Trans.;DTARAF;24/YR
+Desalination=Desalination;DSLNAH;36/YR
+Designed Monomers and Polymers=Des. Monomers Polym.;DMPOF3;6/YR
+Development (Cambridge, United Kingdom)=Development (Cambridge, U. K.);DEVPED;SM
+Developmental Biology (San Diego, CA, United States)=Dev. Biol. (San Diego, CA, U. S.);DEBIAO;SM
+Developmental Brain Research=Dev. Brain Res.;DBRRDB;14/YR
+Developmental Cell=Dev. Cell;DCEEBE;M
+Developmental Neuroscience (Basel, Switzerland)=Dev. Neurosci. (Basel, Switz.);DENED7;BM
+Developments in Biologicals (Basel, Switzerland)=Dev. Biol. (Basel, Switz.);DBEIAI;IRR
+Diabetes=Diabetes;DIAEAZ;M
+Diamond and Related Materials=Diamond Relat. Mater.;DRMTE3;M
+Dianhuaxue=Dianhuaxue;DIANFX;Q
+Differentiation (Malden, MA, United States)=Differentiation (Malden, MA, U. S.);DFFNAW;10/YR
+Diffusion and Defect Data--Solid State Data, Pt. A: Defect and Diffusion Forum=Diffus. Defect Data, Pt. A;DDAFE7;12/YR
+Diffusion and Defect Data--Solid State Data, Pt. B: Solid State Phenomena=Diffus. Defect Data, Pt. B;DDBPE8;6/YR
+Diqiu Huaxue=Diqiu Huaxue;TCHHCB;BM
+DNA and Cell Biology=DNA Cell Biol.;DCEBE8;M
+DNA Repair=DNA Repair;DRNEAR;M
+DNA Research=DNA Res.;DARSE8;6/YR
+DNA Sequence=DNA Sequence;DNSEES;BM
+Doklady Biochemistry and Biophysics=Dokl. Biochem. Biophys.;DBBOAL;BM
+Doklady Chemistry=Dokl. Chem.;DKCHAY;M
+Doklady Earth Sciences=Dokl. Earth Sci.;DESOAP;9/YR
+Doklady Physical Chemistry=Dokl. Phys. Chem.;DKPCAG;M
+Doklady Physics=Dokl. Phys.;DOPHFU;M
+Dopovidi Natsional'noi Akademii Nauk Ukraini=Dopov. Nats. Akad. Nauk Ukr.;DNAUFL;M
+Drug and Chemical Toxicology (1977)=Drug Chem. Toxicol. (1977);DCTODJ;Q
+Drug Delivery=Drug Delivery;DDELEB;BM
+Drug Development and Industrial Pharmacy=Drug Dev. Ind. Pharm.;DDIPD8;10/YR
+Drug Development Research=Drug Dev. Res.;DDREDK;M
+Drug Metabolism and Disposition=Drug Metab. Dispos.;DMDSAI;M
+Drug Metabolism and Drug Interactions=Drug Metab. Drug Interact.;DMDIEQ;Q
+Drug Metabolism and Pharmacokinetics=Drug Metab. Pharmacokinet.;DMPRB8;BM
+Dyes and Pigments=Dyes Pigm.;DYPIDX;M
+Earth and Planetary Science Letters=Earth Planet. Sci. Lett.;EPSLA2;48/YR
+Economic Geology=Econ. Geol.;EGCEA8;8/YR
+Ecotoxicology and Environmental Safety=Ecotoxicol. Environ. Saf.;EESADV;9/YR
+Ekotekhnologii i Resursosberezhenie=Ekotekhnol. Resursosberezhenie;ERKTE4;BM
+Eksperimental'naya i Klinicheskaya Farmakologiya=Eksp. Klin. Farmakol.;EKFAE9;BM
+Electroanalysis=Electroanalysis;ELANEU;24/YR
+Electrochemical and Solid-State Letters=Electrochem. Solid-State Lett.;ESLEF6;M
+Electrochemical Society Interface=Electrochem. Soc. Interface;ELSIE3;Q
+Electrochemistry (Tokyo, Japan)=Electrochemistry (Tokyo, Jpn.);EECTFA;M
+Electrochemistry Communications=Electrochem. Commun.;ECCMF9;M
+Electrochimica Acta=Electrochim. Acta;ELCAAV;SM
+Electrophoresis=Electrophoresis;ELCTDN;24/YR
+EMBO Journal=EMBO J.;EMJODG;SM
+EMBO Reports=EMBO Rep.;ERMEAX;M
+Endocrine=Endocrine;EOCRE5;9/YR
+Endocrinology=Endocrinology;ENDOAO;M
+Energy & Fuels=Energy Fuels;ENFUEM;BM
+Engineering in Life Sciences=Eng. Life Sci.;ELSNAE;BM
+Environment Protection Engineering=Environ. Prot. Eng.;EPEND9;Q
+Environmental and Molecular Mutagenesis=Environ. Mol. Mutagen.;EMMUEG;9/YR
+Environmental Chemistry=Environ. Chem.;ECNHAA;4/YR
+Environmental Chemistry Letters=Environ. Chem. Lett.;ECLNBJ;4/YR
+Environmental Engineering Science=Environ. Eng. Sci.;EESCF5;BM
+Environmental Geochemistry and Health=Environ. Geochem. Health;EGHEE3;BM
+Environmental Pollution (Amsterdam, Netherlands)=Environ. Pollut. (Amsterdam, Neth.);ENPOEK;18/YR
+Environmental Progress=Environ. Prog.;ENVPDI;4/YR
+Environmental Research=Environ. Res.;ENVRAL;9/YR
+Environmental Science and Technology=Environ. Sci. Technol.;ESTHAG;SM
+Environmental Technology=Environ. Technol.;ENVTEV;M
+Environmental Toxicology=Environ. Toxicol.;ETOXFH;BM
+Environmental Toxicology and Chemistry=Environ. Toxicol. Chem.;ETOCDK;M
+Environmental Toxicology and Pharmacology=Environ. Toxicol. Pharmacol.;ETOPFR;6/YR
+Enzyme and Microbial Technology=Enzyme Microb. Technol.;EMTED2;M
+Erdoel, Erdgas, Kohle=Erdoel, Erdgas, Kohle;EEKOEY;M
+Eukaryotic Cell=Eukaryotic Cell;ECUEA2;M
+European Cytokine Network=Eur. Cytokine Network;ECYNEJ;4/YR
+European Food Research and Technology=Eur. Food Res. Technol.;EFRTFO;M
+European Journal of Cell Biology=Eur. J. Cell Biol.;EJCBDN;M
+European Journal of Drug Metabolism and Pharmacokinetics=Eur. J. Drug Metab. Pharmacokinet.;EJDPD2;Q
+European Journal of Endocrinology=Eur. J. Endocrinol.;EJOEEP;M
+European Journal of Immunology=Eur. J. Immunol.;EJIMAF;M
+European Journal of Inorganic Chemistry=Eur. J. Inorg. Chem.;EJICFO;SM
+European Journal of Lipid Science and Technology=Eur. J. Lipid Sci. Technol.;EJLTFM;M
+European Journal of Mass Spectrometry=Eur. J. Mass Spectrom.;EJMSCL;6/YR
+European Journal of Medicinal Chemistry=Eur. J. Med. Chem.;EJMCA5;M
+European Journal of Mineralogy=Eur. J. Mineral.;EJMIER;BM
+European Journal of Organic Chemistry=Eur. J. Org. Chem.;EJOCFK;SM
+European Journal of Pharmaceutical Sciences=Eur. J. Pharm. Sci.;EPSCED;15/YR
+European Journal of Pharmacology=Eur. J. Pharmacol.;EJPHAZ;72/YR
+European Neuropsychopharmacology=Eur. Neuropsychopharmacol.;EURNE8;BM
+European Physical Journal A: Hadrons and Nuclei=Eur. Phys. J. A;EPJAFV;M
+European Physical Journal B: Condensed Matter Physics=Eur. Phys. J. B;EPJBFY;SM
+European Physical Journal C: Particles and Fields=Eur. Phys. J. C;EPCFFB;16/YR
+European Physical Journal D: Atomic, Molecular and Optical Physics=Eur. Phys. J. D;EPJDF6;M
+European Physical Journal E: Soft Matter=Eur. Phys. J. E;EPJSFH;M
+European Polymer Journal=Eur. Polym. J.;EUPJAG;M
+Europhysics Letters=Europhys. Lett.;EULEEJ;SM
+Experimental and Clinical Endocrinology & Diabetes=Exp. Clin. Endocrinol. Diabetes;ECEDFQ;10/YR
+Experimental and Molecular Medicine=Exp. Mol. Med.;EMMEF3;BM
+Experimental and Molecular Pathology=Exp. Mol. Pathol.;EXMPA6;BM
+Experimental Animals=Exp. Anim.;JIDOAA;Q
+Experimental Biology and Medicine (Maywood, NJ, United States)=Exp. Biol. Med. (Maywood, NJ, U. S.);EBMMBE;11/YR
+Experimental Cell Research=Exp. Cell Res.;ECREAL;20/YR
+Experimental Eye Research=Exp. Eye Res.;EXERA6;M
+Expert Opinion on Investigational Drugs=Expert Opin. Invest. Drugs;EOIDER;M
+Expert Opinion on Therapeutic Patents=Expert Opin. Ther. Pat.;EOTPEG;M
+Faraday Discussions=Faraday Discuss.;FDISE6;3/YR
+Farmaco=Farmaco;FRMCE8;M
+FASEB Journal=FASEB J.;FAJOEC;15/YR
+FEBS Journal=FEBS J.;FJEOAC;SM
+FEBS Letters=FEBS Lett.;FEBLAL;BW
+FEMS Immunology and Medical Microbiology=FEMS Immunol. Med. Microbiol.;FIMIEV;9/YR
+FEMS Microbiology Ecology=FEMS Microbiol. Ecol.;FMECEZ;M
+FEMS Microbiology Letters=FEMS Microbiol. Lett.;FMLED7;SM
+FEMS Microbiology Reviews=FEMS Microbiol. Rev.;FMREE4;5/YR
+FEMS Yeast Research=FEMS Yeast Res.;FYREAG;M
+Fenxi Huaxue=Fenxi Huaxue;FHHHDT;M
+Fenzi Cuihua=Fenzi Cuihua;FECUEN;BM
+Ferroelectrics=Ferroelectrics;FEROA8;16/YR
+Ferroelectrics, Letters Section=Ferroelectr., Lett. Sect.;FELEDJ;BM
+Fibre Chemistry=Fibre Chem.;FICYAP;BM
+Fire and Materials=Fire Mater.;FMATDV;BM
+Fish Physiology and Biochemistry=Fish Physiol. Biochem.;FPBIEP;4/YR
+Fisheries Science (Carlton, Australia)=Fish. Sci. (Carlton, Aust.);FSCIEH;BM
+Fizika Goreniya i Vzryva=Fiz. Goreniya Vzryva;FGVZA7;BM
+Fizika i Khimiya Obrabotki Materialov=Fiz. Khim. Obrab. Mater.;FKOMAT;BM
+Fizika Metallov i Metallovedenie=Fiz. Met. Metalloved.;FMMTAK;M
+Fluid Phase Equilibria=Fluid Phase Equilib.;FPEQDT;15/YR
+Folia Microbiologica (Prague, Czech Republic)=Folia Microbiol. (Prague, Czech Repub.);FOMIAZ;BM
+Food Additives & Contaminants=Food Addit. Contam.;FACOEB;M
+Food and Chemical Toxicology=Food Chem. Toxicol.;FCTOD7;M
+Food Chemistry=Food Chem.;FOCHDJ;20/YR
+Food Hydrocolloids=Food Hydrocolloids;FOHYES;BM
+Free Radical Biology & Medicine=Free Radical Biol. Med.;FRBMEH;24/YR
+Free Radical Research=Free Radical Res.;FRARER;M
+Fresenius Environmental Bulletin=Fresenius Environ. Bull.;FENBEL;M
+Fuel=Fuel;FUELAC;15/YR
+Fuel Cells (Weinheim, Germany)=Fuel Cells (Weinheim, Ger.);FUCEFK;4/YR
+Fuel Processing Technology=Fuel Process. Technol.;FPTEDY;15/YR
+Fullerenes, Nanotubes, and Carbon Nanostructures=Fullerenes, Nanotubes, Carbon Nanostruct.;FNCNAR;Q
+Functional & Integrative Genomics=Funct. Integr. Genomics;FIGUBY;Q
+Fundamental & Clinical Pharmacology=Fundam. Clin. Pharmacol.;FCPHEZ;BM
+Funtai oyobi Funmatsu Yakin=Funtai oyobi Funmatsu Yakin;FOFUA2;M
+Fusion Engineering and Design=Fusion Eng. Des.;FEDEEE;24/YR
+Fusion Science and Technology=Fusion Sci. Technol.;FSTUCY;7/YR
+Ganguang Kexue Yu Guang Huaxue=Ganguang Kexue Yu Guang Huaxue;GKKHE9;BM
+Gaodeng Xuexiao Huaxue Xuebao=Gaodeng Xuexiao Huaxue Xuebao;KTHPDM;M
+Gaofenzi Cailiao Kexue Yu Gongcheng=Gaofenzi Cailiao Kexue Yu Gongcheng;GCKGEI;BM
+Gaofenzi Xuebao=Gaofenzi Xuebao;GAXUE9;BM
+Gaoneng Wuli Yu Hewuli=Gaoneng Wuli Yu Hewuli;KNWLD9;M
+Gaoxiao Huaxue Gongcheng Xuebao=Gaoxiao Huaxue Gongcheng Xuebao;GHGXEG;BM
+Gene=Gene;GENED6;42/YR
+Gene Expression Patterns=Gene Expression Patterns;GEPEAD;6/YR
+Gene Therapy=Gene Ther.;GETHEC;SM
+Gene Therapy and Regulation=Gene Ther. Regul.;GTREBR;IRR
+General and Comparative Endocrinology=Gen. Comp. Endocrinol.;GCENA5;15/YR
+Genes & Development=Genes Dev.;GEDEEP;SM
+Genes to Cells=Genes Cells;GECEFL;M
+Genes, Chromosomes & Cancer=Genes, Chromosomes Cancer;GCCAES;12/YR
+Genome Research=Genome Res.;GEREFS;M
+Genomics=Genomics;GNMCEP;M
+Geochemical Journal=Geochem. J.;GEJOBE;BM
+Geochimica et Cosmochimica Acta=Geochim. Cosmochim. Acta;GCACAK;SM
+Geokhimiya=Geokhimiya;GEOKAQ;M
+Glass Physics and Chemistry=Glass Phys. Chem.;GPHCEE;BM
+Glass Science and Technology (Offenbach, Germany)=Glass Sci. Technol. (Offenbach, Ger.);GSTEEX;BM
+Glass Technology=Glass Technol.;GLSTAK;BM
+GlassResearcher=GlassResearcher;GRESER;SA
+Global Biogeochemical Cycles=Global Biogeochem. Cycles;GBCYEP;Q
+Glycobiology=Glycobiology;GLYCE3;M
+Glycoconjugate Journal=Glycoconjugate J.;GLJOEW;9/YR
+Gongneng Gaofenzi Xuebao=Gongneng Gaofenzi Xuebao;GGXUEH;Q
+Ground Water=Ground Water;GRWAAP;BM
+Growth Factors=Growth Factors;GRFAEC;Q
+Guangpuxue Yu Guangpu Fenxi=Guangpuxue Yu Guangpu Fenxi;GYGFED;M
+Guijinshu=Guijinshu;GUIJE7;Q
+Guisuanyan Xuebao=Guisuanyan Xuebao;KSYHA5;M
+Guocheng Gongcheng Xuebao=Guocheng Gongcheng Xuebao;CJPEB5;BM
+Health Physics=Health Phys.;HLTPAO;M
+Heat Transfer Engineering=Heat Transfer Eng.;HTEND2;8/YR
+Hecheng Xiangjiao Gongye=Hecheng Xiangjiao Gongye;HXGOEA;BM
+Helvetica Chimica Acta=Helv. Chim. Acta;HCACAV;M
+Hemoglobin=Hemoglobin;HEMOD8;Q
+Heteroatom Chemistry=Heteroat. Chem.;HETCE8;7/YR
+Heterocycles=Heterocycles;HTCYAM;14/YR
+Heterocyclic Communications=Heterocycl. Commun.;HCOMEX;BM
+High Energy Chemistry=High Energy Chem.;HIECAP;BM
+High Performance Polymers=High Perform. Polym.;HPPOEX;Q
+High Temperature=High Temp.;HITEA4;BM
+High Temperature Materials and Processes (London, United Kingdom)=High Temp. Mater. Processes (London, U. K.);HTMPEF;6/YR
+High Temperatures - High Pressures=High Temp. - High Pressures;HTHPAK;BM
+Histochemistry and Cell Biology=Histochem. Cell Biol.;HCBIFP;M
+Holzforschung=Holzforschung;HOLZAZ;BM
+Hormone and Metabolic Research=Horm. Metab. Res.;HMMRA2;M
+Hormone Research=Horm. Res.;HRMRA3;M
+Huadong Ligong Daxue Xuebao, Ziran Kexueban=Huadong Ligong Daxue Xuebao, Ziran Kexueban;HLIXEV;BM
+Huagong Xuebao (Chinese Edition)=Huagong Xuebao (Chin. Ed.);HUKHAI;M
+Huanjing Huaxue=Huanjing Huaxue;HUHUDB;BM
+Huanjing Kexue Xuebao=Huanjing Kexue Xuebao;HKXUDL;M
+Huaxue=Huaxue;HUHSA2;Q
+Huaxue Fanying Gongcheng Yu Gongyi=Huaxue Fanying Gongcheng Yu Gongyi;HFGGEU;BM
+Huaxue Shiji=Huaxue Shiji;HUSHDR;M
+Huaxue Tongbao=Huaxue Tongbao;HHTPAU;M
+Huaxue Wuli Xuebao=Huaxue Wuli Xuebao;HWXUE4;BM
+Huaxue Xuebao=Huaxue Xuebao;HHHPA4;SM
+Human Gene Therapy=Hum. Gene Ther.;HGTHE3;M
+Human Molecular Genetics=Hum. Mol. Genet.;HMGEE5;26/YR
+Hungarian Journal of Industrial Chemistry=Hung. J. Ind. Chem.;HJICAI;4/YR
+Hwahak Konghak=Hwahak Konghak;HHKHAT;BM
+Hydrometallurgy=Hydrometallurgy;HYDRDA;M
+Hyperfine Interactions=Hyperfine Interact.;HYINDN;28/YR
+Hypertension=Hypertension;HPRTDN;M
+IEEE Journal of Quantum Electronics=IEEE J. Quantum Electron.;IEJQA7;M
+IEEE Journal of Selected Topics in Quantum Electronics=IEEE J. Sel. Top. Quantum Electron.;IJSQEN;BM
+ILAR Journal=ILAR J.;IJLOAC;Q
+Immunity=Immunity;IUNIEH;M
+Immunobiology=Immunobiology;IMMND4;IRR
+Immunology=Immunology;IMMUAM;M
+Immunology Letters=Immunol. Lett.;IMLED6;15/YR
+Indian Chemical Engineer=Indian Chem. Eng.;ICENFW;Q
+Indian Journal of Biochemistry & Biophysics=Indian J. Biochem. Biophys.;IJBBBQ;BM
+Indian Journal of Chemical Technology=Indian J. Chem. Technol.;ICHTEU;BM
+Anal. Chem. Indian Journal of Chemistry, Section A: Inorganic, Bio-inorganic, Physical, Theoretical & Analytical Chemistry=Indian J. Chem., Sect. A: Inorg., Bio-inorg., Phys., Theor.;ICACEC;M
+Indian Journal of Chemistry, Section B: Organic Chemistry Including Medicinal Chemistry=Indian J. Chem., Sect. B: Org. Chem. Incl. Med. Chem.;IJSBDB;M
+Indian Journal of Fibre & Textile Research=Indian J. Fibre Text. Res.;IJFRET;Q
+Indian Journal of Heterocyclic Chemistry=Indian J. Heterocycl. Chem.;IJCHEI;Q
+Indian Journal of Physics=Indian J. Phys.;IJPNCV;M
+Indian Journal of Pure and Applied Physics=Indian J. Pure Appl. Phys.;IJOPAU;M
+Industrial & Engineering Chemistry Research=Ind. Eng. Chem. Res.;IECRED;BW
+Infection and Immunity=Infect. Immun.;INFIBR;M
+Inflammation Research=Inflammation Res.;INREFB;M
+Inhalation Toxicology=Inhalation Toxicol.;INHTE5;14/YR
+Inorganic Chemistry=Inorg. Chem.;INOCAJ;BW
+Inorganic Chemistry Communications=Inorg. Chem. Commun.;ICCOFP;M
+Inorganic Materials=Inorg. Mater.;INOMAF;M
+Inorganic Reaction Mechanisms (Philadelphia, PA, United States)=Inorg. React. Mech. (Philadelphia, PA, U. S.);IRMEFE;4/YR
+Inorganica Chimica Acta=Inorg. Chim. Acta;ICHAA3;15/YR
+Insect Biochemistry and Molecular Biology=Insect Biochem. Mol. Biol.;IBMBES;M
+Insect Molecular Biology=Insect Mol. Biol.;IMBIE3;BM
+Instrumentation Science & Technology=Instrum. Sci. Technol.;ISCTEF;6/YR
+Intermetallics=Intermetallics;IERME5;M
+International DATA Series, Selected Data on Mixtures, Series A: Thermodynamic Properties of Non-Reacting Binary Systems of Organic Substances=Int. DATA Ser., Sel. Data Mixtures, Ser. A;ISDMAT;Q
+International Immunology=Int. Immunol.;INIMEN;M
+International Immunopharmacology=Int. Immunopharmacol.;IINMBA;M
+International Journal for Vitamin and Nutrition Research=Int. J. Vitam. Nutr. Res.;IJVNAP;BM
+International Journal of Adhesion and Adhesives=Int. J. Adhes. Adhes.;IJAADK;BM
+International Journal of Antimicrobial Agents=Int. J. Antimicrob. Agents;IAAGEA;M
+International Journal of Applied Ceramic Technology=Int. J. Appl. Ceram. Technol.;IJACCP;BM
+International Journal of Biochemistry & Cell Biology=Int. J. Biochem. Cell Biol.;IJBBFU;M
+International Journal of Biological Macromolecules=Int. J. Biol. Macromol.;IJBMDR;9/YR
+International Journal of Cancer=Int. J. Cancer;IJCNAW;30/YR
+International Journal of Chemical Kinetics=Int. J. Chem. Kinet.;IJCKBO;M
+International Journal of Chemistry=Int. J. Chem.;INJCEW;Q
+International Journal of Coal Geology=Int. J. Coal Geol.;IJCGDE;M
+International Journal of Environment and Pollution=Int. J. Environ. Pollut.;IJVLEN;12/YR
+International Journal of Environmental Analytical Chemistry=Int. J. Environ. Anal. Chem.;IJEAA3;15/YR
+International Journal of Food Science and Technology=Int. J. Food Sci. Technol.;IJFTEZ;10/YR
+International Journal of Hydrogen Energy=Int. J. Hydrogen Energy;IJHEDX;15/YR
+International Journal of Immunogenetics=Int. J. Immunogenet.;IJINCU;BM
+International Journal of Mass Spectrometry=Int. J. Mass Spectrom.;IMSPF8;SM
+International Journal of Mineral Processing=Int. J. Miner. Process.;IJMPBL;M
+International Journal of Multiphase Flow=Int. J. Multiphase Flow;IJMFBP;M
+International Journal of Nanoscience=Int. J. Nanosci.;IJNNAJ;BM
+International Journal of Non-Equilibrium Processing=Int. J. Non-Equilib. Process.;IJNPFU;IRR
+International Journal of Peptide Research and Therapeutics=Int. J. Pept. Res. Ther.;IJPRFC;Q
+International Journal of Pharmaceutics=Int. J. Pharm.;IJPHDE;38/YR
+International Journal of PIXE=Int. J. PIXE;IJPXET;2/YR
+International Journal of Polymer Analysis and Characterization=Int. J. Polym. Anal. Charact.;IPACEZ;BM
+International Journal of Polymeric Materials=Int. J. Polym. Mater.;IJPMCS;M
+International Journal of Powder Metallurgy (Princeton, New Jersey)=Int. J. Powder Metall. (Princeton, N. J.);IPMTEA;BM
+International Journal of Quantum Chemistry=Int. J. Quantum Chem.;IJQCB2;30/YR
+International Journal of Radiation Biology=Int. J. Radiat. Biol.;IJRBE7;M
+International Journal of Refractory Metals & Hard Materials=Int. J. Refract. Met. Hard Mater.;IRMME3;BM
+International Journal of Thermophysics=Int. J. Thermophys.;IJTHDY;BM
+International Materials Reviews=Int. Mater. Rev.;INMREO;BM
+International Polymer Processing=Int. Polym. Process.;IPPREJ;Q
+International Reviews in Physical Chemistry=Int. Rev. Phys. Chem.;IRPCDL;Q
+Ionics=Ionics;IONIFA;BM
+Ironmaking and Steelmaking=Ironmaking Steelmaking;IMKSB7;BM
+ISIJ International=ISIJ Int.;IINTEY;M
+Isotopes in Environmental and Health Studies=Isot. Environ. Health Stud.;IEHSF8;4/YR
+Israel Journal of Chemistry=Isr. J. Chem.;ISJCAT;Q
+Italian Journal of Biochemistry=Ital. J. Biochem.;IJBIAC;Q
+IUBMB Life=IUBMB Life;IULIF8;M
+Izvestiya Natsional'noi Akademii Nauk Respubliki Kazakhstan, Seriya Khimicheskaya=Izv. Nats. Akad. Nauk Resp. Kaz., Ser. Khim.;INANDJ;BM
+Izvestiya Rossiiskoi Akademii Nauk, Seriya Fizicheskaya=Izv. Ross. Akad. Nauk, Ser. Fiz.;IRAFEO;M
+Izvestiya Vysshikh Uchebnykh Zavedenii, Khimiya i Khimicheskaya Tekhnologiya=Izv. Vyssh. Uchebn. Zaved., Khim. Khim. Tekhnol.;IVUKAR;9/YR
+Izvestiya Vysshikh Uchebnykh Zavedenii, Tsvetnaya Metallurgiya=Izv. Vyssh. Uchebn. Zaved., Tsvetn. Metall.;IVUTAK;6/YR
+JAMA, the Journal of the American Medical Association=JAMA, J. Am. Med. Assoc.;JAMAAP;48/YR
+Japanese Journal of Applied Physics, Part 1: Regular Papers, Brief Communications & Review Papers=Jpn. J. Appl. Phys., Part 1;JAPNDE;M
+Japanese Journal of Applied Physics, Part 2: Letters & Express Letters=Jpn. J. Appl. Phys., Part 2;JAPLD8;SM
+JBIC, Journal of Biological Inorganic Chemistry=JBIC, J. Biol. Inorg. Chem.;JJBCFA;8/YR
+JCT Research=JCT Res.;JRCEB5;Q
+JETP Letters=JETP Lett.;JTPLA2;SM
+Jiegou Huaxue=Jiegou Huaxue;JHUADF;M
+Jinshu Xuebao=Jinshu Xuebao;CHSPA4;M
+Jisuanji Yu Yingyong Huaxue=Jisuanji Yu Yingyong Huaxue;JYYHE6;M
+Journal - American Water Works Association=J. - Am. Water Works Assoc.;JAWWA5;M
+Journal de Pharmacie de Belgique=J. Pharm. Belg.;JPBEAJ;4/YR
+Journal of Adhesion=J. Adhes.;JADNAJ;M
+Journal of Adhesion Science and Technology=J. Adhes. Sci. Technol.;JATEE8;16/YR
+Journal of Advances in Chemical Physics=J. Adv. Chem. Phys.;JACPCM;M
+Journal of Aerosol Science=J. Aerosol Sci.;JALSB7;13/YR
+Journal of Agricultural and Food Chemistry=J. Agric. Food Chem.;JAFCAU;BW
+Journal of Alloys and Compounds=J. Alloys Compd.;JALCEU;36/YR
+Journal of Analytical and Applied Pyrolysis=J. Anal. Appl. Pyrolysis;JAAPDD;BM
+Journal of Analytical Atomic Spectrometry=J. Anal. At. Spectrom.;JASPE2;M
+Journal of Analytical Chemistry=J. Anal. Chem.;JACTE2;M
+Journal of Analytical Toxicology=J. Anal. Toxicol.;JATOD3;8/YR
+Journal of Animal Science (Savoy, IL, United States)=J. Anim. Sci. (Savoy, IL, U. S.);JANSAG;M
+Journal of Antibiotics=J. Antibiot.;JANTAJ;M
+Journal of Antimicrobial Chemotherapy=J. Antimicrob. Chemother.;JACHDX;M
+Journal of AOAC International=J. AOAC Int.;JAINEE;BM
+Journal of Applied Animal Welfare Science=J. Appl. Anim. Welfare Sci.;JAAWAV;Q
+Journal of Applied Crystallography=J. Appl. Crystallogr.;JACGAR;BM
+Journal of Applied Electrochemistry=J. Appl. Electrochem.;JAELBJ;M
+Journal of Applied Physics=J. Appl. Phys.;JAPIAU;SM
+Journal of Applied Polymer Science=J. Appl. Polym. Sci.;JAPNAB;SM
+Journal of Applied Spectroscopy=J. Appl. Spectrosc.;JASYAP;BM
+Journal of Applied Toxicology=J. Appl. Toxicol.;JJATDK;BM
+Journal of Atmospheric Chemistry=J. Atmos. Chem.;JATCE2;9/YR
+Journal of Automated Methods & Management in Chemistry=J. Autom. Methods Manage. Chem.;JAMCF2;BM
+Journal of Bacteriology=J. Bacteriol.;JOBAAY;SM
+Journal of Biochemical and Biophysical Methods=J. Biochem. Biophys. Methods;JBBMDG;M
+Journal of Biochemical and Molecular Toxicology=J. Biochem. Mol. Toxicol.;JBMTFQ;BM
+Journal of Biochemistry (Tokyo, Japan)=J. Biochem. (Tokyo, Jpn.);JOBIAO;M
+Journal of Biochemistry and Molecular Biology=J. Biochem. Mol. Biol.;JBMBE5;BM
+Journal of Bioenergetics and Biomembranes=J. Bioenerg. Biomembr.;JBBID4;BM
+Journal of Biological Chemistry=J. Biol. Chem.;JBCHA3;W
+Journal of Biomaterials Science, Polymer Edition=J. Biomater. Sci., Polym. Ed.;JBSEEA;M
+Journal of Biomedical Materials Research, Part A=J. Biomed. Mater. Res., Part A;JBMRCH;16/YR
+Journal of Biomedical Materials Research, Part B: Applied Biomaterials=J. Biomed. Mater. Res., Part B;JBMRGL;8/YR
+Journal of Biomedical Nanotechnology=J. Biomed. Nanotechnol.;JBNOAB;Q
+Journal of Biomolecular NMR=J. Biomol. NMR;JBNME9;M
+Journal of Biomolecular Structure & Dynamics=J. Biomol. Struct. Dyn.;JBSDD6;BM
+Journal of Bioscience and Bioengineering=J. Biosci. Bioeng.;JBBIF6;M
+Journal of Biotechnology=J. Biotechnol.;JBITD4;SM
+Journal of Capillary Electrophoresis and Microchip Technology=J. Capillary Electrophor. Microchip Technol.;JCEMF6;6/YR
+Journal of Carbohydrate Chemistry=J. Carbohydr. Chem.;JCACDM;9/YR
+Journal of Cardiovascular Pharmacology=J. Cardiovasc. Pharmacol.;JCPCDT;M
+Journal of Catalysis=J. Catal.;JCTLA5;16/YR
+Journal of Cell Biology=J. Cell Biol.;JCLBA3;BW
+Journal of Cell Science=J. Cell Sci.;JNCSAI;24/YR
+Journal of Cellular Biochemistry=J. Cell. Biochem.;JCEBD5;18/YR
+Journal of Cellular Physiology=J. Cell. Physiol.;JCLLAX;M
+Journal of Chemical and Engineering Data=J. Chem. Eng. Data;JCEAAX;BM
+Journal of Chemical Crystallography=J. Chem. Crystallogr.;JCCYEV;M
+Journal of Chemical Ecology=J. Chem. Ecol.;JCECD8;M
+Journal of Chemical Education=J. Chem. Educ.;JCEDA8;M
+Journal of Chemical Engineering of Japan=J. Chem. Eng. Jpn.;JCEJAQ;M
+Journal of Chemical Information and Modeling=J. Chem. Inf. Model.;JCISD8;BM
+Journal of Chemical Physics=J. Chem. Phys.;JCPSA6;48/YR
+Journal of Chemical Research=J. Chem. Res.;JCROA4;M
+Journal of Chemical Sciences (Bangalore, India)=J. Chem. Sci. (Bangalore, India);JCSBB5;BM
+Journal of Chemical Technology and Biotechnology=J. Chem. Technol. Biotechnol.;JCTBED;M
+Journal of Chemical Theory and Computation=J. Chem. Theory Comput.;JCTCCE;BM
+Journal of Chemical Thermodynamics=J. Chem. Thermodyn.;JCTDAF;M
+Journal of Chemometrics=J. Chemom.;JOCHEU;M
+Journal of Chromatographic Science=J. Chromatogr. Sci.;JCHSBZ;10/YR
+Journal of Chromatography, A=J. Chromatogr., A;JCRAEY;78/YR
+Journal of Chromatography, B: Analytical Technologies in the Biomedical and Life Sciences=J. Chromatogr., B: Anal. Technol. Biomed. Life Sci.;JCBAAI;23/YR
+Journal of Clinical Endocrinology and Metabolism=J. Clin. Endocrinol. Metab.;JCEMAZ;M
+Journal of Clinical Investigation=J. Clin. Invest.;JCINAO;M
+Journal of Cluster Science=J. Cluster Sci.;JCSCEB;Q
+Journal of Colloid and Interface Science=J. Colloid Interface Sci.;JCISA5;SM
+Journal of Combinatorial Chemistry=J. Comb. Chem.;JCCHFF;BM
+Journal of Computational and Theoretical Nanoscience=J. Comput. Theor. Nanosci.;JCTNAB;4/YR
+Journal of Computational Biology=J. Comput. Biol.;JCOBEM;10/yr
+Journal of Computational Chemistry=J. Comput. Chem.;JCCHDD;16/YR
+Journal of Computer Chemistry, Japan=J. Comput. Chem., Jpn.;JCCJAG;Q
+Journal of Computer-Aided Molecular Design=J. Comput.-Aided Mol. Des.;JCADEQ;M
+Journal of Contaminant Hydrology=J. Contam. Hydrol.;JCOHE6;32/YR
+Journal of Controlled Release=J. Controlled Release;JCREEC;24/yr
+Journal of Coordination Chemistry=J. Coord. Chem.;JCCMBQ;18/YR
+Journal of Crystal Growth=J. Cryst. Growth;JCRGAE;SM
+Journal of Dairy Research=J. Dairy Res.;JDRSAN;Q
+Journal of Dairy Science=J. Dairy Sci.;JDSCAE;M
+Journal of Dispersion Science and Technology=J. Dispersion Sci. Technol.;JDTEDS;BM
+Journal of Drug Targeting=J. Drug Targeting;JDTAEH;10/YR
+Journal of Electroanalytical Chemistry=J. Electroanal. Chem.;JECHES;26/YR
+Journal of Electron Spectroscopy and Related Phenomena=J. Electron Spectrosc. Relat. Phenom.;JESRAW;21/YR
+Journal of Electronic Materials=J. Electron. Mater.;JECMA5;M
+Journal of Endocrinology=J. Endocrinol.;JOENAK;M
+Journal of Endotoxin Research=J. Endotoxin Res.;JENREB;BM
+Journal of Energetic Materials=J. Energ. Mater.;JOEMDK;Q
+Journal of Environmental Engineering (Reston, VA, United States)=J. Environ. Eng. (Reston, VA, U. S.);JOEEDU;M
+Journal of Environmental Monitoring=J. Environ. Monit.;JEMOFW;M
+Journal of Environmental Quality=J. Environ. Qual.;JEVQAA;BM
+Journal of Environmental Radioactivity=J. Environ. Radioact.;JERAEE;21/YR
+Journal of Environmental Science & Engineering=J. Environ. Sci. Eng.;JESEAR;Q
+Environ. Eng. Journal of Environmental Science and Health, Part A: Toxic/Hazardous Substances & Environmental Engineering=J. Environ. Sci. Health, Part A: Toxic/Hazard. Subst.;JATEF9;M
+Journal of Environmental Science and Health, Part B: Pesticides, Food Contaminants, and Agricultural Wastes=J. Environ. Sci. Health, Part B;JPFCD2;BM
+Journal of Enzyme Inhibition and Medicinal Chemistry=J. Enzyme Inhib. Med. Chem.;JEIMAZ;BM
+Journal of Experimental and Theoretical Physics=J. Exp. Theor. Phys.;JTPHES;M
+Journal of Experimental Animal Science=J. Exp. Anim. Sci.;JEXSEU;4/YR
+Journal of Experimental Botany=J. Exp. Bot.;JEBOA6;M
+Journal of Experimental Medicine=J. Exp. Med.;JEMEAV;SM
+Journal of Fluorine Chemistry=J. Fluorine Chem.;JFLCAR;M
+Journal of Food Science=J. Food Sci.;JFDSAZ;9/YR
+Journal of Fusion Energy=J. Fusion Energy;JFENDS;Q
+Journal of General and Applied Microbiology=J. Gen. Appl. Microbiol.;JGAMA9;BM
+Journal of General Virology=J. Gen. Virol.;JGVIAY;M
+Journal of Genome Science and Technology=J. Genome Sci. Technol.;JGSTAI;Q
+Journal of Geochemical Exploration=J. Geochem. Explor.;JGCEAT;BM
+Journal of Hazardous Materials=J. Hazard. Mater.;JHMAD9;21/YR
+Journal of Heterocyclic Chemistry=J. Heterocycl. Chem.;JHTCAD;BM
+Journal of Histochemistry and Cytochemistry=J. Histochem. Cytochem.;JHCYAS;M
+Journal of Hypertension=J. Hypertens.;JOHYD3;M
+Journal of Imaging Science and Technology=J. Imaging Sci. Technol.;JIMTE6;BM
+Journal of Immunoassay & Immunochemistry=J. Immunoassay Immunochem.;JIIOAZ;Q
+Journal of Immunological Methods=J. Immunol. Methods;JIMMBG;M
+Journal of Immunology=J. Immunol.;JOIMA3;SM
+Journal of Inclusion Phenomena and Macrocyclic Chemistry=J. Inclusion Phenom. Macrocyclic Chem.;JIPCF5;M
+Journal of Industrial and Engineering Chemistry (Seoul, Republic of Korea)=J. Ind. Eng. Chem. (Seoul, Repub. Korea);JIECFI;BM
+Journal of Industrial Microbiology & Biotechnology=J. Ind. Microbiol. Biotechnol.;JIMBFL;M
+Journal of Inorganic and Organometallic Polymers and Materials=J. Inorg. Organomet. Polym. Mater.;JIOPAY;Q
+Journal of Inorganic Biochemistry=J. Inorg. Biochem.;JIBIDJ;M
+Journal of Insect Physiology=J. Insect Physiol.;JIPHAF;M
+Journal of Interferon & Cytokine Research=J. Interferon Cytokine Res.;JICRFJ;M
+Journal of Investigative Dermatology=J. Invest. Dermatol.;JIDEAE;M
+Journal of Labelled Compounds & Radiopharmaceuticals=J. Labelled Compd. Radiopharm.;JLCRD4;14/YR
+Journal of Leukocyte Biology=J. Leukocyte Biol.;JLBIE7;M
+Journal of Lipid Research=J. Lipid Res.;JLPRAW;M
+Journal of Liquid Chromatography & Related Technologies=J. Liq. Chromatogr. Relat. Technol.;JLCTFC;20/YR
+Journal of Low Temperature Physics=J. Low Temp. Phys.;JLTPAC;M
+Journal of Luminescence=J. Lumin.;JLUMA8;20/YR
+Journal of Macromolecular Science, Part A: Pure and Applied Chemistry=J. Macromol. Sci., Part A: Pure Appl. Chem.;JSPCE6;M
+Journal of Macromolecular Science, Part B: Physics=J. Macromol. Sci., Part B: Phys.;JMAPBR;BM
+Journal of Macromolecular Science, Polymer Reviews=J. Macromol. Sci., Polym. Rev.;JMSPCG;Q
+Journal of Magnetic Resonance=J. Magn. Reson.;JMARF3;M
+Journal of Magnetism and Magnetic Materials=J. Magn. Magn. Mater.;JMMMDC;45/YR
+Journal of Mass Spectrometry=J. Mass Spectrom.;JMSPFJ;M
+Journal of Materials Chemistry=J. Mater. Chem.;JMACEP;48/YR
+Journal of Materials Engineering and Performance=J. Mater. Eng. Perform.;JMEPEG;BM
+Journal of Materials Research=J. Mater. Res.;JMREEE;M
+Journal of Materials Science=J. Mater. Sci.;JMTSAS;SM
+Journal of Materials Science: Materials in Electronics=J. Mater. Sci.: Mater. Electron.;JSMEEV;M
+Journal of Materials Science: Materials in Medicine=J. Mater. Sci.: Mater. Med.;JSMMEL;M
+Journal of Mathematical Chemistry=J. Math. Chem.;JMCHEG;8/YR
+Journal of Medicinal Chemistry=J. Med. Chem.;JMCMAR;BW
+Journal of Membrane Biology=J. Membr. Biol.;JMBBBO;18/YR
+Journal of Membrane Science=J. Membr. Sci.;JMESDO;36/YR
+Journal of Microencapsulation=J. Microencapsulation;JOMIEF;8/YR
+Journal of Molecular and Cellular Cardiology=J. Mol. Cell. Cardiol.;JMCDAY;M
+Journal of Molecular Biology=J. Mol. Biol.;JMOBAK;50/YR
+Journal of Molecular Catalysis A: Chemical=J. Mol. Catal. A: Chem.;JMCCF2;SM
+Journal of Molecular Catalysis B: Enzymatic=J. Mol. Catal. B: Enzym.;JMCEF8;8/YR
+Journal of Molecular Endocrinology=J. Mol. Endocrinol.;JMLEEI;BM
+Journal of Molecular Evolution=J. Mol. Evol.;JMEVAU;M
+Journal of Molecular Graphics & Modelling=J. Mol. Graphics Modell.;JMGMFI;BM
+Journal of Molecular Liquids=J. Mol. Liq.;JMLIDT;21/YR
+Journal of Molecular Microbiology and Biotechnology=J. Mol. Microbiol. Biotechnol.;JMMBFF;8/YR
+Journal of Molecular Neuroscience=J. Mol. Neurosci.;JMNEES;BM
+Journal of Molecular Recognition=J. Mol. Recognit.;JMORE4;BM
+Journal of Molecular Spectroscopy=J. Mol. Spectrosc.;JMOSA3;M
+Journal of Molecular Structure=J. Mol. Struct.;JMOSB4;66/YR
+Journal of Nanoscience and Nanotechnology=J. Nanosci. Nanotechnol.;JNNOAR;M
+Journal of Natural Gas Chemistry=J. Nat. Gas Chem.;JGCHE8;Q
+Journal of Natural Products=J. Nat. Prod.;JNPRDF;M
+Journal of Near Infrared Spectroscopy=J. Near Infrared Spectrosc.;JNISEI;BM
+Journal of Neurochemistry=J. Neurochem.;JONRA9;SM
+Journal of Neuroendocrinology=J. Neuroendocrinol.;JOUNE2;M
+Journal of Neuroimmunology=J. Neuroimmunol.;JNRIDW;24/YR
+Journal of Neuroscience=J. Neurosci.;JNRSDS;W
+Journal of Neuroscience Research=J. Neurosci. Res.;JNREDK;SM
+Journal of Non-Crystalline Solids=J. Non-Cryst. Solids;JNCSBJ;54/YR
+Journal of Non-Newtonian Fluid Mechanics=J. Non-Newtonian Fluid Mech.;JNFMDI;24/YR
+Journal of Nuclear Materials=J. Nucl. Mater.;JNUMAM;36/YR
+Journal of Nuclear Science and Technology (Tokyo, Japan)=J. Nucl. Sci. Technol. (Tokyo, Jpn.);JNSTAX;M
+Journal of Nutrition=J. Nutr.;JONUAI;M
+Journal of Nutritional Biochemistry=J. Nutr. Biochem.;JNBIEL;M
+Journal of Nutritional Science and Vitaminology=J. Nutr. Sci. Vitaminol.;JNSVA5;BM
+Journal of Ocular Pharmacology and Therapeutics=J. Ocul. Pharmacol. Ther.;JOPTFU;BM
+Journal of Oleo Science=J. Oleo Sci.;JOSOAP;M
+Journal of Organic Chemistry=J. Org. Chem.;JOCEAH;BW
+Journal of Organometallic Chemistry=J. Organomet. Chem.;JORCAI;BW
+Journal of Peptide Research=J. Pept. Res.;JPERFA;M
+Journal of Peptide Science=J. Pept. Sci.;JPSIEI;M
+Journal of Petroleum Science & Engineering=J. Pet. Sci. Eng.;JPSEE6;8/YR
+Journal of Petrology=J. Petrol.;JPTGAD;M
+Journal of Pharmaceutical and Biomedical Analysis=J. Pharm. Biomed. Anal.;JPBADA;15/YR
+Journal of Pharmaceutical Sciences=J. Pharm. Sci.;JPMSAE;M
+Journal of Pharmacological and Toxicological Methods=J. Pharmacol. Toxicol. Methods;JPTMEZ;BM
+Journal of Pharmacological Sciences (Tokyo, Japan)=J. Pharmacol. Sci. (Tokyo, Jpn.);JPSTGJ;M
+Journal of Pharmacology and Experimental Therapeutics=J. Pharmacol. Exp. Ther.;JPETAB;M
+Journal of Pharmacy and Pharmacology=J. Pharm. Pharmacol.;JPPMAB;M
+Journal of Phase Equilibria and Diffusion=J. Phase Equilib. Diffus.;JPEDAV;BM
+Journal of Photochemistry and Photobiology, A: Chemistry=J. Photochem. Photobiol., A;JPPCEJ;30/YR
+Journal of Photochemistry and Photobiology, B: Biology=J. Photochem. Photobiol., B;JPPBEG;M
+Journal of Photochemistry and Photobiology, C: Photochemistry Reviews=J. Photochem. Photobiol., C;JPPCAF;4/YR
+Journal of Photopolymer Science and Technology=J. Photopolym. Sci. Technol.;JSTEEW;5/YR
+Journal of Physical and Chemical Reference Data=J. Phys. Chem. Ref. Data;JPCRBU;Q
+Journal of Physical Chemistry A=J. Phys. Chem. A;JPCAFH;W
+Journal of Physical Chemistry B=J. Phys. Chem. B;JPCBFK;W
+Journal of Physical Organic Chemistry=J. Phys. Org. Chem.;JPOCEE;M
+Journal of Physics and Chemistry of Solids=J. Phys. Chem. Solids;JPCSAW;M
+Journal of Physics B: Atomic, Molecular and Optical Physics=J. Phys. B: At., Mol. Opt. Phys.;JPAPEH;SM
+Journal of Physics D: Applied Physics=J. Phys. D: Appl. Phys.;JPAPBE;SM
+Journal of Physics G: Nuclear and Particle Physics=J. Phys. G: Nucl. Part. Phys.;JPGPED;M
+Journal of Physics: Condensed Matter=J. Phys.: Condens. Matter;JCOMEL;50/YR
+Journal of Physiology (Oxford, United Kingdom)=J. Physiol. (Oxford, U. K.);JPHYA7;SM
+Journal of Pineal Research=J. Pineal Res.;JPRSE9;8/YR
+Journal of Planar Chromatography--Modern TLC=J. Planar Chromatogr.--Mod. TLC;JPCTE5;BM
+Journal of Plant Growth Regulation=J. Plant Growth Regul.;JPGRDI;Q
+Journal of Plant Nutrition=J. Plant Nutr.;JPNUDS;M
+Journal of Plant Nutrition and Soil Science=J. Plant Nutr. Soil Sci.;JNSSFZ;BM
+Journal of Plant Physiology=J. Plant Physiol.;JPPHEY;M
+Journal of Polymer Materials=J. Polym. Mater.;JOPME8;Q
+Journal of Polymer Research=J. Polym. Res.;JPOREP;Q
+Journal of Polymer Science, Part A: Polymer Chemistry=J. Polym. Sci., Part A: Polym. Chem.;JPACEC;SM
+Journal of Polymer Science, Part B: Polymer Physics=J. Polym. Sci., Part B: Polym. Phys.;JPBPEM;SM
+Journal of Polymers and the Environment=J. Polym. Environ.;JPENFW;Q
+Journal of Porphyrins and Phthalocyanines=J. Porphyrins Phthalocyanines;JPPHFZ;M
+Journal of Power Sources=J. Power Sources;JPSODZ;24/YR
+Journal of Process Control=J. Process Control;JPCOEO;8/YR
+Journal of Proteome Research=J. Proteome Res.;JPROBS;BM
+Journal of Pulp and Paper Science=J. Pulp Pap. Sci.;JPUSDN;Q
+Journal of Quantitative Spectroscopy & Radiative Transfer=J. Quant. Spectrosc. Radiat. Transfer;JQSRAE;28/YR
+Journal of Radioanalytical and Nuclear Chemistry=J. Radioanal. Nucl. Chem.;JRNCDM;M
+Journal of Raman Spectroscopy=J. Raman Spectrosc.;JRSPAF;M
+Journal of Receptors and Signal Transduction=J. Recept. Signal Transduction;JRSTCT;Q
+Journal of Reinforced Plastics and Composites=J. Reinf. Plast. Compos.;JRPCDW;18/YR
+Journal of Rheology (New York, NY, United States)=J. Rheol. (N. Y., NY, U. S.);JORHD2;BM
+Journal of Separation Science=J. Sep. Sci.;JSSCCJ;18/YR
+Journal of Sol-Gel Science and Technology=J. Sol-Gel Sci. Technol.;JSGTEC;12/YR
+Journal of Solid State Chemistry=J. Solid State Chem.;JSSCBI;12/YR
+Journal of Solid State Electrochemistry=J. Solid State Electrochem.;JSSEFS;12/YR
+Journal of Solution Chemistry=J. Solution Chem.;JSLCAG;M
+Journal of Steroid Biochemistry and Molecular Biology=J. Steroid Biochem. Mol. Biol.;JSBBEZ;SM
+Journal of Structural and Functional Genomics=J. Struct. Funct. Genomics;JSFGAW;Q
+Journal of Structural Chemistry=J. Struct. Chem.;JSTCAM;BM
+Journal of Sulfur Chemistry=J. Sulfur Chem.;JSCOFC;BM
+Journal of Superconductivity=J. Supercond.;JOUSEH;BM
+Journal of Supercritical Fluids=J. Supercrit. Fluids;JSFLEH;9/yr
+Journal of Surfactants and Detergents=J. Surfactants Deterg.;JSDEFL;Q
+Journal of the American Ceramic Society=J. Am. Ceram. Soc.;JACTAW;M
+Journal of the American Chemical Society=J. Am. Chem. Soc.;JACSAT;W
+Journal of the American Oil Chemists' Society=J. Am. Oil Chem. Soc.;JAOCA7;M
+Journal of the American Society for Mass Spectrometry=J. Am. Soc. Mass Spectrom.;JAMSEF;M
+Journal of the American Society of Brewing Chemists=J. Am. Soc. Brew. Chem.;JSBCD3;Q
+Journal of the Argentine Chemical Society=J. Argent. Chem. Soc.;JACSFY;2/YR
+Journal of the Brazilian Chemical Society=J. Braz. Chem. Soc.;JOCSET;BM
+Journal of the Ceramic Society of Japan=J. Ceram. Soc. Jpn.;JCSJEW;M
+Journal of the Chemical Society of Pakistan=J. Chem. Soc. Pak.;JCSPDF;Q
+Journal of the Chilean Chemical Society=J. Chil. Chem. Soc.;JCCSCB;Q
+Journal of the Chinese Chemical Society (Taipei, Taiwan)=J. Chin. Chem. Soc. (Taipei, Taiwan);JCCTAC;BM
+Journal of the Chinese Institute of Chemical Engineers=J. Chin. Inst. Chem. Eng.;JCICAP;BM
+Journal of the Electrochemical Society=J. Electrochem. Soc.;JESOAN;M
+Journal of the Electrochemical Society of India=J. Electrochem. Soc. India;JESIA5;Q
+Journal of the Energy Institute=J. Energy Inst.;JEIOB8;4/YR
+Journal of the European Ceramic Society=J. Eur. Ceram. Soc.;JECSER;16/YR
+Journal of the Indian Chemical Society=J. Indian Chem. Soc.;JICSAH;M
+Journal of the Institution of Chemists (India)=J. Inst. Chem. (India);JOICA7;BM
+Journal of the Japan Petroleum Institute=J. Jpn. Pet. Inst.;JJPIAP;BM
+Journal of the Korean Ceramic Society=J. Korean Ceram. Soc.;JKCSBW;M
+Journal of the Korean Chemical Society=J. Korean Chem. Soc.;JKCSEZ;BM
+Journal of the Optical Society of America B: Optical Physics=J. Opt. Soc. Am. B;JOBPDE;M
+Journal of the Physical Society of Japan=J. Phys. Soc. Jpn.;JUPSAU;M
+Journal of the Science of Food and Agriculture=J. Sci. Food Agric.;JSFAAE;15/YR
+Journal of the Serbian Chemical Society=J. Serb. Chem. Soc.;JSCSEN;M
+Journal of the Society of Inorganic Materials, Japan=J. Soc. Inorg. Mater., Jpn.;JSIJFR;BM
+Journal of Theoretical & Computational Chemistry=J. Theor. Comput. Chem.;JTCCAC;Q
+Journal of Thermal Analysis and Calorimetry=J. Therm. Anal. Calorim.;JTACF7;M
+Journal of Thermophysics and Heat Transfer=J. Thermophys. Heat Transfer;JTHTEO;Q
+Journal of Toxicology and Environmental Health, Part A=J. Toxicol. Environ. Health, Part A;JTEHF8;SM
+Journal of Toxicology and Environmental Health, Part B: Critical Reviews=J. Toxicol. Environ. Health, Part B;JTECFR;BM
+Journal of Vacuum Science & Technology, A: Vacuum, Surfaces, and Films=J. Vac. Sci. Technol., A;JVTAD6;BM
+Struct.--Process., Meas., Phenom. Journal of Vacuum Science & Technology, B: Microelectronics and Nanometer Structures--Processing, Measurement, and Phenomena=J. Vac. Sci. Technol., B: Microelectron. Nanometer;JVSTBM;BM
+Journal of Vinyl & Additive Technology=J. Vinyl Addit. Technol.;JVATF4;Q
+Journal of Virological Methods=J. Virol. Methods;JVMEDH;16/yr
+Journal of Virology=J. Virol.;JOVIAM;SM
+Journal of Volcanology and Geothermal Research=J. Volcanol. Geotherm. Res.;JVGRDQ;40/YR
+Journal of Wood Chemistry and Technology=J. Wood Chem. Technol.;JWCTDJ;4/YR
+Kagaku Kogaku=Kagaku Kogaku;KKGKA4;M
+Kagaku Kogaku Ronbunshu=Kagaku Kogaku Ronbunshu;KKRBAW;BM
+Kemija u Industriji=Kem. Ind.;KJUIAR;M
+KGK, Kautschuk Gummi Kunststoffe=KGK, Kautsch. Gummi Kunstst.;KKGKB5;10/YR
+Khimicheskaya Promyshlennost (St. Petersburg, Russian Federation)=Khim. Prom-st. (St. Petersburg, Russ. Fed.);KPRMAW;M
+Khimicheskaya Promyshlennost Segodnya=Khim. Prom-st. Segodnya;KPSHBN;M
+Khimiya i Tekhnologiya Vody=Khim. Tekhnol. Vody;KTVODL;BM
+Khimiya Tverdogo Topliva (Moscow, Russian Federation)=Khim. Tverd. Topl. (Moscow, Russ. Fed.);KTVTBY;BM
+Khimiya v Interesakh Ustoichivogo Razvitiya=Khim. Interesakh Ustoich. Razvit.;KIURFI;BM
+Kinetics and Catalysis=Kinet. Catal.;KICAA8;BM
+Kobunshi Ronbunshu=Kobunshi Ronbunshu;KBRBA3;M
+Koks i Khimiya=Koks Khim.;KOKKAI;M
+Korean Journal of Chemical Engineering=Korean J. Chem. Eng.;KJCHE6;BM
+Lab on a Chip=Lab Chip;LCAHAM;12/YR
+Laboratory Animals=Lab. Anim.;LBANAX;Q
+Langmuir=Langmuir;LANGD5;BW
+Laser and Particle Beams=Laser Part. Beams;LPBEDA;Q
+Latvijas Kimijas Zurnals=Latv. Kim. Z.;LKZUE8;Q
+LCGC North America=LCGC North Am.;LNACBH;M
+Letters in Drug Design & Discovery=Lett. Drug Des. Discovery;LDDDAW;8/YR
+Letters in Organic Chemistry=Lett. Org. Chem.;LOCEC7;8/YR
+Life Sciences=Life Sci.;LIFSAK;W
+Linchan Huaxue Yu Gongye=Linchan Huaxue Yu Gongye;LHYGD7;Q
+Lipids=Lipids;LPDSAP;M
+Liquid Crystals=Liq. Cryst.;LICRE6;M
+Lithos=Lithos;LITHAN;28/YR
+LWT--Food Science and Technology=LWT--Food Sci. Technol.;LSTWB3;8/YR
+Macromolecular Bioscience=Macromol. Biosci.;MBAIBU;M
+Macromolecular Chemistry and Physics=Macromol. Chem. Phys.;MCHPES;SM
+Macromolecular Materials and Engineering=Macromol. Mater. Eng.;MMENFA;M
+Macromolecular Rapid Communications=Macromol. Rapid Commun.;MRCOE3;24/YR
+Macromolecular Research=Macromol. Res.;MRAECT;BM
+Macromolecular Symposia=Macromol. Symp.;MSYMEC;IRR
+Macromolecular Theory and Simulations=Macromol. Theory Simul.;MTHSEK;9/YR
+Macromolecules=Macromolecules;MAMOBX;BW
+Magnesium Research=Magnesium Res.;MAGREF;Q
+Magnetic Resonance in Chemistry=Magn. Reson. Chem.;MRCHEG;M
+Magyar Kemiai Folyoirat, Kemiai Kozlemenyek=Magy. Kem. Foly., Kem. Kozl.;MKFKAL;Q
+Main Group Metal Chemistry=Main Group Met. Chem.;MGMCE8;BM
+Marine Biotechnology=Mar. Biotechnol.;MABIFW;BM
+Marine Chemistry=Mar. Chem.;MRCHBD;20/YR
+Marine Environmental Research=Mar. Environ. Res.;MERSDW;10/YR
+Marine Pollution Bulletin=Mar. Pollut. Bull.;MPNBAZ;IRR
+Materials and Corrosion=Mater. Corros.;MTCREQ;M
+Materials and Manufacturing Processes=Mater. Manuf. Processes;MMAPET;BM
+Materials Characterization=Mater. Charact.;MACHEX;10/YR
+Materials Chemistry and Physics=Mater. Chem. Phys.;MCHPDR;M
+Materials Forum=Mater. Forum;MFOREM;A
+Materials Letters=Mater. Lett.;MLETDJ;SM
+Materials Research Bulletin=Mater. Res. Bull.;MRBUAC;15/YR
+Materials Research Innovations=Mater. Res. Innovations;MRINFV;6/YR
+Materials Research Society Symposium Proceedings=Mater. Res. Soc. Symp. Proc.;MRSPDH;IRR
+Materials Science & Engineering, A: Structural Materials: Properties, Microstructure and Processing=Mater. Sci. Eng., A;MSAPE3;46/YR
+Materials Science & Engineering, B: Solid-State Materials for Advanced Technology=Mater. Sci. Eng., B;MSBTEK;30/YR
+Materials Science & Engineering, C: Biomimetic and Supramolecular Systems=Mater. Sci. Eng., C;MSCEEE;8/YR
+Materials Science and Technology=Mater. Sci. Technol.;MSCTEP;M
+Materials Science in Semiconductor Processing=Mater. Sci. Semicond. Process.;MSSPFQ;BM
+Materials Transactions=Mater. Trans.;MTARCE;M
+Matrix Biology=Matrix Biol.;MTBOEC;8/YR
+Measurement Science and Technology=Meas. Sci. Technol.;MSTCEP;M
+Mechanisms of Development=Mech. Dev.;MEDVE6;M
+Medicinal Chemistry=Med. Chem.;MCEHAJ;6/YR
+Medicinal Chemistry Research=Med. Chem. Res.;MCREEB;9/YR
+Mendeleev Communications=Mendeleev Commun.;MENCEX;BM
+Metabolic Engineering=Metab. Eng.;MEENFM;BM
+Metabolism, Clinical and Experimental=Metab., Clin. Exp.;METAAJ;M
+Metal Science and Heat Treatment=Met. Sci. Heat Treat.;MHTRAN;BM
+Metallofizika i Noveishie Tekhnologii=Metallofiz. Noveishie Tekhnol.;MNTEEU;M
+Metallurgical and Materials Transactions A: Physical Metallurgy and Materials Science=Metall. Mater. Trans. A;MMTAEB;M
+Metallurgical and Materials Transactions B: Process Metallurgy and Materials Processing Science=Metall. Mater. Trans. B;MTBSEO;BM
+Metally=Metally;MEALET;BM
+Meteoritics & Planetary Science=Meteorit. Planet. Sci.;MPSCFY;M
+Methods (San Diego, CA, United States)=Methods (San Diego, CA, U. S.);MTHDE9;M
+Microbiology (New York, NY, United States)=Microbiology (N. Y., NY, U. S.);MIBLAO;BM
+Microbiology (Reading, United Kingdom)=Microbiology (Reading, U. K.);MROBEO;M
+Microbiology and Immunology=Microbiol. Immunol.;MIIMDV;M
+Microchemical Journal=Microchem. J.;MICJAN;BM
+Microchimica Acta=Microchim. Acta;MIACAQ;12/YR
+Microelectronic Engineering=Microelectron. Eng.;MIENEF;8/YR
+Microporous and Mesoporous Materials=Microporous Mesoporous Mater.;MIMMFJ;30/YR
+Microscopy and Microanalysis=Microsc. Microanal.;MIMIF7;BM
+Milchwissenschaft=Milchwissenschaft;MILCAD;4/YR
+Mineralium Deposita=Miner. Deposita;MIDEBE;8/YR
+Mineralogical Magazine=Mineral. Mag.;MNLMBB;BM
+Mineralogy and Petrology=Mineral. Petrol.;MIPEE9;12/YR
+Minerals & Metallurgical Processing=Miner. Metall. Process.;MMPRE8;Q
+Minerals Engineering=Miner. Eng.;MENGEB;15/YR
+Mini-Reviews in Medicinal Chemistry=Mini-Rev. Med. Chem.;MMCIAE;12/YR
+Mini-Reviews in Organic Chemistry=Mini-Rev. Org. Chem.;MOCIBT;4/YR
+Mitochondrion=Mitochondrion;MITOCN;BM
+Modern Physics Letters B=Mod. Phys. Lett. B;MPLBET;30/YR
+Molecular and Biochemical Parasitology=Mol. Biochem. Parasitol.;MBIPDP;M
+Molecular and Cellular Biochemistry=Mol. Cell. Biochem.;MCBIB8;26/YR
+Molecular and Cellular Biology=Mol. Cell. Biol.;MCEBD4;SM
+Molecular and Cellular Endocrinology=Mol. Cell. Endocrinol.;MCEND6;30/YR
+Molecular and Cellular Neuroscience=Mol. Cell. Neurosci.;MOCNED;M
+Molecular and Cellular Probes=Mol. Cell. Probes;MCPRE6;BM
+Molecular and Cellular Proteomics=Mol. Cell. Proteomics;MCPOBS;M
+Molecular Biology (New York, NY, United States, English Edition)=Mol. Biol. (N. Y., NY, U. S., Engl. Ed.);MOLBBJ;BM
+Molecular Biology and Evolution=Mol. Biol. Evol.;MBEVEO;M
+Molecular Biology of the Cell=Mol. Biol. Cell;MBCEEV;M
+Molecular Biology Reports=Mol. Biol. Rep.;MLBRBU;4/YR
+Molecular BioSystems=Mol. BioSyst.;MBOIBW;6/YR
+Molecular Biotechnology=Mol. Biotechnol.;MLBOEO;9/YR
+Molecular Brain Research=Mol. Brain Res.;MBREE4;22/YR
+Molecular Cancer Research=Mol. Cancer Res.;MCROC5;M
+Molecular Cancer Therapeutics=Mol. Cancer Ther.;MCTOCF;M
+Molecular Carcinogenesis=Mol. Carcinog.;MOCAE8;M
+Molecular Cell=Mol. Cell;MOCEFL;SM
+Molecular Crystals and Liquid Crystals=Mol. Cryst. Liq. Cryst.;MCLCD8;18/YR
+Molecular Diversity=Mol. Diversity;MODIF4;4/YR
+Molecular Endocrinology=Mol. Endocrinol.;MOENEN;M
+Molecular Genetics and Genomics=Mol. Genet. Genomics;MGGOAA;M
+Molecular Genetics and Metabolism=Mol. Genet. Metab.;MGMEFF;M
+Molecular Immunology=Mol. Immunol.;MOIMD5;M
+Molecular Membrane Biology=Mol. Membr. Biol.;MMEBE7;BM
+Molecular Microbiology=Mol. Microbiol.;MOMIEE;23/YR
+Molecular Neurobiology=Mol. Neurobiol.;MONBEW;BM
+Molecular Pharmaceutics=Mol. Pharm.;MPOHBP;BM
+Molecular Pharmacology=Mol. Pharmacol.;MOPMA3;M
+Molecular Physics=Mol. Phys.;MOPHAM;SM
+Molecular Plant-Microbe Interactions=Mol. Plant-Microbe Interact.;MPMIEL;M
+Molecular Reproduction and Development=Mol. Reprod. Dev.;MREDEE;M
+Molecular Simulation=Mol. Simul.;MOSIEA;15/YR
+Molecular Therapy=Mol. Ther.;MTOHCK;M
+Molecules=Molecules;MOLEFW;M
+Molecules and Cells=Mol. Cells;MOCEEK;BM
+Monatshefte fuer Chemie=Monatsh. Chem.;MOCMB7;M
+Mutagenesis=Mutagenesis;MUTAEX;BM
+Mutation Research=Mutat. Res.;MUREAV;18/YR
+Nano Letters=Nano Lett.;NALEFD;M
+NanoBiotechnology=NanoBiotechnology;NANOCG;4/YR
+Nanomedicine=Nanomedicine;NANOBF;Q
+Natural Product Reports=Nat. Prod. Rep.;NPRRDF;BM
+Natural Product Research=Nat. Prod. Res.;NPRAAT;8/YR
+Natural Product Sciences=Nat. Prod. Sci.;NPSCFB;Q
+Nature (London, United Kingdom)=Nature (London, U. K.);NATUAS;W
+Nature Biotechnology=Nat. Biotechnol.;NABIF9;M
+Nature Cell Biology=Nat. Cell Biol.;NCBIFN;M
+Nature Chemical Biology=Nat. Chem. Biol.;NCBABT;M
+Nature Genetics=Nat. Genet.;NGENEC;M
+Nature Immunology=Nat. Immunol.;NIAMCZ;M
+Nature Materials=Nat. Mater.;NMAACR;M
+Nature Medicine (New York, NY, United States)=Nat. Med. (N. Y., NY, U. S.);NAMEFI;M
+Nature Methods=Nat. Methods;NMAEA3;M
+Nature Neuroscience=Nat. Neurosci.;NANEFN;M
+Nature Reviews Cancer=Nat. Rev. Cancer;NRCAC4;M
+Nature Reviews Drug Discovery=Nat. Rev. Drug Discovery;NRDDAG;M
+Nature Reviews Genetics=Nat. Rev. Genet.;NRGAAM;M
+Nature Reviews Immunology=Nat. Rev. Immunol.;NRIABX;M
+Nature Reviews Microbiology=Nat. Rev. Microbiol.;NRMACK;M
+Nature Reviews Molecular Cell Biology=Nat. Rev. Mol. Cell Biol.;NRMCBP;M
+Nature Reviews Neuroscience=Nat. Rev. Neurosci.;NRNAAN;M
+Nature Structural & Molecular Biology=Nat. Struct. Mol. Biol.;NSMBCU;M
+Naturwissenschaften=Naturwissenschaften;NATWAY;M
+Naunyn-Schmiedeberg's Archives of Pharmacology=Naunyn-Schmiedeberg's Arch. Pharmacol.;NSAPCC;M
+Neftekhimiya=Neftekhimiya;NEFTAH;BM
+Neues Jahrbuch fuer Mineralogie, Abhandlungen=Neues Jahrb. Mineral., Abh.;NJMIAK;IRR
+Neurochemical Research=Neurochem. Res.;NEREDZ;M
+Neurochemistry International=Neurochem. Int.;NEUIDS;16/YR
+Neuroendocrinology=Neuroendocrinology;NUNDAJ;M
+NeuroImmunoModulation=NeuroImmunoModulation;NROIEM;BM
+NeuroMolecular Medicine=NeuroMol. Med.;NMEEAN;6/YR
+Neuron=Neuron;NERNET;SM
+Neuropeptides (Amsterdam, Netherlands)=Neuropeptides (Amsterdam, Neth.);NRPPDD;BM
+Neuropharmacology=Neuropharmacology;NEPHBW;16/YR
+Neuroscience (Oxford, United Kingdom)=Neuroscience (Oxford, U. K.);NRSCDN;28/YR
+Neuroscience Letters=Neurosci. Lett.;NELED5;57/YR
+Neurosignals=Neurosignals;NEURIQ;BM
+Neurotoxicology and Teratology=Neurotoxicol. Teratol.;NETEEC;BM
+New Diamond and Frontier Carbon Technology=New Diamond Front. Carbon Technol.;NDFTFF;6/YR
+New England Journal of Medicine=N. Engl. J. Med.;NEJMAG;W
+New Journal of Chemistry=New J. Chem.;NJCHE5;M
+Nihon Reoroji Gakkaishi=Nihon Reoroji Gakkaishi;NRGIAC;IRR
+Nippon Kinzoku Gakkaishi=Nippon Kinzoku Gakkaishi;NIKGAV;M
+Nitric Oxide=Nitric Oxide;NIOXF5;8/YR
+Nordic Pulp & Paper Research Journal=Nord. Pulp Pap. Res. J.;NPPJEG;Q
+Nuclear Engineering and Design=Nucl. Eng. Des.;NEDEAU;24/YR
+Nuclear Fusion=Nucl. Fusion;NUFUAU;M
+Nuclear Instruments & Methods in Physics Research, Section A: Accelerators, Spectrometers, Detectors, and Associated Equipment=Nucl. Instrum. Methods Phys. Res., Sect. A;NIMAER;36/YR
+Nuclear Instruments & Methods in Physics Research, Section B: Beam Interactions with Materials and Atoms=Nucl. Instrum. Methods Phys. Res., Sect. B;NIMBEU;21/YR
+Nuclear Medicine and Biology=Nucl. Med. Biol.;NMBIEO;8/YR
+Nuclear Physics A=Nucl. Phys. A;NUPABL;68/YR
+Nuclear Physics B=Nucl. Phys. B;NUPBBO;84/yr
+Nuclear Physics B, Proceedings Supplements=Nucl. Phys. B, Proc. Suppl.;NPBSE7;IRR
+Nuclear Science and Engineering=Nucl. Sci. Eng.;NSENAO;9/YR
+Nuclear Technology=Nucl. Technol.;NUTYBB;M
+Nucleic Acids Research=Nucleic Acids Res.;NARHAD;SM
+Nucleic Acids Research Supplement=Nucleic Acids Res. Suppl.;NARSCE;A
+Nucleosides, Nucleotides & Nucleic Acids=Nucleosides, Nucleotides Nucleic Acids;NNNAFY;M
+Nukleonika=Nukleonika;NUKLAS;Q
+Nutrition Research (New York, NY, United States)=Nutr. Res. (N. Y., NY, U. S.);NTRSDC;M
+O'zbekiston Kimyo Jurnali=O'zb. Kim. J.;OKJZA6;BM
+Oil, Gas (Hamburg, Germany)=Oil, Gas (Hamburg, Ger.);OGEMDJ;Q
+Oligonucleotides=Oligonucleotides;OLIGAJ;Q
+OMICS=OMICS;OMICAE;Q
+Oncogene=Oncogene;ONCNES;58/YR
+Optics and Spectroscopy=Opt. Spectrosc.;OPSUA3;M
+Optics Communications=Opt. Commun.;OPCOB8;84/YR
+Organic & Biomolecular Chemistry=Org. Biomol. Chem.;OBCRAK;24/YR
+Organic Geochemistry=Org. Geochem.;ORGEDE;M
+Organic Letters=Org. Lett.;ORLEF7;BW
+Organic Preparations and Procedures International=Org. Prep. Proced. Int.;OPPIAK;BM
+Organic Process Research & Development=Org. Process Res. Dev.;OPRDFK;BM
+Organic Syntheses=Org. Synth.;ORSYAT;A
+Organometallics=Organometallics;ORGND7;BW
+Oriental Journal of Chemistry=Orient. J. Chem.;OJCHEG;3/YR
+Oxidation Communications=Oxid. Commun.;OXCODW;4/YR
+Oxidation of Metals=Oxid. Met.;OXMEAF;BM
+Oyo Yakuri=Oyo Yakuri;OYYAA2;BM
+Ozone: Science & Engineering=Ozone: Sci. Eng.;OZSEDS;BM
+Particulate Science and Technology=Part. Sci. Technol.;PTCHDS;Q
+Peptides (New York, NY, United States)=Peptides (N. Y., NY, U. S.);PPTDD5;M
+Pest Management Science=Pest Manage. Sci.;PMSCFC;M
+Pesticide Biochemistry and Physiology=Pestic. Biochem. Physiol.;PCBPBS;9/YR
+Petroleum Science and Technology=Pet. Sci. Technol.;PSTEFV;M
+Pfluegers Archiv=Pfluegers Arch.;PFLABK;M
+Pharmaceutical Chemistry Journal=Pharm. Chem. J.;PCJOAU;M
+Pharmaceutical Development and Technology=Pharm. Dev. Technol.;PDTEFS;Q
+Pharmaceutical Research=Pharm. Res.;PHREEB;M
+Pharmacogenetics and Genomics=Pharmacogenet. Genomics;PGHEAI;M
+Pharmacogenomics Journal=Pharmacogenomics J.;PJHOAZ;BM
+Pharmacology=Pharmacology;PHMGBN;12/YR
+Pharmacology & Therapeutics=Pharmacol. Ther.;PHTHDT;M
+Pharmacology, Biochemistry and Behavior=Pharmacol., Biochem. Behav.;PBBHAU;M
+Pharmazie=Pharmazie;PHARAT;M
+Phase Transitions=Phase Transitions;PHTRDP;M
+Philosophical Magazine=Philos. Mag.;PMHABF;36/YR
+Philosophical Magazine Letters=Philos. Mag. Lett.;PMLEEG;M
+Phosphorus, Sulfur and Silicon and the Related Elements=Phosphorus, Sulfur Silicon Relat. Elem.;PSSLEC;M
+Photochemical & Photobiological Sciences=Photochem. Photobiol. Sci.;PPSHCB;M
+Photochemistry and Photobiology=Photochem. Photobiol.;PHCBAP;BM
+Photosynthesis Research=Photosynth. Res.;PHRSDI;M
+Physica B: Condensed Matter (Amsterdam, Netherlands)=Physica B (Amsterdam, Neth.);PHYBE3;16/YR
+Physica C: Superconductivity and Its Applications (Amsterdam, Netherlands)=Physica C (Amsterdam, Neth.);PHYCE6;68/YR
+Physica Scripta=Phys. Scr.;PHSTBO;M
+Physica Scripta, T=Phys. Scr., T;PHSTER;IRR
+Physica Status Solidi A: Applications and Materials Science=Phys. Status Solidi A;PSSABA;15/YR
+Physica Status Solidi B: Basic Solid State Physics=Phys. Status Solidi B;PSSBBD;15/YR
+Physica Status Solidi C: Conferences and Critical Reviews=Phys. Status Solidi C;PSSCGL;12/YR
+Physical Chemistry Chemical Physics=Phys. Chem. Chem. Phys.;PPCPFQ;SM
+Physical Review A: Atomic, Molecular, and Optical Physics=Phys. Rev. A: At., Mol., Opt. Phys.;PLRAAN;M
+Physical Review B: Condensed Matter and Materials Physics=Phys. Rev. B: Condens. Matter Mater. Phys.;PRBMDO;48/YR
+Physical Review C: Nuclear Physics=Phys. Rev. C: Nucl. Phys.;PRVCAN;M
+Physical Review D: Particles and Fields=Phys. Rev. D: Part. Fields;PRVDAQ;SM
+Physical Review E: Statistical, Nonlinear, and Soft Matter Physics=Phys. Rev. E: Stat., Nonlinear, Soft Matter Phys.;PRESCM;M
+Physical Review Letters=Phys. Rev. Lett.;PRLTAO;W
+Physics and Chemistry of Glasses=Phys. Chem. Glasses;PCGLA6;BM
+Physics and Chemistry of Liquids=Phys. Chem. Liq.;PCLQAC;6/YR
+Physics and Chemistry of Minerals=Phys. Chem. Miner.;PCMIDU;10/YR
+Physics Letters A=Phys. Lett. A;PYLAAG;84/YR
+Physics Letters B=Phys. Lett. B;PYLBAJ;W
+Physics of Atomic Nuclei=Phys. At. Nucl.;PANUEO;M
+Physics of Fluids=Phys. Fluids;PHFLE6;M
+Physics of Plasmas=Phys. Plasmas;PHPAEN;M
+Physics of the Solid State=Phys. Solid State;PSOSED;M
+Physiologia Plantarum=Physiol. Plant.;PHPLAI;M
+Physiology & Behavior=Physiol. Behav.;PHBHA4;15/YR
+Phytochemical Analysis=Phytochem. Anal.;PHANEL;BM
+Phytochemistry (Elsevier)=Phytochemistry (Elsevier);PYTCAS;SM
+Phytochemistry Reviews=Phytochem. Rev.;PRHEBS;3/YR
+Plant and Cell Physiology=Plant Cell Physiol.;PCPHA5;M
+Plant and Soil=Plant Soil;PLSOA2;20/YR
+Plant Cell=Plant Cell;PLCEEW;M
+Plant Cell Reports=Plant Cell Rep.;PCRPD8;12/YR
+Plant Growth Regulation=Plant Growth Regul.;PGRED3;9/YR
+Plant Journal=Plant J.;PLJUED;24/YR
+Plant Molecular Biology=Plant Mol. Biol.;PMBIDB;18/YR
+Plant Physiology=Plant Physiol.;PLPHAY;M
+Plant Physiology and Biochemistry (Amsterdam, Netherlands)=Plant Physiol. Biochem. (Amsterdam, Neth.);PPBIEX;M
+Plant Science (Amsterdam, Netherlands)=Plant Sci. (Amsterdam, Neth.);PLSCE4;M
+Planta=Planta;PLANAB;M
+Planta Medica=Planta Med.;PLMEAA;M
+Plasma Chemistry and Plasma Processing=Plasma Chem. Plasma Process.;PCPPDW;BM
+Plasma Processes and Polymers=Plasma Processes Polym.;PPPLA6;9/YR
+Plasmid=Plasmid;PLSMDX;BM
+Plasticheskie Massy=Plast. Massy;PLMSAI;IRR
+Plastics, Rubber and Composites=Plast., Rubber Compos.;PRUCFN;10/YR
+Platelets=Platelets;PLTEEF;8/YR
+PLoS Biology=PLoS Biol.;PBLIBG;M
+PLoS Computational Biology=PLoS Comput. Biol.;PCBLBG;M
+PLoS Genetics=PLoS Genet.;PGLEB5;M
+PMSE Preprints=PMSE Prepr.;PPMRA9;SA
+Polish Journal of Chemistry=Pol. J. Chem.;PJCHDQ;M
+Polycyclic Aromatic Compounds=Polycyclic Aromat. Compd.;PARCEO;5/YR
+Polyhedron=Polyhedron;PLYHDE;18/YR
+Polymer=Polymer;POLMAG;BW
+Polymer (Korea)=Polymer (Korea);POLLDG;BM
+Polymer Bulletin (Heidelberg, Germany)=Polym. Bull. (Heidelberg, Ger.);POBUDR;M
+Polymer Composites=Polym. Compos.;PCOMDI;BM
+Polymer Degradation and Stability=Polym. Degrad. Stab.;PDSTDW;M
+Polymer Engineering and Science=Polym. Eng. Sci.;PYESAZ;M
+Polymer International=Polym. Int.;PLYIEI;M
+Polymer Journal (Tokyo, Japan)=Polym. J. (Tokyo, Jpn.);POLJB8;M
+Polymer Preprints (American Chemical Society, Division of Polymer Chemistry)=Polym. Prepr. (Am. Chem. Soc., Div. Polym. Chem.);ACPPAY;SA
+Polymer Testing=Polym. Test.;POTEDZ;8/YR
+Polymer-Plastics Technology and Engineering=Polym.-Plast. Technol. Eng.;PPTEC7;9/YR
+Polymers & Polymer Composites=Polym. Polym. Compos.;PPOCEC;8/YR
+Polymers for Advanced Technologies=Polym. Adv. Technol.;PADTE5;M
+Poverkhnost=Poverkhnost;PFKMDJ;M
+Powder Diffraction=Powder Diffr.;PODIE2;Q
+Powder Metallurgy=Powder Metall.;PWMTAU;Q
+Powder Metallurgy and Metal Ceramics=Powder Metall. Met. Ceram.;PMMCEF;BM
+Powder Technology=Powder Technol.;POTEBX;33/YR
+Practical Spectroscopy=Pract. Spectrosc.;PSPED9;IRR
+Precambrian Research=Precambrian Res.;PCBRBY;32/YR
+Preparative Biochemistry & Biotechnology=Prep. Biochem. Biotechnol.;PBBIF4;Q
+Preprints - American Chemical Society, Division of Petroleum Chemistry=Prepr. - Am. Chem. Soc., Div. Pet. Chem.;ACPCAT;4/YR
+Environ. Chem. Preprints of Extended Abstracts presented at the ACS National Meeting, American Chemical Society, Division of Environmental Chemistry=Prepr. Ext. Abstr. ACS Natl. Meet., Am. Chem. Soc., Div.;PEACF2;SA
+Preprints of Symposia - American Chemical Society, Division of Fuel Chemistry=Prepr. Symp. - Am. Chem. Soc., Div. Fuel Chem.;PSADFZ;2/YR
+Proceedings - Electrochemical Society=Proc. - Electrochem. Soc.;PESODO;IRR
+Proceedings of the Estonian Academy of Sciences, Chemistry=Proc. Est. Acad. Sci., Chem.;PESCFO;Q
+Proceedings of the National Academy of Sciences of the United States of America=Proc. Natl. Acad. Sci. U. S. A.;PNASA6;W
+Process Biochemistry (Oxford, United Kingdom)=Process Biochem. (Oxford, U. K.);PBCHE5;12/YR
+Process Safety and Environmental Protection=Process Saf. Environ. Prot.;PSEPEM;6/YR
+Progress in Colloid & Polymer Science=Prog. Colloid Polym. Sci.;PCPSD7;IRR
+Progress in Crystal Growth and Characterization of Materials=Prog. Cryst. Growth Charact. Mater.;PCGMED;BM
+Progress in Inorganic Chemistry=Prog. Inorg. Chem.;PIOCAR;IRR
+Progress in Nuclear Magnetic Resonance Spectroscopy=Prog. Nucl. Magn. Reson. Spectrosc.;PNMRAT;8/YR
+Progress in Organic Coatings=Prog. Org. Coat.;POGCAT;12/YR
+Progress in Polymer Science=Prog. Polym. Sci.;PRPSB8;M
+Progress in Reaction Kinetics and Mechanism=Prog. React. Kinet. Mech.;PRKMF3;4/YR
+Progress in Solid State Chemistry=Prog. Solid State Chem.;PSSTAW;Q
+Progress in Surface Science=Prog. Surf. Sci.;PSSFBP;SM
+Propellants, Explosives, Pyrotechnics=Propellants, Explos., Pyrotech.;PEPYD5;BM
+Prostaglandins & Other Lipid Mediators=Prostaglandins Other Lipid Mediators;POLMFL;3/yr
+Prostaglandins, Leukotrienes and Essential Fatty Acids=Prostaglandins, Leukotrienes Essent. Fatty Acids;PLEAEU;M
+Protection of Metals=Prot. Met.;PTNMAR;BM
+Protein and Peptide Letters=Protein Pept. Lett.;PPELEN;8/YR
+Protein Engineering, Design & Selection=Protein Eng., Des. Sel.;PEDSBR;M
+Protein Expression and Purification=Protein Expression Purif.;PEXPEJ;M
+Protein Journal=Protein J.;PJROAH;8/YR
+Protein Science=Protein Sci.;PRCIEI;M
+Proteins: Structure, Function, and Bioinformatics=Proteins: Struct., Funct., Bioinf.;PSFBAF;16/YR
+Proteomics=Proteomics;PROTC7;18/YR
+Przemysl Chemiczny=Przem. Chem.;PRCHAB;M
+Psychopharmacology (Berlin, Germany)=Psychopharmacology (Berlin, Ger.);PSCHDL;SM
+Pteridines=Pteridines;PTRDEO;Q
+Pulmonary Pharmacology & Therapeutics=Pulm. Pharmacol. Ther.;PPTHFJ;BM
+Pure and Applied Chemistry=Pure Appl. Chem.;PACHAS;M
+Purinergic Signalling=Purinergic Signalling;PSUIA9;Q
+QSAR & Combinatorial Science=QSAR Comb. Sci.;QCSSAU;10/YR
+Quantum Electronics=Quantum Electron.;QUELEZ;M
+Quimica Nova=Quim. Nova;QUNODK;BM
+Radiation Effects and Defects in Solids=Radiat. Eff. Defects Solids;REDSEI;M
+Radiation Measurements=Radiat. Meas.;RMEAEP;BM
+Radiation Physics and Chemistry=Radiat. Phys. Chem.;RPCHDM;18/YR
+Radiation Research=Radiat. Res.;RAREAE;M
+Radiochemistry (New York, NY, United States)=Radiochemistry (N. Y., NY, U. S.);RDIOEO;BM
+Radiochimica Acta=Radiochim. Acta;RAACAP;12/YR
+Radioprotection=Radioprotection;RAPRBA;Q
+Ranliao Huaxue Xuebao=Ranliao Huaxue Xuebao;RHXUD8;BM
+Rapid Communications in Mass Spectrometry=Rapid Commun. Mass Spectrom.;RCMSEF;SM
+Rare Metals (Beijing, China)=Rare Met. (Beijing, China);RARME8;Q
+Rasplavy=Rasplavy;RASPEM;BM
+Reaction Kinetics and Catalysis Letters=React. Kinet. Catal. Lett.;RKCLAU;6/YR
+Reactive & Functional Polymers=React. Funct. Polym.;RFPOF6;12/YR
+Regulatory Peptides=Regul. Pept.;REPPDY;21/YR
+Rengong Jingti Xuebao=Rengong Jingti Xuebao;RJXUEN;BM
+Reproduction (Bristol, United Kingdom)=Reproduction (Bristol, U. K.);RCUKBS;M
+Reproductive Toxicology=Reprod. Toxicol.;REPTED;BM
+Research Communications in Biochemistry and Cell & Molecular Biology=Res. Commun. Biochem. Cell Mol. Biol.;RCBBFC;Q
+Research Communications in Molecular Pathology and Pharmacology=Res. Commun. Mol. Pathol. Pharmacol.;RCMPE6;IRR
+Research Communications in Pharmacology and Toxicology=Res. Commun. Pharmacol. Toxicol.;RCPTFY;Q
+Research on Chemical Intermediates=Res. Chem. Intermed.;RCINEE;9/YR
+Review of Scientific Instruments=Rev. Sci. Instrum.;RSINAK;M
+Reviews in Analytical Chemistry=Rev. Anal. Chem.;RACYAX;4/YR
+Reviews in Inorganic Chemistry=Rev. Inorg. Chem.;RICHD7;Q
+Revista de Chimie (Bucharest, Romania)=Rev. Chim. (Bucharest, Rom.);RCBUAU;M
+Revista de la Sociedad Quimica del Peru=Rev. Soc. Quim. Peru;RSQPAW;Q
+Revista Mexicana de Ingenieria Quimica=Rev. Mex. Ing. Quim.;RMIQBM;3/YR
+Revista Romana de Materiale=Rev. Rom. Mater.;RRMEB7;Q
+Revue Roumaine de Chimie=Rev. Roum. Chim.;RRCHAX;M
+Rheologica Acta=Rheol. Acta;RHEAAK;BM
+RNA=RNA;RNARFU;M
+RNA Biology=RNA Biol.;RBNIBE;BM
+Romanian Journal of Physics=Rom. J. Phys.;RJPHEC;10/YR
+Rossiiskii Khimicheskii Zhurnal=Ross. Khim. Zh.;RKZHEZ;BM
+Rubber Chemistry and Technology=Rubber Chem. Technol.;RCTEA4;5/YR
+Russian Chemical Bulletin=Russ. Chem. Bull.;RCBUEY;M
+Russian Chemical Reviews=Russ. Chem. Rev.;RCRVAB;M
+Russian Journal of Applied Chemistry=Russ. J. Appl. Chem.;RJACEO;M
+Russian Journal of Bioorganic Chemistry=Russ. J. Bioorg. Chem.;RJBCET;BM
+Russian Journal of Coordination Chemistry=Russ. J. Coord. Chem.;RJCCEY;M
+Russian Journal of Electrochemistry=Russ. J. Electrochem.;RJELE3;M
+Russian Journal of General Chemistry=Russ. J. Gen. Chem.;RJGCEK;M
+Russian Journal of Genetics=Russ. J. Genet.;RJGEEQ;M
+Russian Journal of Organic Chemistry=Russ. J. Org. Chem.;RJOCEQ;M
+Russian Journal of Physical Chemistry=Russ. J. Phys. Chem.;RJPCAR;M
+Russian Journal of Plant Physiology=Russ. J. Plant Physiol.;RJPPE2;BM
+SAR and QSAR in Environmental Research=SAR QSAR Environ. Res.;SQERED;BM
+Scandinavian Journal of Laboratory Animal Science=Scand. J. Lab. Anim. Sci.;SJLSE2;Q
+Scandinavian Journal of Metallurgy=Scand. J. Metall.;SJMLAG;BM
+Science (Washington, DC, United States)=Science (Washington, DC, U. S.);SCIEAS;W
+Science in China, Series B: Chemistry=Sci. China, Ser. B: Chem.;SCBCFQ;BM
+Science of the Total Environment=Sci. Total Environ.;STENDL;36/YR
+Scripta Materialia=Scr. Mater.;SCMAF7;SM
+Seibutsu Kogaku Kaishi=Seibutsu Kogaku Kaishi;SEKAEA;M
+Semiconductor Science and Technology=Semicond. Sci. Technol.;SSTEET;M
+Semiconductors=Semiconductors;SMICES;M
+Sensors and Actuators, A: Physical=Sens. Actuators, A;SAAPEB;16/yr
+Sensors and Actuators, B: Chemical=Sens. Actuators, B;SABCEB;BW
+Separation and Purification Technology=Sep. Purif. Technol.;SPUTFP;18/yr
+Separation Science and Technology=Sep. Sci. Technol.;SSTEDS;16/YR
+Sepu=Sepu;SEPUER;BM
+Shiyou Huagong=Shiyou Huagong;SHHUE8;M
+Shiyou Xuebao, Shiyou Jiagong=Shiyou Xuebao, Shiyou Jiagong;SXSHEY;BM
+Shuichuli Jishu=Shuichuli Jishu;SHJIEG;M
+Signal Transduction=Signal Transduction;STIRCI;6/YR
+Silicon Chemistry=Silicon Chem.;SCIHB4;BM
+Small=Small;SMALBC;12/YR
+Soft Matter=Soft Matter;SMOABF;6/YR
+Soil Biology & Biochemistry=Soil Biol. Biochem.;SBIOAH;M
+Soil Science=Soil Sci.;SOSCAK;M
+Soil Science Society of America Journal=Soil Sci. Soc. Am. J.;SSSJD4;BM
+Solar Energy Materials & Solar Cells=Sol. Energy Mater. Sol. Cells;SEMCEQ;20/YR
+Solid State Communications=Solid State Commun.;SSCOA4;48/YR
+Solid State Ionics=Solid State Ionics;SSIOD3;40/YR
+Solid State Nuclear Magnetic Resonance=Solid State Nucl. Magn. Reson.;SSNRE4;8/YR
+Solid State Sciences=Solid State Sci.;SSSCFJ;M
+Solid-State Electronics=Solid-State Electron.;SSELA5;M
+Solvent Extraction and Ion Exchange=Solvent Extr. Ion Exch.;SEIEDB;BM
+Solvent Extraction Research and Development, Japan=Solvent Extr. Res. Dev., Jpn.;SERDEK;A
+Somatic Cell and Molecular Genetics=Somatic Cell Mol. Genet.;SCMGDN;BM
+South African Journal of Chemistry=S. Afr. J. Chem.;SAJCDG;IRR
+SPE Production & Facilities=SPE Prod. Facil.;SPRFEZ;Q
+SPE Reservoir Evaluation & Engineering=SPE Reservoir Eval. Eng.;SREEFG;BM
+Spectrochimica Acta, Part A: Molecular and Biomolecular Spectroscopy=Spectrochim. Acta, Part A;SAMCAS;14/YR
+Spectrochimica Acta, Part B: Atomic Spectroscopy=Spectrochim. Acta, Part B;SAASBH;M
+Spectroscopy (Amsterdam, Netherlands)=Spectroscopy (Amsterdam, Neth.);SPIJDZ;6/YR
+Spectroscopy Letters=Spectrosc. Lett.;SPLEBX;6/YR
+STAL, Sciences et Techniques de l'Animal de Laboratoire=STAL, Sci. Tech. Anim. Lab.;STALDT;Q
+Starch/Staerke=Starch/Staerke;STARDD;M
+Steel Research International=Steel Res. Int.;SRITB9;M
+Steroids=Steroids;STEDAM;M
+Structural Chemistry=Struct. Chem.;STCHES;BM
+Structure (Cambridge, MA, United States)=Structure (Cambridge, MA, U. S.);STRUE6;M
+Superconductor Science and Technology=Supercond. Sci. Technol.;SUSTEF;M
+Superlattices and Microstructures=Superlattices Microstruct.;SUMIEK;M
+Supramolecular Chemistry=Supramol. Chem.;SCHEER;8/YR
+Surface and Coatings Technology=Surf. Coat. Technol.;SCTEEJ;39/YR
+Surface and Interface Analysis=Surf. Interface Anal.;SIANDQ;13/YR
+Surface Engineering=Surf. Eng.;SUENET;6/YR
+Surface Review and Letters=Surf. Rev. Lett.;SRLEFH;BM
+Surface Science=Surf. Sci.;SUSCAS;36/YR
+Surface Science Reports=Surf. Sci. Rep.;SSREDI;32/YR
+Synapse (New York, NY, United States)=Synapse (N. Y., NY, U. S.);SYNAET;16/YR
+Synlett=Synlett;SYNLES;20/YR
+Synthesis=Synthesis;SYNTBF;20/YR
+Synthesis and Reactivity in Inorganic, Metal-Organic, and Nano-Metal Chemistry=Synth. React. Inorg., Met.-Org., Nano-Met. Chem.;SRIMDO;10/YR
+Synthetic Communications=Synth. Commun.;SYNCAV;SM
+Synthetic Lubrication=Synth. Lubr.;SYLUEB;Q
+Synthetic Metals=Synth. Met.;SYMEDZ;24/YR
+Taehan Kumsok, Chaeryo Hakhoechi=Taehan Kumsok, Chaeryo Hakhoechi;TKHABB;M
+Talanta=Talanta;TLNTA2;M
+Tappi Journal=Tappi J.;TAJODT;M
+Technical Physics=Tech. Phys.;TEPHEX;M
+Technical Physics Letters=Tech. Phys. Lett.;TPLEED;M
+Tenside, Surfactants, Detergents=Tenside, Surfactants, Deterg.;TSDEES;BM
+Tetrahedron=Tetrahedron;TETRAB;W
+Tetrahedron Letters=Tetrahedron Lett.;TELEAY;W
+Tetrahedron: Asymmetry=Tetrahedron: Asymmetry;TASYE3;SM
+Tetsu to Hagane=Tetsu to Hagane;TEHAA2;M
+Textile Research Journal=Text. Res. J.;TRJOA9;M
+THEOCHEM=THEOCHEM;THEODJ;72/YR
+Theoretical and Experimental Chemistry=Theor. Exp. Chem.;TEXCAK;BM
+Theoretical Chemistry Accounts=Theor. Chem. Acc.;TCACFW;10/YR
+Theoretical Foundations of Chemical Engineering=Theor. Found. Chem. Eng.;TFCEAU;BM
+Thermochimica Acta=Thermochim. Acta;THACAS;SM
+Thin Solid Films=Thin Solid Films;THSFAP;46/YR
+Thrombosis and Haemostasis=Thromb. Haemostasis;THHADQ;M
+Thrombosis Research=Thromb. Res.;THBRAA;M
+Topics in Catalysis=Top. Catal.;TOCAFI;20/YR
+Toxicological and Environmental Chemistry=Toxicol. Environ. Chem.;TECSDY;BM
+Toxicological Sciences=Toxicol. Sci.;TOSCF2;M
+Toxicology=Toxicology;TXCYAC;42/YR
+Toxicology and Applied Pharmacology=Toxicol. Appl. Pharmacol.;TXAPA9;SM
+Toxicology in Vitro=Toxicol. in Vitro;TIVIEQ;8/YR
+Toxicology Letters=Toxicol. Lett.;TOLED5;24/YR
+Toxicology Mechanisms and Methods=Toxicol. Mech. Methods;TMMOCP;BM
+Toxicon=Toxicon;TOXIA6;16/YR
+TrAC, Trends in Analytical Chemistry=TrAC, Trends Anal. Chem.;TTAEDJ;11/YR
+Traffic (Oxford, United Kingdom)=Traffic (Oxford, U. K.);TRAFFA;M
+Transactions of the Indian Ceramic Society=Trans. Indian Ceram. Soc.;TICSAP;Q
+Transactions of the Institute of Metal Finishing=Trans. Inst. Met. Finish.;TIMFA2;BM
+Transactions of the SAEST=Trans. SAEST;TSETA6;Q
+Transgenic Research=Transgenic Res.;TRSEES;BM
+Transition Metal Chemistry (Dordrecht, Netherlands)=Transition Met. Chem. (Dordrecht, Neth.);TMCHDN;8/YR
+Trends in Biochemical Sciences=Trends Biochem. Sci.;TBSCDB;M
+Trends in Biotechnology=Trends Biotechnol.;TRBIDM;M
+Trends in Endocrinology and Metabolism=Trends Endocrinol. Metab.;TENME4;10/YR
+Trends in Food Science & Technology=Trends Food Sci. Technol.;TFTEEH;M
+Trends in Genetics=Trends Genet.;TRGEE2;M
+Trends in Immunology=Trends Immunol.;TIRMAE;M
+Trends in Microbiology=Trends Microbiol.;TRMIEA;M
+Trends in Neurosciences=Trends Neurosci.;TNSCDR;M
+Trends in Pharmacological Sciences=Trends Pharmacol. Sci.;TPHSDY;M
+Trends in Plant Science=Trends Plant Sci.;TPSCF9;M
+Tribology Transactions=Tribol. Trans.;TRTRE4;Q
+Turkish Journal of Chemistry=Turk. J. Chem.;TJCHE3;6/YR
+Ukrains'kii Biokhimichnii Zhurnal=Ukr. Biokhim. Zh.;UBZKAA;BM
+Ukrains'kii Fizichnii Zhurnal=Ukr. Fiz. Zh.;UFZHFY;M
+Ukrainskii Khimicheskii Zhurnal (Russian Edition)=Ukr. Khim. Zh. (Russ. Ed.);UKZHAU;6/YR
+Ultramicroscopy=Ultramicroscopy;ULTRD6;16/YR
+Ultrasonics Sonochemistry=Ultrason. Sonochem.;ULSOER;BM
+Vacuum=Vacuum;VACUAV;16/yr
+Vascular Pharmacology=Vasc. Pharmacol.;VPAHAJ;M
+Vestnik Moskovskogo Universiteta, Seriya 2: Khimiya=Vestn. Mosk. Univ., Ser. 2: Khim.;VMUKA5;BM
+Vestnik Sankt-Peterburgskogo Universiteta, Seriya 4: Fizika, Khimiya=Vestn. S.-Peterb. Univ., Ser. 4: Fiz., Khim.;VSUKEH;Q
+Vestsi Natsyyanal'nai Akademii Navuk Belarusi, Seryya Khimichnykh Navuk=Vestsi Nats. Akad. Navuk Belarusi, Ser. Khim. Navuk;VNBNFX;Q
+Vibrational Spectroscopy=Vib. Spectrosc.;VISPEK;BM
+Viral Immunology=Viral Immunol.;VIIMET;Q
+Virology=Virology;VIRLAX;26/YR
+Virus Genes=Virus Genes;VIGEET;BM
+Virus Research=Virus Res.;VIREDF;M
+Vysokomolekulyarnye Soedineniya, Seriya A i Seriya B=Vysokomol. Soedin., Ser. A Ser. B;VSSBEE;M
+Water Environment Research=Water Environ. Res.;WAERED;7/YR
+Water Quality Research Journal of Canada=Water Qual. Res. J. Can.;WQRCFA;Q
+Water Research=Water Res.;WATRAG;20/YR
+Water Resources=Water Resour.;WARED4;BM
+Water, Air, & Soil Pollution=Water, Air, Soil Pollut.;WAPLAC;36/YR
+Wear=Wear;WEARAH;M
+Weed Science=Weed Sci.;WEESA6;BM
+Wood and Fiber Science=Wood Fiber Sci.;WFSCD4;Q
+Wood Science and Technology=Wood Sci. Technol.;WOSTBE;8/YR
+Wuji Huaxue Xuebao=Wuji Huaxue Xuebao;WHUXEO;M
+Wuli Huaxue Xuebao=Wuli Huaxue Xuebao;WHXUEU;M
+Wuli Xuebao=Wuli Xuebao;WLHPAR;M
+X-Ray Spectrometry=X-Ray Spectrom.;XRSPAX;BM
+X-Ray Structure Analysis Online=X-Ray Struct. Anal. Online;XSAOAF;IRR
+Xenobiotica=Xenobiotica;XENOBH;M
+Yakhak Hoechi=Yakhak Hoechi;YAHOA3;BM
+Yakugaku Zasshi=Yakugaku Zasshi;YKKZAJ;M
+Yeast=Yeast;YESTE3;16/YR
+Yingyong Huaxue=Yingyong Huaxue;YIHUED;M
+Yosetsu Gakkai Ronbunshu=Yosetsu Gakkai Ronbunshu;YGRODU;Q
+Youji Huaxue=Youji Huaxue;YCHHDX;M
+Yuki Gosei Kagaku Kyokaishi=Yuki Gosei Kagaku Kyokaishi;YGKKAE;M
+Zeitschrift fuer Anorganische und Allgemeine Chemie=Z. Anorg. Allg. Chem.;ZAACAB;M
+Zeitschrift fuer Kristallographie=Z. Kristallogr.;ZEKRDZ;12/YR
+Zeitschrift fuer Kristallographie - New Crystal Structures=Z. Kristallogr. - New Cryst. Struct.;ZKNSFT;4/YR
+Zeitschrift fuer Metallkunde=Z. Metallkd.;ZEMTAE;M
+Zeitschrift fuer Naturforschung, A: Physical Sciences=Z. Naturforsch., A: Phys. Sci.;ZNASEI;M
+Zeitschrift fuer Naturforschung, B: Chemical Sciences=Z. Naturforsch., B: Chem. Sci.;ZNBSEN;M
+Zeitschrift fuer Naturforschung, C: Journal of Biosciences=Z. Naturforsch., C: J. Biosci.;ZNCBDA;BM
+Zeitschrift fuer Physikalische Chemie (Muenchen, Germany)=Z. Phys. Chem. (Muenchen, Ger.);ZPCFAX;12/YR
+Zhipu Xuebao=Zhipu Xuebao;ZXHUBO;Q
+Zhongguo Shengwu Huaxue Yu Fenzi Shengwu Xuebao=Zhongguo Shengwu Huaxue Yu Fenzi Shengwu Xuebao;ZSHXF2;BM
+Zhurnal Neorganicheskoi Khimii=Zh. Neorg. Khim.;ZNOKAQ;M
+Zhurnal Organichnoi ta Farmatsevtichnoi Khimii=Zh. Org. Farm. Khim.;ZOFKAM;4/YR
diff --git a/src/resource/layout/tablerefs/tablerefs.begin.layout b/src/resource/layout/tablerefs/tablerefs.begin.layout
new file mode 100644
index 0000000..647ded6
--- /dev/null
+++ b/src/resource/layout/tablerefs/tablerefs.begin.layout
@@ -0,0 +1,152 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html lang="en">
+<head>
+<title>JabRef References output</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+
+<script type="text/javascript">
+<!--
+// QuickSearch script for tables
+//
+// Copyright (c) 2006, Mark Schenk
+//
+// Permission to use, copy, modify, and distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+
+// Some features:
+// + combination of CSS/JavaScript degrades nicely
+// + easy to set number of columns to search
+// + allows RegExp searches
+// e.g. to search for entries between 1980 and 1989, type: 198[0-9]
+// e.g. for any entry ending with 'symmetry', type: symmetry$
+// e.g. for all reftypes that are books: ^book$, or ^article$
+
+if (window.opera) {
+ document.addEventListener("load",initSearch,false) }
+else if (window.addEventListener) {
+ window.addEventListener("load",initSearch,false) }
+else if (window.attachEvent) {
+ window.attachEvent("onload", initSearch); }
+
+function initSearch() {
+ // basic object detection
+ if(!document.getElementById || !document.getElementsByTagName) { return; }
+
+ // check if QuickSearch table AND search area is present
+ if (!document.getElementById('qstable')||!document.getElementById('qs')) { return; }
+
+ // give id of the table that has QuickSearch
+ // is global variable on purpose
+ searchTable = document.getElementById('qstable');
+
+ setStatistics(-1)
+
+ document.getElementById('qs').style.display = 'block';
+ document.getElementById('qsfield').onkeyup = testEvent;
+}
+
+function quickSearch(tInput){
+ searchText = new RegExp(tInput.value,"i");
+ var inRows = searchTable.getElementsByTagName('tbody')[0].getElementsByTagName('tr');
+
+ // find/set number of searchable columns
+ // by default script searches all columns
+ var cols = searchTable.getElementsByTagName('thead')[0].getElementsByTagName('th').length;
+ // to set a fixed number of columns, uncomment next line
+ // var cols = 4 // search the left 'cols' columns
+
+ // count number of hits
+ var hits = 0;
+
+ // start looping through all rows
+ for (var i = 0; cRow = inRows[i]; i++){
+ inCells = cRow.getElementsByTagName('td');
+ var gevonden = false;
+
+ for (var j=0; j<cols; j++) { // only first 'cols' columns
+ cCell = inCells[j];
+ var t = cCell.innerText?cCell.innerText:getTextContent(cCell);
+ if ((tInput.value.length == 0) || (t.search(searchText) != -1)){ gevonden=true; }
+ }
+
+ gevonden == true?cRow.className = 'entry show':cRow.className = 'entry noshow';
+ gevonden == true?hits++:hits=hits;
+ }
+
+ // update statistics
+ setStatistics(hits)
+}
+
+function setStatistics (hits) {
+ var allRows = searchTable.getElementsByTagName('tbody')[0].getElementsByTagName('tr');
+ var entries = 0
+ for (var i=0; i<allRows.length;i++) {
+ if (allRows[i].className.indexOf('entry') != -1) {
+ entries++;
+ }
+ }
+
+ if(hits < 0) { hits=entries; }
+
+ var stats = document.getElementById('stat');
+ if(stats) { stats.firstChild.data = hits + '/' + entries}
+}
+
+function getTextContent(node) {
+ // Function written by Arve Bersvendsen
+ // http://www.virtuelvis.com
+
+ if (node.nodeType == 3) {
+ return node.nodeValue;
+ } // text node
+ if (node.nodeType == 1) { // element node
+ var text = [];
+ for (var chld = node.firstChild;chld;chld=chld.nextSibling) {
+ text.push(getTextContent(chld));
+ }
+ return text.join("");
+ } return ""; // some other node, won't contain text nodes.
+}
+
+function testEvent(e){
+ if (!e) var e = window.event;
+ quickSearch(this);
+}
+
+function clearQS() {
+ qsfield = document.getElementById('qsfield');
+ qsfield.value = '';
+ quickSearch(qsfield);
+}
+
+function redoQS(){
+ qsfield = document.getElementById('qsfield');
+ quickSearch(qsfield);
+}
+-->
+</script>
+<style type="text/css">
+body { background-color: white; font-family: "Trebuchet MS", Arial, sans-serif; font-size: 12px; line-height: 1.2; padding: 1em; }
+
+#qs { width: auto; border-style: solid; border-color: gray; border-width: 1px 1px 0px 1px; padding: 0.5em 0.5em; display:none; }
+#qs form { padding: 0px; margin: 0px; }
+#qs form p { padding: 0px; margin: 0px; }
+
+table { border: 1px gray solid; width: 100%; empty-cells: show; }
+th, td { border: 1px gray solid; padding: 0.5em; vertical-align: top; }
+td { text-align: left; vertical-align: top; }
+th { background-color: #EFEFEF; }
+
+td a, td a:hover { color: navy; font-weight: bold; }
+
+tr.noshow { display: none;}
+</style>
+</head>
+<body>
+
+<div id="qs"><form action=""><p>QuickSearch: <input type="text" name="qsfield" id="qsfield" autocomplete="off" title="Allows plain text as wel as RegExp searches" /><input type="button" onclick="clearQS()" value="clear" /> Number of matching entries: <span id="stat">0</span>.</p></form></div>
+<table id="qstable" border="1">
+<thead><tr><th width="20%">Author</th><th width="30%">Title</th><th width="5%">Year</th><th width="30%">Journal/Proceedings</th><th width="10%">Reftype</th><th width="5%">DOI/URL</th></tr></thead>
+<tbody>
\ No newline at end of file
diff --git a/src/resource/layout/tablerefs/tablerefs.end.layout b/src/resource/layout/tablerefs/tablerefs.end.layout
new file mode 100644
index 0000000..dde4022
--- /dev/null
+++ b/src/resource/layout/tablerefs/tablerefs.end.layout
@@ -0,0 +1,12 @@
+</tbody>
+</table>
+
+<p>
+ <small>Created by <a href="http://jabref.sourceforge.net">JabRef</a> on \format[CurrentDate]{dd/MM/yyyy}.</small>
+</p>
+
+</body>
+</html>
+
+<!-- File generated by JabRef; Export Filter written by Mark Schenk -->
+
diff --git a/src/resource/layout/tablerefs/tablerefs.layout b/src/resource/layout/tablerefs/tablerefs.layout
new file mode 100644
index 0000000..84abf2b
--- /dev/null
+++ b/src/resource/layout/tablerefs/tablerefs.layout
@@ -0,0 +1,8 @@
+<tr id="\format{\bibtexkey}" class="entry">
+ <td>\format[AuthorLastFirst,AuthorLastFirstAbbreviator,AuthorAndsCommaReplacer,HTMLChars]{\author}</td>
+ <td>\format[HTMLChars]{\title}</td>
+ <td>\year</td>
+ <td>\format[HTMLChars]{\journal}\format[HTMLChars]{\booktitle}\begin{school}<i>School</i>: \format[HTMLChars]{\school}\end{school} </td>
+ <td>\format[ToLowerCase]{\bibtextype}</td>
+ <td>\begin{doi}<a href="\format[DOICheck]{\doi}">DOI</a>\end{doi}\begin{url}<a href="\format{\url}">URL</a>\end{url} </td>
+</tr>
diff --git a/src/resource/layout/tablerefsabsbib/tablerefsabsbib.begin.layout b/src/resource/layout/tablerefsabsbib/tablerefsabsbib.begin.layout
new file mode 100644
index 0000000..fb955c8
--- /dev/null
+++ b/src/resource/layout/tablerefsabsbib/tablerefsabsbib.begin.layout
@@ -0,0 +1,221 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html lang="en">
+<head>
+<title>JabRef References output</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+
+<script type="text/javascript">
+<!--
+// QuickSearch script for tables
+//
+// Copyright (c) 2006, Mark Schenk
+//
+// Permission to use, copy, modify, and distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+
+// Some features:
+// + combination of CSS/JavaScript degrades nicely
+// + easy to set number of columns to search
+// + allows RegExp searches
+// e.g. to search for entries between 1980 and 1989, type: 198[0-9]
+// e.g. for any entry ending with 'symmetry', type: symmetry$
+// e.g. for all reftypes that are books: ^book$, or ^article$
+// + easy toggling of Abstract/Review/BibTeX
+
+if (window.opera) {
+ document.addEventListener("load",initSearch,false) }
+else if (window.addEventListener) {
+ window.addEventListener("load",initSearch,false) }
+else if (window.attachEvent) {
+ window.attachEvent("onload", initSearch); }
+
+function initSearch() {
+ // basic object detection
+ if(!document.getElementById || !document.getElementsByTagName) { return; }
+
+ // check if QuickSearch table AND search area is present
+ if (!document.getElementById('qstable')||!document.getElementById('qs')) { return; }
+
+ // give id of the table that has QuickSearch
+ // is global variable on purpose
+ searchTable = document.getElementById('qstable');
+
+ setStatistics(-1)
+
+ document.getElementById('qs').style.display = 'block';
+ document.getElementById('qsfield').onkeyup = testEvent;
+}
+
+function quickSearch(tInput){
+ searchText = new RegExp(tInput.value,"i");
+ var allRows = searchTable.getElementsByTagName('tbody')[0].getElementsByTagName('tr');
+ var inRows = new Array();
+
+ for (var i=0, k=0; i<allRows.length;i++) {
+ if (allRows[i].className.indexOf('entry') != -1) {
+ inRows[k++] = allRows[i];
+ } else if (allRows[i].className.indexOf('noshow') == -1) {
+ allRows[i].className = allRows[i].className + ' noshow';
+ }
+ }
+
+ // find/set number of searchable columns
+ // by default script searches all columns
+ var cols = searchTable.getElementsByTagName('thead')[0].getElementsByTagName('th').length;
+ // to set a fixed number of columns, uncomment next line
+ // var cols = 4 // search the left 'cols' columns
+
+ // count number of hits
+ var hits = 0;
+
+ // start looping through all rows
+ for (var i = 0; cRow = inRows[i]; i++){
+
+ inCells = cRow.getElementsByTagName('td');
+ var gevonden = false;
+
+ for (var j=0; j<cols; j++) { // only first 'cols' columns
+ cCell = inCells[j];
+ var t = cCell.innerText?cCell.innerText:getTextContent(cCell);
+ if ((tInput.value.length == 0) || (t.search(searchText) != -1)){ gevonden=true; }
+ }
+
+ gevonden == true?cRow.className = 'entry show':cRow.className = 'entry noshow';
+ gevonden == true?hits++:hits=hits;
+ }
+
+ // update statistics
+ setStatistics(hits)
+}
+
+function toggleInfo(articleid,info) {
+
+ var entry = document.getElementById(articleid);
+ var abs = document.getElementById('abs_'+articleid);
+ var rev = document.getElementById('rev_'+articleid);
+ var bib = document.getElementById('bib_'+articleid);
+
+ if (abs && info == 'abstract') {
+ if(abs.className.indexOf('abstract') != -1) {
+ abs.className.indexOf('noshow') == -1?abs.className = 'abstract noshow':abs.className = 'abstract';
+ }
+ } else if (rev && info == 'review') {
+ if(rev.className.indexOf('review') != -1) {
+ rev.className.indexOf('noshow') == -1?rev.className = 'review noshow':rev.className = 'review';
+ }
+ } else if (bib && info == 'bibtex') {
+ if(bib.className.indexOf('bibtex') != -1) {
+ bib.className.indexOf('noshow') == -1?bib.className = 'bibtex noshow':bib.className = 'bibtex';
+ }
+ } else {
+ return;
+ }
+
+ // check if one or the other is available
+ var revshow = false;
+ var absshow = false;
+ var bibshow = false;
+ (abs && abs.className.indexOf('noshow') == -1)? absshow = true: absshow = false;
+ (rev && rev.className.indexOf('noshow') == -1)? revshow = true: revshow = false;
+ (bib && bib.className == 'bibtex')? bibshow = true: bibshow = false;
+
+ // highlight original entry
+ if(entry) {
+ if (revshow || absshow || bibshow) {
+ entry.className = 'entry highlight show';
+ } else {
+ entry.className = 'entry show';
+ }
+ }
+
+ // When there's a combination of abstract/review/bibtex showing, need to add class for correct styling
+ if(absshow) {
+ (revshow||bibshow)?abs.className = 'abstract nextshow':abs.className = 'abstract';
+ }
+ if (revshow) {
+ bibshow?rev.className = 'review nextshow': rev.className = 'review';
+ }
+
+}
+
+function setStatistics (hits) {
+ var allRows = searchTable.getElementsByTagName('tbody')[0].getElementsByTagName('tr');
+ var entries = 0
+ for (var i=0; i<allRows.length;i++) {
+ if (allRows[i].className.indexOf('entry') != -1) {
+ entries++;
+ }
+ }
+
+ if(hits < 0) { hits=entries; }
+
+ var stats = document.getElementById('stat');
+ if(stats) { stats.firstChild.data = hits + '/' + entries}
+}
+
+function getTextContent(node) {
+ // Function written by Arve Bersvendsen
+ // http://www.virtuelvis.com
+
+ if (node.nodeType == 3) {
+ return node.nodeValue;
+ } // text node
+ if (node.nodeType == 1) { // element node
+ var text = [];
+ for (var chld = node.firstChild;chld;chld=chld.nextSibling) {
+ text.push(getTextContent(chld));
+ }
+ return text.join("");
+ } return ""; // some other node, won't contain text nodes.
+}
+
+function testEvent(e){
+ if (!e) var e = window.event;
+ quickSearch(this);
+}
+
+function clearQS() {
+ qsfield = document.getElementById('qsfield');
+ qsfield.value = '';
+ quickSearch(qsfield);
+}
+
+function redoQS(){
+ qsfield = document.getElementById('qsfield');
+ quickSearch(qsfield);
+}
+-->
+</script>
+<style type="text/css">
+body { background-color: white; font-family: "Trebuchet MS", Arial, sans-serif; font-size: 12px; line-height: 1.2; padding: 1em; }
+
+#qs { width: auto; border-style: solid; border-color: gray; border-width: 1px 1px 0px 1px; padding: 0.5em 0.5em; display:none; }
+#qs form { padding: 0px; margin: 0px; }
+#qs form p { padding: 0px; margin: 0px; }
+
+table { border: 1px gray solid; width: 100%; empty-cells: show; }
+th, td { border: 1px gray solid; padding: 0.5em; vertical-align: top; }
+td { text-align: left; vertical-align: top; }
+th { background-color: #EFEFEF; }
+
+td a, td a:hover { color: navy; font-weight: bold; }
+
+tr.noshow { display: none;}
+
+tr.highlight td { background-color: #F1F1F1; border-top: 2px black solid; font-weight: bold; }
+tr.abstract td, tr.review td, tr.bibtex td { background-color: #F1F1F1; border-bottom: 2px black solid; }
+tr.nextshow td { border-bottom: 1px gray solid; }
+
+tr.bibtex pre { width: 100%; overflow: auto;}
+
+p.infolinks { margin: 0.5em 0em 0em 0em; padding: 0px; }
+</style>
+</head>
+<body>
+
+<div id="qs"><form action=""><p>QuickSearch: <input type="text" name="qsfield" id="qsfield" autocomplete="off" title="Allows plain text as wel as RegExp searches" /><input type="button" onclick="clearQS()" value="clear" /> Number of matching entries: <span id="stat">0</span>.</p></form></div>
+<table id="qstable" border="1">
+<thead><tr><th width="20%">Author</th><th width="30%">Title</th><th width="5%">Year</th><th width="30%">Journal/Proceedings</th><th width="10%">Reftype</th><th width="5%">DOI/URL</th></tr></thead>
+<tbody>
\ No newline at end of file
diff --git a/src/resource/layout/tablerefsabsbib/tablerefsabsbib.end.layout b/src/resource/layout/tablerefsabsbib/tablerefsabsbib.end.layout
new file mode 100644
index 0000000..760fba8
--- /dev/null
+++ b/src/resource/layout/tablerefsabsbib/tablerefsabsbib.end.layout
@@ -0,0 +1,12 @@
+</tbody>
+</table>
+
+<p>
+ <small>Created by <a href="http://jabref.sourceforge.net">JabRef</a> on \format[CurrentDate]{dd/MM/yyyy}.</small>
+</p>
+
+</body>
+</html>
+
+<!-- File generated by JabRef ; Export Filter written by Mark Schenk -->
+
diff --git a/src/resource/layout/tablerefsabsbib/tablerefsabsbib.layout b/src/resource/layout/tablerefsabsbib/tablerefsabsbib.layout
new file mode 100644
index 0000000..428bc52
--- /dev/null
+++ b/src/resource/layout/tablerefsabsbib/tablerefsabsbib.layout
@@ -0,0 +1,36 @@
+<tr id="\format{\bibtexkey}" class="entry">
+ <td>\format[AuthorLastFirst,AuthorLastFirstAbbreviator,AuthorAndsCommaReplacer,HTMLChars]{\author}</td>
+ <td>\format[HTMLChars]{\title} <p class="infolinks">\begin{abstract}[<a href="javascript:toggleInfo('\format{\bibtexkey}','abstract')">Abstract</a>] \end{abstract}\begin{review}[<a href="javascript:toggleInfo('\format{\bibtexkey}','review')">Review</a>] \end{review}[<a href="javascript:toggleInfo('\format{\bibtexkey}','bibtex')">BibTeX</a>]</p></td>
+ <td>\year</td>
+ <td>\format[HTMLChars]{\journal}\format[HTMLChars]{\booktitle}\begin{school}<i>School</i>: \format[HTMLChars]{\school}\end{school} </td>
+ <td>\format[ToLowerCase]{\bibtextype}</td>
+ <td>\begin{doi}<a href="\format[DOICheck]{\doi}">DOI</a>\end{doi}\begin{url}<a href="\format{\url}">URL</a>\end{url} </td>
+</tr>\begin{abstract}
+<tr id="abs_\format{\bibtexkey}" class="abstract noshow">
+ <td colspan="6"><b>Abstract</b>: \format[HTMLChars]{\abstract}</td>
+</tr>\end{abstract}\begin{review}
+<tr id="rev_\format{\bibtexkey}" class="review noshow">
+ <td colspan="6"><b>Review</b>: \format[HTMLChars]{\review}</td>
+</tr>\end{review}
+<tr id="bib_\format{\bibtexkey}" class="bibtex noshow">
+<td colspan="6">
+<b>BibTeX</b>:
+<pre>
+@\format[ToLowerCase]{\bibtextype}{\bibtexkey,\begin{author}
+ author = {\author}\end{author}\begin{title},
+ title = {\title}\end{title}\begin{booktitle},
+ booktitle = {\booktitle}\end{booktitle}\begin{journal},
+ journal = {\journal}\end{journal}\begin{publisher},
+ publisher = {\publisher}\end{publisher}\begin{school},
+ school = {\school}\end{school}\begin{year},
+ year = {\year}\end{year}\begin{volume},
+ volume = {\volume}\end{volume}\begin{number},
+ number = {\number}\end{number}\begin{pages},
+ pages = {\pages}\end{pages}\begin{edition},
+ edition = {\edition}\end{edition}\begin{note},
+ note = {\note}\end{note}\begin{url},
+ url = {\url}\end{url}\begin{doi},
+ doi = {\format[DOICheck]{\doi}}\end{doi}
+}
+</pre></td>
+</tr>
diff --git a/src/resource/log4j.properties b/src/resource/log4j.properties
new file mode 100644
index 0000000..c596db8
--- /dev/null
+++ b/src/resource/log4j.properties
@@ -0,0 +1,7 @@
+#Uncomment next line for debugging
+#log4j.rootCategory=ALL,stderr
+log4j.rootCategory=WARN,stderr
+log4j.appender.stderr=org.apache.log4j.ConsoleAppender
+log4j.appender.stderr.target=System.err
+log4j.appender.stderr.layout=org.apache.log4j.PatternLayout
+log4j.appender.stderr.layout.ConversionPattern=[%d{ABSOLUTE}] <%t> %5p (%c{2}:%L) %m%n
\ No newline at end of file
diff --git a/src/tests/encrypted.pdf b/src/tests/encrypted.pdf
new file mode 100644
index 0000000..fa5d199
--- /dev/null
+++ b/src/tests/encrypted.pdf
@@ -0,0 +1,51 @@
+%PDF-1.4
+%����
+1 0 obj
+<<
+/Type /Catalog
+/Version /1.4
+/Pages 2 0 R
+>>
+endobj
+2 0 obj
+<<
+/Type /Pages
+/Kids [3 0 R]
+/Count 1
+>>
+endobj
+3 0 obj
+<<
+/Type /Page
+/MediaBox [0 0 612 792]
+/Parent 2 0 R
+>>
+endobj
+4 0 obj
+<<
+/Filter /Standard
+/V 1
+/R 3
+/Length 40
+/P -4
+/O <DE6D5B98EDAA9BF0D22386B155A9112FE34B6D702571BEE246E10252FC4F1817>
+/U <B489B251529F5204C61D58A92DBF334028BF4E5E4E758A4164004E56FFFA0108>
+>>
+endobj
+xref
+0 5
+0000000000 65535 f
+0000000017 00000 n
+0000000087 00000 n
+0000000151 00000 n
+0000000229 00000 n
+trailer
+<<
+/Root 1 0 R
+/ID [<5A3B45F717FB6A727A135C85396AE04E> <5A3B45F717FB6A727A135C85396AE04E>]
+/Encrypt 4 0 R
+/Size 5
+>>
+startxref
+446
+%%EOF
\ No newline at end of file
diff --git a/src/tests/net/sf/jabref/bst/abbrv.bst b/src/tests/net/sf/jabref/bst/abbrv.bst
new file mode 100644
index 0000000..2e7fe53
--- /dev/null
+++ b/src/tests/net/sf/jabref/bst/abbrv.bst
@@ -0,0 +1,1098 @@
+% BibTeX standard bibliography style `abbrv'
+ % version 0.99a for BibTeX versions 0.99a or later, LaTeX version 2.09.
+ % Copyright (C) 1985, all rights reserved.
+ % Copying of this file is authorized only if either
+ % (1) you make absolutely no changes to your copy, including name, or
+ % (2) if you do make changes, you name it something other than
+ % btxbst.doc, plain.bst, unsrt.bst, alpha.bst, and abbrv.bst.
+ % This restriction helps ensure that all standard styles are identical.
+ % The file btxbst.doc has the documentation for this style.
+
+
+ENTRY
+ { address
+ author
+ booktitle
+ chapter
+ edition
+ editor
+ howpublished
+ institution
+ journal
+ key
+ month
+ note
+ number
+ organization
+ pages
+ publisher
+ school
+ series
+ title
+ type
+ volume
+ year
+ }
+ {}
+ { label }
+
+INTEGERS { output.state before.all mid.sentence after.sentence after.block }
+
+FUNCTION {init.state.consts}
+{ #0 'before.all :=
+ #1 'mid.sentence :=
+ #2 'after.sentence :=
+ #3 'after.block :=
+}
+
+STRINGS { s t }
+
+FUNCTION {output.nonnull}
+{ 's :=
+ output.state mid.sentence =
+ { ", " * write$ }
+ { output.state after.block =
+ { add.period$ write$
+ newline$
+ "\newblock " write$
+ }
+ { output.state before.all =
+ 'write$
+ { add.period$ " " * write$ }
+ if$
+ }
+ if$
+ mid.sentence 'output.state :=
+ }
+ if$
+ s
+}
+
+FUNCTION {output}
+{ duplicate$ empty$
+ 'pop$
+ 'output.nonnull
+ if$
+}
+
+FUNCTION {output.check}
+{ 't :=
+ duplicate$ empty$
+ { pop$ "empty " t * " in " * cite$ * warning$ }
+ 'output.nonnull
+ if$
+}
+
+FUNCTION {output.bibitem}
+{ newline$
+ "\bibitem{" write$
+ cite$ write$
+ "}" write$
+ newline$
+ ""
+ before.all 'output.state :=
+}
+
+FUNCTION {fin.entry}
+{ add.period$
+ write$
+ newline$
+}
+
+FUNCTION {new.block}
+{ output.state before.all =
+ 'skip$
+ { after.block 'output.state := }
+ if$
+}
+
+FUNCTION {new.sentence}
+{ output.state after.block =
+ 'skip$
+ { output.state before.all =
+ 'skip$
+ { after.sentence 'output.state := }
+ if$
+ }
+ if$
+}
+
+FUNCTION {not}
+{ { #0 }
+ { #1 }
+ if$
+}
+
+FUNCTION {and}
+{ 'skip$
+ { pop$ #0 }
+ if$
+}
+
+FUNCTION {or}
+{ { pop$ #1 }
+ 'skip$
+ if$
+}
+
+FUNCTION {new.block.checka}
+{ empty$
+ 'skip$
+ 'new.block
+ if$
+}
+
+FUNCTION {new.block.checkb}
+{ empty$
+ swap$ empty$
+ and
+ 'skip$
+ 'new.block
+ if$
+}
+
+FUNCTION {new.sentence.checka}
+{ empty$
+ 'skip$
+ 'new.sentence
+ if$
+}
+
+FUNCTION {new.sentence.checkb}
+{ empty$
+ swap$ empty$
+ and
+ 'skip$
+ 'new.sentence
+ if$
+}
+
+FUNCTION {field.or.null}
+{ duplicate$ empty$
+ { pop$ "" }
+ 'skip$
+ if$
+}
+
+FUNCTION {emphasize}
+{ duplicate$ empty$
+ { pop$ "" }
+ { "{\em " swap$ * "}" * }
+ if$
+}
+
+INTEGERS { nameptr namesleft numnames }
+
+FUNCTION {format.names}
+{ 's :=
+ #1 'nameptr :=
+ s num.names$ 'numnames :=
+ numnames 'namesleft :=
+ { namesleft #0 > }
+ { s nameptr "{f.~}{vv~}{ll}{, jj}" format.name$ 't :=
+ nameptr #1 >
+ { namesleft #1 >
+ { ", " * t * }
+ { numnames #2 >
+ { "," * }
+ 'skip$
+ if$
+ t "others" =
+ { " et~al." * }
+ { " and " * t * }
+ if$
+ }
+ if$
+ }
+ 't
+ if$
+ nameptr #1 + 'nameptr :=
+ namesleft #1 - 'namesleft :=
+ }
+ while$
+}
+
+FUNCTION {format.authors}
+{ author empty$
+ { "" }
+ { author format.names }
+ if$
+}
+
+FUNCTION {format.editors}
+{ editor empty$
+ { "" }
+ { editor format.names
+ editor num.names$ #1 >
+ { ", editors" * }
+ { ", editor" * }
+ if$
+ }
+ if$
+}
+
+FUNCTION {format.title}
+{ title empty$
+ { "" }
+ { title "t" change.case$ }
+ if$
+}
+
+FUNCTION {n.dashify}
+{ 't :=
+ ""
+ { t empty$ not }
+ { t #1 #1 substring$ "-" =
+ { t #1 #2 substring$ "--" = not
+ { "--" *
+ t #2 global.max$ substring$ 't :=
+ }
+ { { t #1 #1 substring$ "-" = }
+ { "-" *
+ t #2 global.max$ substring$ 't :=
+ }
+ while$
+ }
+ if$
+ }
+ { t #1 #1 substring$ *
+ t #2 global.max$ substring$ 't :=
+ }
+ if$
+ }
+ while$
+}
+
+FUNCTION {format.date}
+{ year empty$
+ { month empty$
+ { "" }
+ { "there's a month but no year in " cite$ * warning$
+ month
+ }
+ if$
+ }
+ { month empty$
+ 'year
+ { month " " * year * }
+ if$
+ }
+ if$
+}
+
+FUNCTION {format.btitle}
+{ title emphasize
+}
+
+FUNCTION {tie.or.space.connect}
+{ duplicate$ text.length$ #3 <
+ { "~" }
+ { " " }
+ if$
+ swap$ * *
+}
+
+FUNCTION {either.or.check}
+{ empty$
+ 'pop$
+ { "can't use both " swap$ * " fields in " * cite$ * warning$ }
+ if$
+}
+
+FUNCTION {format.bvolume}
+{ volume empty$
+ { "" }
+ { "volume" volume tie.or.space.connect
+ series empty$
+ 'skip$
+ { " of " * series emphasize * }
+ if$
+ "volume and number" number either.or.check
+ }
+ if$
+}
+
+FUNCTION {format.number.series}
+{ volume empty$
+ { number empty$
+ { series field.or.null }
+ { output.state mid.sentence =
+ { "number" }
+ { "Number" }
+ if$
+ number tie.or.space.connect
+ series empty$
+ { "there's a number but no series in " cite$ * warning$ }
+ { " in " * series * }
+ if$
+ }
+ if$
+ }
+ { "" }
+ if$
+}
+
+FUNCTION {format.edition}
+{ edition empty$
+ { "" }
+ { output.state mid.sentence =
+ { edition "l" change.case$ " edition" * }
+ { edition "t" change.case$ " edition" * }
+ if$
+ }
+ if$
+}
+
+INTEGERS { multiresult }
+
+FUNCTION {multi.page.check}
+{ 't :=
+ #0 'multiresult :=
+ { multiresult not
+ t empty$ not
+ and
+ }
+ { t #1 #1 substring$
+ duplicate$ "-" =
+ swap$ duplicate$ "," =
+ swap$ "+" =
+ or or
+ { #1 'multiresult := }
+ { t #2 global.max$ substring$ 't := }
+ if$
+ }
+ while$
+ multiresult
+}
+
+FUNCTION {format.pages}
+{ pages empty$
+ { "" }
+ { pages multi.page.check
+ { "pages" pages n.dashify tie.or.space.connect }
+ { "page" pages tie.or.space.connect }
+ if$
+ }
+ if$
+}
+
+FUNCTION {format.vol.num.pages}
+{ volume field.or.null
+ number empty$
+ 'skip$
+ { "(" number * ")" * *
+ volume empty$
+ { "there's a number but no volume in " cite$ * warning$ }
+ 'skip$
+ if$
+ }
+ if$
+ pages empty$
+ 'skip$
+ { duplicate$ empty$
+ { pop$ format.pages }
+ { ":" * pages n.dashify * }
+ if$
+ }
+ if$
+}
+
+FUNCTION {format.chapter.pages}
+{ chapter empty$
+ 'format.pages
+ { type empty$
+ { "chapter" }
+ { type "l" change.case$ }
+ if$
+ chapter tie.or.space.connect
+ pages empty$
+ 'skip$
+ { ", " * format.pages * }
+ if$
+ }
+ if$
+}
+
+FUNCTION {format.in.ed.booktitle}
+{ booktitle empty$
+ { "" }
+ { editor empty$
+ { "In " booktitle emphasize * }
+ { "In " format.editors * ", " * booktitle emphasize * }
+ if$
+ }
+ if$
+}
+
+FUNCTION {empty.misc.check}
+{ author empty$ title empty$ howpublished empty$
+ month empty$ year empty$ note empty$
+ and and and and and
+ key empty$ not and
+ { "all relevant fields are empty in " cite$ * warning$ }
+ 'skip$
+ if$
+}
+
+FUNCTION {format.thesis.type}
+{ type empty$
+ 'skip$
+ { pop$
+ type "t" change.case$
+ }
+ if$
+}
+
+FUNCTION {format.tr.number}
+{ type empty$
+ { "Technical Report" }
+ 'type
+ if$
+ number empty$
+ { "t" change.case$ }
+ { number tie.or.space.connect }
+ if$
+}
+
+FUNCTION {format.article.crossref}
+{ key empty$
+ { journal empty$
+ { "need key or journal for " cite$ * " to crossref " * crossref *
+ warning$
+ ""
+ }
+ { "In {\em " journal * "\/}" * }
+ if$
+ }
+ { "In " key * }
+ if$
+ " \cite{" * crossref * "}" *
+}
+
+FUNCTION {format.crossref.editor}
+{ editor #1 "{vv~}{ll}" format.name$
+ editor num.names$ duplicate$
+ #2 >
+ { pop$ " et~al." * }
+ { #2 <
+ 'skip$
+ { editor #2 "{ff }{vv }{ll}{ jj}" format.name$ "others" =
+ { " et~al." * }
+ { " and " * editor #2 "{vv~}{ll}" format.name$ * }
+ if$
+ }
+ if$
+ }
+ if$
+}
+
+FUNCTION {format.book.crossref}
+{ volume empty$
+ { "empty volume in " cite$ * "'s crossref of " * crossref * warning$
+ "In "
+ }
+ { "Volume" volume tie.or.space.connect
+ " of " *
+ }
+ if$
+ editor empty$
+ editor field.or.null author field.or.null =
+ or
+ { key empty$
+ { series empty$
+ { "need editor, key, or series for " cite$ * " to crossref " *
+ crossref * warning$
+ "" *
+ }
+ { "{\em " * series * "\/}" * }
+ if$
+ }
+ { key * }
+ if$
+ }
+ { format.crossref.editor * }
+ if$
+ " \cite{" * crossref * "}" *
+}
+
+FUNCTION {format.incoll.inproc.crossref}
+{ editor empty$
+ editor field.or.null author field.or.null =
+ or
+ { key empty$
+ { booktitle empty$
+ { "need editor, key, or booktitle for " cite$ * " to crossref " *
+ crossref * warning$
+ ""
+ }
+ { "In {\em " booktitle * "\/}" * }
+ if$
+ }
+ { "In " key * }
+ if$
+ }
+ { "In " format.crossref.editor * }
+ if$
+ " \cite{" * crossref * "}" *
+}
+
+FUNCTION {article}
+{ output.bibitem
+ format.authors "author" output.check
+ new.block
+ format.title "title" output.check
+ new.block
+ crossref missing$
+ { journal emphasize "journal" output.check
+ format.vol.num.pages output
+ format.date "year" output.check
+ }
+ { format.article.crossref output.nonnull
+ format.pages output
+ }
+ if$
+ new.block
+ note output
+ fin.entry
+}
+
+FUNCTION {book}
+{ output.bibitem
+ author empty$
+ { format.editors "author and editor" output.check }
+ { format.authors output.nonnull
+ crossref missing$
+ { "author and editor" editor either.or.check }
+ 'skip$
+ if$
+ }
+ if$
+ new.block
+ format.btitle "title" output.check
+ crossref missing$
+ { format.bvolume output
+ new.block
+ format.number.series output
+ new.sentence
+ publisher "publisher" output.check
+ address output
+ }
+ { new.block
+ format.book.crossref output.nonnull
+ }
+ if$
+ format.edition output
+ format.date "year" output.check
+ new.block
+ note output
+ fin.entry
+}
+
+FUNCTION {booklet}
+{ output.bibitem
+ format.authors output
+ new.block
+ format.title "title" output.check
+ howpublished address new.block.checkb
+ howpublished output
+ address output
+ format.date output
+ new.block
+ note output
+ fin.entry
+}
+
+FUNCTION {inbook}
+{ output.bibitem
+ author empty$
+ { format.editors "author and editor" output.check }
+ { format.authors output.nonnull
+ crossref missing$
+ { "author and editor" editor either.or.check }
+ 'skip$
+ if$
+ }
+ if$
+ new.block
+ format.btitle "title" output.check
+ crossref missing$
+ { format.bvolume output
+ format.chapter.pages "chapter and pages" output.check
+ new.block
+ format.number.series output
+ new.sentence
+ publisher "publisher" output.check
+ address output
+ }
+ { format.chapter.pages "chapter and pages" output.check
+ new.block
+ format.book.crossref output.nonnull
+ }
+ if$
+ format.edition output
+ format.date "year" output.check
+ new.block
+ note output
+ fin.entry
+}
+
+FUNCTION {incollection}
+{ output.bibitem
+ format.authors "author" output.check
+ new.block
+ format.title "title" output.check
+ new.block
+ crossref missing$
+ { format.in.ed.booktitle "booktitle" output.check
+ format.bvolume output
+ format.number.series output
+ format.chapter.pages output
+ new.sentence
+ publisher "publisher" output.check
+ address output
+ format.edition output
+ format.date "year" output.check
+ }
+ { format.incoll.inproc.crossref output.nonnull
+ format.chapter.pages output
+ }
+ if$
+ new.block
+ note output
+ fin.entry
+}
+
+FUNCTION {inproceedings}
+{ output.bibitem
+ format.authors "author" output.check
+ new.block
+ format.title "title" output.check
+ new.block
+ crossref missing$
+ { format.in.ed.booktitle "booktitle" output.check
+ format.bvolume output
+ format.number.series output
+ format.pages output
+ address empty$
+ { organization publisher new.sentence.checkb
+ organization output
+ publisher output
+ format.date "year" output.check
+ }
+ { address output.nonnull
+ format.date "year" output.check
+ new.sentence
+ organization output
+ publisher output
+ }
+ if$
+ }
+ { format.incoll.inproc.crossref output.nonnull
+ format.pages output
+ }
+ if$
+ new.block
+ note output
+ fin.entry
+}
+
+FUNCTION {conference} { inproceedings }
+
+FUNCTION {manual}
+{ output.bibitem
+ author empty$
+ { organization empty$
+ 'skip$
+ { organization output.nonnull
+ address output
+ }
+ if$
+ }
+ { format.authors output.nonnull }
+ if$
+ new.block
+ format.btitle "title" output.check
+ author empty$
+ { organization empty$
+ { address new.block.checka
+ address output
+ }
+ 'skip$
+ if$
+ }
+ { organization address new.block.checkb
+ organization output
+ address output
+ }
+ if$
+ format.edition output
+ format.date output
+ new.block
+ note output
+ fin.entry
+}
+
+FUNCTION {mastersthesis}
+{ output.bibitem
+ format.authors "author" output.check
+ new.block
+ format.title "title" output.check
+ new.block
+ "Master's thesis" format.thesis.type output.nonnull
+ school "school" output.check
+ address output
+ format.date "year" output.check
+ new.block
+ note output
+ fin.entry
+}
+
+FUNCTION {misc}
+{ output.bibitem
+ format.authors output
+ title howpublished new.block.checkb
+ format.title output
+ howpublished new.block.checka
+ howpublished output
+ format.date output
+ new.block
+ note output
+ fin.entry
+ empty.misc.check
+}
+
+FUNCTION {phdthesis}
+{ output.bibitem
+ format.authors "author" output.check
+ new.block
+ format.btitle "title" output.check
+ new.block
+ "PhD thesis" format.thesis.type output.nonnull
+ school "school" output.check
+ address output
+ format.date "year" output.check
+ new.block
+ note output
+ fin.entry
+}
+
+FUNCTION {proceedings}
+{ output.bibitem
+ editor empty$
+ { organization output }
+ { format.editors output.nonnull }
+ if$
+ new.block
+ format.btitle "title" output.check
+ format.bvolume output
+ format.number.series output
+ address empty$
+ { editor empty$
+ { publisher new.sentence.checka }
+ { organization publisher new.sentence.checkb
+ organization output
+ }
+ if$
+ publisher output
+ format.date "year" output.check
+ }
+ { address output.nonnull
+ format.date "year" output.check
+ new.sentence
+ editor empty$
+ 'skip$
+ { organization output }
+ if$
+ publisher output
+ }
+ if$
+ new.block
+ note output
+ fin.entry
+}
+
+FUNCTION {techreport}
+{ output.bibitem
+ format.authors "author" output.check
+ new.block
+ format.title "title" output.check
+ new.block
+ format.tr.number output.nonnull
+ institution "institution" output.check
+ address output
+ format.date "year" output.check
+ new.block
+ note output
+ fin.entry
+}
+
+FUNCTION {unpublished}
+{ output.bibitem
+ format.authors "author" output.check
+ new.block
+ format.title "title" output.check
+ new.block
+ note "note" output.check
+ format.date output
+ fin.entry
+}
+
+FUNCTION {default.type} { misc }
+
+MACRO {jan} {"Jan."}
+
+MACRO {feb} {"Feb."}
+
+MACRO {mar} {"Mar."}
+
+MACRO {apr} {"Apr."}
+
+MACRO {may} {"May"}
+
+MACRO {jun} {"June"}
+
+MACRO {jul} {"July"}
+
+MACRO {aug} {"Aug."}
+
+MACRO {sep} {"Sept."}
+
+MACRO {oct} {"Oct."}
+
+MACRO {nov} {"Nov."}
+
+MACRO {dec} {"Dec."}
+
+MACRO {acmcs} {"ACM Comput. Surv."}
+
+MACRO {acta} {"Acta Inf."}
+
+MACRO {cacm} {"Commun. ACM"}
+
+MACRO {ibmjrd} {"IBM J. Res. Dev."}
+
+MACRO {ibmsj} {"IBM Syst.~J."}
+
+MACRO {ieeese} {"IEEE Trans. Softw. Eng."}
+
+MACRO {ieeetc} {"IEEE Trans. Comput."}
+
+MACRO {ieeetcad}
+ {"IEEE Trans. Comput.-Aided Design Integrated Circuits"}
+
+MACRO {ipl} {"Inf. Process. Lett."}
+
+MACRO {jacm} {"J.~ACM"}
+
+MACRO {jcss} {"J.~Comput. Syst. Sci."}
+
+MACRO {scp} {"Sci. Comput. Programming"}
+
+MACRO {sicomp} {"SIAM J. Comput."}
+
+MACRO {tocs} {"ACM Trans. Comput. Syst."}
+
+MACRO {tods} {"ACM Trans. Database Syst."}
+
+MACRO {tog} {"ACM Trans. Gr."}
+
+MACRO {toms} {"ACM Trans. Math. Softw."}
+
+MACRO {toois} {"ACM Trans. Office Inf. Syst."}
+
+MACRO {toplas} {"ACM Trans. Prog. Lang. Syst."}
+
+MACRO {tcs} {"Theoretical Comput. Sci."}
+
+READ
+
+FUNCTION {sortify}
+{ purify$
+ "l" change.case$
+}
+
+INTEGERS { len }
+
+FUNCTION {chop.word}
+{ 's :=
+ 'len :=
+ s #1 len substring$ =
+ { s len #1 + global.max$ substring$ }
+ 's
+ if$
+}
+
+FUNCTION {sort.format.names}
+{ 's :=
+ #1 'nameptr :=
+ ""
+ s num.names$ 'numnames :=
+ numnames 'namesleft :=
+ { namesleft #0 > }
+ { nameptr #1 >
+ { " " * }
+ 'skip$
+ if$
+ s nameptr "{vv{ } }{ll{ }}{ f{ }}{ jj{ }}" format.name$ 't :=
+ nameptr numnames = t "others" = and
+ { "et al" * }
+ { t sortify * }
+ if$
+ nameptr #1 + 'nameptr :=
+ namesleft #1 - 'namesleft :=
+ }
+ while$
+}
+
+FUNCTION {sort.format.title}
+{ 't :=
+ "A " #2
+ "An " #3
+ "The " #4 t chop.word
+ chop.word
+ chop.word
+ sortify
+ #1 global.max$ substring$
+}
+
+FUNCTION {author.sort}
+{ author empty$
+ { key empty$
+ { "to sort, need author or key in " cite$ * warning$
+ ""
+ }
+ { key sortify }
+ if$
+ }
+ { author sort.format.names }
+ if$
+}
+
+FUNCTION {author.editor.sort}
+{ author empty$
+ { editor empty$
+ { key empty$
+ { "to sort, need author, editor, or key in " cite$ * warning$
+ ""
+ }
+ { key sortify }
+ if$
+ }
+ { editor sort.format.names }
+ if$
+ }
+ { author sort.format.names }
+ if$
+}
+
+FUNCTION {author.organization.sort}
+{ author empty$
+ { organization empty$
+ { key empty$
+ { "to sort, need author, organization, or key in " cite$ * warning$
+ ""
+ }
+ { key sortify }
+ if$
+ }
+ { "The " #4 organization chop.word sortify }
+ if$
+ }
+ { author sort.format.names }
+ if$
+}
+
+FUNCTION {editor.organization.sort}
+{ editor empty$
+ { organization empty$
+ { key empty$
+ { "to sort, need editor, organization, or key in " cite$ * warning$
+ ""
+ }
+ { key sortify }
+ if$
+ }
+ { "The " #4 organization chop.word sortify }
+ if$
+ }
+ { editor sort.format.names }
+ if$
+}
+
+FUNCTION {presort}
+{ type$ "book" =
+ type$ "inbook" =
+ or
+ 'author.editor.sort
+ { type$ "proceedings" =
+ 'editor.organization.sort
+ { type$ "manual" =
+ 'author.organization.sort
+ 'author.sort
+ if$
+ }
+ if$
+ }
+ if$
+ " "
+ *
+ year field.or.null sortify
+ *
+ " "
+ *
+ title field.or.null
+ sort.format.title
+ *
+ #1 entry.max$ substring$
+ 'sort.key$ :=
+}
+
+ITERATE {presort}
+
+SORT
+
+STRINGS { longest.label }
+
+INTEGERS { number.label longest.label.width }
+
+FUNCTION {initialize.longest.label}
+{ "" 'longest.label :=
+ #1 'number.label :=
+ #0 'longest.label.width :=
+}
+
+FUNCTION {longest.label.pass}
+{ number.label int.to.str$ 'label :=
+ number.label #1 + 'number.label :=
+ label width$ longest.label.width >
+ { label 'longest.label :=
+ label width$ 'longest.label.width :=
+ }
+ 'skip$
+ if$
+}
+
+EXECUTE {initialize.longest.label}
+
+ITERATE {longest.label.pass}
+
+FUNCTION {begin.bib}
+{ preamble$ empty$
+ 'skip$
+ { preamble$ write$ newline$ }
+ if$
+ "\begin{thebibliography}{" longest.label * "}" * write$ newline$
+}
+
+EXECUTE {begin.bib}
+
+EXECUTE {init.state.consts}
+
+ITERATE {call.type$}
+
+FUNCTION {end.bib}
+{ newline$
+ "\end{thebibliography}" write$ newline$
+}
+
+EXECUTE {end.bib}
diff --git a/src/txt/README b/src/txt/README
index 85f3c8b..c2f1e71 100644
--- a/src/txt/README
+++ b/src/txt/README
@@ -1,6 +1,6 @@
-JabRef 2.1
-----------
+JabRef 2.2 beta 2
+-----------------
Introduction:
@@ -80,6 +80,64 @@ If you choose languages other than English, some or all help pages may
appear in your chosen languages.
Change log:
+2.2b2 - Redesigned export functions to simplify GUI and provide "Export selected
+ entries" functionality. Export filter is now chosen using the file type
+ dropdown menu in the file dialog.
+ - Fixed bug that caused UnsupportedEncodingException on Windows when saving.
+ - Added warning dialog when exporting failed.
+ - Added fix for exporting special chars in RTF like ���...
+ - Added NameFormat LayoutFormatter based on Bibtex method name.format$
+ - Added Fetch from ArXiv.org to Web Search
+ [ 1587342 ] Quering ArXiv (and any OAI2 Repository)
+ - [ 1594123 ] Fixed: Failure to import big numbers in Bibtex
+ - [ 1594169 ] Fixed: Entry editor navigation between panels faulty
+ - [ 1588028 ] Fixed: Export HTML table has relative DOI URL
+ - [ 1601651 ] Fixed: PDF subdirectory - missing first character
+2.2b - Added Mark Schenk's advanced HTML export filter.
+ - Added options to copy/move/link to dragged linkable file (pdf, ps, etc.).
+ - Removed unnecessary output text when scanning for external file changes.
+ - Changed layout of entry editor to solve problem with collapsing text fields.
+ - Added first version of support for XMP-metadata in PDFs.
+ - "Import into..."
+ - Integrate with copy/move/link.
+ - Added option to write all/selected PDFs in database
+ - Added tooltips to database tabs showing the file's full path.
+ - Added function for setting or clearing specific fields in selected or
+ all entries.
+ - Setting a relative PDF/PS path in Database Properties now makes JabRef
+ look for the directory relative to the bib file's location.
+ - Removed Oxford comma from AuthorList...Comma-LayoutFormatters.
+ - Added LayoutFormatters that print the Oxford comma.
+ - Added missing space between abbreviated author first names:
+ William Andrew Paul => W. A. Paul (used to be W.A. Paul)
+ - Added LayoutFormatter for HTML paragraphs.
+ - Changing Database Properties now causes the database to be marked as changed.
+ - Improved simple search. Words are now treated as separate search terms,
+ and phrases can be indicated with "double quotes".
+ - When a letter key is pressed in the table, the first entry starting with the
+ same letter (in the current sort column) is selected.
+ - Bib files dragged into JabRef now appear in the Recent files menu.
+ - Fixed bug in import dialog.
+ - Better support for ISI files in general (should basically be better than INSPEC) including IEEE parsing.
+ - Added regular expression search for auto-linking. Search is now more flexible by default.
+ - Search operation also now search relative to the JabRef directory.
+ - General improvements in Inspec ISI handling.
+ - New LayoutFormatter: AuthorOrgSci - first author is in "last, first"
+ all others in "first last". First names are abbreviated.
+ - New LayoutFormatter: NoSpaceBetweenAbbreviations - spaces between multiple
+ abbreviated first names are removed.
+ - Improved PDF link resolver to produce proper URIs.
+ - [ 1503956 ] Fixed: Help text instead of Help icon.
+ - [ 1542552 ] Fixed: Wrong author import from ISI file.
+ - [ 1534537 ] Fixed: resize groups interface
+ - [ 1465610 ] Fixed: (Double-)Names containing hyphen (-) not handled correctly
+ - [ 1436014 ] Fixed: No comma added to separate keywords
+ - [ 1548875 ] Fixed: download pdf produces unsupported filename
+ - [ 1545601 ] Fixed: downloading pdf corrupts pdf field text
+ - [ 1285977 ] Fixed: Impossible to properly sort a numeric field
+ - [ 1535044 ] Fixed: Month sorting
+ - [ 1540646 ] Fixed: Default sort order: bibtexkey
+ - [ 1553552 ] Fixed: Not properly detecting changes to flag as changed
2.1 - Added capability to drag files and WWW links into JabRef. BibTeX files will be
opened normally, other files imported, and WWW links downloaded and imported.
- The -v command line option now makes the application only print version number
@@ -96,6 +154,9 @@ Change log:
while downloading PDF/PS file.
- Fixed bug (only in 2.1b2) in calling file open/save dialog on Mac OS X.
- Fixed bug that made duplicate resolver dialog pop under import inspection dialog.
+ - Fixed bug in windows-installer which prevented running JabRef from the
+ command-line with arguments.
+ - Added windows-installer-option to associate JabRef with .bib files.
2.1b2 - Added option to toggle floating of marked entries to the top of the table.
- Added option to open, append and import multiple BibTeX files.
- Improved support for LaTeX special characters in HTML and RTF representations.
diff --git a/src/txt/TODO b/src/txt/TODO
new file mode 100644
index 0000000..cc1aad0
--- /dev/null
+++ b/src/txt/TODO
@@ -0,0 +1,9 @@
+
+Chris:
+------
+ * Think about synchronizing XMP.
+ * Document data schema used (BibteXmp)
+ * Add build.xml target to export standalone XMPUtil for the CLI.
+ * Plugin-Architecture for LayoutFormatters.
+ * Allow search relativ to bibtex-file
+
\ No newline at end of file
diff --git a/src/windows/nsis/.cvsignore b/src/windows/nsis/.cvsignore
new file mode 100644
index 0000000..25d747f
--- /dev/null
+++ b/src/windows/nsis/.cvsignore
@@ -0,0 +1,2 @@
+dist
+JabRefSetup.exe
diff --git a/src/windows/nsis/README.txt b/src/windows/nsis/README.txt
new file mode 100644
index 0000000..51f5de4
--- /dev/null
+++ b/src/windows/nsis/README.txt
@@ -0,0 +1,38 @@
+
+JabRef Installer Documentation
+------------------------------
+
+How to build the installer:
+
+ * Create a build.properties file in root-directory and set the
+ nsis.executable variable to point to makensis.exe
+ * Run the win.installer.build target from the ant-file in root-directory.
+
+What is here?
+
+ * dist
+ * Should contain everything that is supposed to be shipped to the user.
+ * Run target win.installer.prepare to let this be created and filled.
+ * launcher.nsi - Will create the exe-wrapper.
+ * setup.nsi - Will create the installer.
+ * fileassoc.nsh - Helper script to set file-associations
+
+Requirements + Current Status
+
+ Exe-Wrapper:
+ * Pass arguments to JabRef [done]
+ * JabRef-Ico 16x16, 32x32, 48x48 [done]
+
+ Installer:
+ * Display GPL [done]
+ * Add file association for .bib (if desired) [done]
+ * Install into custom start-menu location (if desired) [done]
+ * Install onto desktop (if desired)
+ * Install onto quicklaunch (if desired)
+
+ Uninstaller:
+ * Uninstaller
+ * Allow to keep configuration
+
+ All:
+ * Localization
\ No newline at end of file
diff --git a/src/windows/nsis/fileassoc.nsh b/src/windows/nsis/fileassoc.nsh
new file mode 100644
index 0000000..c03f62e
--- /dev/null
+++ b/src/windows/nsis/fileassoc.nsh
@@ -0,0 +1,119 @@
+; fileassoc.nsh
+; File association helper macros
+; Written by Saivert
+;
+; Features automatic backup system and UPDATEFILEASSOC macro for
+; shell change notification.
+;
+; |> How to use <|
+; To associate a file with an application so you can double-click it in explorer, use
+; the APP_ASSOCIATE macro like this:
+;
+; Example:
+; !insertmacro APP_ASSOCIATE "txt" "myapp.textfile" "$INSTDIR\myapp.exe,0" \
+; "Open with myapp" "$INSTDIR\myapp.exe $\"%1$\""
+;
+; Never insert the APP_ASSOCIATE macro multiple times, it is only ment
+; to associate an application with a single file and using the
+; the "open" verb as default. To add more verbs (actions) to a file
+; use the APP_ASSOCIATE_ADDVERB macro.
+;
+; Example:
+; !insertmacro APP_ASSOCIATE_ADDVERB "myapp.textfile" "edit" "Edit with myapp" \
+; "$INSTDIR\myapp.exe /edit $\"%1$\""
+;
+; To have access to more options when registering the file association use the
+; APP_ASSOCIATE_EX macro. Here you can specify the verb and what verb is to be the
+; standard action (default verb).
+;
+; And finally: To remove the association from the registry use the APP_UNASSOCIATE
+; macro. Here is another example just to wrap it up:
+; !insertmacro APP_UNASSOCIATE "txt" "myapp.textfile"
+;
+; |> Note <|
+; When defining your file class string always use the short form of your application title
+; then a period (dot) and the type of file. This keeps the file class sort of unique.
+; Examples:
+; Winamp.Playlist
+; NSIS.Script
+; Photoshop.JPEGFile
+;
+; |> Tech info <|
+; The registry key layout for a file association is:
+; HKEY_CLASSES_ROOT
+; <applicationID> = <"description">
+; shell
+; <verb> = <"menu-item text">
+; command = <"command string">
+;
+
+!macro APP_ASSOCIATE EXT FILECLASS DESCRIPTION ICON COMMANDTEXT COMMAND
+ ; Backup the previously associated file class
+ ReadRegStr $R0 HKCR ".${EXT}" ""
+ WriteRegStr HKCR ".${EXT}" "${FILECLASS}_backup" "$R0"
+
+ WriteRegStr HKCR ".${EXT}" "" "${FILECLASS}"
+
+ WriteRegStr HKCR "${FILECLASS}" "" `${DESCRIPTION}`
+ WriteRegStr HKCR "${FILECLASS}\DefaultIcon" "" `${ICON}`
+ WriteRegStr HKCR "${FILECLASS}\shell" "" "open"
+ WriteRegStr HKCR "${FILECLASS}\shell\open" "" `${COMMANDTEXT}`
+ WriteRegStr HKCR "${FILECLASS}\shell\open\command" "" `${COMMAND}`
+!macroend
+
+!macro APP_ASSOCIATE_EX EXT FILECLASS DESCRIPTION ICON VERB DEFAULTVERB SHELLNEW COMMANDTEXT COMMAND
+ ; Backup the previously associated file class
+ ReadRegStr $R0 HKCR ".${EXT}" ""
+ WriteRegStr HKCR ".${EXT}" "${FILECLASS}_backup" "$R0"
+
+ WriteRegStr HKCR ".${EXT}" "" "${FILECLASS}"
+ StrCmp "${SHELLNEW}" "0" +2
+ WriteRegStr HKCR ".${EXT}\ShellNew" "NullFile" ""
+
+ WriteRegStr HKCR "${FILECLASS}" "" `${DESCRIPTION}`
+ WriteRegStr HKCR "${FILECLASS}\DefaultIcon" "" `${ICON}`
+ WriteRegStr HKCR "${FILECLASS}\shell" "" `${DEFAULTVERB}`
+ WriteRegStr HKCR "${FILECLASS}\shell\${VERB}" "" `${COMMANDTEXT}`
+ WriteRegStr HKCR "${FILECLASS}\shell\${VERB}\command" "" `${COMMAND}`
+!macroend
+
+!macro APP_ASSOCIATE_ADDVERB FILECLASS VERB COMMANDTEXT COMMAND
+ WriteRegStr HKCR "${FILECLASS}\shell\${VERB}" "" `${COMMANDTEXT}`
+ WriteRegStr HKCR "${FILECLASS}\shell\${VERB}\command" "" `${COMMAND}`
+!macroend
+
+!macro APP_ASSOCIATE_REMOVEVERB FILECLASS VERB
+ DeleteRegKey HKCR `${FILECLASS}\shell\${VERB}`
+!macroend
+
+
+!macro APP_UNASSOCIATE EXT FILECLASS
+ ; Backup the previously associated file class
+ ReadRegStr $R0 HKCR ".${EXT}" `${FILECLASS}_backup`
+ WriteRegStr HKCR ".${EXT}" "" "$R0"
+
+ DeleteRegKey HKCR `${FILECLASS}`
+!macroend
+
+!macro APP_ASSOCIATE_GETFILECLASS OUTPUT EXT
+ ReadRegStr ${OUTPUT} HKCR ".${EXT}" ""
+!macroend
+
+
+; !defines for use with SHChangeNotify
+!ifdef SHCNE_ASSOCCHANGED
+!undef SHCNE_ASSOCCHANGED
+!endif
+!define SHCNE_ASSOCCHANGED 0x08000000
+!ifdef SHCNF_FLUSH
+!undef SHCNF_FLUSH
+!endif
+!define SHCNF_FLUSH 0x1000
+
+!macro UPDATEFILEASSOC
+; Using the system.dll plugin to call the SHChangeNotify Win32 API function so we
+; can update the shell.
+ System::Call "shell32::SHChangeNotify(i,i,i,i) (${SHCNE_ASSOCCHANGED}, ${SHCNF_FLUSH}, 0, 0)"
+!macroend
+
+;EOF
\ No newline at end of file
diff --git a/src/windows/nsis/launcher.nsi b/src/windows/nsis/launcher.nsi
new file mode 100644
index 0000000..f7a4c3d
--- /dev/null
+++ b/src/windows/nsis/launcher.nsi
@@ -0,0 +1,106 @@
+;
+; JabRef Application launcher
+;
+; Script based upon:
+; Jelude launcher - http://www.sfu.ca/~tyuen/jelude/
+; Java Launcher http://nsis.sourceforge.net/archive/nsisweb.php?page=326&instances=0,64
+;
+; Christopher Oezbek - oezi at oezi.de - 2006
+
+;--------- CONFIGURATION ---------
+!define APPNAME "JabRef"
+!ifndef JARFILE
+ !define JARFILE "JabRef.jar"
+!endif
+!ifdef APPICON
+ Icon "${APPICON}"
+!endif
+Name "${APPNAME}"
+Caption "${APPNAME}"
+OutFile "dist\${APPNAME}.exe"
+;-------- END CONFIGURATION ------
+
+SilentInstall silent
+XPStyle on
+
+Section ""
+
+ Call GetJRE
+ Pop $R0
+
+ StrCpy $R1 ""
+ Call GetParameters
+ Pop $R1
+
+ StrCpy $R0 '"$R0" -jar "${JARFILE}" $R1'
+
+ SetOutPath $EXEDIR
+ Exec "$R0"
+
+ Quit
+SectionEnd
+
+Function GetParameters
+ Push $R0
+ Push $R1
+ Push $R2
+ StrCpy $R0 $CMDLINE 1
+ StrCpy $R1 '"'
+ StrCpy $R2 1
+ StrCmp $R0 '"' loop
+ StrCpy $R1 ' '
+ loop:
+ StrCpy $R0 $CMDLINE 1 $R2
+ StrCmp $R0 $R1 loop2
+ StrCmp $R0 "" loop2
+ IntOp $R2 $R2 + 1
+ Goto loop
+ loop2:
+ IntOp $R2 $R2 + 1
+ StrCpy $R0 $CMDLINE 1 $R2
+ StrCmp $R0 " " loop2
+ StrCpy $R0 $CMDLINE "" $R2
+ Pop $R2
+ Pop $R1
+ Exch $R0
+FunctionEnd
+
+Function GetJRE
+;
+; Find JRE (Java.exe)
+; 1 - in .\jre directory (JRE Installed with application)
+; 2 - in JAVA_HOME environment variable
+; 3 - in the registry
+; 4 - assume java.exe in current dir or PATH
+ Push $R0
+ Push $R1
+
+ ClearErrors
+ StrCpy $R0 "$EXEDIR\jre\bin\javaw.exe"
+ IfFileExists $R0 JreFound
+ StrCpy $R0 ""
+
+ ClearErrors
+ ReadEnvStr $R0 "JAVA_HOME"
+ StrCpy $R0 "$R0\bin\javaw.exe"
+ IfErrors 0 JreFound
+
+ ClearErrors
+ ReadRegStr $R1 HKLM "SOFTWARE\JavaSoft\Java Runtime Environment" "CurrentVersion"
+ ReadRegStr $R0 HKLM "SOFTWARE\JavaSoft\Java Runtime Environment\$R1" "JavaHome"
+ StrCpy $R0 "$R0\bin\javaw.exe"
+
+ IfErrors 0 JreFound
+ Sleep 800
+ MessageBox MB_ICONEXCLAMATION|MB_YESNO \
+ 'Could not find a Java Runtime Environment installed on your computer. \
+ $\nWithout it you cannot run "${APPNAME}". \
+ $\n$\nWould you like to visit the Java website to download it?' \
+ IDNO +2
+ ExecShell open "http://java.sun.com/getjava"
+ Quit
+
+ JreFound:
+ Pop $R1
+ Exch $R0
+FunctionEnd
\ No newline at end of file
diff --git a/src/windows/nsis/setup.nsi b/src/windows/nsis/setup.nsi
new file mode 100644
index 0000000..be360a0
--- /dev/null
+++ b/src/windows/nsis/setup.nsi
@@ -0,0 +1,159 @@
+# Auto-generated by EclipseNSIS Script Wizard
+# 29.12.2005 01:09:51
+
+!ifndef VERSION
+ !define VERSION "2.1"
+!endif
+
+Name "JabRef ${VERSION}"
+
+!define REGKEY "SOFTWARE\$(^Name)"
+!define COMPANY "JabRef Team"
+!define URL http://jabref.sourceforge.net/
+
+# MUI defines
+!define MUI_ICON "${NSISDIR}\Contrib\Graphics\Icons\modern-install-full.ico"
+!define MUI_FINISHPAGE_NOAUTOCLOSE
+!define MUI_STARTMENUPAGE_REGISTRY_ROOT HKLM
+!define MUI_STARTMENUPAGE_REGISTRY_KEY "Software\JabRef"
+!define MUI_STARTMENUPAGE_REGISTRY_VALUENAME StartMenuGroup
+!define MUI_STARTMENUPAGE_DEFAULT_FOLDER "JabRef"
+!define MUI_UNICON "${NSISDIR}\Contrib\Graphics\Icons\modern-uninstall-full.ico"
+!define MUI_FINISHPAGE_RUN $INSTDIR/JabRef.exe
+!define MUI_UNFINISHPAGE_NOAUTOCLOSE
+!define MUI_COMPONENTSPAGE_SMALLDESC
+
+# Included files
+!include Sections.nsh
+!include MUI.nsh
+!include fileassoc.nsh
+
+# Reserved Files
+
+# Variables
+Var StartMenuGroup
+
+# Installer pages
+!insertmacro MUI_PAGE_WELCOME
+!insertmacro MUI_PAGE_LICENSE dist/GPL.txt
+!insertmacro MUI_PAGE_DIRECTORY
+!insertmacro MUI_PAGE_STARTMENU Application $StartMenuGroup
+!insertmacro MUI_PAGE_COMPONENTS
+!insertmacro MUI_PAGE_INSTFILES
+!insertmacro MUI_PAGE_FINISH
+
+!insertmacro MUI_UNPAGE_CONFIRM
+!insertmacro MUI_UNPAGE_INSTFILES
+
+# Installer languages
+!insertmacro MUI_LANGUAGE English
+
+# Installer attributes
+OutFile JabRefSetup.exe
+InstallDir "$PROGRAMFILES\JabRef"
+CRCCheck on
+XPStyle on
+ShowInstDetails show
+VIProductVersion 1.3.0.0
+VIAddVersionKey ProductName "JabRef"
+VIAddVersionKey ProductVersion "${VERSION}"
+VIAddVersionKey CompanyName "${COMPANY}"
+VIAddVersionKey CompanyWebsite "${URL}"
+VIAddVersionKey FileVersion ""
+VIAddVersionKey FileDescription ""
+VIAddVersionKey LegalCopyright ""
+InstallDirRegKey HKLM "${REGKEY}" Path
+ShowUninstDetails show
+
+# Installer sections
+Section -Main SEC0000
+ SetOutPath $INSTDIR
+ SetOverwrite on
+ File /r dist\*.*
+ WriteRegStr HKLM "${REGKEY}\Components" Main 1
+SectionEnd
+
+Section "Associate .bib with JabRef" AssociateBib
+ !insertmacro APP_ASSOCIATE "bib" "JabRef.BibTeX" "BibTeX File" "$INSTDIR\JabRef.exe,0" "Open in JabRef" "$INSTDIR\JabRef.exe $\"%1$\""
+SectionEnd
+
+LangString DESC_AssociateBib {LANG_ENGLISH} "Will associate files of extension .bib with JabRef."
+
+!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN
+ !insertmacro MUI_DESCRIPTION_TEXT ${AssociateBib} $(DESC_AssociateBib)
+!insertmacro MUI_FUNCTION_DESCRIPTION_END
+
+Section "un.Associate .bib with JabRef" un.AssociateBib
+
+ !insertmacro APP_UNASSOCIATE "bib" "JabRef.BibTeX"
+
+SectionEnd
+
+
+
+Section -post SEC0001
+ WriteRegStr HKLM "${REGKEY}" Path $INSTDIR
+ WriteUninstaller $INSTDIR\uninstall.exe
+ !insertmacro MUI_STARTMENU_WRITE_BEGIN Application
+ SetOutPath $SMPROGRAMS\$StartMenuGroup
+ CreateShortCut "$SMPROGRAMS\$StartMenuGroup\Start $(^Name).lnk" $INSTDIR\JabRef.exe
+ CreateShortCut "$SMPROGRAMS\$StartMenuGroup\Uninstall $(^Name).lnk" $INSTDIR\uninstall.exe
+ !insertmacro MUI_STARTMENU_WRITE_END
+ WriteRegStr HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" DisplayName "$(^Name)"
+ WriteRegStr HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" DisplayVersion "${VERSION}"
+ WriteRegStr HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" Publisher "${COMPANY}"
+ WriteRegStr HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" URLInfoAbout "${URL}"
+ WriteRegStr HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" DisplayIcon $INSTDIR\uninstall.exe
+ WriteRegStr HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" UninstallString $INSTDIR\uninstall.exe
+ WriteRegDWORD HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" NoModify 1
+ WriteRegDWORD HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" NoRepair 1
+
+SectionEnd
+
+# Macro for selecting uninstaller sections
+!macro SELECT_UNSECTION SECTION_NAME UNSECTION_ID
+ Push $R0
+ ReadRegStr $R0 HKLM "${REGKEY}\Components" "${SECTION_NAME}"
+ StrCmp $R0 1 0 next${UNSECTION_ID}
+ !insertmacro SelectSection "${UNSECTION_ID}"
+ Goto done${UNSECTION_ID}
+next${UNSECTION_ID}:
+ !insertmacro UnselectSection "${UNSECTION_ID}"
+done${UNSECTION_ID}:
+ Pop $R0
+!macroend
+
+# Uninstaller sections
+Section /o un.Main UNSEC0000
+ Delete /REBOOTOK $INSTDIR\jabref.jar
+ Delete /REBOOTOK $INSTDIR\JabRef.exe
+ Delete /REBOOTOK $INSTDIR\GPL.txt
+ Delete /REBOOTOK $INSTDIR\Credits.txt
+ DeleteRegValue HKLM "${REGKEY}\Components" Main
+SectionEnd
+
+Section un.post UNSEC0001
+ DeleteRegKey HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)"
+ Delete /REBOOTOK "$SMPROGRAMS\$StartMenuGroup\Uninstall $(^Name).lnk"
+ Delete /REBOOTOK "$SMPROGRAMS\$StartMenuGroup\Start $(^Name).lnk"
+ Delete /REBOOTOK $INSTDIR\uninstall.exe
+ DeleteRegValue HKLM "${REGKEY}" StartMenuGroup
+ DeleteRegValue HKLM "${REGKEY}" Path
+ DeleteRegKey /ifempty HKLM "${REGKEY}\Components"
+ DeleteRegKey /ifempty HKLM "${REGKEY}"
+ RMDir /REBOOTOK $SMPROGRAMS\$StartMenuGroup
+ RMDir /REBOOTOK $INSTDIR
+SectionEnd
+
+# Installer functions
+Function .onInit
+ InitPluginsDir
+FunctionEnd
+
+# Uninstaller functions
+Function un.onInit
+ ReadRegStr $INSTDIR HKLM "${REGKEY}" Path
+ ReadRegStr $StartMenuGroup HKLM "${REGKEY}" StartMenuGroup
+ !insertmacro SELECT_UNSECTION Main ${UNSEC0000}
+FunctionEnd
+
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-java/jabref.git
More information about the pkg-java-commits
mailing list