[jabref] 01/459: [svn-inject] Installing original source of jabref

gregor herrmann gregoa at debian.org
Thu Sep 15 20:39:27 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 3c53380dc7863abeee9ba1f8fb61d875bd5a9022
Author: gregor herrmann <gregoa at debian.org>
Date:   Sat Feb 25 17:54:00 2006 +0000

    [svn-inject] Installing original source of jabref
---
 build.number                                       |    3 +
 build.xml                                          |  483 ++++
 lib/EndNote.zip                                    |  Bin 0 -> 20530 bytes
 lib/JavaApplicationStub                            |  Bin 0 -> 51856 bytes
 lib/OSXAdapter.class                               |  Bin 0 -> 1815 bytes
 lib/antlr.jar                                      |  Bin 0 -> 435563 bytes
 lib/forms-1.0.4.jar                                |  Bin 0 -> 83278 bytes
 lib/glazedlists-1.5.0_java14.jar                   |  Bin 0 -> 341472 bytes
 lib/jarbundler-1.4.jar                             |  Bin 0 -> 13141 bytes
 lib/looks-1.2.2.jar                                |  Bin 0 -> 324952 bytes
 lib/spin.jar                                       |  Bin 0 -> 49065 bytes
 src/help/About.html                                |   98 +
 src/help/BaseFrameHelp.html                        |   90 +
 src/help/BibtexHelp.html                           |   50 +
 src/help/CiteSeerHelp.html                         |   44 +
 src/help/CommandLine.html                          |   85 +
 src/help/ContentSelectorHelp.html                  |   32 +
 src/help/Contents.html                             |   44 +
 src/help/CustomEntriesHelp.html                    |   70 +
 src/help/CustomExports.html                        |  172 ++
 src/help/CustomImports.html                        |  125 +
 src/help/EndNoteFilters.html                       |  105 +
 src/help/EntryEditorHelp.html                      |  102 +
 src/help/ExternalFiles.html                        |   41 +
 src/help/GeneralFields.html                        |   25 +
 src/help/GroupsHelp.html                           |  255 ++
 src/help/HelpHelp.html                             |   27 +
 src/help/ImportInspectionDialog.html               |   22 +
 src/help/JabRef-UserManual.lyx                     |  229 ++
 src/help/JabRefHelp.html                           |   33 +
 src/help/JournalAbbreviations.html                 |   75 +
 src/help/LabelPatterns.html                        |   98 +
 src/help/LabelPatterns.txt                         |   33 +
 src/help/License.html                              |  494 ++++
 src/help/MarkingHelp.html                          |   20 +
 src/help/MedlineHelp.html                          |   35 +
 src/help/OpenOfficeHelp.html                       |   53 +
 src/help/OwnerHelp.html                            |   15 +
 src/help/PreviewHelp.html                          |   17 +
 src/help/RemoteHelp.html                           |   35 +
 src/help/SearchHelp.html                           |   67 +
 src/help/ShortIntegrityCheck.html                  |    8 +
 src/help/ShortPlainImport.html                     |    7 +
 src/help/StringEditorHelp.html                     |   41 +
 src/help/TimeStampHelp.html                        |   37 +
 src/help/autumn.png                                |  Bin 0 -> 307468 bytes
 src/help/cpl-v10.html                              |  125 +
 src/help/credits.txt                               |   38 +
 src/help/de/About.html                             |   77 +
 src/help/de/BaseFrameHelp.html                     |   61 +
 src/help/de/BibtexHelp.html                        |   33 +
 src/help/de/CiteSeerHelp.html                      |   53 +
 src/help/de/CommandLine.html                       |   93 +
 src/help/de/ContentSelectorHelp.html               |   37 +
 src/help/de/Contents.html                          |   35 +
 src/help/de/CustomEntriesHelp.html                 |   73 +
 src/help/de/CustomExports.html                     |  179 ++
 src/help/de/CustomImports.html                     |  131 +
 src/help/de/EndNoteFilters.html                    |  101 +
 src/help/de/EntryEditorHelp.html                   |  104 +
 src/help/de/ExternalFiles.html                     |   57 +
 src/help/de/GeneralFields.html                     |   29 +
 src/help/de/GroupsHelp.html                        |  137 +
 src/help/de/HelpHelp.html                          |   23 +
 src/help/de/ImportInspectionDialog.html            |   16 +
 src/help/de/JabRef-UserManual_de.bib               |   52 +
 src/help/de/JabRef-UserManual_de.tex               | 2601 +++++++++++++++++++
 src/help/de/JabRefHelp.html                        |   20 +
 src/help/de/LabelPatterns.html                     |   89 +
 src/help/de/MarkingHelp.html                       |   24 +
 src/help/de/MedlineHelp.html                       |   34 +
 src/help/de/OpenOfficeHelp.html                    |   46 +
 src/help/de/OwnerHelp.html                         |   16 +
 src/help/de/PreviewHelp.html                       |   12 +
 src/help/de/SearchHelp.html                        |   56 +
 src/help/de/ShortIntegrityCheck.html               |    8 +
 src/help/de/ShortPlainImport.html                  |    8 +
 src/help/de/StringEditorHelp.html                  |   41 +
 src/help/de/TimeStampHelp.html                     |   35 +
 src/help/fr/About.html                             |   91 +
 src/help/fr/BaseFrameHelp.html                     |   94 +
 src/help/fr/BibtexHelp.html                        |   50 +
 src/help/fr/CiteSeerHelp.html                      |   43 +
 src/help/fr/CommandLine.html                       |  116 +
 src/help/fr/ContentSelectorHelp.html               |   24 +
 src/help/fr/Contents.html                          |   47 +
 src/help/fr/CustomEntriesHelp.html                 |   80 +
 src/help/fr/CustomExports.html                     |  176 ++
 src/help/fr/CustomImports.html                     |   95 +
 src/help/fr/EndNoteFilters.html                    |  127 +
 src/help/fr/EntryEditorHelp.html                   |  114 +
 src/help/fr/ExternalFiles.html                     |   67 +
 src/help/fr/GeneralFields.html                     |   25 +
 src/help/fr/GroupsHelp.html                        |  136 +
 src/help/fr/HelpHelp.html                          |   30 +
 src/help/fr/ImportInspectionDialog.html            |   19 +
 src/help/fr/JabRefHelp.html                        |   34 +
 src/help/fr/JournalAbbreviations.html              |   52 +
 src/help/fr/LabelPatterns.html                     |   80 +
 src/help/fr/MarkingHelp.html                       |   26 +
 src/help/fr/MedlineHelp.html                       |   43 +
 src/help/fr/OpenOfficeHelp.html                    |   45 +
 src/help/fr/OwnerHelp.html                         |   16 +
 src/help/fr/PreviewHelp.html                       |   17 +
 src/help/fr/RemoteHelp.html                        |   34 +
 src/help/fr/SearchHelp.html                        |   87 +
 src/help/fr/ShortIntegrityCheck.html               |    8 +
 src/help/fr/ShortPlainImport.html                  |    9 +
 src/help/fr/StringEditorHelp.html                  |   43 +
 src/help/fr/TimeStampHelp.html                     |   40 +
 src/help/jgoodies.html                             |   25 +
 src/help/no/ShortPlainImport.html                  |    8 +
 src/images/Close.gif                               |  Bin 0 -> 119 bytes
 src/images/CopyKey.gif                             |  Bin 0 -> 239 bytes
 src/images/Hourglass.png                           |  Bin 0 -> 558 bytes
 src/images/JabRef-Logo-small.gif                   |  Bin 0 -> 717 bytes
 src/images/JabRef-Logo.icns                        |  Bin 0 -> 35556 bytes
 src/images/JabRef-icon.png                         |  Bin 0 -> 747 bytes
 src/images/absIcon.png                             |  Bin 0 -> 180 bytes
 src/images/addtsk_tsk.gif                          |  Bin 0 -> 125 bytes
 src/images/backward_nav.gif                        |  Bin 0 -> 108 bytes
 src/images/close_view.gif                          |  Bin 0 -> 73 bytes
 src/images/completeItem.png                        |  Bin 0 -> 458 bytes
 src/images/configure2.png                          |  Bin 0 -> 332 bytes
 src/images/contents2.png                           |  Bin 0 -> 257 bytes
 src/images/copy_edit.gif                           |  Bin 0 -> 167 bytes
 src/images/cut_edit.gif                            |  Bin 0 -> 152 bytes
 src/images/defaults_ps.gif                         |  Bin 0 -> 241 bytes
 src/images/delete_edit.gif                         |  Bin 0 -> 143 bytes
 src/images/doismall.png                            |  Bin 0 -> 738 bytes
 src/images/duplicate.png                           |  Bin 0 -> 359 bytes
 src/images/editcopy.png                            |  Bin 0 -> 235 bytes
 src/images/editcut.png                             |  Bin 0 -> 249 bytes
 src/images/editdelete.png                          |  Bin 0 -> 214 bytes
 src/images/editpaste.png                           |  Bin 0 -> 283 bytes
 src/images/edittsk_tsk.gif                         |  Bin 0 -> 149 bytes
 src/images/emacs.png                               |  Bin 0 -> 272 bytes
 src/images/exclamation.gif                         |  Bin 0 -> 139 bytes
 src/images/fileclose.png                           |  Bin 0 -> 238 bytes
 src/images/fileclose2.png                          |  Bin 0 -> 250 bytes
 src/images/fldr_obj.gif                            |  Bin 0 -> 152 bytes
 src/images/forward_nav.gif                         |  Bin 0 -> 138 bytes
 src/images/g_icon.gif                              |  Bin 0 -> 123 bytes
 src/images/genIcon.png                             |  Bin 0 -> 180 bytes
 src/images/goto.png                                |  Bin 0 -> 240 bytes
 src/images/groupIncluding.png                      |  Bin 0 -> 169 bytes
 src/images/groupRefining.png                       |  Bin 0 -> 160 bytes
 src/images/groupsHighlightAll.png                  |  Bin 0 -> 240 bytes
 src/images/groupsHighlightAny.png                  |  Bin 0 -> 239 bytes
 src/images/incomplete.png                          |  Bin 0 -> 387 bytes
 src/images/integrity.png                           |  Bin 0 -> 748 bytes
 src/images/jabref-2.0-splash.png                   |  Bin 0 -> 177980 bytes
 src/images/lyx2.png                                |  Bin 0 -> 483 bytes
 src/images/mark.png                                |  Bin 0 -> 345 bytes
 src/images/messageFail.png                         |  Bin 0 -> 937 bytes
 src/images/messageInfo.png                         |  Bin 0 -> 978 bytes
 src/images/messageWarn.png                         |  Bin 0 -> 1014 bytes
 src/images/minus.gif                               |  Bin 0 -> 845 bytes
 src/images/newBibFile.png                          |  Bin 0 -> 702 bytes
 src/images/new_page.gif                            |  Bin 0 -> 127 bytes
 src/images/new_wiz.gif                             |  Bin 0 -> 226 bytes
 src/images/next_nav.gif                            |  Bin 0 -> 105 bytes
 src/images/o_icon.gif                              |  Bin 0 -> 123 bytes
 src/images/optIcon.png                             |  Bin 0 -> 200 bytes
 src/images/paste_edit.gif                          |  Bin 0 -> 245 bytes
 src/images/pdf.png                                 |  Bin 0 -> 349 bytes
 src/images/pdf_small.gif                           |  Bin 0 -> 865 bytes
 src/images/plus.gif                                |  Bin 0 -> 859 bytes
 src/images/postscript.png                          |  Bin 0 -> 233 bytes
 src/images/preamble.png                            |  Bin 0 -> 264 bytes
 src/images/prev_nav.gif                            |  Bin 0 -> 132 bytes
 src/images/preview.png                             |  Bin 0 -> 218 bytes
 src/images/queue.png                               |  Bin 0 -> 185 bytes
 src/images/r_icon.gif                              |  Bin 0 -> 99 bytes
 src/images/redo_edit.gif                           |  Bin 0 -> 146 bytes
 src/images/refresh_nav.gif                         |  Bin 0 -> 182 bytes
 src/images/reqIcon.png                             |  Bin 0 -> 182 bytes
 src/images/run.png                                 |  Bin 0 -> 314 bytes
 src/images/save_edit.gif                           |  Bin 0 -> 187 bytes
 src/images/saveas_edit.gif                         |  Bin 0 -> 173 bytes
 src/images/search.gif                              |  Bin 0 -> 153 bytes
 src/images/showerr_tsk.gif                         |  Bin 0 -> 167 bytes
 src/images/strings.png                             |  Bin 0 -> 233 bytes
 src/images/toc_closed.gif                          |  Bin 0 -> 158 bytes
 src/images/undo_edit.gif                           |  Bin 0 -> 147 bytes
 src/images/unmark.png                              |  Bin 0 -> 410 bytes
 src/images/up_nav.gif                              |  Bin 0 -> 165 bytes
 src/images/view.gif                                |  Bin 0 -> 169 bytes
 src/images/viewsource.gif                          |  Bin 0 -> 119 bytes
 src/images/window_nofullscreen.png                 |  Bin 0 -> 183 bytes
 src/images/winedt.png                              |  Bin 0 -> 944 bytes
 src/images/wizard.png                              |  Bin 0 -> 265 bytes
 src/images/wrongItem.png                           |  Bin 0 -> 776 bytes
 src/images/www.png                                 |  Bin 0 -> 725 bytes
 src/images/wwwciteseer.png                         |  Bin 0 -> 478 bytes
 src/java/Eclipse_formatter.xml                     |  186 ++
 .../jgoodies/uif_lite/component/UIFSplitPane.java  |  270 ++
 .../uif_lite/panel/SimpleInternalFrame.java        |  474 ++++
 src/java/gnu/dtools/ritopt/ArrayOption.java        |   82 +
 src/java/gnu/dtools/ritopt/BooleanOption.java      |  245 ++
 src/java/gnu/dtools/ritopt/ByteOption.java         |  203 ++
 src/java/gnu/dtools/ritopt/CharOption.java         |  196 ++
 src/java/gnu/dtools/ritopt/DoubleOption.java       |  203 ++
 src/java/gnu/dtools/ritopt/FloatOption.java        |  203 ++
 src/java/gnu/dtools/ritopt/IntOption.java          |  204 ++
 src/java/gnu/dtools/ritopt/LongOption.java         |  203 ++
 src/java/gnu/dtools/ritopt/NotifyOption.java       |  318 +++
 src/java/gnu/dtools/ritopt/Option.java             |  913 +++++++
 src/java/gnu/dtools/ritopt/OptionArrayable.java    |   65 +
 src/java/gnu/dtools/ritopt/OptionEvent.java        |  195 ++
 src/java/gnu/dtools/ritopt/OptionException.java    |   48 +
 src/java/gnu/dtools/ritopt/OptionListener.java     |   54 +
 src/java/gnu/dtools/ritopt/OptionMenu.java         |  271 ++
 src/java/gnu/dtools/ritopt/OptionModifiable.java   |   48 +
 .../dtools/ritopt/OptionModificationException.java |   49 +
 src/java/gnu/dtools/ritopt/OptionModule.java       |  450 ++++
 .../gnu/dtools/ritopt/OptionModuleRegistrar.java   |   62 +
 src/java/gnu/dtools/ritopt/OptionNotifier.java     |   57 +
 .../dtools/ritopt/OptionProcessingException.java   |   49 +
 src/java/gnu/dtools/ritopt/OptionRegistrar.java    |   98 +
 .../dtools/ritopt/OptionRegistrationException.java |   78 +
 src/java/gnu/dtools/ritopt/Options.java            |  872 +++++++
 src/java/gnu/dtools/ritopt/ShortOption.java        |  202 ++
 src/java/gnu/dtools/ritopt/SimpleProcess.java      |  217 ++
 src/java/gnu/dtools/ritopt/Stoppable.java          |   46 +
 src/java/gnu/dtools/ritopt/StreamPrinter.java      |  191 ++
 src/java/gnu/dtools/ritopt/StringOption.java       |  184 ++
 src/java/gnu/dtools/ritopt/Utility.java            |  339 +++
 src/java/jalopy.format.convention.xml              |  406 +++
 src/java/net/sf/ext/BrowserLauncher.java           |  596 +++++
 src/java/net/sf/jabref/AbstractWorker.java         |   51 +
 src/java/net/sf/jabref/AdvancedTab.java            |  158 ++
 src/java/net/sf/jabref/AppearancePrefsTab.java     |  157 ++
 src/java/net/sf/jabref/AuthorList.java             |  820 ++++++
 src/java/net/sf/jabref/BaseAction.java             |   10 +
 src/java/net/sf/jabref/BasePanel.java              | 2562 +++++++++++++++++++
 src/java/net/sf/jabref/BibtexDatabase.java         |  530 ++++
 src/java/net/sf/jabref/BibtexEntry.java            |  415 +++
 src/java/net/sf/jabref/BibtexEntryType.java        |  803 ++++++
 src/java/net/sf/jabref/BibtexString.java           |   68 +
 src/java/net/sf/jabref/BibtexStringComparator.java |  106 +
 src/java/net/sf/jabref/CallBack.java               |    8 +
 src/java/net/sf/jabref/CheckBoxMessage.java        |   36 +
 src/java/net/sf/jabref/ClipBoardManager.java       |   78 +
 src/java/net/sf/jabref/ContentSelectorDialog.java  |  309 +++
 src/java/net/sf/jabref/ContentSelectorDialog2.java |  438 ++++
 .../net/sf/jabref/CrossRefEntryComparator.java     |   57 +
 src/java/net/sf/jabref/CustomEntryType.java        |  118 +
 src/java/net/sf/jabref/DatabaseChangeEvent.java    |   36 +
 src/java/net/sf/jabref/DatabaseChangeListener.java |    8 +
 src/java/net/sf/jabref/DatabaseSearch.java         |  107 +
 src/java/net/sf/jabref/DisplayPanel.java           |   29 +
 .../net/sf/jabref/DuplicateResolverDialog.java     |  216 ++
 src/java/net/sf/jabref/DuplicateSearch.java        |  194 ++
 src/java/net/sf/jabref/EntryComparator.java        |  144 ++
 .../net/sf/jabref/EntryCustomizationDialog.java    |  428 ++++
 src/java/net/sf/jabref/EntryEditor.java            | 1379 ++++++++++
 src/java/net/sf/jabref/EntryEditorTab.java         |  293 +++
 src/java/net/sf/jabref/EntryEditorTabList.java     |   45 +
 src/java/net/sf/jabref/EntrySorter.java            |  188 ++
 src/java/net/sf/jabref/EntryTable.java             |  845 +++++++
 src/java/net/sf/jabref/EntryTableModel.java        |  587 +++++
 src/java/net/sf/jabref/EntryTypeDialog.java        |  149 ++
 src/java/net/sf/jabref/ErrorMessageDisplay.java    |   25 +
 src/java/net/sf/jabref/ExternalProgramsTab.java    |  134 +
 src/java/net/sf/jabref/ExternalTab.java            |  186 ++
 src/java/net/sf/jabref/FieldComparator.java        |   80 +
 src/java/net/sf/jabref/FieldComparatorStack.java   |   29 +
 src/java/net/sf/jabref/FieldContentSelector.java   |  240 ++
 src/java/net/sf/jabref/FieldEditor.java            |   52 +
 .../net/sf/jabref/FieldEditorFocusListener.java    |   30 +
 src/java/net/sf/jabref/FieldNameLabel.java         |   28 +
 src/java/net/sf/jabref/FieldTextArea.java          |  193 ++
 src/java/net/sf/jabref/FieldTextField.java         |   97 +
 src/java/net/sf/jabref/FieldTextMenu.java          |  268 ++
 src/java/net/sf/jabref/FileHistory.java            |  121 +
 src/java/net/sf/jabref/FocusRequester.java         |   25 +
 src/java/net/sf/jabref/FontSelectorDialog.java     |  419 +++
 src/java/net/sf/jabref/GUIGlobals.java             |  565 +++++
 src/java/net/sf/jabref/GeneralRenderer.java        |   73 +
 src/java/net/sf/jabref/GeneralTab.java             |  342 +++
 src/java/net/sf/jabref/GlobalFocusListener.java    |   27 +
 src/java/net/sf/jabref/Globals.java                |  965 +++++++
 src/java/net/sf/jabref/HelpAction.java             |  144 ++
 src/java/net/sf/jabref/HelpContent.java            |  202 ++
 src/java/net/sf/jabref/HelpDialog.java             |  167 ++
 src/java/net/sf/jabref/IconStringRenderer.java     |   42 +
 src/java/net/sf/jabref/IncrementalSearcher.java    |   83 +
 src/java/net/sf/jabref/JabRef.java                 |  784 ++++++
 src/java/net/sf/jabref/JabRefFileChooser.java      |   97 +
 src/java/net/sf/jabref/JabRefFrame.java            | 2663 ++++++++++++++++++++
 src/java/net/sf/jabref/JabRefPreferences.java      |  862 +++++++
 src/java/net/sf/jabref/KeyBindingsDialog.java      |  362 +++
 src/java/net/sf/jabref/KeyCollisionException.java  |   49 +
 src/java/net/sf/jabref/MarkedComparator.java       |   41 +
 src/java/net/sf/jabref/MergeDialog.java            |  130 +
 src/java/net/sf/jabref/MetaData.java               |  228 ++
 src/java/net/sf/jabref/MnemonicAwareAction.java    |   64 +
 src/java/net/sf/jabref/NameCache.java              |   33 +
 src/java/net/sf/jabref/OpenFileFilter.java         |  102 +
 src/java/net/sf/jabref/PreambleEditor.java         |  221 ++
 src/java/net/sf/jabref/PrefsDialog2.java           |  150 ++
 src/java/net/sf/jabref/PrefsDialog3.java           |  300 +++
 src/java/net/sf/jabref/PrefsTab.java               |   34 +
 src/java/net/sf/jabref/PreviewPanel.java           |  226 ++
 src/java/net/sf/jabref/PreviewPrefsTab.java        |  204 ++
 src/java/net/sf/jabref/RegExpRule.java             |   86 +
 src/java/net/sf/jabref/ReplaceStringDialog.java    |  237 ++
 src/java/net/sf/jabref/RightClickMenu.java         |  340 +++
 src/java/net/sf/jabref/SearchManager2.java         |  574 +++++
 src/java/net/sf/jabref/SearchRule.java             |   37 +
 src/java/net/sf/jabref/SearchRuleSet.java          |   52 +
 src/java/net/sf/jabref/SidePane.java               |  114 +
 src/java/net/sf/jabref/SidePaneComponent.java      |  115 +
 src/java/net/sf/jabref/SidePaneHeader.java         |  130 +
 src/java/net/sf/jabref/SidePaneManager.java        |  227 ++
 src/java/net/sf/jabref/SimpleSearchRule.java       |   72 +
 src/java/net/sf/jabref/SimpleUrlDragDrop.java      |  153 ++
 src/java/net/sf/jabref/SplashScreen.java           |  110 +
 src/java/net/sf/jabref/StrictDuplicateSearch.java  |   86 +
 src/java/net/sf/jabref/StringDialog.java           |  550 ++++
 src/java/net/sf/jabref/TabLabelPattern.java        |  409 +++
 src/java/net/sf/jabref/TableColumnsTab.java        |  397 +++
 src/java/net/sf/jabref/TablePrefsTab.java          |  312 +++
 src/java/net/sf/jabref/TitleLabel.java             |   17 +
 .../net/sf/jabref/TransferableBibtexEntry.java     |   79 +
 src/java/net/sf/jabref/UnknownEntryType.java       |   49 +
 src/java/net/sf/jabref/UrlDragDrop.java            |  219 ++
 src/java/net/sf/jabref/Util.java                   | 1365 ++++++++++
 src/java/net/sf/jabref/Worker.java                 |   13 +
 src/java/net/sf/jabref/about/About2.java           |  102 +
 src/java/net/sf/jabref/about/AboutPanel.java       |  487 ++++
 src/java/net/sf/jabref/about/AboutTextLine.java    |  226 ++
 .../net/sf/jabref/about/AnimationListener.java     |   44 +
 .../net/sf/jabref/about/ExtendedInfoPanel.java     |  179 ++
 src/java/net/sf/jabref/about/HighlightFilter.java  |  104 +
 src/java/net/sf/jabref/about/NewAboutAction.java   |   67 +
 src/java/net/sf/jabref/about/TextBlock.java        |   85 +
 .../DetectSwingSingleThreadRuleViolations.aj       |   41 +
 src/java/net/sf/jabref/collab/Change.java          |   64 +
 .../net/sf/jabref/collab/ChangeDisplayDialog.java  |  117 +
 src/java/net/sf/jabref/collab/ChangeScanner.java   |  502 ++++
 src/java/net/sf/jabref/collab/EntryAddChange.java  |   44 +
 src/java/net/sf/jabref/collab/EntryChange.java     |  151 ++
 .../net/sf/jabref/collab/EntryDeleteChange.java    |   50 +
 .../net/sf/jabref/collab/FileUpdateListener.java   |   15 +
 .../net/sf/jabref/collab/FileUpdateMonitor.java    |  223 ++
 src/java/net/sf/jabref/collab/FileUpdatePanel.java |   59 +
 src/java/net/sf/jabref/collab/GroupChange.java     |   43 +
 src/java/net/sf/jabref/collab/InfoPane.java        |   19 +
 src/java/net/sf/jabref/collab/PreambleChange.java  |   51 +
 src/java/net/sf/jabref/collab/StringAddChange.java |   57 +
 src/java/net/sf/jabref/collab/StringChange.java    |   70 +
 .../net/sf/jabref/collab/StringNameChange.java     |   55 +
 .../net/sf/jabref/collab/StringRemoveChange.java   |   53 +
 .../net/sf/jabref/export/CustomExportDialog.java   |  250 ++
 .../net/sf/jabref/export/CustomExportList.java     |   80 +
 .../net/sf/jabref/export/ExpandEndnoteFilters.java |   67 +
 .../net/sf/jabref/export/ExportComparator.java     |   13 +
 .../jabref/export/ExportCustomizationDialog.java   |  159 ++
 src/java/net/sf/jabref/export/FieldFormatter.java  |   43 +
 src/java/net/sf/jabref/export/FileActions.java     |  724 ++++++
 .../net/sf/jabref/export/LatexFieldFormatter.java  |  201 ++
 src/java/net/sf/jabref/export/OOCalcDatabase.java  |  196 ++
 .../jabref/export/OpenDocumentRepresentation.java  |  199 ++
 .../export/OpenDocumentSpreadsheetCreator.java     |  115 +
 .../jabref/export/OpenOfficeDocumentCreator.java   |  116 +
 src/java/net/sf/jabref/export/RtfSelection.java    |   50 +
 src/java/net/sf/jabref/export/SaveException.java   |   82 +
 src/java/net/sf/jabref/export/SaveSession.java     |   78 +
 src/java/net/sf/jabref/export/VerifyingWriter.java |   51 +
 .../net/sf/jabref/export/layout/EntryLayout.java   |   39 +
 .../net/sf/jabref/export/layout/FieldLayout.java   |   39 +
 .../jabref/export/layout/FieldLayoutFormatter.java |   42 +
 src/java/net/sf/jabref/export/layout/Layout.java   |  266 ++
 .../net/sf/jabref/export/layout/LayoutEntry.java   |  447 ++++
 .../sf/jabref/export/layout/LayoutFormatter.java   |   42 +
 .../net/sf/jabref/export/layout/LayoutHelper.java  |  672 +++++
 .../export/layout/format/AuthorAbbreviator.java    |  133 +
 .../layout/format/AuthorAndsCommaReplacer.java     |   44 +
 .../export/layout/format/AuthorAndsReplacer.java   |   50 +
 .../layout/format/AuthorFirstAbbrLastCommas.java   |   26 +
 .../export/layout/format/AuthorFirstFirst.java     |   46 +
 .../layout/format/AuthorFirstLastCommas.java       |   26 +
 .../export/layout/format/AuthorLastFirst.java      |   34 +
 .../layout/format/AuthorLastFirstAbbrCommas.java   |   26 +
 .../layout/format/AuthorLastFirstAbbreviator.java  |  150 ++
 .../layout/format/AuthorLastFirstCommas.java       |   26 +
 .../export/layout/format/CreateDocBookAuthors.java |  134 +
 .../export/layout/format/CreateDocBookEditors.java |   79 +
 .../jabref/export/layout/format/CurrentDate.java   |   59 +
 .../export/layout/format/FormatPagesForHTML.java   |   10 +
 .../export/layout/format/FormatPagesForXML.java    |   10 +
 .../export/layout/format/GetOpenOfficeType.java    |   62 +
 .../sf/jabref/export/layout/format/HTMLChars.java  |  139 +
 .../sf/jabref/export/layout/format/RTFChars.java   |  140 +
 .../export/layout/format/RemoveBrackets.java       |   59 +
 .../layout/format/RemoveBracketsAddComma.java      |   64 +
 .../export/layout/format/RemoveLatexCommands.java  |  110 +
 .../export/layout/format/RemoveWhitespace.java     |   60 +
 .../sf/jabref/export/layout/format/ResolvePDF.java |   16 +
 .../jabref/export/layout/format/ToLowerCase.java   |   46 +
 .../sf/jabref/export/layout/format/XMLChars.java   |   71 +
 .../external/AutoSetExternalFileForEntries.java    |  293 +++
 .../net/sf/jabref/external/ExternalFilePanel.java  |  273 ++
 src/java/net/sf/jabref/external/PushToEmacs.java   |   87 +
 src/java/net/sf/jabref/external/PushToLyx.java     |   94 +
 src/java/net/sf/jabref/groups/AbstractGroup.java   |  213 ++
 .../net/sf/jabref/groups/AddToGroupAction.java     |  124 +
 src/java/net/sf/jabref/groups/AllEntriesGroup.java |  117 +
 .../net/sf/jabref/groups/AndOrSearchRuleSet.java   |   68 +
 src/java/net/sf/jabref/groups/AutoGroupDialog.java |  221 ++
 .../jabref/groups/EntryTableTransferHandler.java   |   75 +
 src/java/net/sf/jabref/groups/ExplicitGroup.java   |  240 ++
 src/java/net/sf/jabref/groups/GroupDialog.java     |  556 ++++
 src/java/net/sf/jabref/groups/GroupMatcher.java    |   19 +
 src/java/net/sf/jabref/groups/GroupSelector.java   | 1265 ++++++++++
 .../sf/jabref/groups/GroupTreeCellRenderer.java    |  159 ++
 src/java/net/sf/jabref/groups/GroupTreeNode.java   |  343 +++
 src/java/net/sf/jabref/groups/GroupsPrefsTab.java  |  121 +
 src/java/net/sf/jabref/groups/GroupsTree.java      |  451 ++++
 src/java/net/sf/jabref/groups/KeywordGroup.java    |  370 +++
 .../sf/jabref/groups/RemoveFromGroupAction.java    |   66 +
 src/java/net/sf/jabref/groups/SearchGroup.java     |  400 +++
 .../jabref/groups/TransferableEntrySelection.java  |   99 +
 .../sf/jabref/groups/UndoableAddOrRemoveGroup.java |  177 ++
 .../sf/jabref/groups/UndoableChangeAssignment.java |  103 +
 .../net/sf/jabref/groups/UndoableModifyGroup.java  |   79 +
 .../sf/jabref/groups/UndoableModifySubtree.java    |  105 +
 .../net/sf/jabref/groups/UndoableMoveGroup.java    |   93 +
 .../net/sf/jabref/groups/UndoableResetGroups.java  |   85 +
 .../jabref/groups/UnsupportedVersionException.java |   32 +
 src/java/net/sf/jabref/groups/VersionHandling.java |  208 ++
 src/java/net/sf/jabref/gui/AttachFileDialog.java   |  137 +
 src/java/net/sf/jabref/gui/ColorSetupPanel.java    |  146 ++
 .../sf/jabref/gui/DatabasePropertiesDialog.java    |   87 +
 .../sf/jabref/gui/EntryCustomizationDialog2.java   |  390 +++
 src/java/net/sf/jabref/gui/EntryTypeList.java      |  127 +
 src/java/net/sf/jabref/gui/FieldSetComponent.java  |  344 +++
 src/java/net/sf/jabref/gui/FieldWeightDialog.java  |  128 +
 .../net/sf/jabref/gui/FirstColumnComparator.java   |   39 +
 .../net/sf/jabref/gui/GenFieldsCustomizer.java     |  211 ++
 src/java/net/sf/jabref/gui/GlazedEntrySorter.java  |   98 +
 src/java/net/sf/jabref/gui/IconComparator.java     |   35 +
 .../net/sf/jabref/gui/ImportInspectionDialog.java  |  831 ++++++
 src/java/net/sf/jabref/gui/MainTable.java          |  497 ++++
 src/java/net/sf/jabref/gui/MainTableFormat.java    |  210 ++
 .../net/sf/jabref/gui/MainTableSelectionListener.  |  268 ++
 .../sf/jabref/gui/MainTableSelectionListener.java  |  268 ++
 .../net/sf/jabref/gui/components/JPanelXBox.java   |   21 +
 .../gui/components/JPanelXBoxLeftJustify.java      |   19 +
 .../gui/components/JPanelXBoxPreferredHeight.java  |   18 +
 .../gui/components/JPanelXBoxPreferredSize.java    |   16 +
 .../net/sf/jabref/gui/components/JPanelYBox.java   |   14 +
 .../gui/components/JPanelYBoxPreferredHeight.java  |   12 +
 .../gui/components/JPanelYBoxPreferredSize.java    |   16 +
 .../gui/components/JPanelYBoxPreferredWidth.java   |   12 +
 src/java/net/sf/jabref/imports/AuthorDialog.java   |   28 +
 .../net/sf/jabref/imports/BibTeXMLHandler.java     |  113 +
 .../net/sf/jabref/imports/BiblioscapeImporter.java |  266 ++
 .../net/sf/jabref/imports/BibteXMLImporter.java    |   89 +
 src/java/net/sf/jabref/imports/BibtexParser.java   |  776 ++++++
 .../net/sf/jabref/imports/BiomailImporter.java     |  191 ++
 src/java/net/sf/jabref/imports/BooleanAssign.java  |   31 +
 .../sf/jabref/imports/CiteSeerCitationHandler.java |   69 +
 .../net/sf/jabref/imports/CiteSeerFetcher.java     |  604 +++++
 .../sf/jabref/imports/CiteSeerFetcherPanel.java    |  199 ++
 .../net/sf/jabref/imports/CiteSeerUndoHandler.java |  230 ++
 src/java/net/sf/jabref/imports/CsaImporter.java    |  450 ++++
 .../net/sf/jabref/imports/CustomImportList.java    |  189 ++
 .../net/sf/jabref/imports/EndnoteImporter.java     |  194 ++
 .../net/sf/jabref/imports/FieldContentParser.java  |  174 ++
 .../jabref/imports/ImportCustomizationDialog.java  |  299 +++
 src/java/net/sf/jabref/imports/ImportFormat.java   |  156 ++
 .../net/sf/jabref/imports/ImportFormatReader.java  |  487 ++++
 src/java/net/sf/jabref/imports/ImportMenuItem.java |  105 +
 .../sf/jabref/imports/ImportUnknownMenuItem.java   |  126 +
 src/java/net/sf/jabref/imports/InspecImporter.java |  138 +
 src/java/net/sf/jabref/imports/IsiImporter.java    |  235 ++
 src/java/net/sf/jabref/imports/JstorImporter.java  |   92 +
 src/java/net/sf/jabref/imports/MedlineFetcher.java |  484 ++++
 src/java/net/sf/jabref/imports/MedlineHandler.java |  292 +++
 .../net/sf/jabref/imports/MedlineImporter.java     |   73 +
 .../net/sf/jabref/imports/OpenDatabaseAction.java  |  274 ++
 src/java/net/sf/jabref/imports/OvidImporter.java   |  243 ++
 src/java/net/sf/jabref/imports/ParserResult.java   |  121 +
 .../net/sf/jabref/imports/RepecNepImporter.java    |  491 ++++
 src/java/net/sf/jabref/imports/RisImporter.java    |  204 ++
 .../net/sf/jabref/imports/ScifinderImporter.java   |  101 +
 .../sf/jabref/imports/SilverPlatterImporter.java   |  177 ++
 .../net/sf/jabref/imports/SixpackImporter.java     |  138 +
 src/java/net/sf/jabref/imports/TextAnalyzer.java   |  208 ++
 src/java/net/sf/jabref/imports/ZipFileChooser.java |  269 ++
 .../net/sf/jabref/journals/AbbreviateAction.java   |   58 +
 .../sf/jabref/journals/JournalAbbreviations.java   |  314 +++
 .../sf/jabref/journals/ManageJournalsAction.java   |   31 +
 .../sf/jabref/journals/ManageJournalsPanel.java    |  602 +++++
 .../net/sf/jabref/journals/UnabbreviateAction.java |   56 +
 src/java/net/sf/jabref/label/ArticleLabelRule.java |  129 +
 src/java/net/sf/jabref/label/BookLabelRule.java    |   89 +
 src/java/net/sf/jabref/label/DefaultLabelRule.java |   44 +
 .../net/sf/jabref/label/IncollectionLabelRule.java |   46 +
 .../sf/jabref/label/InproceedingsLabelRule.java    |   99 +
 src/java/net/sf/jabref/label/KeyWord.java          |   93 +
 src/java/net/sf/jabref/label/LabelMaker.java       |   85 +
 src/java/net/sf/jabref/label/LabelRule.java        |   39 +
 .../jabref/labelPattern/DefaultLabelPatterns.java  |   58 +
 .../net/sf/jabref/labelPattern/LabelPattern.java   |  100 +
 .../sf/jabref/labelPattern/LabelPatternUtil.java   |  733 ++++++
 src/java/net/sf/jabref/mods/MODSDatabase.java      |   62 +
 src/java/net/sf/jabref/mods/MODSEntry.java         |  283 +++
 src/java/net/sf/jabref/mods/PageNumbers.java       |   61 +
 src/java/net/sf/jabref/mods/PersonName.java        |   67 +
 src/java/net/sf/jabref/net/URLDownload.java        |   75 +
 src/java/net/sf/jabref/remote/RemoteListener.java  |  196 ++
 .../net/sf/jabref/search/HitOrMissComparator.java  |   29 +
 src/java/net/sf/jabref/search/Lexer.g              |   65 +
 src/java/net/sf/jabref/search/NoSearchMatcher.java |   18 +
 src/java/net/sf/jabref/search/Parser.g             |  103 +
 src/java/net/sf/jabref/search/RegExNode.java       |   24 +
 .../net/sf/jabref/search/SearchExpression.java     |   44 +
 .../sf/jabref/search/SearchExpressionLexer.java    |  330 +++
 .../search/SearchExpressionLexerTokenTypes.java    |   23 +
 .../sf/jabref/search/SearchExpressionParser.java   |  486 ++++
 .../search/SearchExpressionParserTokenTypes.java   |   29 +
 .../jabref/search/SearchExpressionTreeParser.java  |  308 +++
 .../SearchExpressionTreeParserTokenTypes.java      |   31 +
 src/java/net/sf/jabref/search/SearchMatcher.java   |   21 +
 src/java/net/sf/jabref/search/TreeParser.g         |  110 +
 .../net/sf/jabref/undo/CountingUndoManager.java    |   82 +
 src/java/net/sf/jabref/undo/NamedCompound.java     |   56 +
 .../net/sf/jabref/undo/UndoableChangeType.java     |   66 +
 .../net/sf/jabref/undo/UndoableFieldChange.java    |   92 +
 .../net/sf/jabref/undo/UndoableInsertEntry.java    |   88 +
 .../net/sf/jabref/undo/UndoableInsertString.java   |   76 +
 src/java/net/sf/jabref/undo/UndoableKeyChange.java |   79 +
 .../net/sf/jabref/undo/UndoablePreambleChange.java |   82 +
 .../net/sf/jabref/undo/UndoableRemoveEntry.java    |   88 +
 .../net/sf/jabref/undo/UndoableRemoveString.java   |   77 +
 .../net/sf/jabref/undo/UndoableStringChange.java   |   92 +
 src/java/net/sf/jabref/util/CaseChangeMenu.java    |   62 +
 src/java/net/sf/jabref/util/CaseChanger.java       |  120 +
 .../net/sf/jabref/util/QuotedStringTokenizer.java  |   64 +
 src/java/net/sf/jabref/util/ResourceExtractor.java |   45 +
 src/java/net/sf/jabref/util/TBuildInfo.java        |  144 ++
 .../sf/jabref/wizard/auximport/AuxCommandLine.java |   77 +
 .../jabref/wizard/auximport/AuxSubGenerator.java   |  371 +++
 .../jabref/wizard/auximport/gui/FromAuxDialog.java |  382 +++
 .../sf/jabref/wizard/integrity/IntegrityCheck.java |  283 +++
 .../jabref/wizard/integrity/IntegrityMessage.java  |  145 ++
 .../integrity/gui/IntegrityMessagePanel.java       |  234 ++
 .../wizard/integrity/gui/IntegrityWizard.java      |  182 ++
 .../jabref/wizard/text/TagToMarkedTextStore.java   |  124 +
 .../sf/jabref/wizard/text/gui/HintListModel.java   |   27 +
 .../sf/jabref/wizard/text/gui/OverlayPanel.java    |   97 +
 .../sf/jabref/wizard/text/gui/TextInputDialog.java |  865 +++++++
 .../format/AuthorLastFirstAbbreviatorTester.java   |   87 +
 src/java/wsi/ra/tool/ExternalHelper.java           |   84 +
 src/java/wsi/ra/tool/ResourceLoader.java           |  486 ++++
 src/java/wsi/ra/tool/WSITools.java                 |  124 +
 src/java/wsi/ra/types/StringInt.java               |   77 +
 src/osx/osxadapter/OSXAdapter.java                 |  133 +
 src/resource/IntegrityMessage.properties           |   11 +
 src/resource/IntegrityMessage_de.properties        |   11 +
 src/resource/IntegrityMessage_en.properties        |   11 +
 src/resource/IntegrityMessage_fr.properties        |   11 +
 src/resource/IntegrityMessage_no.properties        |   11 +
 src/resource/JabRef_de.properties                  | 1034 ++++++++
 src/resource/JabRef_de.properties.orig             | 1029 ++++++++
 src/resource/JabRef_en.properties                  | 1036 ++++++++
 src/resource/JabRef_en.properties.orig             | 1030 ++++++++
 src/resource/JabRef_fr.properties                  | 1025 ++++++++
 src/resource/JabRef_fr.properties.orig             | 1019 ++++++++
 src/resource/JabRef_no.properties                  | 1028 ++++++++
 src/resource/Menu_de.properties                    |   95 +
 src/resource/Menu_en.properties                    |   96 +
 src/resource/Menu_fr.properties                    |   95 +
 src/resource/Menu_no.properties                    |   95 +
 src/resource/build.properties                      |    3 +
 src/resource/journalList.txt                       | 1556 ++++++++++++
 src/resource/layout/bibtexml.begin.layout          |    4 +
 src/resource/layout/bibtexml.end.layout            |    1 +
 src/resource/layout/bibtexml.layout                |   35 +
 src/resource/layout/docbook.begin.layout           |    5 +
 src/resource/layout/docbook.end.layout             |    1 +
 src/resource/layout/docbook.layout                 |   18 +
 src/resource/layout/endnote/EndNote.article.layout |   42 +
 src/resource/layout/endnote/EndNote.book.layout    |   42 +
 src/resource/layout/endnote/EndNote.booklet.layout |   42 +
 src/resource/layout/endnote/EndNote.inbook.layout  |   42 +
 .../layout/endnote/EndNote.incollection.layout     |   42 +
 .../layout/endnote/EndNote.inproceedings.layout    |   42 +
 src/resource/layout/endnote/EndNote.layout         |   42 +
 src/resource/layout/endnote/EndNote.manual.layout  |   42 +
 .../layout/endnote/EndNote.mastersthesis.layout    |   42 +
 src/resource/layout/endnote/EndNote.misc.layout    |   42 +
 src/resource/layout/endnote/EndNote.other.layout   |   42 +
 .../layout/endnote/EndNote.phdthesis.layout        |   42 +
 .../layout/endnote/EndNote.proceedings.layout      |   42 +
 .../layout/endnote/EndNote.techreport.layout       |   42 +
 .../layout/endnote/EndNote.unpublished.layout      |   42 +
 src/resource/layout/endnote/Readme.txt             |   70 +
 src/resource/layout/harvard/harvard.article.layout |   13 +
 src/resource/layout/harvard/harvard.begin.layout   |    3 +
 src/resource/layout/harvard/harvard.book.layout    |   19 +
 src/resource/layout/harvard/harvard.end.layout     |    1 +
 src/resource/layout/harvard/harvard.inbook.layout  |   19 +
 .../layout/harvard/harvard.incollection.layout     |   16 +
 .../layout/harvard/harvard.inproceedings.layout    |   17 +
 src/resource/layout/harvard/harvard.layout         |   37 +
 .../layout/harvard/harvard.mastersthesis.layout    |    7 +
 .../layout/harvard/harvard.phdthesis.layout        |    7 +
 .../layout/harvard/harvard.proceedings.layout      |   19 +
 src/resource/layout/harvard/harvard.readme         |   55 +
 src/resource/layout/html.begin.layout              |   62 +
 src/resource/layout/html.book.layout               |   51 +
 src/resource/layout/html.end.layout                |    6 +
 src/resource/layout/html.inbook.layout             |   63 +
 src/resource/layout/html.inproceedings.layout      |   63 +
 src/resource/layout/html.layout                    |   69 +
 src/resource/layout/html.mastersthesis.layout      |   45 +
 src/resource/layout/html.phdthesis.layout          |   45 +
 src/resource/layout/openoffice/README              |   15 +
 .../layout/openoffice/openoffice-csv.begin.layout  |    1 +
 .../layout/openoffice/openoffice-csv.layout        |    1 +
 src/resource/layout/simplehtml.layout              |   15 +
 src/resource/layout/text.layout                    |   10 +
 src/resource/log4j.properties                      |    7 +
 src/resource/ods/manifest.xml                      |    8 +
 src/resource/ods/meta.xml                          |   14 +
 src/resource/ods/settings.xml                      |    6 +
 src/resource/openoffice/manifest.xml               |    7 +
 src/resource/openoffice/meta.xml                   |    7 +
 src/resource/openoffice/mimetype                   |    1 +
 src/txt/INSTALL                                    |   31 +
 src/txt/README                                     |  441 ++++
 src/txt/apache-license.txt                         |   62 +
 src/txt/cpl-v10.html                               |  125 +
 src/txt/gpl.txt                                    |  340 +++
 src/txt/lesser.txt                                 |  504 ++++
 src/windows/JabRef-Logo.gif                        |  Bin 0 -> 1150 bytes
 src/windows/jabref.jsmooth                         |   36 +
 src/windows/jabref.wxs                             |   38 +
 643 files changed, 95567 insertions(+)

diff --git a/build.number b/build.number
new file mode 100644
index 0000000..765b15f
--- /dev/null
+++ b/build.number
@@ -0,0 +1,3 @@
+#Build Number for ANT. Do not edit!
+#Thu Feb 02 19:19:17 CET 2006
+build.number=186
diff --git a/build.xml b/build.xml
new file mode 100644
index 0000000..d4d9625
--- /dev/null
+++ b/build.xml
@@ -0,0 +1,483 @@
+<?xml version="1.0"?>
+<!--++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+   Filename: $RCSfile: build.xml,v $
+   Purpose:  Ant build file for Jabref.
+
+             Ant-Download: http://jakarta.apache.org/ant
+             Ant-Manual:   http://jakarta.apache.org/ant/manual/index.html
+
+             Jabref-Homepage:    http://jabref.sourceforge.net
+             Jabref at SourceForge: http://sourceforge.net/projects/jabref
+             Jabref at FreshMeat:   http://freshmeat.net
+             Jabref-CVSRoot:     :pserver:anonymous at cvs.jabref.sourceforge.net:/cvsroot/jabref
+
+             Further questions:
+               help mailing list:      must be inserted
+
+   Precondition: 1. Ant should be installed.
+                 2. JAVA_HOME environment variable contains the path to JDK1.4 or higher
+                 3. ANT_HOME environment variable contains the path to ant's home directory
+
+   Language: XML
+   Compiler: Ant
+   Authors:  Joerg K. Wegner, wegnerj at informatik.uni-tuebingen.de
+             Morten O. Alver
+   Version:  $Revision: 1.54.2.3 $
+             $Date: 2006/02/02 09:31:59 $
+             $Author: mortenalver $
+
+   modified:
+             28.07.2005 r.nagel
+             - insert dynamic build info generation (resource/build.properties)
+             - copy fonts directory, used by the new about dialog
+             - change static "version" into mainfest file into ${jabref.version}
+             09.06.2005 r.nagel
+             - bugfix, first it should be made a rebuild of the build directory
+             and then a jar should be generated from this directory
+             - take all files for the jar archive !!! FROM BUILD directory !!!
+
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-->
+
+<project name="JabRef" default="jars" basedir=".">
+
+        <!-- ==========================================================================================
+        PROPERTY SETUP
+     ========================================================================================== -->
+
+        <!-- some version information -->
+        <property name="jabref.bin" value="jabref" />
+        <property name="jabref.version" value="2.0.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.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" />
+
+
+        <!-- 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-1.2.2.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>
+         </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-1.2.2.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-1.2.2.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>
+      </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-1.2.2.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>
+      </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-1.2.2.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>
+                </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-1.2.2.jar" />
+                                <pathelement location="${library.directory}/spin.jar" />
+                        </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">
+                <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" />
+                        </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 :-),
+          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}
+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>
+
+        <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-1.2.2.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.5.0_java14.jar" dest="${build.tmp}" />
+
+            <delete dir="${build.tmp}/META-INF"/>
+        </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>
+
+
+        <!--++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+        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
+Complexity             Ease of       Risk
+Number (CCN)           maintenance
+(McCabe metric)
+---------------------------------------------
+1-10, simple           easy          minimum
+11-20, complex         moderate      moderate
+21-50, more complex    hard          high
+>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-1.2.2.jar" />
+                                <pathelement location="${library.directory}/looks-1.2.2.jar" />
+                                <pathelement location="${library.directory}/spin.jar" />
+                        </classpath>
+
+                        <!--<test name="tests.net.sf.jabref.export.layout.format.AuthorLastFirstAbbreviatorTester"/>-->
+                </junit>
+        </target>
+
+</project>
diff --git a/lib/EndNote.zip b/lib/EndNote.zip
new file mode 100644
index 0000000..860ede1
Binary files /dev/null and b/lib/EndNote.zip differ
diff --git a/lib/JavaApplicationStub b/lib/JavaApplicationStub
new file mode 100755
index 0000000..2c34fcb
Binary files /dev/null and b/lib/JavaApplicationStub differ
diff --git a/lib/OSXAdapter.class b/lib/OSXAdapter.class
new file mode 100644
index 0000000..8451e95
Binary files /dev/null and b/lib/OSXAdapter.class differ
diff --git a/lib/antlr.jar b/lib/antlr.jar
new file mode 100644
index 0000000..fbe5e3c
Binary files /dev/null and b/lib/antlr.jar differ
diff --git a/lib/forms-1.0.4.jar b/lib/forms-1.0.4.jar
new file mode 100755
index 0000000..9ecbef7
Binary files /dev/null and b/lib/forms-1.0.4.jar differ
diff --git a/lib/glazedlists-1.5.0_java14.jar b/lib/glazedlists-1.5.0_java14.jar
new file mode 100644
index 0000000..8af40f5
Binary files /dev/null and b/lib/glazedlists-1.5.0_java14.jar differ
diff --git a/lib/jarbundler-1.4.jar b/lib/jarbundler-1.4.jar
new file mode 100644
index 0000000..b74baa6
Binary files /dev/null and b/lib/jarbundler-1.4.jar differ
diff --git a/lib/looks-1.2.2.jar b/lib/looks-1.2.2.jar
new file mode 100644
index 0000000..a68ba26
Binary files /dev/null and b/lib/looks-1.2.2.jar differ
diff --git a/lib/spin.jar b/lib/spin.jar
new file mode 100644
index 0000000..d5103e4
Binary files /dev/null and b/lib/spin.jar differ
diff --git a/src/help/About.html b/src/help/About.html
new file mode 100755
index 0000000..175538d
--- /dev/null
+++ b/src/help/About.html
@@ -0,0 +1,98 @@
+<HTML>
+
+<BODY text="#275856">
+<basefont size="4" color="#2F4958" face="arial">
+<CENTER>
+<H1>JabRef version @version@ </H1>
+
+(c) 2006
+
+
+<P>
+JabRef is freely distributable under the terms of the
+<a href="License.html">GNU Public License</a>, version 2.
+
+<H2>Developers:</H2>
+Morten O. Alver<BR>
+Nizar N. Batada<BR>
+Michel Baylac<BR>
+Guillaume Gardey<BR>
+Cyrille d'Haese<BR>
+Raik Nagel<BR>
+Ellen Reitmayr<BR>
+Andreas Rudert<BR>
+Michael Spiegel<BR>
+Ulrik Stervbo<BR>
+Dominik Waßenhoven<BR>
+Joerg K. Wegner<BR>
+Michael Wrighton<BR>
+Egon Willighagen <BR>
+Jörg Zieren<BR>
+
+<H2>Contributions from:</H2>
+Kolja Brix<BR>
+Frédéric Darboux<BR>
+Fabrice Dessaint<BR>
+Nathan Dunn<BR>
+Brian van Essen<br>
+Alexis Gallagher<BR>
+Sascha Hunold<BR>
+Bernd Kalbfuss<BR>
+Martin Kähmer<BR>
+Jeffrey Kuhn<BR>
+Alex Montgomery<BR>
+John Relph<BR>
+Moritz Ringler<BR>
+Andreas Rudert<BR>
+Rudolf Seemann<BR>
+Toralf Senger<br>
+Mike Smoot<BR>
+Martin Stolle<BR>
+David Weitzman<BR>
+Seb Wills<BR>
+
+<H2>Thanks to:</H2>
+Samin Muhammad Ridwanul Karim<BR>
+Stefan Robert<BR>
+
+<H2>Third-party software used:</H2>
+JabRef uses JGoodies Looks 1.2.2 and JGoodies Forms 1.0.4, distributed by JGoodies
+(<code>http://www.jgoodies.com</code>) under the terms of the BSD License (see
+<code>http://www.opensource.org/licenses/bsd-license.html</code> for details).
+<P>
+Also included are two additional classes (SimpleInternalFrame and UIFSplitPane) by Karsten
+Lentzsch, which are distributed under <A HREF="jgoodies.html">these terms</A>.
+
+<P>
+Command line options are parsed using RitOpt (<code>http://ritopt.sourceforge.net</code>). RitOpt
+is distributed under the terms of the <a href="License.html">GNU Public License</a>,
+version 2.
+<P>
+JabRef uses the ANTLR parser generator for interpreting search strings. ANTLR is
+public domain software - see <code>http://www.antlr.org/license.html</code> for the
+licensing terms.
+<p>
+For table presentation and filtering, JabRef uses the Glazed Lists library
+    (<code>http://publicobject.com/glazedlists</code>), which is
+    distributed under the Lesser GNU Public License.
+<P>
+JabRef also uses the threading library Spin 1.3.1, which is distributed under the terms of
+the Lesser GNU Public License.
+<P>
+This product includes software developed by the Apache Software
+Foundation (http://www.apache.org/). The libraries Commons Logging and
+Commons HTTP Client are distributed by The Jakarta Project
+(<code>http://jakarta.apache.org</code>) under the Apache Software
+License, Version 1.1. See the enclosed file
+<code>apache-license.txt</code> or
+<code>http://opensource.org/licenses/apachepl.php</code> for details.
+
+<P>
+Some icons are by us, but most are either from the Eclipse project (<code>http://www.eclipse.org</code>),
+distributed under the <a href="cpl-v10.html">Common Public License</a>, and from the QIcons package
+(<code>http://qt.osdn.org.ua</code>), which is distributed under the terms of the
+<a href="License.html">GNU Public License</a>.
+
+</CENTER>
+</BODY>
+</HTML>
diff --git a/src/help/BaseFrameHelp.html b/src/help/BaseFrameHelp.html
new file mode 100755
index 0000000..c15ceb1
--- /dev/null
+++ b/src/help/BaseFrameHelp.html
@@ -0,0 +1,90 @@
+<HTML>
+
+<BODY text="#275856">
+
+<basefont size="4" color="#2F4958" face="arial">
+
+<H1>The JabRef main window</H1>
+
+<em>Note:</em> most menu actions referred in the following have keyboard shortcuts,
+and many are available from the toolbar. The keyboard shortcuts are found in the
+pull-down menus.
+<p>
+This is the main window from where you work with your databases. Below
+the menubar and the toolbar is a tabbed pane containing a panel for
+each of your currently open databases. When you select one of these
+panels, a table appears, listing all the database's entries, as well
+as a configurable selection of their fields.
+<ul>
+<li>You decide which fields are shown in the table by checking the fields you want
+to see in the <strong>Preferences</strong> dialog.</li>
+<li>Fields can be edited directly in the table, by simply clicking on a cell and
+typing the contents
+(this edition mode is possible only if "Allow editing in table cells"
+is selected in <strong>Options --> Preferences --> General</strong>).
+Double-click a cell to enter a more powerful edit mode.
+You can navigate the table with the arrow keys.</li>
+<li>The table is sorted according to a set of fields of your choosing.
+The default sort order is set up in <strong>Preferences -> Entry table</strong>,
+but to quickly change the order,
+    click the header of a column to set it as the primary sort criterion, or
+    reverse the sorting if it is already set. Another click will deselect the column
+    as sorting criterion. Hold down <b>CONTROL</b> and click a column to add, reverse
+    or remove it as a sub-criterion after the primary column. You can add an arbitrary
+    number of sub-criteria.
+<li>Adjust the width of each column by dragging the borders between
+their headers.</li>
+<li>In the <strong>Preferences</strong> dialog, toggle whether the table should be
+resized to fit the window. Enable this to ensure visibility of the whole table,
+and disable it to make room for displaying more information.</li>
+<li>Color codes can be toggled in the <strong>Preferences</strong> dialog, and
+they help you visualize the completeness of your database by coloring cells as
+follows:
+  <ul>
+  <li>A <font color="red">red</font> cell in the leftmost column denotes an
+  incomplete entry.</li>
+  <li>A <font color="#909000">yellow</font> cell in the leftmost column denotes an entry
+  that doesn't define all required fields by itself, but that contains a
+  cross-reference.</li>
+  <li>A <font color="blue">blue</font> cell denotes a required field.</li>
+  <li>A <font color="green">green</font> cell denotes an optional field.</li>
+  <li>An uncolored cell denotes a field which is not used by the <em>bibtex</em>
+  program for this type of entry. The field can still be edited in JabRef.</li>
+  </ul>
+</li>
+
+</ul>
+
+<H2>Adding a new entry</H2>
+There are several ways to add a new entry. The <strong>New entry</strong> menu
+action shows a dialog where you can choose the type of the entry from a list. To
+bypass this dialog, there are also separate menu actions for each entry type, and
+keyboard shortcuts for the most common types.
+<P>When a new entry is added, by default an
+<a href="EntryEditorHelp.html">editor dialog</a> for the entry will be
+opened. This behaviour can be toggled in the <strong>Preferences</strong> dialog.
+<P><em>Note:</em> We strongly recommend learning the shortcuts for
+the entry types you use most often, e.g. CTRL-SHIFT-A for adding an
+<em>article</em> entry.
+
+<H2>Editing an entry</H2> To open an <a
+href="EntryEditorHelp.html">editor dialog</a> for an existing entry,
+simply double-click in the leftmost column of the appropriate line, or
+select the entry and press ENTER.
+If "Allow editing in table cells" is not selected in the dialog window
+<strong>Options --> Preferences --> General</strong>, a double-click anywhere
+on the appropriate line will open the <a href="EntryEditorHelp.html">editor dialog</a>.
+
+
+<H2>Referencing a <em>bibtex</em> string in a field</H2>
+In JabRef you write the contents of all fields the same way as you
+would in a text editor, with one exception: to reference a string,
+enclose the name of the string in a set of # characters, e.g.:<BR>
+  '#jan# 1997',<BR>
+which will be interpreted as the string named 'jan' followed by ' 1997'.
+<P>See also: <a href="StringEditorHelp.html">string editor</a>.
+
+</font>
+
+</BODY>
+</HTML>
diff --git a/src/help/BibtexHelp.html b/src/help/BibtexHelp.html
new file mode 100755
index 0000000..a5e2ed7
--- /dev/null
+++ b/src/help/BibtexHelp.html
@@ -0,0 +1,50 @@
+<HTML>
+
+<BODY text="#275856">
+<basefont size="4" color="#2F4958" face="arial">
+
+<H1>About <em>bibtex</em></H1>
+
+JabRef helps you work with your <em>bibtex</em> databases, but
+there are still rules to keep in mind when editing your entries, to
+ensure that your database is treated properly by the <em>bibtex</em>
+program.
+
+<H2><em>Bibtex</em> fields</H2>
+
+There is a lot of different fields in <em>bibtex</em>, and some
+additional fields that you can set in JabRef. 
+<P>
+Generally, you can use LaTeX commands inside of fields containing
+text. <em>Bibtex</em> will automatically format your reference lists,
+and those fields that are included in the lists will be
+(de)capitalized according to your bibliography style. To ensure that
+certain characters remain capitalized, enclose them in braces, like in
+the word {B}elgium.
+
+<P>
+Notes about some of the field types:
+<ul>
+<li><em>Author:</em> This field should contain the complete author
+list for your entry. The names are separated by the word <em>and</em>,
+even if there are more than two authors. Each name can be written
+in two equivalent forms:<br>
+ Donald E. Knuth <em>or</em> Knuth, Donald E.<br>
+ Eddie van Halen <em>or</em> van Halen, Eddie<br>
+
+The second form should be used for authors with more than two names,
+to differentiate between middle names and last names.
+
+<li><em>Editor:</em> This field is analogue to the <em>author</em> field.
+
+<li><em>Year:</em> The year of the publication. This field is required
+for most entry types.
+
+<li><em>Bibtexkey:</em> A unique string used to refer to the entry in
+LaTeX documents. Note that when referencing an entry from LaTeX, the
+key must match case-sensitively with the reference string.
+
+</ul>
+
+
+</HTML>
diff --git a/src/help/CiteSeerHelp.html b/src/help/CiteSeerHelp.html
new file mode 100644
index 0000000..6c56bd3
--- /dev/null
+++ b/src/help/CiteSeerHelp.html
@@ -0,0 +1,44 @@
+<HTML>
+
+<BODY text="#275856">
+<basefont size="4" color="#2F4958" face="arial">
+
+<H1>Importing From CiteSeer</H1>
+
+<H2>Importing An Entry From CiteSeer</H2>
+
+JabRef can download information about a particular citation from the CiteSeer database.
+To start this process, add a new entry into your database and populate the citeseerurl field with
+a link to its content page on CiteSeer.  The citeseerurl field must be in one of the following formats:
+
+<p>http://citeseer.ist.psu.edu/DDDDDD[.html], or <br>
+oai:CiteSeerPSU:DDDDDD, or <br>
+DDDDDD
+
+<p>where DDDDD is a sequence of digits.  To find the sequence of digits (DDDDD) for a CiteSeer entry,
+goto the citation's document page of the format http://citeseer.ist.psu.edu/<i>nameYearTitle</i>.html
+and click on the (Update) link for this citation.  The URL for the Update link will contain the numeric
+ID for this citation.
+
+<p>Once you have populated the citeseerurl field, you may download the CiteSeer fields by selecting
+ <b>BibTex -> Import Data from CiteSeer</b>.  Make sure you have selected the row(s) you wish to 
+ update.
+
+<H2>Generating a Citation Database</H2>
+
+Given a set of references, you can generate a list of documents that cite the elements of this set.
+To facilitate this feature, each citation in a database must have a citeseerurl field with the format specified
+in <b>Importing An Entry From CiteSeer</b>.  To use this feature, select <b>Tools -> Fetch Citations
+from CiteSeer</b>.
+
+<H2>Using a Proxy Server</H2>
+
+If you need to use an http proxy server, pass the server name and
+port number to java at runtime.  These environment settings are documented
+at <p> http://java.sun.com/j2se/1.4.2/docs/guide/net/properties.html
+
+<p><code>java -Dhttp.proxyHost="hostname" -Dhttp.proxyPort="portnumber"</code>
+
+<p> 
+
+</HTML>
diff --git a/src/help/CommandLine.html b/src/help/CommandLine.html
new file mode 100644
index 0000000..a5de77c
--- /dev/null
+++ b/src/help/CommandLine.html
@@ -0,0 +1,85 @@
+<HTML>
+
+<BODY text="#275856">
+<basefont size="4" color="#2F4958" face="arial">
+
+<H1>Command line options</H1>
+
+Although JabRef is primarily a GUI based application, it offers several command line options
+that may be useful, and can even perform file conversion operations without opening the graphical
+interface.
+
+<P>You can always specify one or more BibTeX files to load by simply listing their filenames. Take care to
+  specify all options before your list of file names. You must make sure the first file name is not misunderstood
+  as being an argument for an option - this simply means that if a boolean option like <code>-n</code> or
+<code>-l</code>	immediately precedes a file name, add the word "true" as an argument. For instance, the command
+line:
+<p><code>jabref -o filetoexport.xml,docbook -n true original.bib</code>
+<p>will correctly load the file <code>original.bib</code>, export it in docbook format to <code>filetoexport.xml</code>,
+  and suppress the GUI. The word <em>true</em> prevents the file name from being interpreted as an argument to the
+  -n option.
+
+<H2>Help: -h</H2>
+
+This option causes JabRef to display a summary of the command line options, and quit immediately.
+
+<H2>No-GUI mode: -n</H2>
+
+This option suppresses both the JabRef window and the splash window normally shown at startup. It
+causes the program to quit immediately once the command line options have been processed.
+<P>This option is useful for performing file conversion operations from the command line or a script.
+
+<H2>Load session: -l</H2>
+
+This option causes JabRef to load the saved session, if any, before opening the main window.
+
+<H2>Import file: -i filename[,format]</H2>
+
+This option causes JabRef to import or load the specified file. If only a filename is specified, or
+the filename is followed by a comma and a * character, JabRef will attempt to detect the file format
+automatically. This should work for all BibTeX files and files in any import format supported by JabRef.
+If the filename is followed by a comma and the name of an import format, the given import
+filter will be used. Use the <code>-h</code> option to get a list of availiable import formats.
+
+<P>If an output option is also specified, an import will always be processed before it, and the imported or
+  loaded file will be given to the export filter. If the GUI is not suppressed using the <code>-n</code> option,
+  any imported or loaded file will show up in the main window.
+<p>The -i option can be specified only once, and for one file only.
+
+<H2>Export file: -o filename[,format]</H2>
+
+This option causes JabRef to save or export a file imported or loaded by the same command line. If a file is
+imported using the <code>-i</code> option, that database will be exported. Otherwise, the <em>last</em> file
+specified (and successfully loaded) without the <code>-i</code> option will be exported.
+
+<P>If only a filename
+is specified, it will be saved in BibTeX format. If the filename is followed by a comma and an export format,
+the given export filter will be used. A custom export filter can be used in this way, and will be preferred if
+the export name matches both a custom and a standard export filter.
+<P>Use the <code>-h</code> option to get a list of availiable export formats.
+
+<P>If the <code>-n</code> option has not been invoked, any export operation will be performed before the JabRef
+  window is opened, and the imported database will show up in the window.
+
+<p>The -o option can be specified only once, and for one file only.
+
+<H2>Export preferences: -x filename</H2>
+
+Using this option, you can have JabRef export all user preferences to an XML file. After exporting,
+JabRef will start normally.
+
+<H2>Import preferences: -p filename</H2>
+
+This option causes JabRef to import user preferences exported using the <code>-x</code>
+option. After importing, JabRef will start normally.
+
+<H2>Export only used items: -a filename[.aux],newBibFile[.bib]</H2>
+
+Sometimes it is helpful, to have a bibtex file that contains only the used bibtex entries.
+A list of these used entries is located in an aux file. Jabref can parse this file to
+generate a new bibtex file, which contains only the known and used entries. That will mean, 
+if an entry is not defined in the standard bibtex file, it cannot be located in the new 
+file.
+
+</BODY>
+</HTML>
diff --git a/src/help/ContentSelectorHelp.html b/src/help/ContentSelectorHelp.html
new file mode 100755
index 0000000..272939c
--- /dev/null
+++ b/src/help/ContentSelectorHelp.html
@@ -0,0 +1,32 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+
+  <BODY text="#275856">
+  <basefont size="4" color="#2F4958" face="arial">
+
+  <head>
+    <title>Word selector</title>
+  </head>
+
+  <body>
+    <h1>Field content selector</h1>
+
+	This feature allows you to store a selection of often-used
+	words or phrases that you use often in your
+	database. By default it is enabled for the fields
+	<em>Journal</em>, <em>Keywords</em> and <em>Publisher</em>, but you
+	can also add selectors to other fields, in the upper part of the
+	<em>Manage</em> dialog (menu <strong> Tools --> Manage content selectors</strong>).
+
+	<P>
+	The word selection is database-specific, and is saved along
+	with your references in the .bib file.
+	<P>
+	To add a new word, you can simply write it into the selector
+	combo box and press Enter. Using the <em>Manage</em> dialog
+	you can also remove words that you have added.
+
+
+
+  </body>
+</html>
diff --git a/src/help/Contents.html b/src/help/Contents.html
new file mode 100755
index 0000000..aad3eae
--- /dev/null
+++ b/src/help/Contents.html
@@ -0,0 +1,44 @@
+<HTML>
+
+    <BODY text="#275856">
+    <basefont size="4" color="#2F4958" face="arial">
+
+    <H1>Help contents</H1>
+
+    <a href="HelpHelp.html">About the Help window</a><br>
+    <a href="JabRefHelp.html">General information</a><br>
+    <p>
+    <a href="BibtexHelp.html"><em>Bibtex</em> help</a><br>
+    <a href="CommandLine.html">Command line options</a><br>
+    <a href="CustomExports.html">Custom export filters</a><br>
+    <a href="CustomImports.html">Custom import filters</a><br>
+    <a href="LabelPatterns.html">Customizing the BibTex key generator</a><br>
+    <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="CiteSeerHelp.html">Fetching entries from <em>CiteSeer</em></a><br>
+    <a href="MedlineHelp.html">Fetching entries from <em>Medline</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="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="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>
+
+
+
+
+
+
+
+
+
+
+</HTML>
diff --git a/src/help/CustomEntriesHelp.html b/src/help/CustomEntriesHelp.html
new file mode 100644
index 0000000..74ce9a9
--- /dev/null
+++ b/src/help/CustomEntriesHelp.html
@@ -0,0 +1,70 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+  <head>
+    <title>Customizing entry types</title>
+  </head>
+
+  <BODY text="#275856">
+    <basefont size="4" color="#2F4958" face="arial">
+
+    <h1>Customizing entry types</h1>
+    <p>
+    To customize entry types, select the menu
+    <strong>Options --> Customize entry types</strong>.
+    <p>
+    When customizing an entry type, you both define how its entry editor should look, and what
+    it takes for JabRef to consider an entry complete. You can both make changes to the existing
+    entry types, and define new ones.
+    <p>
+    Note that no modifications you make in this dialog will be stored until you click <b>Apply</b>
+    or <b>OK</b>. If you click <b>Cancel</b> or simply close the dialog, unapplied changes will
+    be lost.
+
+    <h2>Using the entry customization dialog</h2> 
+
+The entry customization dialog is divided in three main panels. The leftmost panel
+is where you can select an entry type for modification, and add new ones. The middle
+panel is used for setting up the required fields of the selected entry type, and
+the right panel for setting up the optional fields.
+
+<h3>Adding and removing entry types</h3>
+
+<p>The currently available entry types are listed in the left panel. Whenever
+you select an entry type, the other panels will update to show what fields are
+required and optional for this entry type.
+
+<p>To add a new entry type, you must enter a name for it in the text field below
+the type list, and click <b>Add</b>. The new entry type will be added to the list,
+and selected for modification.
+
+<p>To remove a custom entry type, select it and click <b>Remove</b>. This operation will
+only be available for custom entry types that are not merely modifications of standard types.
+It is not possible to remove a standard entry type.
+
+<p>To return a modified standard type to its default setup, select it and click <b>Default</b>.
+This operation will only be available for customized entry types that modify a standard type.
+
+<h2>Editing entry types</h2>
+
+When an entry type is selected, the current required and optional fields will be listed
+in the center and right panels of the dialog. The process of editing the lists are identical
+for the required and optional fields.
+
+<p>To add a new field, edit the text field below the list, or select a field name from the
+dropdown menu, then click <b>Add</b>. The chosen field name will be added at the end of the
+list.
+
+<p>To remove one or more fields, select them in the list, and click <b>Remove</b>.
+
+<p>To change the order of the fields, choose one field name, and click the arrow buttons to move
+it up or down in the list.
+
+<p>
+There is one limitation to customizing entry types; certain types have
+an and/or condition in their required fields. For instance, a <em>book</em>
+entry is complete with either the <em>author</em> or the <em>editor</em>
+field, or both. This type of condition cannot be represented in a customized
+entry.
+
+  </body>
+</html>
diff --git a/src/help/CustomExports.html b/src/help/CustomExports.html
new file mode 100644
index 0000000..07d468d
--- /dev/null
+++ b/src/help/CustomExports.html
@@ -0,0 +1,172 @@
+<HTML>
+
+<BODY text="#275856">
+<basefont size="4" color="#2F4958" face="arial">
+
+<H1>Custom export filters</H1>
+
+JabRef allows you to define and use your own export filters, in the same way as the
+standard export filters are defined. An export filter is defined by one or more
+<i>layout files</i>, which with the help of a collection of built-in formatter
+routines specify the format of the exported files. Your layout files must be prepared
+in a text editor outside of JabRef.
+
+<H2>Adding a custom export filter</H2>
+
+The only requirement for a valid export filter is the existence of a file with
+the extension <b>.layout</b>. To add a new custom export filter, open the
+dialog box <b>Options -> Manage custom exports</b>, and click <b>Add new</b>.
+A new dialog box will appear, allowing you to specify a name for the export filter
+(which will appear in the <b>File -> Custom export</b> menu of the JabRef window),
+the path to the <b>.layout</b> file, and the preferred file extension for the export
+filter (which will be the suggested extension in the file dialog when you use the
+export filter).
+
+<H2>Creating the export filter</H2>
+
+To see examples of how export filters are made, look for the package containing the layout files
+for the standard export filters on our download page.
+
+<H3>Layout files</H3>
+
+Let us assume that we are creating an HTML export filter.
+
+<P>While the export filter only needs to consist of a single <b>.layout</b> file, which in this case
+could be called <i>html.layout</i>, you may also want to add two files called
+<i>html.begin.layout</i> and <i>html.end.layout</i>. The former contains the header part
+of the output, and the latter the footer part. JabRef will look for these two files whenever
+the export filter is used, and if found, either of these will be copied verbatim to the output
+before or after the individual entries are written.
+
+<P>Note that these files must reside in the same directory as <i>html.layout</i>, and must be
+named by inserting <b>.begin</b> and <b>.end</b>, respectively.
+
+<P>In our example export filter, these could look like the following:
+
+<p><i>html.begin.layout</i>:<br>
+<code><HTML><br>
+  <BODY> text="#275856"><br>
+<basefont size="4" color="#2F4958" face="arial"></code>
+
+<p><i>html.end.layout</i>:<br>
+<code></BODY><br>
+  </HTML></code>
+
+<P>The file <i>html.layout</i> provides the <i>default</i> template for exporting one single entry. If
+you want to use different templates for different entry types, you can do this by adding entry-specific
+<b>.layout</b> files. These must also reside in the same directory as the main layout file, and
+are named by inserting <b>.entrytype</b> into the name of the main layout file. The entry type name
+must be in all lowercase. In our example, we might want to add a template for book entries, and this
+would go into the file <i>html.book.layout</i>. For a PhD thesis we would add the file
+<i>html.phdthesis.layout</i>, and so on. These files are similar to the default layout file, except that
+they will only be used for entries of the matching type. Note that the default file can easily be made
+general enough to cover most entry types in most export filters.
+
+<H3>The layout file format</H3>
+
+Layout files are created using a simple markup format where commands are identified by a preceding
+backslash. All text not identified as part of a command will be copied verbatim to the output file.
+
+<H3>Field commands</H3>
+
+<p>An arbitrary word preceded by a backslash, e.g. <code>\author</code>, <code>\editor</code>,
+<code>\title</code> or <code>\year</code>, will be interpreted as a reference to the corresponding field,
+which will be copied directly to the output.
+
+<H3>Field formatters</H3>
+
+<p>Often there will be a need for some preprocessing of the field contents before output. This is
+  done using a <i>field formatter</i> - a java class containing a single method that manipulates the
+  contents of a field.
+<p>A formatter is used by inserting the <code>\format</code> command followed by the formatter name in
+  square braces, and the field command in curly braces, e.g.:
+
+  <p><code>\format[ToLowerCase]{\author}</code>
+
+<p>You can also specify multiple formatters separated by commas. These will be called sequentially,
+  from left to right, e.g.
+
+  <p><code>\format[ToLowerCase,HTMLChars]{\author}</code>
+
+<p>will cause the formatter <b>ToLowerCase</b> to be called first, and then <b>HTMLChars</b> will be
+  called to format the result. You can list an arbitrary number of formatters in this way.
+
+<p>The argument to the formatters, withing the curly braces, does not have to be a field command. Instead,
+you can insert normal text, which will then be passed to the formatters instead of the contents of any field.
+This can be useful for some fomatters, e.g. the CurrentDate formatter (described below).
+
+<p>JabRef provides the following set of formatters, some of which depend on the others:
+<ul>
+<li><code>HTMLChars</code> : replaces TeX-specific special characters (e.g. {\^a} or {\"{o}})
+  with their HTML representations.
+<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>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.
+    <code>\format[CurrentDate]{yyyy.MM.dd}</code> will give the date only, e.g. 2005.11.30.
+
+<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>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>AuthorAndsCommaReplacer</code> : replaces "and" between names with ",", and "&" between the last two.
+<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>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.
+</ul>
+
+<p>If none of the available formatters can do what you want to achieve, you can add your own by implementing
+  the <code>net.sf.jabref.export.layout.LayoutFormatter</code> interface. If you insert your class
+  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.
+
+<H3>Conditional output</H3>
+
+Some static output might only make sense if a specific field is set. For instance, say we want to follow
+the editor names with the text <code>(Ed.)</code>. This can be done with the following text:
+
+<p><code>\format[HTMLChars,AuthorFirstFirst]{\editor} (Ed.)</code>
+
+<p>However, if the <code>editor</code> field has not been set - it might not even make sense for the entry
+  being exported - the <code>(Ed.)</code> would be left hanging. This can be prevented by instead using the
+<code>\begin</code> and <code>\end</code> commands:
+
+<p><code>\begin{editor}<br>\format[HTMLChars,AuthorFirstFirst]{\editor} (Ed.)
+<br>\end{editor}</code>
+
+<p>The <code>\begin</code> and <code>\end</code> commands make sure the text in between is printed if and
+only if the field referred in the curly braces is defined for the ently being exported.
+
+<p><b>Note:</b> Use of the <code>\begin</code> and <code>\end</code> commands is a key to creating
+  layout files that work well with a variety of entry types.
+
+<H3>Grouped output</H3>
+
+If you wish to separate your entries into groups based on a certain field, use the grouped output commands.
+Grouped output is very similar to conditional output, except that the text in between is printed only if the
+field referred in the curly braces has changed value.
+
+<p>For example, let's assume I wish to group by keyword.  Before exporting the file, make sure you have sorted
+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>
+
+<H2>Sharing your work</H2>
+
+With external layout files, it's fairly simple to share custom export formats between users.
+If you write an export filter for a format not supported by JabRef, or an improvement over an
+existing one, we encourage you to post your work on our SourceForge.net page. The same goes for
+formatter classes that you write. We'd be happy to distribute a collection of submitted
+layout files, or to add to the selection of standard export filters and formatters.
+
+</HTML>
diff --git a/src/help/CustomImports.html b/src/help/CustomImports.html
new file mode 100644
index 0000000..2cc1b37
--- /dev/null
+++ b/src/help/CustomImports.html
@@ -0,0 +1,125 @@
+<HTML>
+
+<BODY text="#275856">
+<basefont size="4" color="#2F4958" face="arial">
+
+<H1>Custom import filters</H1>
+
+<p>JabRef allows you to define and use your own importers, in very much the same way as the
+standard import filters are defined. An import filter is defined by one or more
+Java <i>classes</i>, which parse the contents of a file from an input stream
+and create BibTex-Entries. So with some basic Java programming you can add an importer
+for your favorite source of references or register a new, improved version of an existing
+importer. Also, this allows you to add compiled custom importers that you might
+have obtained e.g. from SourceForge without rebuilding JabRef (see "Sharing your work").</p>
+
+<p>Custom importers take precedence over standard importers. This way, you can override
+existing importers for the Autodetect and Command Line features of JabRef. Custom importers
+are ordered by name.</p>
+
+<H2>Adding a custom import filter</H2>
+
+<p>Make sure, you have a compiled custom import filter (one or more <code>.class</code> files
+as described below) and the class files are in a directory structure according to 
+their package structure. To add a new custom import filter, open the dialog box 
+<b>Options -> Manage custom imports</b>, and click <b>Add from folder</b>. 
+A file chooser will appear, allowing you to select the classpath of your importer, 
+i.e. the directory where the top folder of the package structure of your importer 
+resides. In a second file chooser you select your importer
+class file, which must be derived from <code>ImportFormat</code>. By clicking
+<b>Select new ImportFormat Subclass</b>, your new importer will appear in the list 
+of custom import filters. All custom importers will appear in the <b>File -> Import -> 
+Custom Importers</b> and <b>File -> Import and Append -> Custom Importers</b> submenus 
+of the JabRef window.</p>
+
+<p>Please note that if you move the class to another directory you will have to
+remove and re-add the importer. If you add a custom importer under a name that
+already exists, the existing importer will be replaced. Although in some cases
+it is possible to update an existing custom importer without restarting JabRef 
+(when the importer is not on the classpath), we recommend restarting JabRef 
+after updating an custom-importer. You can also register importers 
+contained in a ZIP- or JAR-file, simply select the Zip- or Jar-archive, then the 
+entry (class-file) that represents the new importer.</p>
+
+<H2>Creating an import filter</H2>
+
+For examples and some helpful files on how to build your own importer, please check
+our download page.
+
+<H3>A simple example</H3>
+
+<p>Let us assume that we want to import files of the following form:
+<pre>
+1936;John Maynard Keynes;The General Theory of Employment, Interest and Money
+2003;Boldrin & Levine;Case Against Intellectual Monopoly
+2004;ROBERT HUNT AND JAMES BESSEN;The Software Patent Experiment
+</pre></p>
+
+<p>In your favorite IDE or text editor create a class derived from <code>ImportFormat</code>
+that implements methods <code>getFormatName()</code>, <code>isRecognizedFormat</code>
+and <code>importEntries()</code>. Here is an example:
+<pre>
+import java.io.*;
+import java.util.*;
+import net.sf.jabref.*;
+import net.sf.jabref.imports.ImportFormat;
+import net.sf.jabref.imports.ImportFormatReader;
+
+public class SimpleCsvImporter extends ImportFormat {
+
+  public String getFormatName() {
+    return "Simple CSV Importer";
+  }
+
+  public boolean isRecognizedFormat(InputStream stream) throws IOException {
+    return true; // this is discouraged except for demonstration purposes
+  }
+  
+  public List importEntries(InputStream stream) throws IOException {    
+  	ArrayList bibitems = new ArrayList();
+    BufferedReader in = new BufferedReader(ImportFormatReader.getReaderDefaultEncoding(stream));
+      
+    String line = in.readLine();
+    while (line != null) {
+      if (!"".equals(line.trim())) {
+        String[] fields = line.split(";");
+        BibtexEntry be = new BibtexEntry(Util.createNeutralId());
+        be.setType(BibtexEntryType.getType("techreport"));
+        be.setField("year", fields[0]);
+        be.setField("author", fields[1]);
+        be.setField("title", fields[2]);
+        bibitems.add(be);
+        line = in.readLine();
+      }     
+    }
+  	return bibitems;	  	
+  }
+}
+</pre></p>
+
+<p>Note that the example is in the default package. Suppose you have saved it
+under <code>/mypath/SimpleCsvImporter.java</code>. Also suppose the JabRef-2.0.jar is in the
+same folder as <code>SimpleCsvImporter.java</code> and Java is on your command path. 
+Compile it using a JSDK 1.4 e.g. with 
+<pre>
+javac -classpath JabRef-2.0.jar SimpleCsvImporter.java
+</pre>
+Now there should be a file <code>/mypath/SimpleCsvImporter.class</code>.</p>
+
+<p>In JabRef, open <b>Options -> Manage custom imports</b>, and click <b>Add from folder</b>.
+Navigate to <code>/mypath</code> and click the <b>Select ...</b> button. Select the
+<code>SimpleCsvImporter.class</code> and click the <b>Select ...</b> button.
+Your importer should now appear in the list of custom importers under the name 
+"Simple CSV Importer" and, after you click <b>Close</bd> also in the <b>File -> Import -> 
+Custom Importers</b> and <b>File -> Import and Append -> Custom Importers</b> submenus 
+of the JabRef window.</p>
+
+<H2>Sharing your work</H2>
+
+With custom importer files, it's fairly simple to share custom import formats between users.
+If you write an import filter for a format not supported by JabRef, or an improvement over an
+existing one, we encourage you to post your work on our SourceForge.net page. We'd be happy to 
+distribute a collection of submitted import files, or to add to the selection of standard 
+importers.
+
+</HTML>
diff --git a/src/help/EndNoteFilters.html b/src/help/EndNoteFilters.html
new file mode 100644
index 0000000..446dd1b
--- /dev/null
+++ b/src/help/EndNoteFilters.html
@@ -0,0 +1,105 @@
+<HTML>
+
+<BODY text="#275856">
+<basefont size="4" color="#2F4958" face="arial">
+
+<h1>EndNote Export Filter</h1>
+
+<h2>Export from JabRef</h2>
+
+JabRef can export databases to EndNote-readable files.
+To use this feature, choose <b>File -> Export -> EndNote</b>, 
+then specify the name of the export file.
+
+<h2>Import to EndNote</h2>
+
+The default EndNote Import filter does not handle multiple authors or
+editors properly. There are two options to work around this:
+
+<ol>
+
+<li>Use the built-in filter and fix the file later. To open up
+the file in EndNote, create a new database or open an old database in
+EndNote. Then select <b>File -> Import</b>, click on <b>Choose
+File</b>, then highlight the exported file and
+click <b>Choose</b>. Click on <b>Import Options</b> and
+select <b>EndNote Import</b>. Click <b>Import</b> to start the
+import. After import, select <b>Edit-> Change Text</b>. Change <b>Any
+Field</b> to <b>Author</b>. Enter " and " into the search field
+(without quotes). enter a return character into the change field
+(option-return on Mac OS X, ctrl-return on Windows
+XP). Click <b>Change</b>. Repeat with the <b>Secondary Author</b>
+field.
+
+<li>Install the <i>EndNote Import from JabRef filter</i> in
+the <i>EndNote Extras</i>. Follow the instructions in <i>Advanced
+Use</i> below. To open up the file in EndNote, create a new database
+or open an old database in EndNote. Then select <b>File -> Import</b>,
+click on <b>Choose File</b>, then highlight the exported file and
+click <b>Choose</b>. Click on <b>Import Options</b> and
+select <b>EndNote Import from JabRef</b> (if it does not appear,
+select Other filters. If it still doesn't appear, it was not correctly
+installed.) Click <b>Import</b> to start the import.
+
+</ol>
+
+<h2>Notes</h2>
+
+The EndNote Export filter maps BibTeX entrytypes to EndNote reference
+types as follows:
+
+<pre>
+BibTeX entrytype -> Endnote Reference Type
+------------------------------------------
+misc, other -> Generic
+unpublished -> Manuscript
+manual -> Computer Program
+article -> Journal Article
+book -> Book
+booklet -> Personal Communication
+inbook,incollection -> Book Section
+inproceedings -> Conference Proceedings
+techreport -> Report
+mastersthesis, phdthesis -> Thesis
+</pre>
+
+<h2>Corporate Authors</h2>
+
+By default, the export filter assumes that entries in the author or
+editor fields in brackets are corporate authors and replaces the
+brackets with a trailing comma. However, this means that entries that
+include LaTeX code in brackets will be assumed to be corporate authors
+and therefore will be improperly formatted.
+
+<H2>Advanced Use: Endnote Extras</h2>
+
+<h3>Installing the EndNote Import from JabRef filter</h3>
+
+The default EndNote Import filter does not properly parse authors. The
+EndNote Import from JabRef filter does.  Additionally, this filter
+will recognize a field endnotereftype that will override the default
+mapping. To install the filter, extract the EndNote Extras (<b>File -> 
+Export - > Unpack EndNote filter set</b>) and unpack the Zip file which is created.
+Then follow the directions in the file Readme.txt.<p>
+
+<h3>Modifying EndNote Reference Types</h3>
+
+Several fields used by BibTeX are not part of EndNote's default
+Reference Types. While import from JabRef and export to JabRef will
+work fine without modifying reference types, the field names will not
+display correctly in EndNote (e.g. an entry window will call the pdf
+field <i>Custom 1</i> instead of <i>pdf</i>. Additionally, these
+fields cannot be added to new entries in EndNote, since they will not
+appear in the entry window. To modify the EndNote Reference Types,
+extract the EndNote Extras and follow the directions in the file
+readme.txt.<p>
+
+<h3>Export to JabRef</h3> 
+
+EndNote comes with an export style BibTeX. However, this does not
+support all BibTeX types and fields, and does not support the
+additional General Fields supported by JabRef (<i>pdf, owner, key,</i> etc.)
+If you wish to have these fields supported, extract the EndNote
+Extras and follow the directions in the file readme.txt.<p>
+
+</HTML>
diff --git a/src/help/EntryEditorHelp.html b/src/help/EntryEditorHelp.html
new file mode 100755
index 0000000..db3e093
--- /dev/null
+++ b/src/help/EntryEditorHelp.html
@@ -0,0 +1,102 @@
+<HTML>
+
+<BODY text="#275856">
+<basefont size="4" color="#2F4958" face="arial">
+
+<H1>The entry editor</H1>
+
+<em>Opened from main window by double-clicking on the leftmost column of an entry
+(by double-clicking anywhere on the entry line if "Allow editing in table cells"
+is not selected in <strong>Options --> Preferences --> General</strong>)
+, or by pressing ENTER. The panel is closed by pressing ESC.</em>
+<P>
+In this panel you can specify all relevant information on a single entry.
+The entry editor checks the type of your entry, and lists all the fields that
+are required, and the ones that are optional, for referring the entry
+with <em>bibtex</em>. In addition, there are several fields termed <em>General
+fields</em>, that are common to all entry types.
+
+<P>You can fully customize which fields should be regarded as required and optional for each
+type of entry, and which fields appear in the General fields tab. See
+<a href="CustomEntriesHelp.html">Customizing entry types</a> for more information about this.
+
+<P>For information about how the fields should be filled out, see <a href="BibtexHelp.html">Bibtex help</a>.
+
+<H2>The entry editor's panels</H2>
+
+The entry editor contains five panels, <em>required fields</em>,
+<em>optional fields</em>, <em>general fields</em>, <em>abstract</em> and <em>bibtex
+source</em>, where <em>general fields</em> and <em>abstract</em> can be customized
+(see <a href="GeneralFields.html">Customizing general fields</a> for details).
+Inside the three first panels, TAB and SHIFT-TAB are used
+to switch focus between the text fields.
+
+<P>Switch panels by clicking on the tabs, or navigate to the panel to
+the left or right using the following key combinations: CTRL-TAB or CTRL-PLUS
+switch to the tab to the right, and CTRL-SHIFT-TAB or CTRL-MINUS switch to the
+tab to the left. You can also switch to the next or previous entry by pressing
+CTRL-SHIFT-DOWN or CTRL-SHIFT-UP, respectively, or by clicking the
+appropriate toolbar button.
+
+<P>The <em>bibtex source</em> panel shows how the entry will appear
+when the database is saved in <em>bibtex</em> format.  If you wish,
+you can edit the <em>bibtex</em> source directly in this panel. When
+you move to a different panel, press CTRL-S or close the entry editor,
+JabRef will try to parse the contents of the source panel. If there
+are problems, you will be notified, and given the option to edit your
+entry further, or to revert to the former contents.
+
+If <strong>Show source by default</strong> is checked in the
+<strong>General options</strong> tab of the
+<strong>Preferences</strong> dialog, the source panel will be the one
+shown each time you open the entry editor. If you prefer editing the
+source rather than using the other four panels, you should check this
+option.
+
+<P><strong>Tip:</strong> If your database contains fields unknown to
+JabRef, these will be visible in the source panel.
+
+<P><strong>Tip:</strong> the <I>pdf</I> and <I>url</I> fields support Drag and Drop operations.
+You can drop there an url from your browser. either a link to a pdf file
+(that JabRef can download for you) or you can keep the link.
+
+<H2>Field consistency checking</H2>
+When the contents of a field is changed, JabRef checks if the new
+contents are acceptable. For field types that are used by
+<em>bibtex</em>, the contents are checked with respect to the use of
+the '#' character. The hash symbol is <em>only</em> to be used in
+pairs, wrapping the name of a <em>bibtex</em> string that is
+referenced. Note that JabRef does not check if the referenced string
+actually exists (this is not trivial, since the <em>bibtex</em> style
+you use can define an arbitrary set of strings unknown to JabRef).
+<P>
+If the contents are not accepted, the field will turn red,
+indicating an error. In this case the change will not be stored.
+
+<!--<H2>Word/name autocompletion</H2>
+The entry editor offers autocompletion of words. In the Preferences dialog
+you can enable or disable autocompletion, and choose for which fields
+autocompletion is active.
+<P>With autocompletion, JabRef records all words that appear in
+each of the chosen fields throughout your database. Whenever you write
+the beginning of one of these words, it will be suggested visually. To
+ignore the suggestion, simply write on. To accept the suggestion,
+either press <em>ENTER</em> or use your arrow keys or other keys to
+remove the selection box around the suggested characters.
+<P><em>Note:</em> the words considered for suggestion are only the ones
+appearing in the same field in entries of the same database as the one you
+are editing. There are many ways to realise this kind of feature, and if you feel
+it should have been implemented differently, we'd like to hear your suggestions!
+
+<H2>Copy <em>bibtex</em> key</H2>
+Pressing CTRL-K or the 'key' button causes the <em>bibtex</em> key for your entry
+to be copied to the clipboard.
+-->
+<H2>Autogenerate <em>bibtex</em> key</H2>
+Press CTRL-G or the 'gen key' button (the magic wand) to autogenerate a <em>bibtex</em> key for your entry
+based on the contents of its required fields.
+<p>
+For more information on how JabRef generates <em>bibtex</em> keys, see <a href="LabelPatterns.html">Customizing the BibTex key generator</a>.
+
+</BODY>
+</HTML>
\ No newline at end of file
diff --git a/src/help/ExternalFiles.html b/src/help/ExternalFiles.html
new file mode 100644
index 0000000..ff746dd
--- /dev/null
+++ b/src/help/ExternalFiles.html
@@ -0,0 +1,41 @@
+<HTML>
+
+<BODY text="#275856">
+<basefont size="4" color="#2F4958" face="arial">
+
+<H1>PDF/PS/URL/DOI links in JabRef</H1>
+
+JabRef lets you link up your entries with PDF or PS files stored on your system, as well as
+links to the document on the web in the form of an URL or a DOI identifier.
+
+<H2>Setting up external viewers</H2>
+
+The program has to know which external viewers to use for PDF, PS and web pages. These are by default
+set to values that probably make sense for your operating system, so there's a fair chance you don't
+have to change these values.
+<p>To change the external viewer settings, go to <b>Preferences -> General</b>.
+
+<H2>Opening external files or links</H2>
+
+There are several ways to open an external file or web page. In the entry editor, you can double click on the text field
+containing the file name, DOI or URL. In the entry table you can select an entry and use the menu choice, keyboard shortcut
+or the right-click menu to open the file or web page. Finally, you can click on a PDF, PS, URL or DOI icon.
+<P> By default the entry table will contain two columns with icons for those entries that link to external files and URLs.
+  You can disable any of these in <b>Preferences -> Table</b>. The second column of the entry table shows icons for PDF or PS files (only PDF if both
+ are present), and the third column shows icons for URL or DOI (only URL if both are present). You open the file or web
+ page by clicking on an icon.
+
+<H2>The main PDF directory</H2>
+
+PDF files get a special treatment to make it as easy as possible to link them to your entries. To take advantage of this
+you have to indicate a directory in <b>Options -> Preferences -> External programs</b> as your main PDF directory. All PDF files that are stored in
+or below this directory will be referred to with a relative path by JabRef, making it easy for you if you need to move the
+PDF directory or if several users use the same database from different network places.
+<P>Additionally, if you give your PDF files names that correspond to the relevant entry's bibtex key (plus '.pdf'),
+  JabRef will be able to search your main directory and its subfolders for the correct PDF. Once the correctly-named
+  PDF is in place you access this function by clicking the 'Auto' button next to the PDF field in the entry editor. If
+  the PDF is found, the field will immediately be set.
+<P>If you name a PDF file as mentioned, you can also open the PDF without setting the PDF field of the entry at all.
+  The downside is that the PDF icon will not appear in the table unless you do (manually or with the 'Auto' button).
+
+</HTML>
diff --git a/src/help/GeneralFields.html b/src/help/GeneralFields.html
new file mode 100644
index 0000000..2ca86af
--- /dev/null
+++ b/src/help/GeneralFields.html
@@ -0,0 +1,25 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+  <head>
+    <title>Customizing entry types</title>
+  </head>
+
+  <BODY text="#275856">
+    <basefont size="4" color="#2F4958" face="arial">
+
+    <h1>Customizing general fields</h1>
+    <p>
+    You can add an arbitrary number of tabs to the entry editor. These will be present for all entry types.
+    To customize these tabs, go to "Options -> Set up general fields".
+    
+    <p>
+    You specify one tab on each line. The line should start with the name of the tab, followed by a colon (:),
+    and the fields it should contain, separated by semicolons (;).
+    
+    <p>
+    E.g.<BR><code>General:url;keywords;doi;pdf<BR>
+        Abstract:abstract;annote</CODE>
+    <P>which would give one tab named "General" containing the fields <em>url</em>, <em>keywords</em>, <em>doi</em> and <em>pdf</em>,
+    and another tab named "Abstract" containing the fields <em>abstract</em> and <em>annote</em>.
+  </body>
+</html>
diff --git a/src/help/GroupsHelp.html b/src/help/GroupsHelp.html
new file mode 100644
index 0000000..21aa6cb
--- /dev/null
+++ b/src/help/GroupsHelp.html
@@ -0,0 +1,255 @@
+<HTML>
+
+<BODY text="#275856">
+<basefont size="4" color="#2F4958" face="arial">
+
+<H1>Groups</H1>
+
+Groups allow to structure a BibTeX database in a tree-like way that is similar to organizing files on disk in directories and subdirectories. The two main differences are:
+
+<ul>
+<li> While a file is always located in exactly one directory, an entry may be contained in more than one group.
+<li> Groups may use certain criteria to dynamically define their content. New entries that match these criteria are automatically contained in these groups. This feature is not available in common file systems, but in several Email clients (e.g. Thunderbird and Opera).
+</ul>
+
+Selecting a group shows the entries contained in that group. Selecting multiple groups shows the entries contained in any group (union) or those contained in all groups (intersection), depending on the current settings. All this is explained in detail below.
+<p>
+Group definitions are database-specific; they are saved as a <tt>@COMMENT</tt> block in the <tt>.bib</tt>-file and are shared among all users. (Future versions of JabRef might support user-dependent groups.)
+
+<H2>Interface</H2>
+
+The groups interface is shown in the side pane on the left of the screen. It can be toggled on or off by pressing <tt>CTRL-SHIFT-G</tt> or by the groups button in the toolbar. The interface has several buttons, but most functions are accessed via a context ("right-click") menu. Drag and Drop is also supported.
+<p>
+
+<table cellspacing=0 cellpadding=5 border=0 bgcolor=#c0ffc0>
+<tr><td>
+<h2>Some quick examples</h2>
+
+You might want to...
+
+<h3>...just create a group and assign some entries to it</h3>
+
+Ensure that the groups interface is visible. Press the <b>New Group</b> button, enter a name for the group, then press OK, leaving all values at their defaults. Now select the entries to be assigned to the group and use Drag and Drop to the group, or the option <b>Add to group</b> in the context menu. Finally select the group to see its content (which should be the entries you just assigned).
+
+<h3>...use the <tt>keywords</tt> field to group the entries</h3>
+
+Ensure that the groups interface is visible. Press the <b>New Group</b> button, enter a name for the group, and select the option to dynamically group entries by searching a field for a keyword. Enter the keyword to search for, then click OK. Finally select the group to see its content (which should be all entries whose <tt>keywords</tt> field contains the keyword you specified).
+
+<h3>...use a free-form search expression to define a group</h3>
+
+Ensure that the groups interface is visible. Press the <b>New Group</b> button, enter a name for the group, and select the option to dynamically group entries by a free-form search expression. Enter <tt>author=smith</tt> as a search expression (replace <tt>smith</tt> with a name that actually occurs in your database) and click <b>OK</b>. Finally select the group to see its content (which should be all entries whose <tt>author</tt> field contains the name you specified).
+
+<h3>...combine multiple groups</h3>
+
+Create two different groups (e.g. as described above). Click the <b>Settings</b> button and make sure that <b>Union</b> is selected. Now select both groups. You should see all entries contained in any of the two groups. Click <b>Settings</b> again and select <b>Intersection</b>. Now you should see only those entries contained in both groups (which might be none at all, or exactly the same entries as before in case both groups contain the same entries).
+
+<h3>...identify overlapping groups</h3>
+
+JabRef allows you to easily identify groups that overlap with the currently selected groups (i.e. that contain at least one entry that is also contained in the currently selected groups). Click <b>Settings</b> and activate the option to highlight overlapping groups. Then select a group that overlaps with other groups. The other groups should be highlighted.
+
+</tr></td>
+</table>
+<p>
+
+<H2>Types of groups</H2>
+
+In JabRef 1.8 there are four different types of groups:
+
+<ol>
+<li> The group <b>All Entries</b>, which -- as the name suggests -- contains all entries, is always present and cannot be edited or removed.
+<li> <b>Static groups</b> behave like directories on disk and contain only those entries that you explicitly assign to them.
+<li> <b>Dynamic groups based on keyword search</b> contain entries in which a certain BibTeX field (e.g. <tt>keywords</tt>) contains a certain keyword (e.g. <tt>electrical</tt>). This method does not require manual assignment of entries, but uses information that is already present in the database. If all entries in your database have suitable keywords in their <tt>keywords</tt> field, using this type of group might be the best choice.
+<li> <b>Dynamic groups based on free-form search expressions</b> contain entries that match a specified search expression, using the same syntax as the <a href="SearchHelp.html">search panel</a> on the side pane. This <a href="SearchHelp.html#advanced">syntax</a> supports logical operators (<tt>AND</tt>, <tt>OR</tt>, <tt>NOT</tt>) and allows to specify one or more BibTeX fields to search, facilitating more flexible group definitions than a keyword search (e.g. <tt>author=smith and title= [...]
+</ol>
+
+Every group that you create is of one of the last three types. The group editing dialog, which is invoked by double-clicking on a group, shows a short description of the selected/edited group in plain English.
+
+<H2>Groups structure, creating and removing groups</H2>
+
+Just like directories, groups are structured like a tree, with the group <b>All Entries</b> at the root. By right-clicking on a group you can add a new group to the tree, either at the same level as the selected group or as a subgroup of it. The <b>New Group</b> button lets you create a new subgroup of the group <b>All Entries</b>, regardless of the currently selected group(s). The context menu also allows to remove groups and/or subgroups, to sort subgroups alphabetically, or to move gr [...]
+<p>
+Undo and redo is supported for all edits.
+
+<H3>Static groups</h3>
+
+Static groups are populated only by explicit manual assignment of entries. After creating a static group you select the entries to be assigned to it, and use either Drag and Drop or the main table's context menu to perform the assignment. To remove entries from a static group, select them and use the main table's context menu. There are no options to be configured.
+<p>
+This method of grouping requires that all entries have a unique BibTeX key. In case of missing or duplicate BibTeX keys, the assignment of the affected entries cannot be correctly restored in future sessions.
+
+<H3>Dynamic groups</h3>
+
+The content of a dynamic group is defined by a logical condition. Only entries that meet this condition are contained in the group. This method uses the information stored in the database itself, and updates dynamically whenever the database changes.
+<p>
+Two types of conditions can be used: 
+<dl>
+<dt><b>Searching a field for a keyword</b></dt>
+<dd>
+This method groups entries in which a specified BibTeX field (e.g. <tt>keywords</tt>) contains a specified search term (e.g. <tt>electrical</tt>). Obviously, for this to work, the grouping field must be present in every entry, and its content must be accurate. The above example would group all entries referring to something electrical. Using the field <tt>author</tt> allows to group entries by a certain author, etc. The search can either be done as a plain-text or a regular expression se [...]
+</dd>
+<dt><b>Using a free-form search expression</b></dt>
+<dd>
+This is similar to the above, but rather than search a single field for a single search term, the <a href="SearchHelp.html#advanced">search expression syntax</a> can be used, which supports logical operators (<tt>AND</tt>, <tt>OR</tt>, <tt>NOT</tt>) and allows to search multiple BibTeX fields. For example, the search expression <tt>keywords=regression and not keywords=linear</tt> groups entries concerned with non-linear regression.
+</dd>
+</dl>
+
+In the groups view, dynamic groups are shown in <i>italics</i> by default. This can be turned off in the preferences.
+
+<h3>Hierarchical context</h3>
+
+By default, a group is <b>independent</b> of its position in the groups tree: When selected, only the group's contents are shown. However, especially when using dynamic groups, it is often useful to define a subgroup that <b>refines its supergroup</b>, i.e., when selected, entries contained in both groups are displayed. For example, create a supergroup containing entries with the keyword <tt>distribution</tt> and a subgroup containing entries with the keyword <tt>gauss</tt> that refines  [...]
+<p>
+The logical complement to a refining group is a group that <b>includes its subgroups</b>, i.e. when selected, not only the group's own entries, but also its subgroups' entries are shown. In the groups tree, this type of group has a special icon (this can be turned off in the preferences).
+
+<h2>Viewing a group's entries, combining multiple groups</H2>
+
+Selecting a group shows the entries contained in that group by highlighting them and, depending on the settings (accessible by clicking the <b>Settings</b> button), moving them to the top of the list and/or selecting them. These options are identical to those available for the regular search.
+<p>
+When multiple groups are selected, either the union or the intersection of their content is shown, depending on the current settings. This allows to quickly combine multiple conditions, e.g. if you have a static group <tt>Extremely Important</tt> to which you assign all extremely important entries, you can view the extremely important entries in any other group by selecting both groups (this requires to have <b>Intersection</b> selected in the settings).
+
+<h2>Groups and searching</h2>
+
+When viewing the contents of the selected group(s), a search can be performed within these contents using the regular search facility.
+
+<h2>Highlighting overlapping groups</h2>
+
+The <b>Settings</b> button offers an option to highlight overlapping groups. If this is activated, upon selection of one or more groups, all groups that contain at least one of the entries contained in the currently selected group(s) are highlighted. This quickly identifies overlap between the groups' contents. You might, for example, create a group <tt>To Read</tt> that contains all entries which you plan to read. Now, whenever you select any group, the group <tt>To Read</tt> is highlig [...]
+
+<h2>Advanced features</h2>
+
+After mastering the grouping concepts described above, the following advanced features might come in handy.
+
+<h3>Automatically creating dynamic groups</h3>
+
+By clicking the <b>Automatically create groups for database</b> button, you can quickly create a set of groups appropriate for your database. This feature will gather all words found in a specific field of your choice, and create a group for each word. This is useful for instance if your database contains suitable keywords for all entries. By autogenerating groups based on the <tt>keywords</tt> field, you should have a basic set of groups at no cost.
+<p>
+You can also specify characters to ignore, for instance commas used between keywords. These will be treated as separators between words, and not part of them. This step is important for combined keywords such as <tt>laplace distribution</tt> to be recognized as a single semantic unit. (You cannot use this option to remove complete words. Instead, delete the unwanted groups manually after they were created automatically.)
+
+<h3>Refreshing the groups view</h3>
+
+The <b>Refresh</b> button updates the entry table to reflect the current groups selection. This is usually done automatically, but in rare occasions (e.g. after a group-related undo/redo) a manual refresh is required.
+
+<h3>Mixing refining groups with including groups</h3>
+
+If a refining group is a subgroup of a group that includes its subgroups -- the refining group's siblings --, these siblings are ignored when the refining group is selected.
+
+Selecting a group shows the entries contained in that group. Selecting multiple groups shows the entries contained in any group (union) or those contained in all groups (intersection), depending on the current settings. All this is explained in detail below.
+<p>
+Group definitions are database-specific; they are saved as a <tt>@COMMENT</tt> block in the <tt>.bib</tt>-file and are shared among all users. (Future versions of JabRef might support user-dependent groups.)
+
+<H2>Interface</H2>
+
+The groups interface is shown in the side pane on the left of the screen. It can be toggled on or off by pressing <tt>CTRL-SHIFT-G</tt> or by the groups button in the toolbar. The interface has several buttons, but most functions are accessed via a context ("right-click") menu. Drag and Drop is also supported.
+<p>
+
+<table cellspacing=0 cellpadding=5 border=0 bgcolor=#c0ffc0>
+<tr><td>
+<h2>Some quick examples</h2>
+
+You might want to...
+
+<h3>...just create a group and assign some entries to it</h3>
+
+Ensure that the groups interface is visible. Press the <b>New Group</b> button, enter a name for the group, then press OK, leaving all values at their defaults. Now select the entries to be assigned to the group and use Drag and Drop to the group, or the option <b>Add to group</b> in the context menu. Finally select the group to see its content (which should be the entries you just assigned).
+
+<h3>...use the <tt>keywords</tt> field to group the entries</h3>
+
+Ensure that the groups interface is visible. Press the <b>New Group</b> button, enter a name for the group, and select the option to dynamically group entries by searching a field for a keyword. Enter the keyword to search for, then click OK. Finally select the group to see its content (which should be all entries whose <tt>keywords</tt> field contains the keyword you specified).
+
+<h3>...use a free-form search expression to define a group</h3>
+
+Ensure that the groups interface is visible. Press the <b>New Group</b> button, enter a name for the group, and select the option to dynamically group entries by a free-form search expression. Enter <tt>author=smith</tt> as a search expression (replace <tt>smith</tt> with a name that actually occurs in your database) and click <b>OK</b>. Finally select the group to see its content (which should be all entries whose <tt>author</tt> field contains the name you specified).
+
+<h3>...combine multiple groups</h3>
+
+Create two different groups (e.g. as described above). Click the <b>Settings</b> button and make sure that <b>Union</b> is selected. Now select both groups. You should see all entries contained in any of the two groups. Click <b>Settings</b> again and select <b>Intersection</b>. Now you should see only those entries contained in both groups (which might be none at all, or exactly the same entries as before in case both groups contain the same entries).
+
+<h3>...identify overlapping groups</h3>
+
+JabRef allows you to easily identify groups that overlap with the currently selected groups (i.e. that contain at least one entry that is also contained in the currently selected groups). Click <b>Settings</b> and activate the option to highlight overlapping groups. Then select a group that overlaps with other groups. The other groups should be highlighted.
+
+</tr></td>
+</table>
+<p>
+
+<H2>Types of groups</H2>
+
+In JabRef 1.8 there are four different types of groups:
+
+<ol>
+<li> The group <b>All Entries</b>, which -- as the name suggests -- contains all entries, is always present and cannot be edited or removed.
+<li> <b>Static groups</b> behave like directories on disk and contain only those entries that you explicitly assign to them.
+<li> <b>Dynamic groups based on keyword search</b> contain entries in which a certain BibTeX field (e.g. <tt>keywords</tt>) contains a certain keyword (e.g. <tt>electrical</tt>). This method does not require manual assignment of entries, but uses information that is already present in the database. If all entries in your database have suitable keywords in their <tt>keywords</tt> field, using this type of group might be the best choice.
+<li> <b>Dynamic groups based on free-form search expressions</b> contain entries that match a specified search expression, using the same syntax as the <a href="SearchHelp.html">search panel</a> on the side pane. This <a href="SearchHelp.html#advanced">syntax</a> supports logical operators (<tt>AND</tt>, <tt>OR</tt>, <tt>NOT</tt>) and allows to specify one or more BibTeX fields to search, facilitating more flexible group definitions than a keyword search (e.g. <tt>author=smith and title= [...]
+</ol>
+
+Every group that you create is of one of the last three types. The group editing dialog, which is invoked by double-clicking on a group, shows a short description of the selected/edited group in plain English.
+
+<H2>Groups structure, creating and removing groups</H2>
+
+Just like directories, groups are structured like a tree, with the group <b>All Entries</b> at the root. By right-clicking on a group you can add a new group to the tree, either at the same level as the selected group or as a subgroup of it. The <b>New Group</b> button lets you create a new subgroup of the group <b>All Entries</b>, regardless of the currently selected group(s). The context menu also allows to remove groups and/or subgroups, to sort subgroups alphabetically, or to move gr [...]
+<p>
+Undo and redo is supported for all edits.
+
+<H3>Static groups</h3>
+
+Static groups are populated only by explicit manual assignment of entries. After creating a static group you select the entries to be assigned to it, and use either Drag and Drop or the main table's context menu to perform the assignment. To remove entries from a static group, select them and use the main table's context menu. There are no options to be configured.
+<p>
+This method of grouping requires that all entries have a unique BibTeX key. In case of missing or duplicate BibTeX keys, the assignment of the affected entries cannot be correctly restored in future sessions.
+
+<H3>Dynamic groups</h3>
+
+The content of a dynamic group is defined by a logical condition. Only entries that meet this condition are contained in the group. This method uses the information stored in the database itself, and updates dynamically whenever the database changes.
+<p>
+Two types of conditions can be used: 
+<dl>
+<dt><b>Searching a field for a keyword</b></dt>
+<dd>
+This method groups entries in which a specified BibTeX field (e.g. <tt>keywords</tt>) contains a specified search term (e.g. <tt>electrical</tt>). Obviously, for this to work, the grouping field must be present in every entry, and its content must be accurate. The above example would group all entries referring to something electrical. Using the field <tt>author</tt> allows to group entries by a certain author, etc. The search can either be done as a plain-text or a regular expression se [...]
+</dd>
+<dt><b>Using a free-form search expression</b></dt>
+<dd>
+This is similar to the above, but rather than search a single field for a single search term, the <a href="SearchHelp.html#advanced">search expression syntax</a> can be used, which supports logical operators (<tt>AND</tt>, <tt>OR</tt>, <tt>NOT</tt>) and allows to search multiple BibTeX fields. For example, the search expression <tt>keywords=regression and not keywords=linear</tt> groups entries concerned with non-linear regression.
+</dd>
+</dl>
+
+In the groups view, dynamic groups are shown in <i>italics</i> by default. This can be turned off in the preferences.
+
+<h3>Hierarchical context</h3>
+
+By default, a group is <b>independent</b> of its position in the groups tree: When selected, only the group's contents are shown. However, especially when using dynamic groups, it is often useful to define a subgroup that <b>refines its supergroup</b>, i.e., when selected, entries contained in both groups are displayed. For example, create a supergroup containing entries with the keyword <tt>distribution</tt> and a subgroup containing entries with the keyword <tt>gauss</tt> that refines  [...]
+<p>
+The logical complement to a refining group is a group that <b>includes its subgroups</b>, i.e. when selected, not only the group's own entries, but also its subgroups' entries are shown. In the groups tree, this type of group has a special icon (this can be turned off in the preferences).
+
+<h2>Viewing a group's entries, combining multiple groups</H2>
+
+Selecting a group shows the entries contained in that group by highlighting them and, depending on the settings (accessible by clicking the <b>Settings</b> button), moving them to the top of the list and/or selecting them. These options are identical to those available for the regular search.
+<p>
+When multiple groups are selected, either the union or the intersection of their content is shown, depending on the current settings. This allows to quickly combine multiple conditions, e.g. if you have a static group <tt>Extremely Important</tt> to which you assign all extremely important entries, you can view the extremely important entries in any other group by selecting both groups (this requires to have <b>Intersection</b> selected in the settings).
+
+<h2>Groups and searching</h2>
+
+When viewing the contents of the selected group(s), a search can be performed within these contents using the regular search facility.
+
+<h2>Highlighting overlapping groups</h2>
+
+The <b>Settings</b> button offers an option to highlight overlapping groups. If this is activated, upon selection of one or more groups, all groups that contain at least one of the entries contained in the currently selected group(s) are highlighted. This quickly identifies overlap between the groups' contents. You might, for example, create a group <tt>To Read</tt> that contains all entries which you plan to read. Now, whenever you select any group, the group <tt>To Read</tt> is highlig [...]
+
+<h2>Advanced features</h2>
+
+After mastering the grouping concepts described above, the following advanced features might come in handy.
+
+<h3>Automatically creating dynamic groups</h3>
+
+By clicking the <b>Automatically create groups for database</b> button, you can quickly create a set of groups appropriate for your database. This feature will gather all words found in a specific field of your choice, and create a group for each word. This is useful for instance if your database contains suitable keywords for all entries. By autogenerating groups based on the <tt>keywords</tt> field, you should have a basic set of groups at no cost.
+<p>
+You can also specify characters to ignore, for instance commas used between keywords. These will be treated as separators between words, and not part of them. This step is important for combined keywords such as <tt>laplace distribution</tt> to be recognized as a single semantic unit. (You cannot use this option to remove complete words. Instead, delete the unwanted groups manually after they were created automatically.)
+
+<h3>Refreshing the groups view</h3>
+
+The <b>Refresh</b> button updates the entry table to reflect the current groups selection. This is usually done automatically, but in rare occasions (e.g. after a group-related undo/redo) a manual refresh is required.
+
+<h3>Mixing refining groups with including groups</h3>
+
+If a refining group is a subgroup of a group that includes its subgroups -- the refining group's siblings --, these siblings are ignored when the refining group is selected.
+
+</HTML> 
\ No newline at end of file
diff --git a/src/help/HelpHelp.html b/src/help/HelpHelp.html
new file mode 100755
index 0000000..d318d85
--- /dev/null
+++ b/src/help/HelpHelp.html
@@ -0,0 +1,27 @@
+<HTML>
+
+<BODY text="#275856">
+<basefont size="4" color="#2F4958" face="arial">
+
+<H1>The help window</H1>
+<em>Opened by clicking the help button or pressing F1.</em>
+<P>
+The help window is there to provide information about using JabRef.
+
+<H2>Navigating the help files</H2>
+
+The help window is in fact a lightweight HTML browser, and the help files
+are standard HTML files.
+<P>
+When opened, the help window will default to different files depending on which
+program window it is called from. If this file doesn't explain the aspect you
+are interested in, the <em>Contents</em> button in the toolbar will take you 
+to a list of the available help files.
+<P>
+In addition the toolbar contains navigation buttons for showing the next or
+previous file. These are similar to the <em>Back</em> and <em>Forward</em>
+buttons of a standard web browser. The keyboard shortcuts for navigation are
+CTRL-SHIFT and arrow key left for <em>Back</em> and right for <em>Forward</em>.
+<P>
+The help window is closed by pressing ESCAPE.
+</HTML>
\ No newline at end of file
diff --git a/src/help/ImportInspectionDialog.html b/src/help/ImportInspectionDialog.html
new file mode 100644
index 0000000..1a1f48e
--- /dev/null
+++ b/src/help/ImportInspectionDialog.html
@@ -0,0 +1,22 @@
+<HTML>
+
+<BODY text="#275856">
+<basefont size="4" color="#2F4958" face="arial">
+
+<h1>Import inspection window</h1>
+
+When you import new entries from a supported reference format, or fetch entries directly from
+the Internet, they are first shown in this window for inspection. At this point none of the entries
+have been added to the database you already have open (if any).
+
+<P>The inspection window allows you to discard entries you don't want to keep, and to perform some
+simple operations like generating BibTeX keys for the entries, or adding them to
+<a href="GroupsHelp.html">groups</a>. If you are importing into an existing database, it is often
+easier to perform these operations before they are mixed in between the entries of the existing
+database. 
+
+<h2></h2>
+
+
+
+</HTML>
diff --git a/src/help/JabRef-UserManual.lyx b/src/help/JabRef-UserManual.lyx
new file mode 100644
index 0000000..a11b26e
--- /dev/null
+++ b/src/help/JabRef-UserManual.lyx
@@ -0,0 +1,229 @@
+#LyX 1.3 created this file. For more info see http://www.lyx.org/
+\lyxformat 221
+\textclass article
+\begin_preamble
+\usepackage{fancyhdr}
+\usepackage{charter}
+\usepackage{bbm} % for symbols
+\usepackage{fullpage}
+\def\FileAuthor{ {\sc Batada, Shepp \& Siegmund} }
+\def\FileTitle{  }
+\fancyhead[L]{\small \FileTitle{}}
+\fancyhead[R]{\small \FileAuthor{}}
+\fancyfoot[L]{\small \today}
+%\pagestyle{fancy}
+%\setstretch{1.8} % table row height
+% \renewcommand{\baselinestretch}{2.0} %2.0} % triplespacing
+%\usepackage[nofiglist,notablist,nomarker]{endfloat}
+%\usepackage{pstricks}
+
+%\beamertemplateshadingbackground{red!5}{structure!5}
+%\usepackage{beamerthemeshadow}
+ %\beamertemplatetransparentcovereddynamic
+%\beamertemplatetransparentcovered
+\newcommand{\E}[1]{\mathbf{\mathbbm{E}}\left[#1\right]}
+\newcommand{\V}[1]{\mathbf{Var}\left[#1\right]}
+\newcommand{\N}{\mathcal{N}}
+\newcommand{\ang}{\mathring{A}}
+\renewcommand{\P}[1]{\mathbf{\mathbbm{P}}\bigl(#1\bigr)}
+\usepackage{color}
+\newcommand{\jabref}{ {\color{red}J}ab{\color{blue}R}ef}
+\end_preamble
+\language english
+\inputencoding latin1
+\fontscheme default
+\graphics default
+\paperfontsize 11
+\spacing single 
+\papersize Default
+\paperpackage a4
+\use_geometry 0
+\use_amsmath 1
+\use_natbib 0
+\use_numerical_citations 0
+\paperorientation portrait
+\secnumdepth 4
+\tocdepth 3
+\paragraph_separation indent
+\defskip medskip
+\quotes_language english
+\quotes_times 2
+\papercolumns 1
+\papersides 1
+\paperpagestyle default
+
+\layout Title
+
+
+\begin_inset ERT
+status Collapsed
+
+\layout Standard
+
+\backslash 
+jabref
+\end_inset 
+
+\SpecialChar ~
+(1.2) User Manual 
+\layout Author
+
+Morten Alver and Nizar Batada
+\layout Date
+
+Feb 20, 2004
+\layout Standard
+
+
+\begin_inset LatexCommand \tableofcontents{}
+
+\end_inset 
+
+
+\layout Standard
+
+\layout Standard
+
+
+\begin_inset ERT
+status Collapsed
+
+\layout Standard
+
+\backslash 
+newpage
+\end_inset 
+
+
+\layout Section
+
+Revision
+\layout Enumerate
+
+Initial Draft: Nizar Batada Feb 20, 2004
+\layout Section
+
+About This Guide
+\layout Standard
+
+This manual is a brief introduction to some of the most useful features
+ and functions of JabRef.
+ Learning this short list of features will enable you to use the JabRef
+ efficiently.
+ This manual is not an exhaustive list of the capabilities of this software.
+ JabRef is a result of merger between BibKeeper and JBibtexManager.
+\layout Standard
+
+Additional Information is available at : http://jabref.sourceforge.net and
+ in help\SpecialChar \menuseparator
+Help content from the menu bar.
+ 
+\layout Section
+
+Introduction to BibTeX 
+\layout Section
+
+Installation
+\layout Section
+
+Features
+\layout Subsection
+
+Import
+\layout Standard
+
+Following formats are supported.
+ 
+\layout Enumerate
+
+Medline (XML) (also Fetch Medline)
+\layout Enumerate
+
+RIS
+\layout Enumerate
+
+Endnote
+\layout Enumerate
+
+Scifinder
+\layout Standard
+
+If you like other formats to be supported, please send an example file and
+ put in a request at the sourceforge site.
+\layout Subsection
+
+Export
+\layout Subsection
+
+Editing
+\layout Subsection
+
+Grouping
+\layout Subsection
+
+Defining New Entry Types
+\layout Subsection
+
+Preamble and Strings
+\layout Subsection
+
+External Program
+\layout Section
+
+Customization
+\layout Subsection
+
+Table Display Content
+\layout Subsection
+
+Toolbar
+\layout Subsection
+
+Sidepanel
+\layout Subsection
+
+Appearance
+\layout Enumerate
+
+Fonts (see 
+\begin_inset LatexCommand \ref{sub:How-do-install-fonts}
+
+\end_inset 
+
+ for instructions to install new fonts)
+\layout Section
+
+Keyboard Shortcuts
+\layout Section
+
+Limitations and Known Bugs
+\layout Section
+
+Future Additions
+\layout Subsection
+
+Shortcut customization
+\layout Section
+
+Feature Request and Bug Reports
+\layout Section
+
+Developing JabRef
+\layout Section
+
+Acknowledgements
+\layout Section
+
+FAQ
+\layout Subsection
+
+I don't know programing, is there any way I can contribute?
+\layout Subsection
+
+
+\begin_inset LatexCommand \label{sub:How-do-install-fonts}
+
+\end_inset 
+
+How do install new fonts
+\the_end
diff --git a/src/help/JabRefHelp.html b/src/help/JabRefHelp.html
new file mode 100755
index 0000000..c9ca2d2
--- /dev/null
+++ b/src/help/JabRefHelp.html
@@ -0,0 +1,33 @@
+<HTML>
+
+<BODY text="#275856">
+
+<basefont size="4" color="#2F4958" face="arial">
+
+<H1>JabRef</H1>
+
+<P><strong>Note:</strong> The <em>bibtex</em> program is mentioned many times in these help
+files. <em>Bibtex</em> is a utility for the generation of
+bibliographic references in LaTeX documents, created by Oren
+Patashnik. The same database format is also used with CiteMaker,
+a utility for bibliography generation in Adobe FrameMaker.
+
+<P>JabRef is is a program for working with <em>bibtex</em>
+databases. The program uses no internal file format, which means you
+normally load and save your databases directly in the <em>bibtex</em>
+.bib format. However, you can also import bibliography databases in a
+number of other formats into JabRef.
+
+<P>JabRef provides sorting and searching functionality for getting
+the overview of your databases' contents. You can easily add new
+database entries without having to remember what information is
+required, and <em>bibtex</em> keys can be autogenerated.  JabRef
+will be most useful for those using <em>bibtex</em> or CiteMaker, but
+may also be of use to those using other referencing systems or simply
+wanting to organize their literature sources.
+
+<P>
+<a href="BaseFrameHelp.html">The JabRef main window</a>
+
+</BODY>
+</HTML>
diff --git a/src/help/JournalAbbreviations.html b/src/help/JournalAbbreviations.html
new file mode 100644
index 0000000..bad1f06
--- /dev/null
+++ b/src/help/JournalAbbreviations.html
@@ -0,0 +1,75 @@
+<HTML>
+
+<BODY text="#275856">
+<basefont size="4" color="#2F4958" face="arial">
+
+<H1>Journal abbreviations</H1>
+
+This feature can be configured under <b>Tools -> Manage journal abbreviations</b>.
+
+<p>JabRef can automatically toggle journal names between abbreviated and unabbreviated form, as long
+as the names are contained in one of your journal lists. You can use several lists, all realized as
+external text files on your hard disk.
+
+<H2>Using the feature</H2>
+<p>
+Journal name conversion can be accessed either from within the entry editor, or from the <b>Tools</b> menu.
+In the entry editor you will find a button labelled <i>Toggle abbreviation</i> by the <i>journal</i> field.
+Clicking this button will cause the current journal name to be switched to the next of three modes:
+<ul>
+    <li>Full name, e.g. "Aquacultural Engineering"</li>
+    <li>ISO abbreviation, e.g. "Aquacult. Eng."</li>
+    <li>MEDLINE abbreviation, e.g. "Aquacult Eng"</li>
+</ul>
+If the current journal name is not found in your journal lists, the field will not be modified.
+
+<p>
+To convert the journal names of many entries in bulk, you can select any number of entries, and choose
+<b>Tools -> Abbreviate journal names (ISO)</b>, <b>Tools -> Abbreviate journal names (MEDLINE)</b> or
+    <b>Tools -> Unabbreviate journal names</b>. These two actions
+will abbreviate and unabbreviate the journal names of all selected entries for which the journal name could
+be found in your journal lists.
+
+<h2>Setting up your journal lists</h2>
+
+You can have several journal lists, all external text files linked from JabRef. The primary list can be
+edited from within JabRef.
+
+<H3>Your personal journal abbreviations list</H3>
+
+Your personal journal list is managed in the upper part of the <b>Manage journal abbreviations</b> window.
+To start building your personal journal abbreviations list, choose <i>New file</i>, and enter a filename
+manually or using the <i>Browse</i> button. If you already have a file that you want to use as a starting point,
+choose <i>Existing file</i>, and use the <i>Browse</i> button to choose the file. The table will update to show
+the contents of the list you have selected.
+
+<p>The table and the tool buttons to the right allow you to add, remove and edit journal entries. For each entry
+you must provide the full journal name, and the ISO abbreviation (e.g. "Aquacultural Engineering" and "Aquacult. Eng.").
+To edit an entry, double-click its row in the table.
+
+<p>Once you click <i>OK</i>, if you have selected a file, and the table contains at least one entry, the table
+contents will be stored to the selected file, and JabRef's list of journals will be updated.
+
+<h3>External journal lists</h3>
+
+In addition to your personal list, you can link to a number of external lists. These links can be set up
+in the lower part of the <b>Manage journal abbreviations</b> window. External lists are similar to the personal
+list - the only difference is that JabRef doesn't provide an interface for editing the external lists.
+<p>
+To add a new external list, if necessary, click the <b>+</b> button to add another slot to the interface.
+Then use either the <i>Browse</i> or <i>Download</i> button next to one of the
+slots in the lower part of the window.
+    <ul>
+    <li>The <i>Browse</i> button allows you to select an existing file on
+your computer.</li>
+    <li>The <i>Download</i> button allows you to download a list over the internet by entering and
+URL, store it to a local file on your computer, and link to it as a journal list from JabRef. The URL will
+default to the address of a journal list provided from the JabRef web page. This list is incomplete, but
+may be improved in the future.</li>
+    </ul>
+
+Any entry in your personal journal list will override an entry with the same full journal name in one of the
+external lists. Similarly, the external lists are given precedence in the order they are listed.
+
+</BODY>
+</HTML>
diff --git a/src/help/LabelPatterns.html b/src/help/LabelPatterns.html
new file mode 100644
index 0000000..cee6fd0
--- /dev/null
+++ b/src/help/LabelPatterns.html
@@ -0,0 +1,98 @@
+<HTML>
+
+<BODY text="#275856">
+
+<basefont size="4" color="#2F4958" face="arial">
+
+<H1>Customizing the BibTeX key generator</H1>
+
+In the 'Key pattern' tab in Preferences, one can set the fields used in auto
+generation of BibTex labels. The pattern can be set for each of the standard entry
+types.
+<H2>Key patterns</H2>
+The pattern can contain any text you wish, in addition to field
+markers that indicate that a specific field of the entry should be
+inserted at that position of the key. A field marker generally
+consists of the field name enclosed in square braces,
+e.g. <b>[volume]</b>. If the field is undefined in an entry at the
+time of key generation, no text will be inserted by the field marker.
+<P>
+Several special field markers are offered, which extract only a specific part of a field. These are listed below. Feel free to suggest new special field markers.
+
+<P>
+Special field markers:
+<ul>
+<li><b>[<code>auth</code>]</b>: The last name of the first author<BR>
+<li><b>[<code>authors</code>]</b>: The last name of all authors<BR>
+<li><b>[<code>authorsN</code>]</b>: The last name of up to N authors. If there are more authors, "EtAl" is appended.<BR>
+<li><b>[<code>authIniN</code>]</b>: The beginning of each author's last name, using
+no more than N characters.<BR>
+<li><b>[<code>authorIni</code>]</b>: The first 5 characters of the first author's last name,
+          and the last name initials of the remaining authors.<BR>
+<li><b>[<code>authN</code>]</b>: The first N characters of the first author's last name<BR>
+<li><b>[<code>authN_M</code>]</b>: The first N characters of the Mth author's last name<BR>
+<li><b>[<code>auth.auth.ea</code>]</b>: The last name of the first two authors, and ".ea" if there are more than two.<BR>
+<li><b>[<code>authshort</code>]</b>: The last name if one author is given; the first character of up to three authors' last names if more than one author is given. A plus character is added, if there are more than three authors.<BR>
+</ul>
+<b>Note:</b> If there is no author (as in the case of an edited book), then all of the above <b><code>[auth...]</code></b> markers will use the editor(s) (if any) as a fallback. Thus, the editor(s) of a book with no author will be treated as the author(s) for label-generation purposes. If you do not want this behaviour, i.e. you require a marker which expands to nothing if there is no author, use  <b><code>pureauth</code></b> instead of <b><code>auth</code></b> in the above codes. For ex [...]
+<ul>
+<li><b>[<code>edtr</code>]</b>: The last name of the first editor<BR>
+<li><b>[<code>edtrIniN</code>]</b>: The beginning of each editor's last name, using
+no more than N characters<BR>
+<li><b>[<code>editors</code>]</b>: The last name of all editors<BR>
+<li><b>[<code>editorIni</code>]</b>: The first 5 characters of the first editor's last name,
+ 	and the last name initials of the remaining editors.<BR>
+<li><b>[<code>edtrN</code>]</b>: The first N characters of the first editor's last name<BR>
+<li><b>[<code>edtrN_M</code>]</b>: The first N characters of the Mth editor's last name<BR>
+<li><b>[<code>edtr.edtr.ea</code>]</b>: The last name of the first two editors, and ".ea" if there are more than two.<BR>
+<li><b>[<code>edtrshort</code>]</b>: The last name if one editor is given; the first character of up to three editors' last names if more than one editor is given. A plus character is added, if there are more than three editors.<BR>
+<li><b>[<code>firstpage</code>]</b>: The number of the first page of the publication<BR>
+<li><b>[<code>lastpage</code>]</b>: The number of the last page of the publication<BR>
+<li><b>[<code>shorttitle</code>]</b>: The first 3 words of the title<BR>
+<li><b>[<code>shortyear</code>]</b>: The last 2 digits of the publication year<BR>
+<li><b>[<code>veryshorttitle</code>]</b>: The first word of the title,
+discounting 'the', 'a', 'an'.<BR>
+ </ul>
+
+<P>
+A field name (or one of the above pseudo-field names) may optionally
+be followed by one or more modifiers. Modifiers are applied in the order they are
+specified.
+<ul>
+    <li><b>:abbr</b>: Abbreviates the text produced by the field name or spcial field
+        marker. Only the first character and subsequent characters following white space
+        will be included. For example, <b>[journal:abbr]</b> would from the journal name
+        "Journal of Fish Biology" produce "JoFB".<br>
+    <li><b>:lower</b>: Forces the text inserted by the field marker to
+        be in lowercase.  For example, <b>[auth:lower]</b> expands the last
+        name of the first author in lowercase.<br>
+</ul>
+
+
+<P>
+If you haven't defined a key pattern for a certain entry type, the <b>Default
+key pattern</b> will be used. You can change the default pattern - its setting
+is above the list of entry types in the <b>Key pattern</b> section of the <b>Preferences</b>
+dialog.
+
+<P>
+The default key pattern is [auth][year], and this could produce
+keys like e.g. <code>Yared1998</code> If the key is not unique in the
+current database, it is made unique by adding one of the letters a-z
+until a unique key is found. Thus, the labels might look like:
+<blockquote> <code>Yared1998</code><BR> <code>Yared1998a</code><BR>
+<code>Yared1998b</code> </blockquote>
+
+<h2>Regular expression replace</h2>
+
+    After the key pattern has been applied to produce a key, you can choose to have the
+    key generator search for occurences of a specific regular expression, and replace
+    it with a string. The regular expression and replacement string are entered in the
+    text fields below the list of key patterns.
+
+    If the replacement string is empty, matches of the regular expression will simply
+    be removed from the generated key.
+
+</font>
+</BODY>
+</HTML>
diff --git a/src/help/LabelPatterns.txt b/src/help/LabelPatterns.txt
new file mode 100644
index 0000000..42f9ffb
--- /dev/null
+++ b/src/help/LabelPatterns.txt
@@ -0,0 +1,33 @@
+<HTML>
+
+<BODY text="#275856">
+
+<basefont size="4" color="#2F4958" face="arial">
+
+<H1>Setting the the BibTeX labels</H1>
+
+In the 'Label Pattern' tab in Preferences, one can set the fields used in auto 
+generation of BibTex labels. The pattern can be set for each of the standard entry 
+types.
+
+The pattern is of the form: <code>[field1]separator[field2]separator[field3]...<code>,
+where 'field#' is one of the (required) fields of a given entry type. The square 
+brackets are quite important. They're used to recognize which part of the string is 
+a field, and which part is a separator. This way one is not restricted to use 
+underscore as a separator.
+
+The label can contain the first or last page by using the fields firstpage and lastpage 
+(non BibTeX fields).
+
+The default is [author]_[year], and since this is not a unique key, it's made unique by
+adding one of the letters a-z until a unique key is found, so the labels might look like:
+
+<blockquote>
+	<code>Yared_1998<code>
+	<code>Yared_1998a</code>
+	<code>Yared_1998b</code>
+</blockquote>
+
+</font>
+</BODY>
+</HTML>
\ No newline at end of file
diff --git a/src/help/License.html b/src/help/License.html
new file mode 100644
index 0000000..ce67dad
--- /dev/null
+++ b/src/help/License.html
@@ -0,0 +1,494 @@
+<HTML>
+
+<BODY BGCOLOR="#FFFFFF" TEXT="#000000" LINK="#1F00FF" ALINK="#FF0000" VLINK="#9900DD">
+<H1>GNU General Public License</H1>
+
+<H2>Table of Contents</H2>
+<UL>
+
+  <LI><A NAME="TOC1" HREF="License.html#SEC1">GNU GENERAL PUBLIC LICENSE</A>
+<UL>
+<LI><A NAME="TOC2" HREF="License.html#SEC2">Preamble</A>
+<LI><A NAME="TOC3" HREF="License.html#SEC3">TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION</A>
+<LI><A NAME="TOC4" HREF="License.html#SEC4">How to Apply These Terms to Your New Programs</A>
+
+</UL>
+</UL>
+
+<P>
+
+<HR>
+
+<P>
+
+
+
+<H2><A NAME="SEC1" HREF="License#TOC1">GNU GENERAL PUBLIC LICENSE</A></H2>
+<P>
+Version 2, June 1991
+
+</P>
+
+<PRE>
+Copyright (C) 1989, 1991 Free Software Foundation, Inc.  
+59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
+
+Everyone is permitted to copy and distribute verbatim copies
+of this license document, but changing it is not allowed.
+</PRE>
+
+
+
+<H2><A NAME="SEC2" HREF="License.html#TOC2">Preamble</A></H2>
+
+<P>
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+</P>
+<P>
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+</P>
+<P>
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+</P>
+<P>
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+</P>
+<P>
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+</P>
+<P>
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+</P>
+<P>
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+</P>
+<P>
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+</P>
+
+
+<H2><A NAME="SEC3" HREF="License.html#TOC3">TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION</A></H2>
+
+
+<P>
+
+<STRONG>0.</STRONG>
+ This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+<P>
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+<P>
+
+<STRONG>1.</STRONG>
+ You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+<P>
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+<P>
+
+<STRONG>2.</STRONG>
+ You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+<P>
+
+<UL>
+
+<LI><STRONG>a)</STRONG>
+     You must cause the modified files to carry prominent notices
+     stating that you changed the files and the date of any change.
+
+<P>
+<LI><STRONG>b)</STRONG>
+     You must cause any work that you distribute or publish, that in
+     whole or in part contains or is derived from the Program or any
+     part thereof, to be licensed as a whole at no charge to all third
+     parties under the terms of this License.
+
+<P>
+<LI><STRONG>c)</STRONG>
+     If the modified program normally reads commands interactively
+     when run, you must cause it, when started running for such
+     interactive use in the most ordinary way, to print or display an
+     announcement including an appropriate copyright notice and a
+     notice that there is no warranty (or else, saying that you provide
+     a warranty) and that users may redistribute the program under
+     these conditions, and telling the user how to view a copy of this
+     License.  (Exception: if the Program itself is interactive but
+     does not normally print such an announcement, your work based on
+     the Program is not required to print an announcement.)
+</UL>
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+<P>
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+<P>
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+<P>
+
+<STRONG>3.</STRONG>
+ You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+
+<!-- we use this doubled UL to get the sub-sections indented, -->
+<!-- while making the bullets as unobvious as possible. -->
+<UL>
+
+<LI><STRONG>a)</STRONG>
+     Accompany it with the complete corresponding machine-readable
+     source code, which must be distributed under the terms of Sections
+     1 and 2 above on a medium customarily used for software interchange; or,
+
+<P>
+<LI><STRONG>b)</STRONG>
+     Accompany it with a written offer, valid for at least three
+     years, to give any third party, for a charge no more than your
+     cost of physically performing source distribution, a complete
+     machine-readable copy of the corresponding source code, to be
+     distributed under the terms of Sections 1 and 2 above on a medium
+     customarily used for software interchange; or,
+
+<P>
+<LI><STRONG>c)</STRONG>
+     Accompany it with the information you received as to the offer
+     to distribute corresponding source code.  (This alternative is
+     allowed only for noncommercial distribution and only if you
+     received the program in object code or executable form with such
+     an offer, in accord with Subsection b above.)
+</UL>
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+<P>
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+<P>
+
+<STRONG>4.</STRONG>
+ You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+<P>
+
+<STRONG>5.</STRONG>
+ You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+<P>
+
+<STRONG>6.</STRONG>
+ Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+<P>
+
+<STRONG>7.</STRONG>
+ If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+<P>
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+<P>
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+<P>
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+<P>
+
+<STRONG>8.</STRONG>
+ If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+<P>
+
+<STRONG>9.</STRONG>
+ The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+<P>
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+<P>
+
+
+<STRONG>10.</STRONG>
+ If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+
+
+<P><STRONG>NO WARRANTY</STRONG></P>
+
+<P>
+
+<STRONG>11.</STRONG>
+ BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+<P>
+
+<STRONG>12.</STRONG>
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+<P>
+
+
+<H2>END OF TERMS AND CONDITIONS</H2>
+
+
+
+<H2><A NAME="SEC4" HREF="License.html#TOC4">How to Apply These Terms to Your New Programs</A></H2>
+
+<P>
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+</P>
+<P>
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+</P>
+
+<PRE>
+<VAR>one line to give the program's name and an idea of what it does.</VAR>
+Copyright (C) <VAR>yyyy</VAR>  <VAR>name of author</VAR>
+
+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.
+</PRE>
+
+<P>
+Also add information on how to contact you by electronic and paper mail.
+
+</P>
+<P>
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+</P>
+
+<PRE>
+Gnomovision version 69, Copyright (C) <VAR>year</VAR> <VAR>name of author</VAR>
+Gnomovision comes with ABSOLUTELY NO WARRANTY; for details
+type `show w'.  This is free software, and you are welcome
+to redistribute it under certain conditions; type `show c' 
+for details.
+</PRE>
+
+<P>
+The hypothetical commands <SAMP>`show w'</SAMP> and <SAMP>`show c'</SAMP> should show
+the appropriate parts of the General Public License.  Of course, the
+commands you use may be called something other than <SAMP>`show w'</SAMP> and
+<SAMP>`show c'</SAMP>; they could even be mouse-clicks or menu items--whatever
+suits your program.
+
+</P>
+<P>
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+</P>
+
+<PRE>
+Yoyodyne, Inc., hereby disclaims all copyright
+interest in the program `Gnomovision'
+(which makes passes at compilers) written 
+by James Hacker.
+
+<VAR>signature of Ty Coon</VAR>, 1 April 1989
+Ty Coon, President of Vice
+</PRE>
+
+<P>
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
+
+<P><CENTER><a href="About.html">Back</a>
+</BODY>
+</HTML>
diff --git a/src/help/MarkingHelp.html b/src/help/MarkingHelp.html
new file mode 100644
index 0000000..6871896
--- /dev/null
+++ b/src/help/MarkingHelp.html
@@ -0,0 +1,20 @@
+<HTML>
+
+<BODY text="#275856">
+<basefont size="4" color="#2F4958" face="arial">
+
+<H1>Mark entries</H1>
+
+You have the option of <em>marking</em> entries. Keyboard shortcuts are CTRL-M and CTRL-SHIFT-M to
+mark and unmark the selected entries, respectively, and you can also access these actions in the
+menus.
+
+<p>Note that marking is not the same as selecting entries. Marked entries behave differently from other entries 
+in two ways. First, they are always displayed with a yellow background in the entry table. Second, they will float 
+to the top of your entry list, as long as your table is not sorted according to groups or a Float search.
+
+<p>Saving your database will preserve the markings.
+
+<p>Marking entries can be useful for instance if you need to do several searches without losing your first
+  search results, or if you need to remember which articles or books to look more closely at.
+</HTML>
diff --git a/src/help/MedlineHelp.html b/src/help/MedlineHelp.html
new file mode 100644
index 0000000..7c5311e
--- /dev/null
+++ b/src/help/MedlineHelp.html
@@ -0,0 +1,35 @@
+<HTML>
+
+<BODY text="#275856">
+<basefont size="4" color="#2F4958" face="arial">
+
+<H1>Fetching Medline entries</H1>
+
+JabRef can download citations from the Medline database.
+To use this feature, choose <b>Tools -> Fetch Medline</b>, 
+and the Medline interface will appear in the side pane.
+<P>
+There are two ways of specifying which entries to download:
+
+<ol>
+<li> Enter one or more Medline IDs (separated by comma/semicolon) in the
+text field.
+<li> Enter a set of names and/or words to search for. You can use the operators
+<em>and</em> and <em>or</em> and parentheses to refine your search expression.
+</ol>
+
+In both cases, press <b>Enter</b> or the <b>Fetch</b> button. If you
+use a text search, you will be prompted with the number of entries
+found, and given a choice of how many to download.
+
+<p>The entries fetched will be added to your currently active database.
+
+<H2>Using a Proxy Server</H2>
+
+If you need to use an http proxy server, pass the server name and
+port number to java at runtime.  These environment settings are documented
+at <p> http://java.sun.com/j2se/1.4.2/docs/guide/net/properties.html
+
+<p><code>java -Dhttp.proxyHost="hostname" -Dhttp.proxyPort="portnumber"</code>
+
+</HTML>
diff --git a/src/help/OpenOfficeHelp.html b/src/help/OpenOfficeHelp.html
new file mode 100644
index 0000000..051e02b
--- /dev/null
+++ b/src/help/OpenOfficeHelp.html
@@ -0,0 +1,53 @@
+<HTML>
+
+<BODY text="#275856">
+<basefont size="4" color="#2F4958" face="arial">
+
+<H1>Using JabRef bibliographies in OpenOffice.org</H1>
+
+JabRef can export your database in both the OpenOffice.org 1.1 <b>.sxc</b>
+spreadsheet format, and the OpenDocument <b>.ods</b> spreadsheet format used
+by OpenOffice.org 2.0.
+<p>
+In both cases the exported spreadsheet will contain one data sheet, listing entries
+in rows and the various fields in columns. The order and names of the columns is set
+to be compatible with OpenOffice.org's bibliography functions (OOo 1.1 in the case of
+the <b>.sxc</b> export, and OOo 2.0 in the case of the <b>.ods</b> format).
+
+<h2>Using the exported file as bibliography database in OpenOffice 2.0 or newer</h2>
+
+Use the following steps to set up a spreadsheet exported from JabRef as bibliography
+database in OpenOffice.org:
+<ul>
+    <li>Export your database using the <b>.ods</b> format</li>
+    <li>Start OpenOffice.org</li>
+    <li>Choose <b>Tools -> Options -> OpenOffice.org Base -> Databases</b></li>
+    <li>Edit the <i>Bibliography</i> database, and change the name to something else,
+    e.g. <i>Bibliography-old</i></li>
+    <li>Close the <b>Options</b> window, and choose <b>File -> New -> Database</b></li>
+    <li>Choose <b>Connect to an existing database</b>, select <b>Spreadsheet</b> as
+    the database type, and choose the <b>.ods</b> file you exported</li>
+    <li>Click <b>Finish</b>, then choose the name <i>Bibliography</i> when prompted</li>
+</ul>                                       
+After finishing these steps, choose <b>Tools -> Bibliography Database</b>. Your database
+should now be displayed.
+<p>
+
+<h2>Using the exported file as bibliography database in OpenOffice 1.1.x</h2>
+
+ <ul>
+    <li>Export your database using the <b>.sxc</b> format</li>
+    <li>Start OpenOffice.org</li>
+    <li>Choose <b>Tools -> Data sources</b></li>
+    <li>Select the <i>Bibliography</i> database, and change its name to something else,
+    e.g. <i>Bibliography-old</i>. Click <b>Apply</b>.</li>
+    <li>Click <b>New Data Source</b>. A new entry will appear. Change its name to
+        <i>Bibliography</i>.</li>
+     <li>Change <b>Database type</b> to <b>Spreadsheet</b>. Click  the <b>...</b> button
+     in the <b>Data source URL</b> line. Choose the <b>.sxc</b> file you exported.</li>
+     <li>Click <b>OK</b> to close the <b>Data Sources</b> window.</li>
+</ul>
+After finishing these steps, choose <b>Tools -> Bibliography Database</b>.
+Your database should now be displayed.
+
+</HTML>
diff --git a/src/help/OwnerHelp.html b/src/help/OwnerHelp.html
new file mode 100644
index 0000000..7291951
--- /dev/null
+++ b/src/help/OwnerHelp.html
@@ -0,0 +1,15 @@
+<HTML>
+
+<BODY text="#275856">
+<basefont size="4" color="#2F4958" face="arial">
+
+<H1>The 'owner' field</H1>
+
+JabRef can optionally mark all new entries added or imported to a database with your username.
+You can disable or enable this feature by entering <b>Preferences -> General</b>, and you can also
+change the name used to mark your entries. The default name used is your user name.
+
+<p>The name will be added in a field called 'owner', which by default is visible in the <b>General fields</b>
+  tab in the Entry Editor.
+
+</HTML>
diff --git a/src/help/PreviewHelp.html b/src/help/PreviewHelp.html
new file mode 100644
index 0000000..491dd20
--- /dev/null
+++ b/src/help/PreviewHelp.html
@@ -0,0 +1,17 @@
+<HTML>
+
+<BODY text="#275856">
+<basefont size="4" color="#2F4958" face="arial">
+
+<H1>Entry preview setup</H1>
+
+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
+preview panel.
+
+To modify the appearance and contents of the preview you need to edit the preview layouts
+using the syntax described in the help file on <a href="CustomExports.html">Custom export filters</a>.
+
+</HTML>
diff --git a/src/help/RemoteHelp.html b/src/help/RemoteHelp.html
new file mode 100644
index 0000000..86d28f4
--- /dev/null
+++ b/src/help/RemoteHelp.html
@@ -0,0 +1,35 @@
+<HTML>
+
+<BODY text="#275856">
+<basefont size="4" color="#2F4958" face="arial">
+
+<H1>Remote operation</H1>
+
+This feature can be toggled and configured under <b>Preferences -> Advanced</b>.
+
+<p><i>Note that activating this feature under Windows XP SP2 (and possibly other configurations)
+may prompt a message box stating that certain features of the program have been blocked by the
+Windows firewall. You can safely tell the firewall to keep blocking - the firewall will not interfere
+with remote operation of JabRef.</i>
+
+<p>If listening for remote operation is enabled, JabRef will at startup attempt to start listening
+to a specific port. This means that other applications can send information to JabRef through
+this port. JabRef will only accept local connections, to avoid the risk of interference from
+outside.
+
+<p>
+Binding to this port makes it possible for a second JabRef instance to discover that the first one is
+    running. In this case, unless specifically instructed to run in stand-alone mode,
+    the second JabRef instance will pass its command line options through the port to the first
+    JabRef instance, and then immediately quit.
+
+<p>The first JabRef instance will read the command line options, and perform the indicated actions,
+    such as reading or importing a file, or importing a file to the currently shown database.
+    If a file is imported using the command-line option <code>--importToOpen</code>, the imported
+    entries will be added to the currently shown database. If no database is open, a new one will
+    be created.
+
+
+
+</BODY>
+</HTML>
\ No newline at end of file
diff --git a/src/help/SearchHelp.html b/src/help/SearchHelp.html
new file mode 100644
index 0000000..39ae96c
--- /dev/null
+++ b/src/help/SearchHelp.html
@@ -0,0 +1,67 @@
+<HTML>
+
+<BODY text="#275856">
+<basefont size="4" color="#2F4958" face="arial">
+
+<H1>Searching</H1>
+
+
+There are three different search modes in JabRef.
+
+<p>
+<em>CTRL-F</em> opens or focuses the search interface. Pressing
+<em>CTRL-F</em> several times toggles search mode. When searching
+incrementally, pressing <em>CTRL-F</em> makes the program search for
+the next occurence of the search string.
+<p>
+<em>CTRL-SHIFT-F</em> opens or focuses the search interface, and
+selects incremental search. When searching incrementally,
+<em>CTRL-SHIFT-F</em> also finds the next occurence of the search
+string.
+
+<H2>Incremental search</H2>
+
+When searching incrementally, the program searches immediately each
+time you press a letter. The status line informs you about the success
+of the search. Pressing the search shortcut keys causes the program to
+find the next occurence of the current search string. If no further
+occurences can be found, the status line will notify you about
+this. Repeating the search again causes the search to restart at the
+top. The search order always follows the current sorting of your
+database. To escape an incremental search, press ESC or click "Clear
+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.
+To stop displaying the search results, press ESC or click "Clear search".
+
+<a name="advanced"><H2>Field specification, logical operators</H2>
+
+In order to search specific fields only and/or include logical operators in the search expression, a special syntax is available in which these can be specified. E.g. to search for entries whose author is "Miller", enter (in any but incremental search mode):
+<p>
+author = miller
+<p>
+Both the field specification and the search term support regular expressions. If the search term contains spaces, enclose it in quotes. Do <i>not</i> use spaces in the field specification! E.g. to search for entries about image processing, type:
+<p>
+title|keywords = "image processing"
+<p>
+You can use "and", "or", "not", and braces as intuitively expected:
+<p>
+(author = miller or title|keywords = "image processing") and not author = brown
+<p>
+The "=" sign is actually a shorthand for "contains". Searching for an exact match is possible using "matches" or "==". Using "!=" tests if the search term is <i>not</i> contained in the field (equivalent to "not ... contains ..."). The selection of field types to search (required, optional, all) is always overruled by the field specification in the search expression. To search for entries of a certain type, a pseudo field called "entrytype" is available:
+<p>
+entrytype = thesis
+<p>
+This finds entries whose type (as displayed in the "Entrytype" column) contains the word "thesis" (which would be "phdthesis" and "mastersthesis"). Another pseudo field "bibtexkey" allows to search for citation keys, e.g.
+<p>
+bibtexkey = miller2005
+
+<H2>Search settings</H2>
+
+ The <em>Settings</em> button opens a menu that allows to toggle case sensitivity and use of regular expressions in the search, and whether search results should be selected in the table. 
+
+</BODY>
+</HTML> 
\ No newline at end of file
diff --git a/src/help/ShortIntegrityCheck.html b/src/help/ShortIntegrityCheck.html
new file mode 100644
index 0000000..510f99e
--- /dev/null
+++ b/src/help/ShortIntegrityCheck.html
@@ -0,0 +1,8 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<body>
+<basefont size="-1" color="#2F4958" face="arial">
+Integrity check is a process that checks for indications of wrongly 
+filled out bibtex fields. "Scan" is the button that starts the check.
+<br>
+</body></html>
\ No newline at end of file
diff --git a/src/help/ShortPlainImport.html b/src/help/ShortPlainImport.html
new file mode 100644
index 0000000..c11affb
--- /dev/null
+++ b/src/help/ShortPlainImport.html
@@ -0,0 +1,7 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<body>
+<basefont size="-1" color="#2F4958" face="arial">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. <br>
+</body></html>
\ No newline at end of file
diff --git a/src/help/StringEditorHelp.html b/src/help/StringEditorHelp.html
new file mode 100755
index 0000000..411d8da
--- /dev/null
+++ b/src/help/StringEditorHelp.html
@@ -0,0 +1,41 @@
+<HTML>
+
+<BODY text="#275856">
+<basefont size="4" color="#2F4958" face="arial">
+
+<H1>The string editor</H1>
+<em>Opened from the main window by <em>Edit strings</em> or pressing a
+button in the toolbar.</em>
+<P>
+<em>Strings</em> are the <em>bibtex</em> equivalent to constants in a
+programming language.  Each string is defined with a unique
+<em>name</em> and a <em>content</em>. Elsewhere in the database, the
+name can be used to represent the content.
+
+<P>
+For instance, if many entries are from a journal with an abbreviation
+that may be hard to remember, such as 'J. Theor. Biol.' (Journal of
+Theroretical Biology), a string named JTB could be defined to
+represent the journal's name. Instead of repeating the exact journal
+name in each entry, the characters '#JTB#' (without quotes) are put into the
+<em>journal</em> field of each, ensuring the journal name is written
+identically each time.
+
+<P>
+A string reference can appear anywhere in any field, always by enclosing
+the string's name in a pair of '#' characters. This syntax is specific for
+JabRef, and differs slightly from the <em>bibtex</em> notation that
+is produced when you save your database.
+
+<P>
+A string may in the same way be referred in the content of another
+string, provided the referred string is defined <em>before</em> the
+referring one.
+
+<p>While the order of strings in your BibTeX file is important in some cases,
+you don't have to worry about this when using JabRef. The strings will be displayed
+in alphabetical order in the string editor, and stored in the same order, except when
+a different ordering is required by BibTeX.
+
+</BODY>
+</HTML> 
\ No newline at end of file
diff --git a/src/help/TimeStampHelp.html b/src/help/TimeStampHelp.html
new file mode 100644
index 0000000..acf3f15
--- /dev/null
+++ b/src/help/TimeStampHelp.html
@@ -0,0 +1,37 @@
+<HTML>
+
+<BODY text="#275856">
+<basefont size="4" color="#2F4958" face="arial">
+
+<H1>Entry time stamps</H1>
+
+This feature can be toggled and configured under <b>Preferences -> General</b>.
+
+<p>JabRef can automatically set a field to contain the date an entry was added to the database.
+
+<H2>Formatting</H2>
+
+The formatting of the time stamp is determined by a string containing designator words that indicate
+the position of the various parts of the date.
+<p>
+These are some of the available designator letters (examples are given in parentheses for
+Wednesday 14th of September 2005 at 5.45 PM):
+<ul>
+    <li><b>yy</b>: year (05)</li>
+    <li><b>yyyy</b>: year (2005)</li>
+    <li><b>MM</b>: month (09)</li>
+    <li><b>dd</b>: day in month (14)</li>
+    <li><b>HH</b>: hour in day (17)</li>
+    <li><b>mm</b>: minute in hour (45)</li>
+</ul>
+
+These designators can be combined along with punctuation and whitespace. A couple of examples:
+
+<ul>
+<li><b>yyyy.MM.dd</b> gives <b>2005.09.14</b></li>
+<li><b>yy.MM.dd</b> gives <b>05.09.14</b></li>
+<li><b>yyyy.MM.dd HH:mm</b> gives <b>2005.09.14 17:45</b></li>
+</ul>
+
+</BODY>
+</HTML>
diff --git a/src/help/autumn.png b/src/help/autumn.png
new file mode 100644
index 0000000..77b7590
Binary files /dev/null and b/src/help/autumn.png differ
diff --git a/src/help/cpl-v10.html b/src/help/cpl-v10.html
new file mode 100644
index 0000000..36aa208
--- /dev/null
+++ b/src/help/cpl-v10.html
@@ -0,0 +1,125 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
+<HTML>
+<HEAD>
+<TITLE>Common Public License - v 1.0</TITLE>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+</HEAD>
+
+<BODY BGCOLOR="#FFFFFF" VLINK="#800000">
+
+
+<P ALIGN="CENTER"><B>Common Public License - v 1.0</B>
+<P><B></B><FONT SIZE="3"></FONT>
+<P><FONT SIZE="3"></FONT><FONT SIZE="2">THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT").  ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.</FONT>
+<P><FONT SIZE="2"></FONT>
+<P><FONT SIZE="2"><B>1.  DEFINITIONS</B></FONT>
+<P><FONT SIZE="2">"Contribution" means:</FONT>
+
+<UL><FONT SIZE="2">a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and<BR CLEAR="LEFT">
+b) in the case of each subsequent Contributor:</FONT></UL>
+
+
+<UL><FONT SIZE="2">i)	 	changes to the Program, and</FONT></UL>
+
+
+<UL><FONT SIZE="2">ii)		additions to the Program;</FONT></UL>
+
+
+<UL><FONT SIZE="2">where such changes and/or additions to the Program originate from and are distributed by that particular Contributor.  </FONT><FONT SIZE="2">A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf.  </FONT><FONT SIZE="2">Contributions do not include additions to the Program which:  (i) are separate modules of software distributed in conjunction with the Program under their ow [...]
+
+<P><FONT SIZE="2"></FONT>
+<P><FONT SIZE="2">"Contributor" means any person or entity that distributes the Program.</FONT>
+<P><FONT SIZE="2"></FONT><FONT SIZE="2"></FONT>
+<P><FONT SIZE="2">"Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program.  </FONT>
+<P><FONT SIZE="2"></FONT><FONT SIZE="2"></FONT>
+<P><FONT SIZE="2"></FONT><FONT SIZE="2">"Program" means the Contributions distributed in accordance with this Agreement.</FONT>
+<P><FONT SIZE="2"></FONT>
+<P><FONT SIZE="2">"Recipient" means anyone who receives the Program under this Agreement, including all Contributors.</FONT>
+<P><FONT SIZE="2"><B></B></FONT>
+<P><FONT SIZE="2"><B>2.  GRANT OF RIGHTS</B></FONT>
+
+<UL><FONT SIZE="2"></FONT><FONT SIZE="2">a)	</FONT><FONT SIZE="2">Subject to the terms of this Agreement, each Contributor hereby grants</FONT><FONT SIZE="2"> Recipient a non-exclusive, worldwide, royalty-free copyright license to</FONT><FONT SIZE="2" COLOR="#FF0000"> </FONT><FONT SIZE="2">reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object  [...]
+
+
+<UL><FONT SIZE="2"></FONT></UL>
+
+
+<UL><FONT SIZE="2"></FONT><FONT SIZE="2">b) 	Subject to the terms of this Agreement, each Contributor hereby grants </FONT><FONT SIZE="2">Recipient a non-exclusive, worldwide,</FONT><FONT SIZE="2" COLOR="#008000"> </FONT><FONT SIZE="2">royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form.  This patent license shall apply to the combination of th [...]
+
+
+<UL><FONT SIZE="2"></FONT></UL>
+
+
+<UL><FONT SIZE="2">c)	Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity.  Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise.  As a condition to exercising the rights and  [...]
+
+
+<UL><FONT SIZE="2"></FONT></UL>
+
+
+<UL><FONT SIZE="2">d)	Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. </FONT></UL>
+
+
+<UL><FONT SIZE="2"></FONT></UL>
+
+<P><FONT SIZE="2"><B>3.  REQUIREMENTS</B></FONT>
+<P><FONT SIZE="2"><B></B>A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that:</FONT>
+
+<UL><FONT SIZE="2">a)	it complies with the terms and conditions of this Agreement; and</FONT></UL>
+
+
+<UL><FONT SIZE="2">b)	its license agreement:</FONT></UL>
+
+
+<UL><FONT SIZE="2">i)	effectively disclaims</FONT><FONT SIZE="2"> on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; </FONT></UL>
+
+
+<UL><FONT SIZE="2">ii) 	effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; </FONT></UL>
+
+
+<UL><FONT SIZE="2">iii)</FONT><FONT SIZE="2">	states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and</FONT></UL>
+
+
+<UL><FONT SIZE="2">iv)	states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange.</FONT><FONT SIZE="2" COLOR="#0000FF"> </FONT><FONT SIZE="2" COLOR="#FF0000"></FONT></UL>
+
+
+<UL><FONT SIZE="2" COLOR="#FF0000"></FONT><FONT SIZE="2"></FONT></UL>
+
+<P><FONT SIZE="2">When the Program is made available in source code form:</FONT>
+
+<UL><FONT SIZE="2">a)	it must be made available under this Agreement; and </FONT></UL>
+
+
+<UL><FONT SIZE="2">b)	a copy of this Agreement must be included with each copy of the Program.  </FONT></UL>
+
+<P><FONT SIZE="2"></FONT><FONT SIZE="2" COLOR="#0000FF"><STRIKE></STRIKE></FONT>
+<P><FONT SIZE="2" COLOR="#0000FF"><STRIKE></STRIKE></FONT><FONT SIZE="2">Contributors may not remove or alter any copyright notices contained within the Program.  </FONT>
+<P><FONT SIZE="2"></FONT>
+<P><FONT SIZE="2">Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution.  </FONT>
+<P><FONT SIZE="2"></FONT>
+<P><FONT SIZE="2"><B>4.  COMMERCIAL DISTRIBUTION</B></FONT>
+<P><FONT SIZE="2">Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like.  While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors.   Therefore, if a Contributor includes the Program in a commercial product offering, such Contrib [...]
+<P><FONT SIZE="2"></FONT>
+<P><FONT SIZE="2">For example, a Contributor might include the Program in a commercial product offering, Product X.  That Contributor is then a Commercial Contributor.  If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone.  Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to thos [...]
+<P><FONT SIZE="2"></FONT><FONT SIZE="2" COLOR="#0000FF"></FONT>
+<P><FONT SIZE="2" COLOR="#0000FF"></FONT><FONT SIZE="2"><B>5.  NO WARRANTY</B></FONT>
+<P><FONT SIZE="2">EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is</FONT><FONT SIZE="2"> solely responsible for determining the appropriateness of using and distributing </FONT><FONT SIZE="2">the Program</FONT><FONT  [...]
+<P><FONT SIZE="2"></FONT>
+<P><FONT SIZE="2"></FONT><FONT SIZE="2"><B>6.  DISCLAIMER OF LIABILITY</B></FONT>
+<P><FONT SIZE="2"></FONT><FONT SIZE="2">EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES </FONT><FONT SIZE="2">(INCLUDING WITHOUT LIMITATION LOST PROFITS),</FONT><FONT SIZE="2"> HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR  [...]
+<P><FONT SIZE="2"></FONT><FONT SIZE="2"></FONT>
+<P><FONT SIZE="2"><B>7.  GENERAL</B></FONT>
+<P><FONT SIZE="2"></FONT><FONT SIZE="2">If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable.</FONT>
+<P><FONT SIZE="2"></FONT>
+<P><FONT SIZE="2">If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed.  In addition, if Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program i [...]
+<P><FONT SIZE="2"></FONT>
+<P><FONT SIZE="2">All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance.  If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable.  However, Recipient's obligations under this Agreement and any lice [...]
+<P><FONT SIZE="2"></FONT>
+<P><FONT SIZE="2"></FONT><FONT SIZE="2">Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted  and may only be modified in the following manner. The Agreement Steward reserves the right to </FONT><FONT SIZE="2">publish new versions (including revisions) of this Agreement from time to </FONT><FONT SIZE="2">time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initia [...]
+<P><FONT SIZE="2"></FONT>
+<P><FONT SIZE="2">This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose.  Each party waives its rights to a jury trial in any resulting litigation.</FONT>
+<P><FONT SIZE="2"></FONT><FONT SIZE="2"></FONT>
+<P><FONT SIZE="2"></FONT>
+
+</BODY>
+
+</HTML>
\ No newline at end of file
diff --git a/src/help/credits.txt b/src/help/credits.txt
new file mode 100644
index 0000000..6a4035f
--- /dev/null
+++ b/src/help/credits.txt
@@ -0,0 +1,38 @@
+# Developers
+Morten O. Alver
+Nizar N. Batada
+Michel Baylac
+Guillaume Gardey
+Cyrille d'Haese
+Raik Nagel
+Ellen Reitmayr
+Michael Spiegel
+Ulrik Stervbo
+Dominik Wa�enhoven
+Joerg K. Wegner
+Michael Wrighton
+Egon Willighagen
+J�rg Zieren
+
+# Contributions from
+Kolja Brix
+Fr�d�ric Darboux
+Fabrice Dessaint
+Nathan Dunn
+Alexis Gallagher
+Sascha Hunold
+Bernd Kalbfuss
+Martin K�hmer
+Alex Montgomery
+John Relph
+Moritz Ringler
+Rudolf Seemann
+Mike Smoot
+Martin Stolle
+David Weitzman
+Seb Wills
+
+# Thanks to
+Samin Muhammad Ridwanul Karim
+Stefan Robert
+
diff --git a/src/help/de/About.html b/src/help/de/About.html
new file mode 100644
index 0000000..3482716
--- /dev/null
+++ b/src/help/de/About.html
@@ -0,0 +1,77 @@
+<HTML>
+
+<BODY text="#275856">
+<basefont size="4" color="#2F4958" face="arial">
+<CENTER>
+<H1>JabRef Version @version@</H1>
+
+(c) 2006
+
+
+<P>
+JabRef ist frei verfügbar unter den Bedingungen der
+<a href="License.html">Gnu Public License</a>.
+
+<H2>Entwickler:</H2>
+Morten O. Alver<BR>
+Nizar N. Batada<BR>
+Michel Baylac<BR>
+Guillaume Gardey<BR>
+Cyrille d'Haese<BR>
+Raik Nagel<BR>
+Ellen Reitmayr<BR>
+Andreas Rudert<BR>
+Michael Spiegel<BR>
+Ulrik Stervbo<BR>
+Dominik Waßenhoven<BR>
+Joerg K. Wegner<BR>
+Michael Wrighton<BR>
+Egon Willighagen <BR>
+Jörg Zieren<BR>
+
+<H2>Beiträge von:</H2>
+Kolja Brix<BR>
+Frédéric Darboux<BR>
+Fabrice Dessaint<BR>
+Nathan Dunn<BR>
+Brian van Essen<br>
+Alexis Gallagher<BR>
+Sascha Hunold<BR>
+Bernd Kalbfuss<BR>
+Martin Kähmer<BR>
+Jeffrey Kuhn<BR>
+Alex Montgomery<BR>
+John Relph<BR>
+Moritz Ringler<BR>
+Rudolf Seemann<BR>
+Toralf Senger<br>    
+Mike Smoot<BR>
+Martin Stolle<BR>
+David Weitzman<BR>
+Seb Wills<BR>
+
+<H2>Dank an:</H2>
+Samin Muhammad Ridwanul Karim<BR>
+Stefan Robert<BR>
+
+<H2>Benutzte Fremdsoftware:</H2>
+JabRef benutzt JGoodies Looks 1.2.2 und JGoodiesForms 1.0.4, das von JGoodies (<code>http://www.jgoodies.com</code>) unter den Bedingungen der BSD License vertrieben wird (siehe <code>http://www.opensource.org/licenses/bsd-license.html</code> für nähere Einzelheiten dieser Lizenz).
+<P>
+Außerdem werden zwei zustätzliche Klassen (SimpleInternalFrame and UIFSplitPane) von Karsten Lentzsch benutzt, die unter <A HREF="jgoodies.html">diesen Bedingungen</A> vertrieben werden.
+<P>
+Kommandozeilenbefehle werden geparst mit RitOpt (<code>http://ritopt.sourceforge.net</code>), das unter den Bedingungen der <a href="License.html">GNU Public License</a> (Version 2) verfügbar ist.
+<P>
+JabRef verwendet für die Suche den ANTLR Parser Generator. ANTLR ist public domain software - siehe <code>http://www.antlr.org/license.html</code> für die Lizenzbedingungen.
+<p>
+Für die Darstellung und Filterung der Tabelle benutzt JabRef die Glazed Lists library
+    (<code>http://publicobject.com/glazedlists</code>), die unter den Bedingungen der Lesser GNU Public License vertrieben wird.
+<P>
+JabRef benutzt darüber hinaus die "threading library" Spin 1.3.1, die unter den Bedingungen der LGPL (Lesser GNU Public License) vertrieben wird.
+<P>
+Dieses Produkt beinhaltet Software, die von der Apache Software Foundation (<code>http://www.apache.org</code>) entwickelt wurde. Die Bibliotheken "Commons Logging" und "Commons HTTP Client" werden von The Jakarta Project (<code>http://jakarta.apache.org</code>) unter der Apache Software Lizenz (Version 1.1) vertrieben (siehe die beigelegte Datei <code>apache-license.txt</code> oder <code>http://opensource.org/licenses/apachepl.php</code> für nähere Einzelheiten dieser Lizenz).
+<P>
+Einige Icons sind von uns, aber die meisten stammen vom Eclipse Projekt (<code>http://www.eclipse.org</code>), das unter den Bedingungen der <a href="cpl-v10.html">Common Public License</a> vertrieben wird, sowie vom QIcons Paket (<code>http://qt.osdn.org.ua</code>), das unter den Bedingungen der <a href="License.html">GNU Public License</a> vertrieben wird.
+
+</CENTER>
+</BODY>
+</HTML>
\ No newline at end of file
diff --git a/src/help/de/BaseFrameHelp.html b/src/help/de/BaseFrameHelp.html
new file mode 100644
index 0000000..cefe2e1
--- /dev/null
+++ b/src/help/de/BaseFrameHelp.html
@@ -0,0 +1,61 @@
+<HTML>
+
+<BODY text="#275856">
+
+<basefont size="4" color="#2F4958" face="arial">
+
+<H1>Das Hauptfenster von JabRef</H1>
+
+<em>Anmerkung:</em> Die meisten Menüfunktionen, auf die im Folgenden hingewiesen wird, haben Tastenkürzel, und viele Funktionen können über die Werkzeugleiste aufgerufen werden.
+
+<p>
+Dies ist das Hauptfenster, in dem Sie mit Ihrer Datei arbeiten. Unter der Menüleiste und der Werkzeugleiste befindet sich die Tableiste mit Tabs (Reitern) für jede Ihrer geöffneten Dateien. Wenn Sie einen dieser Tabs anklicken, erscheint eine Tabelle, die alle Datensätze und einige der Datenfelder auflistet.
+
+<ul>
+<li>Die Auswahl der entsprechenden Felder können Sie im <strong>Einstellungs</strong>-Dialog vornehmen.</li>
+
+<li>Die Felder können direkt in der Tabelle bearbeitet werden, indem Sie einfach auf eine Zelle klicken und den Inhalt eingeben (nur möglich, wenn "Bearbeiten in der Tabelle zulassen" im Dialog <strong>Optionen --> Einstellungen --> Allgemein</strong> ausgewählt ist). Ein Doppelklick auf eine Zelle öffnet einen leistungsfähigeren Editor. Sie können mit den Pfeiltasten in der Tabelle navigieren.</li>
+
+<li>Die Tabelle wird nach einem Feld Ihrer Wahl sortiert. Klicken Sie einfach auf die Kopfzeile einer Spalte, um die Einträge nach dem Feld dieser Spalte zu sortieren. Klicken Sie erneut auf den Spaltenkopf, um die Sortierrichtung umzukehren. Einträge mit gleichem Inhalt im ausgewählten Feld werden nach dem zweiten (und eventuell dem dritten) Kriterium sortiert. Diese Sortierkriterien können im <strong>Einstellungs</strong>-Dialog festgelegt werden.</li>
+
+<li>Sie können die Breite der Tabellenspalten einstellen, indem Sie die Trennlinie zwischen den Spaltenköpfen anklicken und verschieben.</li>
+
+<li>Im <strong>Einstellungs</strong>-Dialog können Sie festlegen, ob die Tabelle an die Bildschirmgröße angepasst werden soll oder nicht. Aktivieren Sie diese Funktion, um sicherzustellen, dass Sie die gesamte Tabelle sehen können. Deaktivieren Sie diese Funktion, wenn mehr Informationen dargestellt werden sollen.</li>
+
+<li>Die Farbanzeige kann ebenfalls im <strong>Einstellungs</strong>-Dialog ein- und ausgeschaltet werden. Die Farbanzeige illustriert, ob Ihre Daten vollständig sind, indem sie die Zellen wie folgt darstellt:
+	<ul>
+	<li>Eine <font color="red">rote</font> Zelle in der linken 	Spalte kennzeichnet einen unvollständigen Eintrag.</li>
+	<li>Eine <font color="#909000">gelbe</font> Zelle in der linken 	Spalte kennzeichnet einen Eintrag, der nicht alle benötigten 	Felder selbst enthält, der aber einen Querverweis enthält.</li>
+	<li>Eine <font color="blue">blaue</font> Zelle kennzeichnet ein 	benötigtes Feld.</li>
+	<li>Eine <font color="green">grüne</font> Zelle kennzeichnet 	ein optionales Feld.</li>
+	<li>Eine farblose (weiße) Zelle kennzeichnet ein Feld, das von 	BibTeX für diesen Eintragstyp nicht benutzt wird. Das Feld can 	selbstverständlich in JabRef bearbeitet werden.</li>
+	</ul>
+</li>
+</ul>
+
+<H2>Einen neuen Eintrag hinzufügen</H2>
+
+Es gibt verschiedene Möglichkeiten, einen neuen Eintrag hinzuzufügen. Im Menü <strong>BibTeX</strong> führt ein Klick auf <strong>Neuer Eintrag</strong> zu einem Dialog, in dem Sie den Eintragstyp aus einer Liste wählen können. Um diesen Dialog zu umgehen, gibt es auch eigene Menüpunkte für jeden Eintragstyp und außerdem Tastenkürzel für die gängigsten Typen.
+
+<P>Wenn ein Eintrag hinzugefügt wird, wird standardmäßig ein
+<a href="EntryEditorHelp.html">Editor</a> für den Eintrag geöffnet. Sie können dieses Verhalten im <strong>Einstellungs</strong>-Dialog abstellen.
+
+<P><em>Anmerkung:</em> Wir empfehlen dringend, sich die Tastenkürzel für die Eintragstypen einzuprägen, die Sie am häufigsten benutzen, z.B. STRG-SHIFT-A für einen Zeitschriftenaufsatz (<em>article</em>).
+
+<H2>Einen Eintrag bearbeiten</H2>
+
+Um den <a href="EntryEditorHelp.html">Eintrags-Editor</a> zur Bearbeitung eines existierenden Eintrags zu öffnen, klicken Sie einfach doppelt auf die linke Spalte der entsprechenden Zeile oder markieren den Eintrag und drücken auf ENTER.
+
+Falls "Bearbeiten in der Tabelle zulassen" nicht ausgewählt ist (im Dialog <strong>Optionen --> Einstellungen --> Allgemein</strong>), öffnet ein Doppelklick irgendwo in der zugehörigen Zeile den <a href="EntryEditorHelp.html">Eintrags-Editor</a>.
+
+<H2>Einen <em>BibTeX</em> String in einem Feld verwenden</H2>
+
+In JabRef schreiben Sie den Inhalt aller Felder so, wie Sie es in einem Texteditor machen würden, mit einer Ausnahme: um einen String (Anm. d. Übers.: eine Art Abkürzung) zu verwenden, umschließen Sie den Namen des Strings mit je einem #, z.B.<BR>
+  '#jan# 1997',<BR>
+was interpretiert wird als String mit dem Namen 'jan' gefolgt von '1997'.
+
+<P>Vergleichen Sie dazu auch die Hilfeseite zum <a href="StringEditorHelp.html">String-Editor</a>.
+
+</font>
+</BODY>
+</HTML>
\ No newline at end of file
diff --git a/src/help/de/BibtexHelp.html b/src/help/de/BibtexHelp.html
new file mode 100644
index 0000000..d4eaf40
--- /dev/null
+++ b/src/help/de/BibtexHelp.html
@@ -0,0 +1,33 @@
+<HTML>
+
+<BODY text="#275856">
+<basefont size="4" color="#2F4958" face="arial">
+
+<H1>�ber <em>BibTeX</em></H1>
+
+JabRef hilft Ihnen bei der Arbeit mit Ihren <em>BibTeX</em>-Dateien, aber es m�ssen dennoch Regeln beachtet werden, wenn Sie Ihre Eintr�ge bearbeiten. Nur so kann sichergestellt werden, dass <em>BibTeX</em> Ihre Datei richtig verarbeiten kann.
+
+<H2><em>BibTeX</em> Felder</H2>
+
+Es gibt viele unterschiedliche Felder in <em>BibTeX</em> und einige zus�tzliche Felder, die Sie in JabRef einsetzen k�nnen.
+<P>
+Grunds�tzlich k�nnen Sie LaTeX-Befehle in Feldern, die Text beinhalten, einsetzen. <em>BibTeX</em> wird Ihr Literaturverzeichnis automatisch formatieren und je nach <em>BibTeX</em> style (Stildatei .bst) Gro�buchstaben verkleinern. Um sicherzustellen, dass einzelne Buchstaben gro� bleiben, m�ssen Sie sie in Klammern einschlie�en, wie im Wort {B}elgien. <em>(Anm. d. �bers.: Die meisten deutschen <em>BibTeX</em>-Stile behalten die Gro�buchstaben ohnehin bei.)</em>
+
+<P>
+Hinweise zu einigen Feldtypen:
+<ul>
+<li><em>Author:</em> Dieses Feld sollte alle Autoren Ihres Eintrags enthalten. Die Namen werden durch das Wort <em>and</em> getrennt, auch wenn es mehr als zwei Autoren gibt. Jeder Name kann in zwei gleichwertigen Formen notiert werden:<br>
+ Donald E. Knuth <em>oder</em> Knuth, Donald E.<br>
+ Eddie van Halen <em>oder</em> van Halen, Eddie<br>
+
+Die zweite Form sollte f�r Autoren mit zwei oder mehr Nachnamen benutzt werden, um zwischen dem mittleren und dem Nachnamen zu unterscheiden.
+
+<li><em>Editor:</em> Dieses Feld ist analog zu dem <em>author</em>-Feld.
+
+<li><em>Year:</em> Das Jahr der Publikation. Dieses Feld wird f�r die meisten Eintragstypen ben�tigt. JabRef akzeptiert in diesem Feld nur einen numerischen Wert.
+
+<li><em>Bibtexkey:</em> Eine eindeutige Bezeichnung,um sich in LaTeX-Dokumenten auf den Eintrag beziehen zu k�nnen. Beachten Sie, dass der Bibtexkey genau mit dem Verweis im LaTeX-Dokument �bereinstimmen muss (auch die Gro�-/Kleinschreibung).
+</ul>
+
+
+</HTML>
diff --git a/src/help/de/CiteSeerHelp.html b/src/help/de/CiteSeerHelp.html
new file mode 100644
index 0000000..81e5b37
--- /dev/null
+++ b/src/help/de/CiteSeerHelp.html
@@ -0,0 +1,53 @@
+<HTML>
+
+<BODY text="#275856">
+<basefont size="4" color="#2F4958" face="arial">
+
+<H1>CiteSeer-Import</H1>
+
+<H2>Importieren eines Eintrags von CiteSeer</H2>
+
+JabRef kann Informationen über eine bestimmte Literaturangabe aus der CiteSeer-Datenbank
+herunterladen. Um diesen Vorgang zu starten, fügen Sie Ihrer Datei einen neuen Eintrag hinzu
+und belegen das Feld <em>citeseerurl</em> mit einem Link zur entsprechenden Inhaltsseite auf
+CiteSeer. Das Feld <em>citeseerurl</em> muss in einem der folgenden Formate eingegeben werden:
+
+<p>http://citeseer.ist.psu.edu/DDDDDD[.html], oder <br>
+oai:CiteSeerPSU:DDDDDD, oder <br>
+DDDDDD
+
+<p>wobei DDDDDD eine Ziffernfolge darstellt. Um diese Ziffernfolge (DDDDDD) für einen CiteSeer-Eintrag
+zu finden, gehen Sie auf die Dokumentseite der Literaturangabe des Formats
+http://citeseer.ist.psu.edu/<i>nameYearTitle</i>.html und klicken den (Update)-Link für diese
+Literaturangabe. Die URL für den Update-Link beinhaltet die numerische ID für diese
+Literaturangabe.
+
+<p>Sobald Sie das Feld <em>citeseerurl</em> belegt haben, können Sie die CiteSeer-Felder herunterladen,
+indem Sie <b>BibTeX -> Felder von CiteSeer importieren</b> auswählen. Achten Sie darauf, dass
+Sie die Zeile(n) ausgewählt haben, die Sie aktualisieren wollen.
+
+<H2>Generating a Citation Database</H2>
+
+Hinweis des Übersetzers: Offen gesagt habe ich diesen Absatz nicht verstanden, was daran liegen mag,
+dass ich CiteSeer nicht kenne und deshalb auch die Funktionsweise nicht nachvollziehen kann.
+Für Hinweise, Erklärungen oder eine fertige Übersetzung wäre ich deshalb dankbar.
+Damit die Informationen für deutsche Benutzer nicht verloren gehen, habe ich Sie im Original belassen:
+
+<blockquote>
+Given a set of references, you can generate a list of documents that cite the elements of this set.
+To facilitate this feature, each citation in a database must have a citeseerurl field with the format specified
+in <b>Importing An Entry From CiteSeer</b>.  To use this feature, select <b>Tools -> Fetch Citations
+from CiteSeer</b>.
+</blockquote>
+
+<H2>Benutzung eines Proxy-Servers</H2>
+
+Wenn Sie einen HTTP-Proxy-Server benutzen müssen, übergeben Sie den Servernamen und die Portnummer
+an Java. Diese Umgebungseinstellungen sind dokumentiert unter
+ <p> http://java.sun.com/j2se/1.4.2/docs/guide/net/properties.html
+
+<p><code>java -Dhttp.proxyHost="hostname" -Dhttp.proxyPort="portnumber"</code>
+
+<p> 
+
+</HTML>
diff --git a/src/help/de/CommandLine.html b/src/help/de/CommandLine.html
new file mode 100644
index 0000000..1c9a78b
--- /dev/null
+++ b/src/help/de/CommandLine.html
@@ -0,0 +1,93 @@
+<HTML>
+
+<BODY text="#275856">
+<basefont size="4" color="#2F4958" face="arial">
+
+<H1>JabRef von der Kommandozeile</H1>
+
+Obwohl JabRef in erster Linie ein Programm mit grafischer Benutzeroberfläche ist, bietet es
+einige nützliche Optionen für die Kommandozeile und kann sogar Dateikonvertierungen
+durchführen, ohne die grafische Benutzeroberfläche zu öffnen.
+
+<P>Sie können eine oder mehrere BibTeX-Dateien laden, indem Sie auf der Kommandozeile die
+entsprechenden Dateinamen auflisten. Achten Sie darauf, alle gewünschten Optionen anzugeben,
+bevor Sie die Dateinamen anfügen. Außerdem müssen Sie sich vergewissern, dass der
+erste Dateiname nicht als Argument einer Option missverstanden werden kann - falls eine Bool'sche
+Option wie <code>-n</code> oder <code>-l</code> direkt vor einem Dateinamen steht, müssen Sie
+also "true" als Argument angeben. Das Beispielkommando:
+<p><code>jabref -o filetoexport.xml,docbook -n true original.bib</code>
+<p>lädt die Datei <code>original.bib</code>, exportiert sie in das Docbook-Format, speichert sie
+unter dem Namen <code>filetoexport.xml</code>
+und unterdrückt das Laden der grafischen Oberfläche. Das Word <em>true</em> verhindert, dass der
+Dateiname als Argument der Option <code>-n</code> interpretiert wird.
+
+<H1>Kommandozeilen-Optionen</H2>
+<H2>Hilfe: -h</H2>
+
+Diese Option veranlasst JabRef, eine Zusammenfassung der Kommandozeilen-Optionen anzuzeigen und das
+Programm unmittelbar darauf zu schließen.
+
+<H2>Kein GUI-Modus: -n</H2>
+
+Diese Option unterdrückt sowohl das JabRef-Fenster als auch den Eröffnungsbildschirm, der
+normalerweise beim Programmstart angezeigt wird. Das Programm wird beendet, sobald die Kommandozeilen-Optionen
+abgearbeitet wurden.
+<P>Diese Option ist nützlich, um Dateikonvertierungen von der Kommandozeile oder mit Hilfe eines Scripts
+durchzuführen.
+
+<H2>Sitzung laden: -l</H2>
+
+Diese Option veranlasst JabRef, eine gespeicherte Sitzung zu laden, sofern eine vorhanden ist, bevor sich
+das Hauptfenster öffnet.
+
+<H2>Datei importieren: -i Dateiname[,Importformat]</H2>
+
+Bei dieser Option importiert oder lädt JabRef eine bestimmte Datei. Wenn nur ein Dateiname angegeben wird oder ein Komma und ein *-Zeichen hinter dem Dateinamen stehen, versucht JabRef, das Dateiformat automatisch zu erkennen. Das sollte bei allen BibTeX-Dateien ebenso funktionieren wie bei Dateien, die in einem der von JabRef unterstützten Importformate vorliegen. Wenn dem Dateinamen ein Komma und ein Importformat folgen, wird der
+angegebene Importfilter benutzt. Mit der Option <code>-h</code> können Sie sich eine Liste der
+verfügbaren Importformate anzeigen lassen.
+
+<P>Wenn Sie zusätzlich eine Export-Option angeben, wird der Import immer zuerst ausgeführt, bevor
+die importierte oder geladene Datei an den Exportfilter übergeben wird. Falls die grafische Oberfläche
+nicht mit der Option <code>-n</code> unterdrückt wird, werden alle geladenen oder importierten Dateien
+im Hauptfenster von JabRef angezeigt.
+
+<p>Die Option <code>-i</code> kann nur einmal angegeben werden und nimmt als Argument maximal eine Datei.
+
+<H2>Datei exportieren: -o Dateiname[,Exportformat]</H2>
+
+Diese Option veranlasst JabRef, eine Datei zu speichern oder zu exportieren, die von derselben Kommandozeile geladen
+oder importiert wurde. Wenn eine Datei mit der Option <code>-i</code> importiert wurde, wird diese Datei exportiert.
+Ansonsten wird die Datei exportiert, die <em>zuletzt</em> - ohne die Option <code>-i</code> -
+angegeben (und erfolgreich geladen) wurde.
+
+<P>Wird nur ein Dateiname angegeben, so wird diese Datei im BibTeX-Format gespeichert. Wenn dem Dateinamen ein Komma
+und ein Exportformat folgen, wird der angegebene Exportfilter benutzt. Auf diese Weise wird auch ein benutzerdefinierter
+Exportfilter angewendet; wenn der Name sowohl auf einen Standard-Exportfilter, als auch auf einen benutzerdefinierten
+Exportfilter zutrifft, wird der benutzerdefinierte verwendet.
+<P>Mit der Option <code>-h</code> können Sie sich eine Liste der verfügbaren Exportformate anzeigen lassen.
+
+<P>Falls die Option <code>-n</code> nicht aufgerufen wurde, wird jeder Exportvorgang durchgeführt, bevor das
+JabRef-Fenster geöffnet wird. Dort werden dann die importierten Dateien angezeigt.
+
+<p>Die Option <code>-o</code> kann nur einmal angegeben werden und nimmt als Argument maximal eine Datei.
+
+<H2>Einstellungen exportieren: -x Dateiname</H2>
+
+Mit dieser Option können Sie JabRef veranlassen, alle Benutzer-Einstellungen in eine XML-Datei zu speichern.
+Nach dem Export startet JabRef normal.
+
+<H2>Einstellungen importieren: -p Dateiname</H2>
+
+Mit dieser Option importiert JabRef Benutzer-Einstellungen, die mit der Option <code>-x</code> exportiert wurden.
+Nach dem Import startet JabRef normal.
+
+<H2>Nur benutzte Einträge exportieren: -a Dateiname[.aux],neueBibDatei[.bib]</H2>
+
+Manchmal ist es nützlich, eine BibTeX-Datei zu haben, die nur die benutzten Einträge enthält.
+Eine Liste dieser benutzten Einträge findet sich in einer .aux-Datei (sobald Sie LaTeX aufgerufen haben).
+JabRef kann diese Datei analysieren, um eine neue BibTeX-Datei zu erstellen, die nur die bekannten und benutzten
+Einträge enthält. Das bedeutet, dass ein Eintrag, der in der Standard-BibTeX-Datei nicht definiert ist,
+auch nicht in die neue Datei geschrieben werden kann.
+
+</BODY>
+</HTML>
\ No newline at end of file
diff --git a/src/help/de/ContentSelectorHelp.html b/src/help/de/ContentSelectorHelp.html
new file mode 100644
index 0000000..04cedff
--- /dev/null
+++ b/src/help/de/ContentSelectorHelp.html
@@ -0,0 +1,37 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+
+  <BODY text="#275856">
+  <basefont size="4" color="#2F4958" face="arial">
+
+  <head>
+    <title>Wortauswahl verwalten</title>
+  </head>
+
+  <body>
+    <h1>Wortauswahl verwalten</h1>
+
+	Diese Funktion ermöglicht es, eine Auswahl von oft benutzten Wörtern 
+	oder Phrasen zu speichern. In der Standardeinstellung ist sie für die Felder
+	<em>Journal</em>, <em>Keywords</em> und <em>Publisher</em> aktiviert, aber Sie
+	können die Funktion auch in anderen Feldern verwenden, indem Sie diese
+	Felder im oberen Teil des Dialogs <em>Extras -> Wortauswahl verwalten</em> hinzufügen.
+
+	<P>
+	Die Wortauswahl gilt nur für die jeweilige Datei und wird daher zusammen
+	mit den Literaturangaben in der .bib-Datei gespeichert.
+	<P>
+	Jedes Feld mit Wortauswahl erhält im Eintrags-Editor einen gesonderten Bereich
+	mit einer Auswahlliste und der Schaltfläche <em>Verwalten</em>. Wenn Sie die 
+	Auswahlliste mit der Maus anklicken, erscheint eine Liste der für dieses Feld
+	verfügbaren Wörter. Sobald Sie auf das gewünschte Wort klicken, wird
+	es in das entsprechende Feld geschrieben.
+	<P>
+	Um ein neues Wort hinzuzufügen, schreiben Sie es einfach in das Auswahlfeld
+	und drücken ENTER. Im Dialog <em>Verwalten</em> können Sie hinzugefügte
+	Wörter auch wieder löschen.
+
+
+
+  </body>
+</html>
diff --git a/src/help/de/Contents.html b/src/help/de/Contents.html
new file mode 100644
index 0000000..8e2b2aa
--- /dev/null
+++ b/src/help/de/Contents.html
@@ -0,0 +1,35 @@
+<HTML>
+
+<BODY text="#275856">
+<basefont size="4" color="#2F4958" face="arial">
+
+<H1>Hilfe - Inhalt</H1>
+
+<a href="HelpHelp.html">Über die Hilfe</a><br>
+<a href="JabRefHelp.html">Allgemeines</a><br>
+<br>
+<a href="GeneralFields.html">Allgemeine Felder festlegen</a><br>
+<a href="LabelPatterns.html">Anpassen der automatischen Generierung von BibTeX-keys</a><br>
+<a href="OwnerHelp.html">Das 'Besitzer' (owner) Feld</a><br>
+<a href="BibtexHelp.html"><em>BibTeX</em> Hilfe</a><br>
+<a href="MarkingHelp.html">Einträge markieren</a><br>
+<a href="CiteSeerHelp.html">Einträge von <em>CiteSeer</em> abrufen</a><br>
+<a href="MedlineHelp.html">Einträge von <em>Medline</em> abrufen</a><br>
+<a href="EntryEditorHelp.html">Der Eintrags-Editor</a><br>
+<a href="CustomEntriesHelp.html">Eintragstypen anpassen</a><br>
+<a href="PreviewHelp.html">Eintragsvorschau anpassen</a><br>
+<a href="CustomExports.html">Exportfilter anpassen</a><br>
+<a href="CustomImports.html">Externe Importfilter</a><br>
+<a href="EndNoteFilters.html">Die Exportfilter und Importfilter für EndNote</a><br>
+<a href="BaseFrameHelp.html">Das Hauptfenster von JabRef</a><br>
+<a href="GroupsHelp.html">Hilfe zu den <em>Gruppen</em></a><br>
+<a href="ImportInspectionDialog.html">Import-Kontrollfenster</a><br>
+<a href="OpenOfficeHelp.html">JabRef-Bibliographien in OpenOffice.org benutzen</a><br>
+<a href="CommandLine.html">Kommandozeilen-Optionen</a><br>
+<a href="ExternalFiles.html">Links zu externen Dateien (PDF/PS/URL/DOI) in JabRef</a><br>
+<a href="StringEditorHelp.html">Der String-Editor</a><br>
+<a href="SearchHelp.html">Die Suchfunktionen von JabRef</a><br>
+<a href="ContentSelectorHelp.html">Wortauswahl verwalten</a><br>
+<a href="TimeStampHelp.html">Zeitstempel</a><br>
+
+</HTML>
\ No newline at end of file
diff --git a/src/help/de/CustomEntriesHelp.html b/src/help/de/CustomEntriesHelp.html
new file mode 100644
index 0000000..df85f3b
--- /dev/null
+++ b/src/help/de/CustomEntriesHelp.html
@@ -0,0 +1,73 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+  <head>
+    <title>Eintragstypen anpassen</title>
+  </head>
+
+  <BODY text="#275856">
+    <basefont size="4" color="#2F4958" face="arial">
+
+<h1>Eintragstypen anpassen</h1>
+<p>
+Um Eintragstypen anzupassen, wählen Sie den Menüpunkt <strong>Optionen --> Eintragstypen anpassen</strong>.
+
+<p>Wenn Sie einen Eintragstyp anpassen, definieren Sie sowohl sein Erscheinungsbild im Eintragseditor
+als auch die Bedingungen, nach denen JabRef einen Eintrag als vollständig akzeptiert.
+Sie können die bestehenden Eintragstypen verändern und neue hinzufügen.
+<p>
+Beachten Sie, dass in diesem Dialog keine Änderungen gespeichert werden, solange Sie nicht
+auf <b>Übernehmen</b> oder <b>OK</b> klicken. Wenn Sie <b>Cancel</b> anklicken oder
+einfach den Dialog schließen, gehen die bislang nicht übernommenen Änderungen
+verloren.
+
+<h2>Der Dialog <i>Eintragstypen anpassen</i></h2>
+
+Der Dialog <i>Eintragstypen anpassen</i> ist in drei Hauptbereiche unterteilt. Im linken Bereich
+können Sie den Eintragstyp auswählen, den Sie bearbeiten wollen, und neue
+Eintragstypen hinzufügen. Im mittleren Bereich werden die Einstellungen für die
+benötigten Felder des ausgewählten Eintragstyps vorgenommen und im rechten
+Bereich diejenigen der optionalen Felder.
+
+<h3>Eintragstypen hinzufügen und löschen</h3>
+
+<p>Die derzeit verfügbaren Eintragstypen werden im linken Bereich des Dialogfensters
+aufgelistet. Wenn Sie einen Eintragstyp auswählen, werden die anderen Bereiche
+aktualisiert und zeigen die benötigten und optionalen Felder dieses Eintragstyps.
+
+<p>Um einen neuen Eintragstyp hinzuzufügen, geben Sie einfach seinen Namen in das
+Textfeld unter der Typliste ein und klicken <b>Hinzufügen</b>. Der neue Eintragstyp
+wird zur Liste hinzugefügt und zur Bearbeitung ausgewählt.
+
+<p>Um einen eigenen Eintragstyp zu entfernen, wählen Sie ihn aus und klicken auf
+<b>Löschen</b>. Dieser Vorgang ist nur für eigene Eintragstypen verfügbar,
+die nicht nur Abwandlungen der Standard-Typen sind. Die Standard-Eintragstypen können
+nicht gelöscht werden.
+
+<p>Um einem Eintragstyp seinen Standardwert zurüzugeben, wählen Sie ihn aus
+und drücken auf <b>Standard</b>. Dieser Vorgang ist nur für Standard-Typen
+verfügbar, die bearbeitet wurden.
+
+<h2>Eintragstypen bearbeiten</h2>
+
+Wenn ein Eintragstyp ausgewählt ist, werden die derzeitigen benötigten und optionalen
+Felder im mittleren und rechten Bereich des Dialogfensters aufgelistet. Das Vorgehen beim
+Bearbeiten dieser Listen ist für die benötigten und optionalen Felder identisch.
+
+<p>Um ein neues Feld hinzuzufügen, bearbeiten Sie das Textfeld unterhalb der Liste
+oder wählen einen Feldnamen aus dem Dropdown-Menü und klicken auf <b>Hinzufügen</b>.
+Der gewählte Feldname erscheint am Ende der Liste.
+
+<p>Um eines oder mehrere Felder zu löschen, wählen Sie sie in der Liste aus und
+klicken auf <b>Löschen</b>.
+
+<p>Die Reihenfolge der Felder können Sie ändern, indem Sie einen Feldnamen auswählen
+und die Pfeiltasten benutzen, um das Feld nach oben oder nach unten zu verschieben.
+
+<p>Es gibt eine Beschränkung beim Anpassen der Eintragstypen; bestimmte Typen
+haben eine und/oder-Bedingung in ihren benötigten Feldern. Ein <em>book</em>-Eintrag
+ist beispielsweise komplett, wenn entweder das Feld <em>author</em> oder <em>editor</em>
+oder beide gesetzt sind. Diese Art von Bedingung kann in einem angepassten Eintragstyp
+nicht realisiert werden.
+
+  </body>
+</html>
\ No newline at end of file
diff --git a/src/help/de/CustomExports.html b/src/help/de/CustomExports.html
new file mode 100644
index 0000000..857ed29
--- /dev/null
+++ b/src/help/de/CustomExports.html
@@ -0,0 +1,179 @@
+<HTML>
+
+<BODY text="#275856">
+<basefont size="4" color="#2F4958" face="arial">
+
+<H1>Exportfilter anpassen</H1>
+
+Mit JabRef können Sie Ihre eigenen Exportfilter definieren und genau so wie die
+Standard-Exportfilter benutzen. Ein Exportfilter wird durch eine oder mehr <i>Layout-Dateien</i>
+definiert, die mittels eingebauter Formatierprogramme das Format der exportierten Dateien
+festlegen. Ihre Layout-Datei müssen Sie in einem separaten Texteditor erstellen.
+
+<H2>Hinzufügen eines Exportfilters</H2>
+
+Die einzige Voraussetzung für einen Exportfilter ist, daß eine Datei mit der
+Endung <b>.layout</b> vorhanden ist. Um einen neuen, eigenen Exportfilter hinzuzufügen,
+öffnen Sie das Dialogfenster <b>Optionen -> Verwalte externe Exportfilter</b> und klicken
+auf die Schaltfläche <b>Neu</b>. Es öffnet sich ein neues Fenster, in dem Sie einen
+Namen (der im Menü <b>Datei -> Externe Exportfilter</b> angezeigt wird), eine Pfadangabe
+zur <b>.layout</b>-Datei und die gewünschte Dateiendung für den Exportfilter angeben
+können. Wenn Sie den Exportfilter benutzen, wird diese Endung im Datei-Dialog automatisch
+vorgeschlagen.
+
+<H2>Das Erstellen des Exportfilters</H2>
+
+Um einen Eindruck zu bekommen, wie Exportfilter auszusehen haben, suchen Sie am besten auf unserer
+Homepage nach dem Paket, das die Layout-Dateien der Standard-Exportfilter enthält.
+
+<H3>Layout-Dateien</H3>
+
+Nehmen wir einmal an, dass wir einen HTML-Exportfilter erstellen wollen.
+
+<P>Der Exportfilter muss lediglich aus einer einzigen <b>.layout</b>-Datei bestehen, die in diesem
+Fall <i>html.layout</i> genannt werden könnte. Sie können darüber hinaus auch zwei
+Dateien mit den
+Namen <i>html.begin.layout</i> und <i>html.end.layout</i> anlegen. Die erste dieser beiden Dateien
+enthält den Kopfteil der Ausgabe, die zweite den Fußteil. JabRef sucht jedes Mal, wenn der
+Exportfilter benutzt wird, nach diesen Dateien und fügt sie – falls sie gefunden
+werden – wörtlich vor bzw. nach den einzelnen Einträgen in die Ausgabe ein.
+
+<P>Beachten Sie, dass sich diese Dateien in demselben Verzeichnis wie <i>html.layout</i> befinden
+müssen und die Namensbestandteile <b>.begin</b> bzw. <b>.end</b> enthalten müssen.
+
+<P>In unserem Beispiel-Exportfilter könnten diese Dateien folgendermaßen aussehen:
+
+<p><i>html.begin.layout</i>:<br>
+<code><HTML><br>
+  <BODY> text="#275856"><br>
+<basefont size="4" color="#2F4958" face="arial"></code>
+
+<p><i>html.end.layout</i>:<br>
+<code></BODY><br>
+  </HTML></code>
+
+<P>Die Datei <i>html.layout</i> stellt die <i>Standard</i>-Formatvorlage für den Export
+eines einzelnen Eintrags bereit. Falls Sie unterschiedliche Formatvorlagen für verschiedene
+Eintragstypen anwenden wollen, müssen Sie Eintrags-spezifische <b>.layout</b>-Dateien erstellen.
+Diese müssen sich ebenfalls in demselben Verzeichnis wie die Haupt-Layout-Datei befinden und
+den Namensbestandteil <b>.entrytype</b> enthalten. Der Name des Eintragstyps muss komplett in
+Kleinbuchstaben geschrieben werden. In unserem Beispiel wollen wir eine Formatvorlage für
+Einträge des Typs "book" haben, die in der Datei <i>html.book.layout</i> abgelegt wird.
+Für eine Dissertation würden wir die Datei <i>html.phdthesis.layout</i> anlegen –
+und so weiter. Diese Dateien sind der Standard-Layout-Datei sehr ähnlich, nur dass sie lediglich
+für Einträge des entsprechenden Typs genutzt werden. Beachten Sie, dass die
+Standard-Layout-Datei so allgemein gehalten werden kann, dass sie die meisten
+Eintragstypen abdeckt.
+
+<H3>Das Format der Layout-Datei</H3>
+
+Layout-Dateien werden mit einem einfachen markup-Format erstellt, bei dem die Kommandos mit
+einem "backslash" (<code>\</code>) eingeleitet werden. Alle Textbestandteile, die nicht als
+Kommando identifiziert werden, gelangen direkt in die Ausgabedatei.
+
+<H3>Feldkommandos</H3>
+
+<p>Ein beliebiges Wort, vor dem ein backslash steht, z.B. <code>\author</code>, <code>\editor</code>,
+<code>\title</code> or <code>\year</code>, wird als Verweis auf das entsprechende Feld ausgewertet,
+das dann direkt in die Ausgabe kopiert wird.
+
+<H3>Feldformatierer</H3>
+
+<p>Oft muss der Feldinhalt vor der Ausgabe verarbeitet werden. Dies wird mit Hilfe eines
+<i>Feldformatierers</i> gemacht - einer java class, die eine Methode zur Verarbeitung des
+Feldinhaltes enthält.
+<p>Ein Formatierer wird angewendet, indem man das Kommando <code>\format</code> gefolgt vom Namen
+des Formatierers in eckigen Klammern und dem Feldnamen in geschweiften Klammern einfügt, z.B.:
+
+  <p><code>\format[ToLowerCase]{\author}</code>
+
+<p>Sie können auch mehrere Formatierer angeben, getrennt durch Kommas. Sie werden nacheinander
+aufgerufen, und zwar von links nach rechts. Das Kommando
+
+  <p><code>\format[ToLowerCase,HTMLChars]{\author}</code>
+
+<p>ruft z.B. zunächst den Formatierer <b>ToLowerCase</b> auf, <b>HTMLChars</b> formatiert
+anschließend das Ergebnis. Auf diese Weise können Sie eine beliebige Anzahl an
+Formatierern auflisten.
+
+<p>JabRef bietet die folgenden Formatierer, wobei einige von anderen abhängen:
+
+<ul>
+<li><code>HTMLChars</code> : ersetzt TeX-spezifische Sonderzeichen (z.B. {\^a} oder {\"{o}})
+  durch ihre HTML-Entsprechungen.
+<li><code>XMLChars</code> : ersetzt TeX-spezifische Sonderzeichen (z.B. {\^a} oder {\"{o}})
+  durch ihre XML-Entsprechungen.
+<li><code>CreateDocBookAuthors</code> : formatiert das author-Feld im DocBook-Stil.
+<li><code>AuthorFirstFirst</code> : formatiert die Felder author/editor mit den Vornamen zuerst.
+<li><code>AuthorFirstFirstCommas</code> : formatiert die Felder author/editor mit den Vornamen zuerst
+und abgetrennt durch Kommas.
+<li><code>AuthorLastFirst</code> : formatiert die Felder author/editor mit den Nachnamen zuerst.
+<li><code>AuthorLastFirstAbbreviator</code> : kürzt die Vornamen aller Autoren.
+Dieser Formatierer kann nur angewendet werden, wenn <code>AuthorLastFirst</code> bereits benutzt wurde.
+<li><code>AuthorAndsReplacer</code> : ersetzt "and" zwischen den Namen durch ";", zwischen den letzten beiden Autoren steht "&".
+<li><code>AuthorAndsCommaReplacer</code> : ersetzt "and" zwischen den Namen durch "," sowie "&" zwischen den beiden letzten.
+<li><code>FormatPagesForHTML</code> : ersetzt "--" durch "-".
+<li><code>FormatPagesForXML</code> : ersetzt "--" durch einen XML en-dash (Gedanken- bzw. Bis-Strich).
+<li><code>RemoveBrackets</code> : entfernt alle geschweiften Klammern "{" oder "}".
+<li><code>RemoveLatexCommands</code> : entfernt LaTeX Kommandos wie <code>\em</code>, <code>\textbf</code>
+etc. Zusammen mit <code>HTMLChars</code> oder <code>XMLChars</code> sollte dieser Formatierer
+zuletzt aufgerufen werden.
+<li><code>ToLowerCase</code> : macht aus allen Buchstaben Kleinbuchstaben.
+</ul>
+
+<p>Falls keiner der verfügbaren Formatierer das Ergebnis erzielt, das Sie erreichen möchten,
+können Sie Ihren eigenen Formatierer hinzufügen, indem Sie das
+<code>net.sf.jabref.export.layout.LayoutFormatter</code>-Interface implementieren. Wenn Sie Ihre Klasse
+(class) in das Paket <code>net.sf.jabref.export.layout.format</code> einfügen, können Sie
+den Formatierer mit seinem Klassennamen aufrufen, so wie auch die Standard-Formatierer. Ansonsten
+müssen Sie den Formatierer mit seinem vollen Namen aufrufen (inklusive Paketname). In jedem Fall
+muss der Formatierer in ihrem classpath sein, wenn Sie JabRef starten.
+
+<H3>Bedingte Ausgabe</H3>
+
+Manche statische Ausgabe macht nur Sinn, wenn ein bestimmtes Feld nicht leer ist. Wenn wir z.B. hinter
+den Namen der Editoren den Text <code>(Hrsg.)</code> haben wollen, brauchen wir folgendes:
+
+<p><code>\format[HTMLChars,AuthorFirstFirst]{\editor} (Hrsg.)</code>
+
+<p>Wenn nun aber das <code>editor</code>-Feld leer ist - möglicherweise ist es für den Eintrag,
+der exportiert werden soll, nicht erforderlich -, dann würde das <code>(Hrsg.)</code> dennoch
+erscheinen. Das kann man mit den Kommandos <code>\begin</code> und <code>\end</code> verhindern:
+
+<p><code>\begin{editor}<br>\format[HTMLChars,AuthorFirstFirst]{\editor} (Hrsg.)
+<br>\end{editor}</code>
+
+<p>Die Kommandos <code>\begin</code> und <code>\end</code> sorgen dafür, dass der Text, den sie
+einschließen, nur dann ausgegeben wird, falls das Feld, auf das in den geschweiften Klammern
+verwiesen wird, für den zu exportierenden Eintrag definiert und damit nicht leer ist.
+
+<p><b>Anmerkung:</b> Das Benutzen der Kommandos <code>\begin</code> und <code>\end</code> ist ein
+Schlüssel zum Erstellen von Layout-Dateien, die mit einer Vielzahl von Eintragstypen
+umgehen können.
+
+<H3>Gruppierte Ausgabe</H3>
+
+Wenn Sie Ihre Einträge auf der Basis eines bestimmten Feldes gruppieren wollen, benutzen Sie
+die Kommandos für die gruppierte Ausgabe.
+Die gruppierte Ausgabe ist der bedingten Ausgabe sehr ähnlich, auß dass der Text zwischen
+den Kommandos nur ausgegeben wird, wenn das Feld, auf das in den geschweiften Klammern verwiesen wird,
+unterschiedliche Werte enthält.
+
+<p>Nehmen wir zum Beispiel an, dass wir die Ausgabe nach dem keyword (Stichwort) gruppieren wollen.
+Bevor die Datei exportiert wird, müssen die Einträge nach dem keyword sortiert worden sein.
+Dann benutzen Sie die folgenden Kommandos, um nach keyword zu gruppieren:
+
+<p><code>\begingroup{keywords}New Category: \format[HTMLChars]{\keywords}
+<br>	\endgroup{keywords}</code>
+
+<H2>Teilen Sie Ihre Arbeit mit anderen</H2>
+
+Mit externen Layout-Dateien ist es einfach, Ihre eigenen Export-Formate mit anderen Anwendern
+gemeinsam zu benutzen. Falls Sie einen Exportfilter für ein Format erstellen, das nicht von
+JabRef unterstützt wird, oder falls Sie einen bestehenden Exportfilter verbessern, möchten
+wir Sie ermutigen, Ihre Arbeit auf der SourceForge.net-Seite bereitzustellen. Dasselbe gilt für
+Formatierklassen, die Sie schreiben. Wir würden uns freuen, eine Sammlung von bereitgestellten
+Layout-Dateien verteilen zu können oder die Standard-Export-Filter und Standard-Formatierer
+ zu erweitern.
+
+</HTML>
\ No newline at end of file
diff --git a/src/help/de/CustomImports.html b/src/help/de/CustomImports.html
new file mode 100644
index 0000000..59a5b6e
--- /dev/null
+++ b/src/help/de/CustomImports.html
@@ -0,0 +1,131 @@
+<HTML>
+
+<BODY text="#275856">
+<basefont size="4" color="#2F4958" face="arial">
+
+<H1>Externe Importfilter</H1>
+
+<p>JabRef bietet Ihnen die Möglichkeit, ganz ähnlich den Standard-Importern, eigene Importer 
+zu definieren und zu benutzen. Man definiert einen Importer durch eine oder mehrere Java
+<i>Klassen</i>, die Dateinhalte aus einem sogenannten <i>Input stream</i> lesen
+und daraus BibTex-Einträge erzeugen. Sie können vorkompilierte Importer einbinden, die Sie vielleicht 
+von SourceForge erhalten haben (siehe "Ihre Arbeit anderen zur Verfügung stellen"). Sie können auch
+mit Grundkenntnissen der Java-Programmierung eigene Importer für für Sie wichtige Referenzquellen 
+erstellen oder neue, verbesserte Versionen existierender Importer einbinden, ohne JabRef neu zu
+kompilieren.</p> 
+
+<p>Externe Importfilter haben Vorrang vor Standard-Importern. So können Sie mit Ihren Importern
+die existierenden in der automatischen Formaterkennung und an der Kommandozeile in JabRef überschreiben.
+Externe Importfilter selbst sind dann nach Namen sortiert.</p>
+
+<H2>Einen externen Importfilter hinzufügen</H2>
+
+<p>Stellen Sie sicher, dass Sie den Importer in kompilierter Form haben (eine oder mehrere
+<code>.class</code> Dateien) und dass die Klassendateien
+in einer Verzeichnisstruktur entsprechend ihrer Package-Struktur liegen. 
+Um einen neuen externen Importfilter hinzuzufügen, öffnen Sie den Dialog 
+<b>Optionen -> Verwalte externe Importfilter</b>, und klicken Sie auf
+<b>Aus Klassenpfad hinzufügen</b>. Ein Dateiauswahl-Fenster erscheint, 
+mit dem Sie den Klassenpfad des Importers wählen, dass heißt den obersten Ordner,
+in dem die Package-Struktur Ihres Importers beginnt. In einem zweiten Dateiauswahl-Fenster
+wählen Sie die <i>.class</i>-Datei Ihres Importers, die von <code>ImportFormat</code> abgeleitet
+ist. Wenn Sie <b>Klasse auswählen</b> klicken, erscheint Ihr neuer Importer
+in der Liste der externen Importfilter. Alle externen Importfilter erscheinen in den
+JabRef-Submenüs <b>Datei -> Importieren -> Externe Importfilter</b> und 
+<b>Datei -> Importieren und Anhängen -> Externe Importfilter</b>.</p>
+
+<p>Bitte beachten Sie: wenn Sie die Klassen in ein anderes Verzeichnis verschieben,
+müssen Sie den Importer entfernen und neu hinzufügen. Wenn Sie einen Importfilter
+mit einem bereits vorhandenen Namen registrieren, ersetzt JabRef den vorhandenen
+externen Importfilter. Auch wenn es in manchen Fällen möglich ist, einen schon registrierten
+Importer zu aktualisieren ohne JabRef neu zu starten (nämlich dann,
+wenn der Importer nicht im Klassenpfad von JabRef ist), empfehlen wir, grundsätzlich
+JabRef neu zu starten, wenn Sie ein Update eines externen Importers durchgeführt haben.
+Sie können auch Importer aus ZIP- oder JAR-Archiven registrieren, wählen Sie einfach
+<b>Aus Archiv-Datei hinzufügen</b>, dann das ZIP- oder JAR-Archiv und dann den Eintrag
+(Klassendatei), der den neuen Importer darstellt.</p>
+
+<H2>Einen Importfilter entwickeln</H2>
+
+Bitte schauen Sie auf unseren Download-Seiten nach Beispielen und nützliche Dateien zur 
+Entwicklung Ihres Importfilters.
+
+<H3>Ein einfaches Beispiel</H3>
+
+<p>Angenommen, wir wollen Dateien der folgenden Form importieren:
+<pre>
+1936;John Maynard Keynes;The General Theory of Employment, Interest and Money
+2003;Boldrin & Levine;Case Against Intellectual Monopoly
+2004;ROBERT HUNT AND JAMES BESSEN;The Software Patent Experiment
+</pre></p>
+
+<p>Erzeugen Sie in einem Text-Editor eine von <code>ImportFormat</code> abgeleitete Klasse,
+die die Methoden <code>getFormatName()</code>, <code>isRecognizedFormat()</code>
+und <code>importEntries()</code> implementiert. Hier ein Beispiel:
+<pre>
+import java.io.*;
+import java.util.*;
+import net.sf.jabref.*;
+import net.sf.jabref.imports.ImportFormat;
+import net.sf.jabref.imports.ImportFormatReader;
+
+public class SimpleCsvImporter extends ImportFormat {
+
+  public String getFormatName() {
+    return "Simple CSV Importer";
+  }
+
+  public boolean isRecognizedFormat(InputStream stream) throws IOException {
+    return true; // this is discouraged except for demonstration purposes
+  }
+  
+  public List importEntries(InputStream stream) throws IOException {    
+  	ArrayList bibitems = new ArrayList();
+    BufferedReader in = new BufferedReader(ImportFormatReader.getReaderDefaultEncoding(stream));
+      
+    String line = in.readLine();
+    while (line != null) {
+      if (!"".equals(line.trim())) {
+        String[] fields = line.split(";");
+        BibtexEntry be = new BibtexEntry(Util.createNeutralId());
+        be.setType(BibtexEntryType.getType("techreport"));
+        be.setField("year", fields[0]);
+        be.setField("author", fields[1]);
+        be.setField("title", fields[2]);
+        bibitems.add(be);
+        line = in.readLine();
+      }     
+    }
+    return bibitems;	  	
+  }
+}
+</pre></p>
+
+<p>Beachten Sie, dass die Beispielklasse im Default-Package liegt. Angenommen, Sie haben
+sie unter <code>/meinpfad/SimpleCsvImporter.java</code> gespeichert. Nehmen wir weiter an,
+die Datei <i>JabRef-2.0.jar</i> ist im gleichen Verzeichnis wie
+<code>SimpleCsvImporter.java</code> und Java ist in Ihrem Kommandopfad. 
+Kompilieren Sie die Klasse mit JSDK 1.4 zum Beispiel mit folgendem Kommandozeilen-Aufruf: 
+<pre>
+javac -classpath JabRef-2.0.jar SimpleCsvImporter.java
+</pre>
+Nun sollte dort auch eine Datei <code>/mypath/SimpleCsvImporter.class</code> liegen.</p>
+
+<p>Öffnen Sie in JabRef <b>Optionen -> Verwaltung externer Importfilter</b> und klicken Sie
+auf <b>Aus Klassenpfad hinzufügen</b>. Navigieren Sie nach <code>/meinpfad</code> und 
+klicken Sie <b>Klassenpfad auswählen</b>. Wählen Sie dann <code>SimpleCsvImporter.class</code>
+und klicken Sie <b>Klasse auswählen</b>. Ihr Importfilter sollte nun in der Liste der
+externen Importfilter unter dem Namen "Simple CSV Importer" erscheinen, und,
+sobald Sie <b>Schließen</b> gewählt haben, auch in den Untermenüs <b>Datei -> Importieren -> 
+Externe Importfilter</b> und <b>Datei -> Importieren und Anhängen -> Externe Importfilter</b> 
+des JabRef-Hauptfensters.</p>
+
+<H2>Ihre Arbeit anderen zur Verfügung stellen</H2>
+
+Mit externen Importfiltern ist es recht einfach, Importfilter zwischen Nutzern auszutauschen und
+gemeinsam zu nutzen. Wenn Sie einen Importer für ein  Format schreiben, das JabRef noch nicht unterstützt, 
+oder einen Importer verbessern, bitten wir Sie, Ihre Ergebnisse auf unserer SourceForge.net 
+Seite zu veröffentlichen. Wir bieten gerne eine Sammlung eingereichter Importfilter an oder 
+fügen sie unserer Auswahl an Standard-Importfiltern hinzu.
+
+</HTML>
diff --git a/src/help/de/EndNoteFilters.html b/src/help/de/EndNoteFilters.html
new file mode 100644
index 0000000..3f484ab
--- /dev/null
+++ b/src/help/de/EndNoteFilters.html
@@ -0,0 +1,101 @@
+<HTML>
+
+<BODY text="#275856">
+<basefont size="4" color="#2F4958" face="arial">
+
+<h1>EndNote Exportfilter</h1>
+
+<h2>Exportieren aus JabRef</h2>
+
+JabRef kann Dateien so exportieren, dass EndNote sie lesen kann.
+Um diese Funktion zu nutzen, wählen Sie <b>Datei -> Exportieren -> Endnote</b>
+und wählen dann den Namen der Export-Datei.
+
+<h2>Importieren in EndNote</h2>
+
+Der Standard-EndNote-Importfilter kann nicht richtig mit mehreren Autoren oder Editoren umgehen.
+Es gibt zwei Möglichkeiten, um diese Schwierigkeit zu umgehen:
+
+<ol>
+
+<li>Benutzen Sie den eingebauten Filter und bessern Sie die Datei später aus.
+Um die Datei in EndNote zu öffnen, erstellen Sie eine neue Datei oder öffnen
+eine bestehende Datei in EndNote. Dann wählen Sie <b>Datei -> Importieren</b>,
+klicken mit der Maus auf <b>Datei wählen</b>, wählen die exportierte Datei
+aus und drücken auf <b>Auswählen</b>. Anschließend drücken Sie
+auf <b>Import Optionen</b> und wählen <b>EndNote Import</b>. Mit einem Klick
+auf <b>Importieren</b> starten Sie den Importvorgang. Anschließend gehen Sie zum
+Menüpunkt <b>Bearbeiten -> Text ändern</b> und ändern <b>Any Field</b>
+in <b>Author</b>. Geben Sie " and " in das Suchfeld ein (ohne Anführungszeichen) sowie
+ein RETURN-Zeichen in das Feld Ändern (Option-Return unter Mac OS X, Strg-Return
+unter Windows XP). Dann klicken Sie auf <b>Ändern</b>. Wiederholen Sie das Ganze
+für das Feld <b>Secondary Author</b> (Zweiter Autor).
+
+<li>Installieren Sie den <i>EndNote Import from JabRef Filter</i> in <i>EndNote Extras</i>.
+Folgen Sie den Anweisungen in <i>Erweitert</i> (unten). Um die Datei in EndNote zu
+öffnen, erstellen Sie eine neue Datei oder öffnen eine bestehende Datei in
+EndNote. Dann wählen Sie <b>Datei -> Importieren</b>, klicken auf <b>Datei wählen</b>,
+wählen die exportierte Datei aus und drücken auf <b>Auswählen</b>.
+Anschließend drücken Sie auf <b>Import Optionen</b> und wählen
+<b>EndNote Import from JabRef</b>. (Falls dieser Eintrag nicht erscheint, wählen Sie
+Weitere Filter. Wenn er dann immer noch nicht erscheint, wurde der Filter nicht korrekt installiert.)
+Klicken Sie schließlich auf <b>Importieren</b>, um den Importvorgang zu starten.
+
+</ol>
+
+<h2>Anmerkungen</h2>
+
+Der EndNote Exportfilter ordnet BibTeX-Eintragstypen folgenden EndNote-Referenztypen zu:
+
+<pre>
+BibTeX-Eintragstyp -> Endnote Referenztyp
+------------------------------------------
+misc, other -> Generic
+unpublished -> Manuscript
+manual -> Computer Program
+article -> Journal Article
+book -> Book
+booklet -> Personal Communication
+inbook,incollection -> Book Section
+inproceedings -> Conference Proceedings
+techreport -> Report
+mastersthesis, phdthesis -> Thesis
+</pre>
+
+<h2>Mehrere Autoren</h2>
+
+In der Standardeinstellung geht der Exportfilter davon aus, dass Einträge in den
+Feldern author oder editor, die geklammert sind, mehrere Autoren enthalten und
+ersetzt die Klammern durch ein angehängtes Komma. Dadurch werden Einträge,
+die LaTeX-Befehle mit Klammern enthalten, als Eintrag mit mehreren Autoren gewertet
+und demzufolge unpassend formatiert.
+
+<H2>Erweiterte Benutzung: Endnote Extras</h2>
+
+<h3>Installieren des EndNote Import from JabRef Filters</h3>
+
+Der vorgegebene EndNote-Importfilter kann das Feld author nicht richtig analysieren.
+Der EndNote Import from JabRef Filter kann dies. Außerdem erkennt dieser Filter
+ein Feld <code>endnotereftype</code>, das die vorgegebene Zuordnung überschreibt.
+Um den Filter zu installieren, extrahieren Sie die EndNote Extras (<b>Datei -> Exportieren
+-> EndNote Filter-Set auspacken</b>) und entpacken die Zip-Datei, die dabei erstellt wird. Dann folgen Sie den Angaben in der Datei <code>readme.txt</code>.
+
+<h3>Ändern der EndNote Referenztypen</h3>
+
+Einige Felder, die von BibTeX genutzt werden, gehören nicht zu EndNotes vorgegebenen
+Referenztypen. Während der Import in JabRef und der Export nach JabRef ohne ein
+Ändern der Referenztypen funktioniert, werden die Feldnamen in EndNote nicht
+korrekt dargestellt (z.B. wird das pdf-Feld <i>Custom 1</i> heißen statt <i>pdf</i>).
+Darüber hinaus können diese Felder bei neuen Einträgen in EndNote
+nicht genutzt werden, weil sie nicht im Eintragsdialog erscheinen. Um die EndNote-Referenztypen
+anzupassen, müssen Sie die EndNote Extras extrahieren und den Anweisungen in der
+Datei <code>readme.txt</code> folgen.
+
+<h3>Exportieren nach JabRef</h3>
+
+EndNote hat einen Export-Stil BibTeX, der allerdings nicht alle Eintragstypen und Felder von BibTeX
+und auch nicht die zusätzlich von JabRef genutzten Allgemeinen Felder (<i>pdf, owner, key</i>
+usw.) unterstützt. Falls Sie diese Felder nutzen wollen, extrahieren Sie die EndNote Extras
+und folgen den Anweisungen in der Datei <code>readme.txt</code>.<p>
+
+</HTML>
\ No newline at end of file
diff --git a/src/help/de/EntryEditorHelp.html b/src/help/de/EntryEditorHelp.html
new file mode 100644
index 0000000..29cca8c
--- /dev/null
+++ b/src/help/de/EntryEditorHelp.html
@@ -0,0 +1,104 @@
+<HTML>
+
+<BODY text="#275856">
+<basefont size="4" color="#2F4958" face="arial">
+
+<H1>Der Eintrags-Editor</H1>
+
+<em>Geöffnet wird der Eintrags-Editor im Hauptfenster durch einen Doppelklick
+auf die linke Spalte eines Eintrags (bzw. irgendwo auf die Zeile des Eintrags, wenn "Bearbeiten in der Tabelle zulassen" im Dialog <strong>Optionen --> Einstellungen --> Allgemein</strong> nicht ausgewählt ist), oder durch Drücken auf ENTER. Der
+Eintrags-Editor wird geschlossen, indem man auf ESC drückt.</em>
+<P>
+Im Eintrags-Editor können Sie alle relevanten Informationen eines Eintrags festlegen.
+Der Editor überprüft den Eintragstyp und zeigt alle benötigten und optionalen
+Felder für den Gebrauch mit <em>BibTeX</em> an. Darüber hinaus gibt es
+einige Felder, die <em>Allgemeine Felder</em> genannt werden und für alle
+Eintragstypen gelten.
+
+<P>Sie können die Felder, die für die einzelnen Eintragstypen als benötigt und optional
+angesehen werden, und auch die Allgemeinen Felder anpassen. Schlagen Sie unter
+<a href="CustomEntriesHelp.html">Eintragstypen anpassen</a> nach, wenn Sie mehr Informationen
+darüber erhalten möchten.
+
+<P>Nähere Informationen darüber, was in die Felder eingetragen werden soll,
+finden sie in der <a href="BibtexHelp.html">Bibtex Hilfe</a>.
+
+<H2>Die Panels des Eintrags-Editors</H2>
+
+Der Eintrags-Editor besteht in der Standardeinstellung aus fünf Panels: <em>Benötigte Felder</em>,
+<em>Optionale Felder</em>, <em>General</em>, <em>Abstract</em> und <em>BibTeX
+Quelltext</em>, wobei <em>General</em> und <em>Abstract</em> vom Benutzer angepasst werden können (siehe
+dazu <a href="GeneralFields.html">Allgemeine Felder festlegen</a>).
+In den ersten drei Panels können Sie mit TAB und SHIFT-TAB zwischen
+den einzelnen Feldern hin- und herwechseln.
+
+<P>Zu einem anderen Panel gelangen Sie, indem Sie auf die Tabs klicken. Mit den folgenden
+Tastaturkürzeln können Sie ebenfalls zwischen den Panels navigieren:
+CTRL-TAB oder CTRL-PLUS wechselt zum Panel rechts vom aktuellen Panel,
+ CTRL-SHIFT-TAB oder CTRL-MINUS wechselt dementsprechend zum Panel
+ links vom aktuellen Panel. Außerdem können Sie zum nächsten oder
+ vorherigen Eintrag wechseln, indem Sie "STRG-SHIFT-Pfeil nach unten" bzw. "STRG-SHIFT-Pfeil nach oben"
+ oder die Pfeiltasten in der linken Toolbar drücken.
+
+<P>Das Panel <em>BibTeX Quelltext</em> zeigt, wie der Eintrag aussehen wird, wenn die Datei
+im <em>bibtex</em>-Format gespeichert wird. Wenn Sie wollen, können Sie den
+<em>BibTeX</em> Quelltext direkt bearbeiten. Sobald Sie zu einem anderen Panel wechseln,
+STRG-S drücken oder den Eintrags-Editor schließen, wird JabRef versuchen, den
+Inhalt des Quelltext-Panels zu analysieren. Falls dabei Probleme auftreten, werden Sie benachrichtigt
+und erhalten die Möglichkeit, den Eintrag noch einmal zu überarbeiten oder den
+vorherigen Inhalt wiederherzustellen.
+
+Wenn in den <strong>Einstellungen</strong> (unter <strong>Allgemein</strong>) die Option
+<strong>Quelltext standardmäßig anzeigen</strong> gewählt wurde,
+wird das Quelltext-Panel beim Öffnen des Eintrags-Editors als erstes angezeigt. Wenn Sie
+lieber den Quelltext bearbeiten als die anderen Panels zu benutzen, sollten Sie diese Option wählen.
+
+<P><strong>Tip:</strong> Wenn Ihre Datei Felder enthält, die JabRef nicht kennt,
+erscheinen diese im Quelltext-Panel.
+
+<P><strong>Tip:</strong> Die <I>pdf</I> und <I>url</I>-Felder unterstützen Drag & Drop.
+Sie können z.B. ein URL aus Ihrem Browser dort einfügen.
+
+<H2>Überprüfung der Feldkonsistenz</H2>
+Wenn der Inhalt eines Feldes geändert wird, überprüft JabRef, ob der neue Inhalt
+akzeptiert werden kann. Bei Feldern, die von <em>BibTeX</em> genutzt werden, wird der Inhalt zum
+einen auf die richtige Klammerung mit geschweiften Klammern, aber auch auf die
+Benutzung des Zeichens '#' hin überprüft. Das "hash"-Symbol darf <em>nur</em>
+paarweise benutzt werden, um damit den Namen eines <em>BibTeX</em>-Strings einzuschließen.
+Beachten Sie, dass JabRef nicht überprüft, ob der angeführte String tatsächlich
+vorhanden ist (der <em>BibTeX</em>-Stil, den Sie benutzen, kann eine beliebige Anzahl von Strings
+definieren, die JabRef nicht kennt).
+<P>
+Falls die Inhalte nicht akzeptabel sind, wird das Feld mit roter Farbe hinterlegt, was auf einen Fehler
+hindeutet. In diesem Fall werden die Änderungen nicht gespeichert.
+
+<!--<H2>Autovervollständigung von Wörtern und Namen</H2>
+Der Eintragseditor bietet die Autovervollständigung von Wörtern.
+Im Dialog <em>Einstellungen</em> können Sie die Autovervollständigung
+ein- oder ausschalten und auswählen, in welchen Feldern die Autovervollständigung
+aktiviert werden soll.
+<P>Bei aktiver Autovervollständigung zeichnet JabRef alle Worte auf, die in jedem der
+ausgewählten Felder der Datei vorkommen. Immer wenn Sie den Anfang eines dieser
+Wörter schreiben, wird das Wort sichtbar vorgeschlagen. Sie können den
+Vorschlag ignorieren, indem Sie einfach weiterschreiben. Um den Vorschlag anzunehmen,
+drücken Sie entweder auf <em>ENTER</em> oder benutzen die Pfeiltasten oder
+andere Tasten, um die Auswahlbox um die vorgeschlagenen Buchstaben zu entfernen.
+<P><em>Anmerkung:</em> Bei den Wörtern, die für die Vorschläge berücksichtigt
+werden, handelt es sich nur um solche, die in demselben Feld in Einträgen der Datei vorkommen, die Sie
+gerade bearbeiten. Es gibt viele Möglichkeiten, um dieses Feature zu realisieren, und wenn Sie der
+Meinung sind, das es auf eine andere Art implementiert werden sollte, würden wir gerne Ihre
+Vorschläge hören.
+
+<H2><em>BibTeX</em> Key kopieren</H2>
+Mit STRG-K oder dem 'Key'-Knopf wird der <em>BibTeX</em> Key des ausgewählten Eintrags
+in die Zwischenablage kopiert.
+-->
+<H2><em>BibTeX</em> Key automatisch generieren</H2>
+Um einen <em>BibTeX</em> Key für einen Eintrag automatisch erstellen zu lassen, drücken
+Sie STRG-G oder den entsprechenden (Zauberstab-)Knopf in der Toolbar-Leiste.
+<p>
+Für nähere Informationen, wie die <em>BibTeX</em> Keys generiert werden, schauen Sie
+bitte unter <a href="LabelPatterns.html">Anpassen der automatischen Generierung von BibTeX-keys</a> nach.
+
+</BODY>
+</HTML>
\ No newline at end of file
diff --git a/src/help/de/ExternalFiles.html b/src/help/de/ExternalFiles.html
new file mode 100644
index 0000000..8d65acb
--- /dev/null
+++ b/src/help/de/ExternalFiles.html
@@ -0,0 +1,57 @@
+<HTML>
+
+<BODY text="#275856">
+<basefont size="4" color="#2F4958" face="arial">
+
+<H1>Links zu PDF/PS/URL/DOI-Dateien in JabRef</H1>
+
+Mit JabRef können Sie Ihre Einträge mit den entsprechenden PDF- oder PS-Dateien,
+die sich auf Ihrem Computer befinden, verlinken. Ebenso ist es möglich, Dateien
+im Internet über ein URL oder DOI zu verlinken.
+
+<H2>Externe Betrachter einrichten</H2>
+
+JabRef benötigt Informationen darüber, welche Programme es für PDF- und PS-Dateien
+und Internetseiten benutzen soll. In der Standardeinstellung werden sie auf Werte gesetzt, die
+wahrscheinlich zu Ihrem Betriebssystem passen, so dass eine gute Chance besteht, dass Sie diese
+Werte nicht zu verändern brauchen.
+
+<p>Um die Einstellungen der externen Programme zu ändern, öffnen Sie den Unterpunkt
+<em>Externe Programme</em> im Dialog <em>Optionen -> Einstellungen</em>.
+
+<H2>Externe Dateien oder Links öffnen</H2>
+
+Es gibt verschiedene Möglichkeiten, wie man externe Dateien oder Internetseiten aus JabRef öffnen kann.
+Im Eintrags-Editor können Sie einfach auf das Textfeld, das ein DOI oder URL enthält, doppelklicken.
+In der Tabellenansicht können Sie einen Eintrag auswählen und die Menüeinträge (unter <em>Extras</em>),
+die Tastenkombinationen (in der Standardeinstellung F4 für PDF/PS und F3 für DOI/URL) oder das Kontextmenü
+(mit der rechten Maustaste) benutzen, um die Datei oder Internetseite zu öffnen. Schließlich können Sie
+auch auf ein PDF-, PS-, URL- oder DOI-Icon in der Tabelle klicken.
+
+<P>In der Standardeinstellung zeigt die Tabellenansicht zwei Spalten mit Icons für die Einträge, die mit
+externen Dateien oder URLs verlinkt sind. Beide Spalten können im Unterpunkt <em>Tabellenansicht</em> des
+Dialogs <em>Optionen -> Einstellungen</em> ausgeblendet werden. Die zweite Spalte zeigt Icons für PDF- oder PS-Dateien
+(nur PDF, wenn beide vorhanden sind), die dritte Spalte zeigt Icons für URL oder DOI (nur URL, wenn beide
+vorhanden sind).
+
+<H2>Der Standard-Ordner für PDF-Dateien</H2>
+
+PDF-Dateien erhalten von JabRef eine "Spezialbehandlung", um das Verlinken mit den entsprechenden Einträgen
+so einfach wie möglich zu gestalten. Um diese "Spezialbehandlung" nutzen zu können, müssen Sie im
+Unterpunkt <em>Externe Programme</em> des Dialogs <em>Optionen -> Einstellungen</em> einen Ordner als
+Standard-Ordner für Ihre PDF-Dateien angeben. Alle PDF-Dateien, die in diesem Ordner oder einem Unterordner
+gespeichert sind, werden mit einer relativen Pfadangabe referenziert, so dass Sie problemlos PDF-Verzeichnisse
+verschieben oder mit mehreren Benutzern von verschiedenen Netzwerkarbeitsplätzen aus an derselben
+Datei arbeiten können.
+
+<P>Wenn Sie Ihren PDF-Dateien dann noch Namen geben, die mit dem BibTeX Key des entsprechenden Eintrags
+übereinstimmen (plus '.pdf' im Dateinamen), sucht JabRef in Ihrem Standard-PDF-Ordner und dessen
+Unterordnern nach der richtigen PDF-Datei. Sobald die korrekt benannte PDF-Datei sich dort befindet, klicken
+Sie auf die Schaltfläche <em>Auto</em> neben dem PDF-Feld im Eintrags-Editor. Wenn die PDF-Datei gefunden wird,
+wird das Feld entsprechend gesetzt.
+
+<P>Wenn Sie eine PDF-Datei wie beschrieben benennen, können Sie sie auch öffnen, ohne das PDF-Feld
+überhaupt zu benutzen. Der Nachteil ist in diesem Fall allerdings, dass das PDF-Icon in der Tabellenansicht
+nicht angezeigt wird, solange das PDF-Feld leer bleibt.
+
+</HTML>
\ No newline at end of file
diff --git a/src/help/de/GeneralFields.html b/src/help/de/GeneralFields.html
new file mode 100644
index 0000000..d721a56
--- /dev/null
+++ b/src/help/de/GeneralFields.html
@@ -0,0 +1,29 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+  <head>
+    <title></title>
+  </head>
+
+  <BODY text="#275856">
+    <basefont size="4" color="#2F4958" face="arial">
+
+    <h1>Allgemeine Felder festlegen</h1>
+    <p>
+    Sie können dem Eintragseditor eine beliebige Anzahl von Tabs hinzufügen, die bei allen Eintragstypen sichtbar sind.
+    Wählen Sie dazu den Menüeintrag "Optionen -> Allgemeine Felder festlegen".
+    
+    <p>
+    Jede Zeile repräsentiert einen Tab. Der Anfang der Zeile steht für den Namen des Tabs,
+    gefolgt von einem Doppelpunkt (:). Anschlie�end listen Sie die einzelnen Felder auf, die der
+    Tab enthalten soll, und trennen sie jeweils durch ein Semikolon (;).
+    
+    <p>
+    Das Beispiel<p><code>Allgemeine Felder:url;keywords;doi;pdf<BR>
+        Zusammenfassung:abstract;annote</CODE>
+    <P>
+    ergibt somit einen Tab mit dem Namen "Allgemeine Felder", der die Felder 
+    <em>url</em>, <em>keywords</em>, <em>doi</em> und <em>pdf</em> enthält,
+    sowie einen zweiten Tab namens "Zusammenfassung" mit den Feldern
+    <em>abstract</em> und <em>annote</em>.
+  </body>
+</html>
diff --git a/src/help/de/GroupsHelp.html b/src/help/de/GroupsHelp.html
new file mode 100644
index 0000000..601876a
--- /dev/null
+++ b/src/help/de/GroupsHelp.html
@@ -0,0 +1,137 @@
+<HTML>
+
+<BODY text="#275856">
+<basefont size="4" color="#2F4958" face="arial">
+
+<H1>Gruppen</H1>
+
+Mit Gruppen können Sie Ihre BibTeX-Datei in einer Baumstruktur anordnen, vergleichbar mit einer Dateistruktur in Ordnern und Unterordnern. Die beiden Hauptunterschiede sind:
+
+<ul>
+<li>Während eine Datei auf einer Festplatte immer in genau einem Ordner abgelegt ist, kann ein Literatureintrag in JabRef mehreren Gruppen angehören.</li>
+<li>Gruppen benutzen bestimmte Kriterien, um ihren Inhalt dynamisch zu bestimmen. Neue Einträge, die den Kriterien einer Gruppe entsprechen, gehören automatisch zu dieser Gruppe. Diese Funktionalität gibt es nicht in üblichen Dateisystemen, wohl aber in einigen E-Mail-Programmen (z.B. Thunderbird und Opera).</li>
+</ul>
+
+Wenn Sie eine Gruppe auswählen, werden die Einträge dieser Gruppe angezeigt. Wenn Sie mehrere Gruppen auswählen, werden entweder die Einträge angezeigt, die in einer der Gruppen sind (Vereinigung), oder solche, die in allen Gruppen vorhanden sind (Schnittmenge) -- das hängt von Ihren Einstellungen ab. All dies wird im Folgenden detailliert erläutert.
+<p>
+Gruppendefinitionen sind dateispezifisch; sie werden als <tt>@COMMENT</tt>-Block in der <tt>bib</tt>-Datei gespeichert und werden von allen Benutzern gemeinsam benutzt. (Künftige Versionen von JabRef werden möglicherweise benutzerabhängige Gruppen unterstützen.)
+
+<H2>Die Gruppenansicht</H2>
+
+Die Gruppenansicht wird im linken Bereich des Bildschirms angezeigt. Sie kann mit der Tastenkombination <tt>STRG-SHIFT-G</tt> oder dem Gruppen-Button in der Toolbar ein- und ausgeblendet werden. Die Gruppenansicht verfügt über mehrere Schaltflächen, aber die meisten Funktionen werden über das Kontextmenü angesteuert (also mit der rechten Maustaste). Drag & Drop wird ebenfalls unterstützt.
+<p>
+<table cellspacing=0 cellpadding=5 border=0 bgcolor=#c0ffc0>
+<tr><td>
+<h2>Einige kurze Beispiele</h2>
+
+Sie möchten vielleicht...
+
+<h3>...einfach nur eine Gruppe anlegen und ihr einige Einträge zuordnen</h3>
+
+Vergewissern Sie sich, dass die Gruppenansicht eingeschaltet ist. Drücken Sie auf den Button <b>Neue Gruppe</b>, geben einen Namen für die Gruppe ein und drücken OK. Sie können alle Einstellungen auf ihren Standardwerten belassen. Jetzt wählen Sie die Einträge aus, die der Gruppe zugeordnet werden sollen, und ziehen diese mit der Maus auf die Gruppe oder wählen <b>Zu Gruppe hinzufügen</b> aus dem Kontextmenü. Jetzt können Sie die Gruppe a [...]
+
+<h3>...das Feld <tt>keywords</tt> benutzen, um die Einträge zu gruppieren</h3>
+
+Stellen Sie sicher, dass die Gruppenansicht aktiviert ist. Drücken Sie auf den Button <b>Neue Gruppe</b>, geben einen Namen für die Gruppe ein und wählen die Option <b>Dynamisches Gruppieren der Einträge anhand eines Stichworts in einem Feld</b>. Geben Sie das Stichwort, nach dem gesucht werden soll, ein und drücken OK. Jetzt können Sie die Gruppe anklicken, um sich ihren Inhalt anzeigen zu lassen (das sollten alle Einträge sein, deren <tt>keywords</tt> [...]
+
+<h3>...einen frei wählbaren Suchausdruck verwenden, um eine Gruppe zu definieren</h3>
+
+Stellen Sie sicher, dass die Gruppenansicht aktiviert ist. Drücken Sie auf den Button <b>Neue Gruppe</b>, geben einen Namen für die Gruppe ein und wählen die Option <b>Dynamisches Gruppieren der Einträge anhand eines beliebigen Suchausdrucks</b>. Geben Sie <tt>author=smith</tt> als Suchausdruck ein (ersetzen Sie <tt>smith</tt> mit einem Namen, der wirklich in Ihrer Datei vorkommt) und klicken <b>OK</b>. Jetzt können Sie die Gruppe anklicken, um sich ihren Inhalt  [...]
+
+<h3>...mehrere Gruppen kombinieren</h3>
+
+Erstellen sie zwei unterschiedliche Gruppen (z.B. so wie oben beschrieben). Klicken Sie auf den Button <b>Einstellungen</b> in der Gruppenansicht und wählen <b>Vereinigung</b>. Jetzt wählen Sie beide Gruppen aus (dazu klicken Sie auf eine Gruppe und anschließend bei gedrückter STRG-Taste auf die andere Gruppe). Sie sollten jetzt alle Einträge sehen, die in einer der beiden Gruppen aufgeführt sind. Klicken Sie noch einmal auf <b>Einstellungen</b> und wä [...]
+
+<h3>...sehen, welche Gruppen sich überschneiden</h3>
+
+Mit JabRef können Sie ganz einfach herausfinden, welche Gruppen sich mit den aktuell ausgewählten Gruppen überschneiden (d.h. welche Gruppen zumindest einen Eintrag enthalten, der auch in der aktuell ausgewählten Gruppe ist). Klicken Sie auf <b>Einstellungen</b> und aktivieren die Option <b>Sich überschneidende Gruppen markieren</b>. Wählen Sie dann eine Gruppe, die sich mit anderen überschneidet. Diese anderen Gruppen sollten nun markiert sein.
+
+</tr></td>
+</table>
+<p>
+
+<H2>Arten von Gruppen</H2>
+
+In JabRef 1.8 gibt es vier verschiedene Arten von Gruppen
+
+<ol>
+<li>Die Gruppe <b>Alle Einträge</b>, die -- wie der Name vermuten lässt -- alle Einträge beinhaltet, ist immer vorhanden und kann weder verändert noch gelöscht werden.</li>
+<li><b>Statische Gruppen</b> verhalten sich wie Ordner auf einer Festplatte und beinhalten nur die Einträge, die Sie ihnen explizit zuweisen.</li>
+<li><b>Dynamische Gruppen basierend auf einem Stichwort</b> beinhalten Einträge, die in einem bestimmten BibTeX-Feld (z.B. <tt>keywords</tt>) ein bestimmtes Stichwort (z.B. <tt>elektrisch</tt>) aufweisen. Diese Methode benötigt kein manuelles Zuweisen der Einträge, sondern nutzt die bereits in der Datei vorhandenen Informationen. Wenn alle Einträge in Ihrer Datenbank passende Stichwörter haben, könnte diese Art von Gruppe die beste Wahl für Sie sein.</li>
+<li><b>Dynamische Gruppen basierend auf einer freien Suche</b> beinhalten Einträge, die mit einem bestimmten Suchausdruck übereinstimmen. Dabei wird dieselbe Syntax verwendet wie beim <a href="SearchHelp.html">Suchen</a>. Diese <a href="SearchHelp.html#advanced">Syntax</a> unterstützt logische Operatoren (<tt>AND</tt>, <tt>OR</tt>, <tt>NOT</tt>) und erlaubt es, in einem oder mehreren BibTeX-Feldern zu suchen. Dadurch ist eine flexiblere Definition von Gruppen möglich  [...]
+</ol>
+
+Jede Gruppe, die Sie erstellen, ist von einer der drei letztgenannten Arten. Der Dialog "Gruppe bearbeiten", der mit einem Doppelklick auf eine Gruppe aufgerufen wird, zeigt eine kurze Beschreibung der ausgewählten Gruppe.
+
+<H2>Gruppenstrukturen, Erstellen und Löschen von Gruppen</H2>
+
+Vergleichbar mit Ordnern sind die Gruppen in einer Baumansicht strukturiert, wo die Gruppe <b>Alle Einträge</b> das Stammelement ist. Mit einem Rechtsklick auf eine Gruppe können Sie dem Baum eine neue Gruppe hinzufügen, entweder auf derselben Ebene wie die ausgewählte Gruppe oder als ihre Untergruppe. Der Button <b>Neue Gruppe</b> erzeugt eine neue Untergruppe der Gruppe <b>Alle Einträge</b>, egal ob Sie gerade Gruppen ausgewählt haben oder nicht. Im Kontex [...]
+
+<p>
+Rückgängig und Wiederholen wird für alle Bearbeitungsschritte unterstützt.
+
+<H3>Statische Gruppen</h3>
+
+Statische Gruppen werden nur durch manuelles Zuweisen von Einträgen "gefüttert". Nachdem Sie eine statische Gruppe erstellt haben, wählen Sie die Einträge aus, die Sie ihr zuweisen wollen, und nutzen entweder Drag & Drop oder das Kontextmenü in der Tabelle, um die Zuweisung durchzuführen. Um Einträge aus einer Gruppe zu entfernen, wählen Sie sie aus und benutzen das Kontextmenü in der Tabelle. Es können keine weiteren Option [...]
+<p>
+Diese Methode des Gruppierens setzt voraus, dass alle Einträge einen eindeutigen BibTeX-Key haben. Im Falle von fehlenden oder doppelten BibTeX-Keys kann das Zuweisen der betreffenden Einträge in künftigen Sitzungen nicht korrekt wiederhergestellt werden.
+
+<H3>Dynamische Gruppen</h3>
+
+Der Inhalt einer dynamischen Gruppe wird von einer logischen Bedingung bestimmt. Nur Einträge, die dieser Bedingung entsprechen, gehören zu dieser Gruppe. Diese Methode nutzt die bereits in der Datei vorhandenen Informationen und wird aktualisiert, sobald Sie Veränderungen in der Datei vornehmen.
+<p>
+Es gibt zwei mögliche Arten von Bedingungen:
+<dl>
+<dt><b>Ein Feld nach einem Stichwort durchsuchen</b></dt>
+<dd>
+Diese Methode gruppiert Einträge, bei denen ein bestimmtes BibTeX Feld (z.B. <tt>keywords</tt>) einen bestimmten Suchausdruck (z.B. <tt>elektrisch</tt>) enthält. Damit dies funktioniert, muss das Feld, nach dem sortiert wird, natürlich in jedem Eintrag vorhanden und sein Inhalt fehlerfrei sein. Das obige Beispiel würde alle Einträge zu einer Gruppe zusammenfassen, die sich auf etwas elektrisches beziehen. Benutzt man das Feld <tt>author</tt>, kann man sich Eintr& [...]
+</dd>
+<dt><b>Einen freien Suchausdruck verwenden</b></dt>
+<dd>
+Diese Vorgehensweise ist ganz ähnlich wie die eben beschriebene, aber statt nur ein Feld nach einem Suchausdruck zu durchsuchen, kann hierbei die <a href="SearchHelp.html#advanced">Syntax der Suche</a> angewendet werden, die logische Operatoren (<tt>AND</tt>, <tt>OR</tt>, <tt>NOT</tt>) und die Suche in mehreren Feldern gleichzeitig unterstützt. So fasst z.B. die Suchanfrage <tt>keywords=Regression AND NOT keywords=linear</tt> Einträge, die sich mit nicht-linearer Regressio [...]
+</dd>
+</dl>
+
+In der Gruppenansicht werden dynamische Gruppen standardmäßig <i>kursiv</i> dargestellt. Dies kann unter <strong>Optionen -> Einstellungen -> Gruppen</strong> abgestellt werden.
+
+<h3>Hierarchischer Kontext</h3>
+
+<em>Hinweis des Übersetzers: weiter bin ich noch (03.11.2005) nicht gekommen.</em><br>
+Standardmäßig ist eine Gruppe <b>unabhängig</b> von ihrer Position im Gruppenbaum. Ist eine Gruppe ausgewählt, wird nur der Inhalt dieser Gruppe angezeigt. Es ist jedoch -- besonders beim Verwenden dynamischer Gruppen -- oft nützlich, eine Untergruppe zu erstellen, die <b>ihre Obergruppe verfeinert</b>. Wenn diese Untergruppe ausgewählt wird, werden alle Einträge dieser Gruppe und ihrer Obergruppe angezeigt. Erstellen Sie z.B. eine Obergrupe, die Eintr [...]
+<p>
+Das logische Gegenstück zu einer solchen verfeinernden Untergruppe ist eine Gruppe, die <b>ihre Untergruppen berücksichtigt</b>. Wird sie ausgewählt, werden nicht nur die Einträge dieser Gruppe, sondern auch diejenigen aller Untergruppen angezeigt. Im Gruppenbaum hat auch diese Art von Gruppen ein spezielles Icon. (Dieses Verhalten kann in den Einstellungen abgestellt werden.)
+
+<h2>Einträge einer Gruppe anzeigen, mehrere Gruppen kombinieren</h2>
+
+Wenn Sie eine Gruppe auswählen, werden die Einträge, die dieser Gruppe zugeordnet sind, hervorgehoben und -- je nach Einstellung (die mit einem Klick auf den <b>Einstellungen</b>-Button vorgenommen werden kann) -- an den Anfang der Tabelle verschoben und/oder ausgewählt. Diese Optionen entsprechen denen für die normale Suche.
+<p>
+Wenn Sie meherere Gruppen auswählen (indem Sie die STRG-Taste gedrückt halten und mehrere Gruppen anklicken), wird -- je nach Einstellung -- entweder die Vereinigung oder die Schnittmenge ihrer Inhalte angezeigt. Damit können mehrere Bedingungen schnell miteinander kombiniert werden. Ein Beispiel: Wenn Sie eine statische Gruppe <tt>Sehr wichtig</tt> haben, in der alle sehr wichtigen Einträge sind, können Sie sich die sehr wichtigen Einträge jeder anderen Gru [...]
+
+<h2>Gruppen und Suche</h2>
+
+Wenn der Inhalt einer oder mehrerer Gruppen angezeigt wird, können Sie eine Suche innerhalb dieser Einträge durchführen. Benutzen Sie dazu die normalen Suchfunktionen.
+
+<h2>Sich überschneidende Gruppen markieren</h2>
+
+Der <b>Einstellungs</b>-Button bietet eine Option zum Markieren von sich überschneidenden Gruppen. Wenn diese Option aktiviert ist und Sie eine (oder mehrere) Gruppe(n) auswählen, werden alle Gruppen markiert, die mindestens einen Eintrag enthalten, der auch der ausgewählten Gruppe zugeordnet ist. Damit können Sie schnell Überschneidungen zwischen den Einträgen verschiedener Gruppen erkennen. Sie könnten beispielsweise eine Gruppe <tt>lesen</tt> erstell [...]
+
+<h2>Erweiterte Funktionen</h2>
+
+Wenn Sie sich mit dem oben beschriebenen Gruppenkonzept vertraut gemacht haben, könnten die folgenden erweiterten Funktionen nützlich sein.
+
+<h3>Dynamische Gruppen automatisch erstellen</h3>
+
+Mit einem Klick auf den Button <b>Automatisch Gruppen für die Datei anlegen</b> können Sie ganz schnell passende Gruppen für Ihre Datei erzeugen. Diese Funktion sammelt alle Wörter eines bestimmten Felds Ihrer Wahl und erstellt eine Gruppe für jedes Wort. Das ist zum Beispiel nützlich, wenn Ihre Datei geeignete Stichworte für alle Einträge enthält. Mit dem automatischen Erstellen von Gruppen basierend auf dem Feld <tt>keywords</tt> können [...]
+<p>
+Sie können auch Buchstaben angeben, die ignoriert werden sollen, z.B. Kommas, die zwischen einzelnen Stichworten stehen. Diese werden als Worttrenner behandelt und nicht als Teile des Wortes selbst. Dieser Schritt ist wichtig, damit kombinierte Stichworte wie etwa <tt>Gauß'sche Verteilung</tt> als semantische Einheit interpretiert werden können. (Sie können diese Option allerdings nicht verwenden, um ganze Wörter zu ignorieren. Sie müssen stattdessen die Gr [...]
+
+<h3>Ansicht aktualisieren</h3>
+
+Der <b>Aktualisieren</b>-Button aktualisiert die Tabelle in Bezug auf die aktuell ausgewählten Gruppen. Normalerweise erfolgt dies automatisch, aber in seltenen Fällen (z.B. nach einem Rückgängig- oder Wiederholen-Vorgang, der mit Gruppen zusammenhängt) ist ein händisches Aktualisieren nötig.
+
+<h3>Verfeinernde Untergruppen und einbeziehende Obergruppen mischen</h3>
+
+Wenn eine verfeinernde Gruppe die Untergruppe von einer Gruppe ist, die ihre Untergruppen berücksichtigt -- also sozusagen die Geschwister der verfeinernden Gruppe --, dann werden diese Geschwister ignoriert, sobald die verfeinernde Gruppe ausgewählt wird.
+
+</BODY>
+</HTML>
\ No newline at end of file
diff --git a/src/help/de/HelpHelp.html b/src/help/de/HelpHelp.html
new file mode 100644
index 0000000..4fb8264
--- /dev/null
+++ b/src/help/de/HelpHelp.html
@@ -0,0 +1,23 @@
+<HTML>
+
+<BODY text="#275856">
+<basefont size="4" color="#2F4958" face="arial">
+
+<H1>Das Hilfefenster</H1>
+<em>Das Hilfefenster �ffnet sich, wenn man den Hilfeknopf oder die Taste F1 dr�ckt.</em>
+<P>
+Das Hilfefenster soll Ihnen Informationen zur Nutzung von JabRef geben.
+
+<H2>Navigation in den Hilfedateien</H2>
+
+Das Hilfefenster ist eigentlich ein kleiner HTML-Browser, die Hilfedateien sind normale HTML-Dateien. 
+<P>
+Wenn Sie die Hilfe �ffnen, zeigt das Hilfefenster unterschiedliche Dateien an, je nachdem, von welchem Programmfenster aus Sie die
+Hilfe aufgerufen haben. Falls diese Datei nicht das beinhaltet, was Sie erkl�rt haben wollten, k�nnen Sie mit dem <em>Inhalt</em>-Knopf in der Werkzeugleiste zu einer Liste aller verf�gbaren Hilfedateien gehen.
+
+<P>
+Au�erdem befinden sich in der Werkzeugleiste Kn�pfe zum Zeigen der n�chsten oder vorherigen Datei. Sie sind �hnlich den <em>Zur�ck</em>- und <em>Vorw�rts</em>-Kn�pfen eines gew�hnlichen HTML-Browsers. Die Tastenk�rzel zur Navigation sind STRG-SHIFT und Pfeil nach links f�r <em>Zur�ck</em> sowie Pfeil nach rechts f�r <em>Vorw�rts</em>.
+
+<P>
+Sie k�nnen das Hilfefenster schlie�en, indem Sie ESCAPE dr�cken.
+</HTML>
\ No newline at end of file
diff --git a/src/help/de/ImportInspectionDialog.html b/src/help/de/ImportInspectionDialog.html
new file mode 100644
index 0000000..5f549b3
--- /dev/null
+++ b/src/help/de/ImportInspectionDialog.html
@@ -0,0 +1,16 @@
+<HTML>
+
+<BODY text="#275856">
+<basefont size="4" color="#2F4958" face="arial">
+
+<h1>Import-Kontrollfenster</h1>
+
+Beim Importieren neuer Einträge aus einem unterstützten Format oder beim Herunterladen von Einträgen aus dem Internet werden diese Einträge zunächst im Import-Kontrollfenster gezeigt. Zu diesem Zeitpunkt wurden noch keine Einträge zu einer geöffneten Datei hinzugefügt.
+
+<p>Im Kontrollfenster können Sie Einträge entfernen, die nicht übernommen werden sollen, und einige einfache Arbeiten durchführen wie etwa das Generieren von BibTeX keys für die Einträge oder das Zuordnen von Einträgen zu <a href="GroupsHelp.html">Gruppen</a>. Wenn Sie in eine bestehende Datei importieren, ist es oftmals leichter, diese Arbeiten durchzuführen, bevor die neuen Einträge zwischen die bereits bestehenden sortiert wurden.
+
+<h2></h2>
+
+
+
+</HTML>
\ No newline at end of file
diff --git a/src/help/de/JabRef-UserManual_de.bib b/src/help/de/JabRef-UserManual_de.bib
new file mode 100644
index 0000000..65f6c52
--- /dev/null
+++ b/src/help/de/JabRef-UserManual_de.bib
@@ -0,0 +1,52 @@
+This file was created with JabRef 1.8.1.
+Encoding: ISO8859_1
+
+ at UNPUBLISHED{Markey2005,
+  author = {Markey, Nicolas},
+  title = {Tame the BeaST},
+  month = {6.\,} # mar,
+  year = {2005},
+  annote = {Ausf�hrliches Tutorium rund um Bib\TeX{}, von der Erstellung von bib-Dateien
+	�ber die Programmierung bis hin zu kleinen n�tzlichen Tipps und Tricks
+	und dem "`Missbrauch"' von Bib\TeX{} als Adressbuch oder Glossar~\ldots{};
+	englisch.},
+  timestamp = {2005-11-15},
+  titleaddon = {The B to X of Bib\TeX},
+}
+
+ at UNPUBLISHED{btxdoc,
+  author = {Oren Patashnik},
+  title = {Bib\TeX{}ing},
+  month = {8.\,} # feb,
+  year = {1988},
+  abstract = {Documentation for general {\BibTeX} users},
+  annote = {Einf�hrung in die Benutzung von Bib\TeX{}, vom Autor des Programms
+	selbst; englisch.},
+  timestamp = {2005-11-15},
+  titleaddon = {Datei "`btxdoc"'},
+}
+
+ at UNPUBLISHED{btxhak,
+  author = {Oren Patashnik},
+  title = {Designing Bib\TeX{} Styles},
+  month = {8.\,} # feb,
+  year = {1988},
+  abstract = {The part of \BibTeX's documentation that's not meant for general users},
+  annote = {Einf�hrung in die Bib\TeX{}-Programmierung, vom Autor des Programms
+	selbst; englisch.},
+  timestamp = {2005-11-15},
+  titleaddon = {Datei "`btxhak"'},
+}
+
+ at UNPUBLISHED{Raichle2002,
+  author = {Raichle, Bernd},
+  title = {Tutorium: Einf�hrung in die Bib\TeX{}-Programmierung},
+  year = {2002},
+  address = {Erlangen},
+  annote = {Gibt eine kurze Einf�hrung in den Aufbau einer Bib\TeX{}-Datei, hat
+	seinen Schwerpunkt aber vor allem auf der Erstellung eines Bib\TeX{}-Styles
+	(.bst). Erkl�rt auch die f�r Bib\TeX{} verwendete Programmiersprache
+	UPN (Umgekehrt Polnische Notation); deutsch.},
+  timestamp = {2005-11-15},
+}
+
diff --git a/src/help/de/JabRef-UserManual_de.tex b/src/help/de/JabRef-UserManual_de.tex
new file mode 100644
index 0000000..06a50e8
--- /dev/null
+++ b/src/help/de/JabRef-UserManual_de.tex
@@ -0,0 +1,2601 @@
+%%%%% To do: %%%%%
+% OpenOffice-Export aktualisieren (an aktuelle HTML-Doku anpassen)
+%
+% unter >>Erscheinungsbild<< noch die Punkte Tabellendarstellung,
+% Toolbar, Panels und Schriften erstellen (DW)
+%
+% FAQ ganz am Ende? (halte ich f�r nicht unbedingt n�tig; eine Online-FAQ
+% w�re m.E. besser) (DW)
+
+\documentclass[10pt,normalheadings]{scrartcl}
+\usepackage[T1]{fontenc}
+\usepackage[latin1]{inputenc}
+\setcounter{secnumdepth}{4}
+\setcounter{tocdepth}{2}
+
+%%%%% Page Dimensions %%%%%
+\usepackage{geometry}
+\geometry{verbose,a5paper,tmargin=2cm,bmargin=2cm,lmargin=1cm,rmargin=1cm}
+
+%%%%% Packages %%%%%
+\usepackage{array}
+\usepackage{longtable}
+\usepackage{amsmath}
+\usepackage{graphicx}
+\usepackage{setspace}
+\usepackage{amssymb}
+
+\makeatletter
+%%%%% LyX command %%%%%
+\providecommand{\LyX}{L\kern-.1667em\lower.25em\hbox{Y}\kern-.125emX\@}
+
+%%%%% Because html converters don't know tabularnewline %%%%%
+\providecommand{\tabularnewline}{\\}
+
+%%%%% Environment "lyxcode" %%%%%
+ \usepackage{verbatim}
+ \newenvironment{lyxcode}
+   {\begin{list}{}{
+     \setlength{\rightmargin}{\leftmargin}
+     \setlength{\listparindent}{0pt}% needed for AMS classes
+     \raggedright
+     \setlength{\itemsep}{0pt}
+     \setlength{\parsep}{0pt}
+     \normalfont\ttfamily}%
+    \item[]}
+   {\end{list}}
+%%%%% Environment "revhist" (for revision history) %%%%%
+\newenvironment{revhist}
+    {\list{--}{\setlength\itemsep{0pt}\setlength{\parsep}{0pt}}}
+    {\endlist}
+
+%%%%% PDF 1.2 for Acrobat 3 onwards %%%%%
+\pdfoptionpdfminorversion 2
+
+%%%%% Colors %%%%%
+\usepackage{color}
+\definecolor{dkblue}{rgb}{0,0.1,0.5} % dark blue
+\definecolor{dkred}{rgb}{0.66,0.04,0.04} % dark red
+\definecolor{pyellow}{rgb}{1,0.97,0.75} % pale yellow
+
+%%%%% New commands %%%%%
+%%% JabRef "logo"
+\newcommand{\jabref}{%
+\mbox{%
+  \textit{%
+    {\color{dkred}J}\hspace{-.015em}{\color{black}ab}%
+    \hspace{-.02em}%
+    {\color{dkblue}R}\hspace{-.025em}\raisebox{.15ex}{\color{black}ef}%
+    }%
+  }%
+}
+%%% version number
+\newcommand{\versionnr}{2.0 beta} %
+%%% JabRef logo with version nr
+\newcommand{\jabrefversion}{\jabref{}~\versionnr}
+%%% for Menu references
+\newcommand{\menu}[1]{{\color{dkred}\textit{#1}}}
+%%% Menu separator
+\newcommand{\msep}{{\color{dkred}\textit{\guilsinglright}}}
+%%% yellow box with dark blue text
+\newcommand{\tip}[2][Tipp: ]{%
+  \begin{center}%
+  \colorbox{pyellow}{\parbox{0.7\textwidth}{%
+    \color{dkblue}\textit{#1}#2}}%
+  \end{center}%
+}%
+%%% for CTAN references
+\newcommand{\ctan}[1]{%
+  {CTAN: \color{dkblue}#1}%
+}
+
+%%%%% author, version of file %%%%%
+\def\FileAuthor{Dominik Wa�enhoven}
+\def\FileTitle{\jabrefversion{} Benutzerhandbuch}
+
+%%%%% Headings %%%%%
+\usepackage{scrpage2}
+\pagestyle{scrheadings}
+\ihead{}
+\chead{\FileTitle{}}
+\ohead{}
+\ifoot{}
+\cfoot{\pagemark}
+\ofoot{}
+
+%%%%% Fonts %%%%%
+\usepackage{charter}
+\addtokomafont{sectioning}{\rmfamily} % Headings with serifs
+
+%%%%% Other stuff %%%%%
+\deffootnote{1.5em}{1em}{\makebox[1.5em][l]{\thefootnotemark}}
+\usepackage{microtype} % micro typography
+
+%%%%% Language %%%%%
+\usepackage[ngerman]{babel}
+\hyphenation{
+LaTeX
+BibTeX
+Da-tei-na-men
+Me-n�-be-feh-le
+}
+
+%%%%% Bibliography %%%%%
+\usepackage{jurabib}
+\jurabibsetup{annote=true}
+\renewcommand{\bib at heading}{\section*{Kommentiertes Literaturverzeichnis}}
+
+%%%%% Hyperref %%%%%
+\usepackage{hyperref}
+\hypersetup{%
+breaklinks=true,%
+colorlinks=true,%
+linkcolor=dkblue,%
+urlcolor=dkblue,%
+citecolor=dkblue,%
+pdftitle={JabRef \versionnr{} Benutzerhandbuch},%
+pdfsubject={Einf�hrung in die Benutzung von JabRef},%
+pdfkeywords = {BibTeX, Bibliographie, Literaturverwaltung},%
+pdfauthor={\FileAuthor},%
+pdfstartview=FitH,%
+bookmarksopen=true,%
+bookmarksopenlevel=1,%
+}
+
+\makeatother
+\begin{document}
+
+\subject{\includegraphics[%
+  scale=0.25]{../../images/JabRef-splash.png}}
+
+
+\title{\jabrefversion{}\\
+Benutzerhandbuch}
+
+
+\author{Dominik Wa�enhoven\\
+{\normalsize (\href{mailto:domwass at users.sourceforge.net}{domwass at users.sourceforge.net})}}
+
+
+\date{{}}
+
+\maketitle
+\begin{abstract}
+\jabref{} ist eine grafische Java-Anwendung zur Bearbeitung von Bib\TeX{}-Dateien
+(.bib). Mit \jabref{} k�nnen Literaturangaben in Gruppen organisiert
+und mit einem einfachen Klick die Ansicht auf eine einzelne Gruppe,
+eine Schnittmenge von Gruppen oder die Gesamtmenge mehrerer Gruppen
+eingegrenzt werden. \jabref{} kann Literaturangaben sortieren (f�r
+alle Standard-Bib\TeX{}-Felder) und automatisch Bib\TeX{}-Keys erzeugen.
+Auch Links zu PDF-Dateien oder Webseiten k�nnen mit \jabref{} einfach
+erstellt werden.
+
+\jabref{} kann verschiedene Dateiformate importieren und exportieren,
+au�erdem k�nnen die Exportfilter angepasst werden. \jabref{} kann
+auch von der Kommandozeile gestartet werden, um von einem Importformat
+in ein Exportformat zu konvertieren, ohne die grafische Benutzeroberfl�che
+zu starten.
+\end{abstract}
+\begin{quote}
+\begin{spacing}{0.7}
+\begin{center}{\scriptsize Copyright \textcopyright{} 2005, Dominik
+Wa�enhoven}
+\end{center}
+{\scriptsize Dieser Inhalt ist unter einem Creative Commons Attribution-NonCommercial-ShareAlike 2.0 Germany Lizenzvertrag lizenziert. Um die Lizenz anzusehen, gehen Sie bitte zu \href{http://creativecommons.org/licenses/by-nc-sa/2.0/de/}{http://creativecommons.org\slash{}licenses\slash{}by-nc-sa\slash{}2.0\slash{}de\slash{}} oder schicken Sie einen Brief an Creative Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA. \par}\end{spacing}
+
+\end{quote}
+\thispagestyle{empty}
+
+\newpage
+\tableofcontents{}
+
+\newpage
+
+
+\section{Einleitung}
+
+
+\subsection{�ber dieses Handbuch}
+
+Dieses Handbuch will eine kurze Einf�hrung zu den n�tzlichsten Funktionen
+von \jabref{} bieten, ohne dabei eine ersch�pfende Beschreibung aller
+Funktionalit�ten dieser Software zu liefern. \emph{}\jabref{} ist
+das Ergebnis der Verschmelzung von \emph{BibKeeper} und \emph{JBibtexManager}.
+Weitere Informationen gibt es im Internet unter \url{http://jabref.sourceforge.net}
+sowie im Programm selbst unter \menu{Hilfe} \msep{} \menu{Inhalt}.
+
+Die Anleitungen basieren auf den Hilfeseiten des Programms. Da dieses
+Handbuch und die Hilfeseiten unabh�ngig voneinander gepflegt und aktualisiert
+werden, m�ssen die Beschreibungen jedoch nicht immer �bereinstimmen.
+Im Zweifel sind die Hilfeseiten des Programms aktueller als die hier
+vorgelegte Beschreibung.
+
+Am Anfang jedes Abschnitts sollte~(!) zun�chst stehen, wie man zur
+entsprechenden Funktion gelangt (d.\,h. �ber welches Men� und mit
+welchem Tastenk�rzel). Men�-Eintr�ge werden in einer kursiven, dunkelroten
+Schrift dargestellt (Beispiel: \menu{Men�} \msep{} \menu{Untermen�}).
+Besondere Hinweise und Tipps werden in einem gelb hinterlegten Kasten
+mit dunkelblauer Schrift dargestellt. Hyperlinks sind ebenfalls dunkelblau
+und anklickbar~-- das gilt sowohl f�r die Navigation innerhalb des
+Dokuments als auch f�r Links ins Internet.
+
+�ber den Stand und die >>Geschichte<< dieses Handbuchs gibt der
+Abschnitt >>Versionsgeschichte<< (S.\,\pageref{RevisionHistory})
+Auskunft.
+
+
+\subsection{Einf�hrung in Bib\TeX{}}
+
+\label{BibtexHelp}\tip[]{\jabref{} hilft Ihnen bei der Arbeit mit
+Ihren Bib\TeX{}-Dateien, aber es m�ssen dennoch Regeln beachtet werden,
+wenn Sie Ihre Eintr�ge bearbeiten. Nur so kann sichergestellt werden,
+dass Bib\TeX{} Ihre Datei richtig verarbeiten kann.}
+
+
+\subsubsection*{Bib\TeX{} Felder}
+
+Es gibt viele unterschiedliche Felder in Bib\TeX{} und einige zus�tzliche
+Felder, die Sie in \jabref{} einsetzen k�nnen. Grunds�tzlich k�nnen
+Sie \LaTeX{}-Befehle in Feldern, die Text beinhalten, einsetzen. Bib\TeX{}
+wird Ihr Literaturverzeichnis je nach Bib\TeX{} style (Stildatei \texttt{.bst})
+automatisch formatieren und bei Stildateien f�r englische Texte Gro�buchstaben
+verkleinern. Um sicherzustellen, dass einzelne Buchstaben gro� bleiben,
+m�ssen Sie sie in Klammern einschlie�en, wie im Wort \{B\}elgien.
+Die meisten deutschen Bib\TeX{}-Stile%
+\footnote{Beispielsweise natdin, dinat, jurabib~\ldots{}%
+} behalten die Gro�buchstaben ohnehin bei.
+
+Hier einige Hinweise zu den wichtigsten Feldtypen:
+
+\begin{labeling}{00.00.0000}
+\item [\emph{author}]Dieses Feld sollte alle Autoren Ihres Eintrags enthalten.
+Die Namen werden durch das Wort \emph{and} getrennt,%
+\footnote{Nicht durch Kommata, auch nicht durch >>und<<.%
+} auch wenn es mehr als zwei Autoren gibt. Jeder Name kann in zwei
+gleichwertigen Formen notiert werden:
+
+\begin{quote}
+\texttt{Donald E. Knuth} \emph{oder} \texttt{Knuth, Donald E.}
+
+\texttt{Eddie van Halen} \emph{oder} \texttt{van Halen, Eddie}
+\end{quote}
+Die zweite Form sollte f�r Autoren mit zwei oder mehr Nachnamen benutzt
+werden, um zwischen dem mittleren und dem Nachnamen zu unterscheiden.
+
+\item [\emph{editor}]Dieses Feld ist analog zum \emph{author}-Feld.
+\item [\emph{year}]Das Jahr der Publikation. Dieses Feld wird f�r die meisten
+Eintragstypen ben�tigt. \jabref{} akzeptiert in diesem Feld nur einen
+numerischen Wert.
+\item [\emph{bibtexkey}]Eine eindeutige Bezeichnung, um sich in \LaTeX{}-Dokumenten
+auf den Eintrag beziehen zu k�nnen. Beachten Sie, dass der Bib\TeX{}-Key
+genau mit dem Verweis im \LaTeX{}-Dokument �bereinstimmen muss (auch
+die Gro�"~\slash{}Kleinschreibung).
+\end{labeling}
+F�r weitere Erl�uterungen zu Bib\TeX{} wird verwiesen auf \cite{Markey2005,btxdoc,btxhak,Raichle2002}.
+
+
+\section{Installation}
+
+
+\subsection{System-Voraussetzungen}
+
+\jabref{} ist in Java programmiert und somit betriebssystemunabh�ngig,
+kann prinzipiell also unter Windows, Mac OS X, Linux und anderen UNIXen
+betrieben werden. Voraussetzung ist allerdings, dass die \emph{Java
+Virtual Machine} mindestens in der Version~1.4.2 installiert ist.
+Sie ist kostenlos und kann unter \url{http://java.sun.com/} heruntergeladen
+werden. Im Normalfall sollte das \emph{Java Runtime Environment} ausreichen;
+nur wenn Sie \jabref{} kompilieren m�chten, ben�tigen Sie das \emph{Java
+Development Kit}.
+
+
+\subsection{Windows}
+
+
+\subsubsection*{Installer (msi)}
+
+\jabref{} gibt es im Windows Installer-Format (\texttt{.msi}). Ein
+Doppelklick auf die MSI-Datei installiert \jabref{} und f�gt dem
+Startmen� eine Verkn�pfung hinzu. Falls Java nicht installiert ist,
+wird eine Warnmeldung ausgegeben.%
+\footnote{Die Windows-Installation wurde von Dale Visser erstellt, der dazu
+die folgenden \emph{Open-Source-Tools} benutzt hat: JSmooth, ein \texttt{.exe}
+wrapper f�r Java-Anwendungen (\url{http://jsmooth.sf.net/}); Wix,
+ein Tool zum Kompilieren von MSI-Dateien aus einer XML-Spezifikation
+(\url{http://wix.sf.net/}).%
+}
+
+
+\subsubsection*{Batch-Datei (jar)}
+
+Wenn Sie die ausf�hrbare jar-Datei (\texttt{.jar}) heruntergeladen
+haben, probieren Sie zun�chst, ob ein Doppelklick darauf das Programm
+startet~-- dies funktioniert zumindest auf einigen Systemen. Falls
+\jabref{} nicht direkt startet (Windows also nicht wei�, was es mit
+einer jar-Datei anfangen soll), fahren Sie folgenderma�en fort:
+
+Erstellen Sie in dem Ordner, in dem Sie die Datei \emph{JabRef.jar}
+abgelegt haben, eine Batch-Datei mit dem Namen \emph{jabref-start.bat}.
+Diese Datei soll nur eine Zeile enthalten:
+
+\begin{lyxcode}
+start~javaw~-jar~JabRef.jar
+\end{lyxcode}
+Mit einem Doppelklick auf die Batch-Datei starten Sie \jabref{}.
+
+
+\subsection{Starten von der Kommandozeile}
+
+\begin{enumerate}
+\item mit dem \emph{Java Runtime Environment}:
+
+
+\texttt{jre -new -jar <Pfad zur jar-Datei>}
+
+oder
+
+\texttt{jrew -new -jar <Pfad zur jar-Datei>}
+
+\item mit dem \emph{Java Development Kit}:
+
+
+\texttt{java -jar <Pfad zur jar-Datei>}
+
+\end{enumerate}
+Es wird empfohlen, \jabref{} mit dem Java 5.0 JRE zu benutzen. Falls
+Sie dies tun, sollten Sie die Option \texttt{-Dswing.aatext=true}
+vor der Option \texttt{-jar} einf�gen, um das Benutzen von Anti-Alias-Schriften
+im Programm zu erm�glichen.
+
+Die jar-Datei, die \jabref{} enth�lt, kann entpackt werden mit den
+Kommandos \texttt{jar xf <Pfad zur jar-Datei>} bzw. \texttt{jar xf
+<Pfad zur jar-Datei> <Liste der Dateien, die entpackt werden sollen>}.
+Das Entpacken der jar-Datei ist nicht notwendig, um das Programm zu
+starten!
+
+Weitere Hinweise zur Installation finden Sie auf der \jabref{}-Homepage
+unter \url{http://jabref.sourceforge.net} und in der Datei INSTALL
+(zum Kompilieren aus den \emph{sourcen}).
+
+
+\section{Funktionen}
+
+\label{JabRefHelp}\jabref{} ist ein Programm zur Verwaltung von
+Bib\TeX{}-Dateien. Es benutzt kein eigenes Dateiformat, d.\,h. dass
+Sie Ihre Dateien direkt im Bib\TeX{}-Format (Dateiendung \texttt{.bib})
+laden und speichern. Sie k�nnen aber auch bibliographische Datenbanken
+in anderen Formaten in \jabref{} importieren.
+
+\jabref{} unterst�tzt Sortier- und Suchfunktionen, um einen �berblick
+�ber den Inhalt Ihrer Datei zu bekommen. Sie k�nnen der Datei ganz
+einfach neue Eintr�ge hinzuf�gen, ohne sich daran erinnern zu m�ssen,
+welche Informationen ben�tigt werden. Au�erdem kann \jabref{} Bib\TeX{}-Keys
+automatisch generieren. \jabref{} ist sehr n�tzlich, wenn Sie Bib\TeX{}
+oder CiteMaker benutzen, kann aber auch f�r diejenigen sinnvoll sein,
+die andere Bibliographie-Systeme benutzen oder schlicht und einfach
+ihre Literaturquellen organisieren wollen.
+
+
+\subsection{Das Hauptfenster}
+
+\begin{quote}
+\tip[]{Die meisten Men�funktionen, auf die im Folgenden hingewiesen
+wird, haben Tastenk�rzel, und viele Funktionen k�nnen �ber die Werkzeugleiste
+aufgerufen werden.}
+\end{quote}
+\label{BaseFrameHelp}Im Hauptfenster, in dem Sie mit Ihrer Datei
+arbeiten, befindet sich unter der Men�leiste und der Werkzeugleiste
+die Tableiste mit Tabs (Reitern) f�r jede Ihrer ge�ffneten Dateien.
+Wenn Sie einen dieser Tabs anklicken, erscheint eine Tabelle, die
+alle Datens�tze und einige der Datenfelder auf\textcompwordmark{}listet.
+
+Die Felder k�nnen direkt in der Tabelle bearbeitet werden, indem Sie
+einfach auf eine Zelle klicken und den Inhalt eingeben (nur m�glich,
+wenn \menu{Bearbeiten in der Tabelle zulassen} im Dialog \menu{Optionen}
+\msep{} \menu{Einstellungen} \msep{} \menu{Allgemein} ausgew�hlt
+ist). Ein Doppelklick auf eine Zelle �ffnet einen leistungsf�higeren
+Editor. Sie k�nnen mit den Pfeiltasten in der Tabelle navigieren.
+
+Die Sortierung der Tabelle erfolgt nach einem Feld Ihrer Wahl. Klicken
+Sie einfach auf die Kopfzeile einer Spalte, um die Eintr�ge nach dem
+Feld dieser Spalte zu sortieren. Klicken Sie erneut auf den Spaltenkopf,
+um die Sortierrichtung umzukehren. Eintr�ge mit gleichem Inhalt im
+ausgew�hlten Feld werden nach dem zweiten (und eventuell dem dritten)
+Kriterium sortiert. Diese Sortierkriterien k�nnen im \menu{Einstellungs}-Dialog
+festgelegt werden.
+
+Welche Felder (Spalten) in der Tabelle angezeigt werden sollen, k�nnen
+Sie im \menu{Einstellungs}-Dialog ausw�hlen. Auch die Breite der
+Tabellenspalten kann eingestellt werden, indem man die Trennlinie
+zwischen den Spaltenk�pfen anklickt und nach links oder rechts verschiebt.
+Im \menu{Einstellungs}-Dialog k�nnen Sie festlegen, ob die Tabelle
+an die Bildschirmgr��e angepasst werden soll oder nicht. Aktivieren
+Sie diese Funktion, um sicherzustellen, dass Sie die gesamte Tabelle
+sehen k�nnen. Deaktivieren Sie diese Funktion, wenn mehr Informationen
+dargestellt werden sollen.
+
+Die Farbanzeige kann ebenfalls im \menu{Einstellungs}-Dialog ein-
+und ausgeschaltet werden. Die Farbanzeige illustriert, ob Ihre Daten
+vollst�ndig sind, indem sie die Zellen wie folgt darstellt:
+
+\begin{itemize}
+\item Eine \textcolor{red}{rote} Zelle in der linken Spalte kennzeichnet
+einen unvollst�ndigen Eintrag.
+\item Eine \textcolor{yellow}{gelbe} Zelle in der linken Spalte kennzeichnet
+einen Eintrag, der nicht alle ben�tigten Felder selbst enth�lt, der
+aber einen Querverweis enth�lt.
+\item Eine \textcolor{blue}{blaue} Zelle kennzeichnet ein ben�tigtes Feld.
+\item Eine \textcolor{green}{gr�ne} Zelle kennzeichnet ein optionales Feld.
+\item Eine farblose (wei�e) Zelle kennzeichnet ein Feld, das von Bib\TeX{}
+f�r diesen Eintragstyp nicht benutzt wird. Das Feld kann selbstverst�ndlich
+in \jabref{} bearbeitet werden.
+\end{itemize}
+
+\subsubsection*{Einen neuen Eintrag hinzuf�gen}
+
+Es gibt verschiedene M�glichkeiten, einen neuen Eintrag hinzuzuf�gen.
+Im Men� \menu{BibTeX} f�hrt ein Klick auf \menu{Neuer Eintrag} zu
+einem Dialog, in dem Sie den Eintragstyp aus einer Liste w�hlen k�nnen.
+Um diesen Dialog zu umgehen, gibt es auch eigene Men�punkte f�r jeden
+Eintragstyp und au�erdem Tastenk�rzel f�r die g�ngigsten Typen.
+
+Wenn ein Eintrag hinzugef�gt wird, wird standardm��ig ein Editor f�r
+den Eintrag ge�ffnet. Sie k�nnen dieses Verhalten im \menu{Einstellungs}-Dialog
+abstellen.
+
+\tip[]{Wir empfehlen, sich die Tastenk�rzel f�r die Eintragstypen
+einzupr�gen, die Sie am h�ufigsten benutzen, z.\,B. STRG-SHIFT-A
+f�r einen Zeitschriftenaufsatz \emph{(article)}.}
+
+
+\subsubsection*{Einen Eintrag bearbeiten}
+
+Um den Eintrags-Editor (siehe \ref{EntryEditorHelp}) zur Bearbeitung
+eines existierenden Eintrags zu �ffnen, klicken Sie einfach doppelt
+auf die linke Spalte der entsprechenden Zeile oder markieren den Eintrag
+und dr�cken auf ENTER. Falls \menu{Bearbeiten in der Tabelle zulassen}
+nicht ausgew�hlt ist (im Dialog \menu{Optionen} \msep{} \menu{Einstellungen}
+\msep{} \menu{Allgemein}), �ffnet ein Doppelklick irgendwo in der
+zugeh�rigen Zeile den Eintrags-Editor.
+
+
+\subsubsection*{Einen Bib\TeX{}-String in einem Feld verwenden}
+
+In \jabref{} schreiben Sie den Inhalt aller Felder so, wie Sie es
+in einem Texteditor machen w�rden, mit einer Ausnahme: um einen String
+(eine Art Abk�rzung) zu verwenden, umschlie�en Sie den Namen des Strings
+mit je einem \#, z.\,B.
+
+\begin{lyxcode}
+\#jan\#~1997
+\end{lyxcode}
+was interpretiert wird als String mit dem Namen \texttt{jan} gefolgt
+von \texttt{1997}. Vergleichen Sie dazu auch die Hinweise zum String-Editor
+(\ref{StringEditorHelp}).
+
+
+\subsection{Eintrags-Editor}
+
+\label{EntryEditorHelp}
+
+\begin{quote}
+\emph{Ge�ffnet wird der Eintrags-Editor im Hauptfenster durch einen
+Doppelklick auf die linke Spalte eines Eintrags (bzw. irgendwo auf
+die Zeile des Eintrags, wenn \menu{Bearbeiten in der Tabelle zulassen}
+im Dialog \menu{Optionen}} \msep{} \emph{\menu{Einstellungen}}
+\msep{} \emph{\menu{Allgemein} nicht ausgew�hlt ist), oder durch
+Dr�cken auf ENTER. Der Eintrags-Editor wird geschlossen, indem man
+auf ESC dr�ckt.}
+\end{quote}
+Im Eintrags-Editor k�nnen Sie alle relevanten Informationen eines
+Eintrags festlegen. Der Editor �berpr�ft den Eintragstyp und zeigt
+alle ben�tigten und optionalen Felder f�r den Gebrauch mit Bib\TeX{}
+an. Dar�ber hinaus gibt es einige Felder, die \emph{Allgemeine Felder}
+genannt werden und f�r alle Eintragstypen gelten.
+
+Sie k�nnen die Felder, die f�r die einzelnen Eintragstypen als ben�tigt
+und optional angesehen werden, und auch die Allgemeinen Felder anpassen.
+Schlagen Sie unter Abschnitt~\ref{CustomEntriesHelp} nach, wenn
+Sie mehr Informationen dar�ber erhalten m�chten.
+
+
+\subsubsection*{Die Panels des Eintrags-Editors}
+
+Der Eintrags-Editor besteht in der Standardeinstellung aus f�nf Panels:
+\emph{Ben�tigte Felder}, \emph{Optionale Felder}, \emph{General},
+\emph{Abstract} und \emph{Bib\TeX{}} \emph{Quelltext}, wobei \emph{General}
+und \emph{Abstract} vom Benutzer angepasst werden k�nnen (siehe dazu
+Abschnitt~\ref{GeneralFields}). In den ersten drei Panels k�nnen
+Sie mit TAB und SHIFT-TAB zwischen den einzelnen Feldern hin- und
+herwechseln. Zu einem anderen Panel gelangen Sie, indem Sie auf die
+Tabs klicken. Mit den folgenden Tastaturk�rzeln k�nnen Sie ebenfalls
+zwischen den Panels navigieren:
+
+\begin{itemize}
+\item CTRL-TAB oder CTRL-+ wechselt zum Panel rechts vom aktuellen Panel,
+\item CTRL-SHIFT-TAB oder CTRL-$-$ (MINUS) wechselt dementsprechend zum
+Panel links vom aktuellen Panel.
+\end{itemize}
+Au�erdem k�nnen Sie zum n�chsten oder vorherigen Eintrag wechseln,
+indem Sie >>STRG-SHIFT-$\downarrow$<< bzw. >>STRG-SHIFT-$\uparrow$<<
+oder die Pfeil-Buttons in der linken Toolbar dr�cken.
+
+Das Panel \emph{Bib\TeX{} Quelltext} zeigt, wie der Eintrag aussehen
+wird, wenn die Datei im \texttt{bib}-Format gespeichert wird. Wenn
+Sie wollen, k�nnen Sie den Bib\TeX{} Quelltext direkt bearbeiten.
+Sobald Sie zu einem anderen Panel wechseln, STRG-S dr�cken oder den
+Eintrags-Editor schlie�en, wird \jabref{} versuchen, den Inhalt des
+Quelltext-Panels zu analysieren. Falls dabei Probleme auftreten, werden
+Sie benachrichtigt und erhalten die M�glichkeit, den Eintrag noch
+einmal zu �berarbeiten oder den vorherigen Inhalt wiederherzustellen.
+Wenn in den \menu{Einstellungen} (unter \menu{Allgemein}) die Option
+\menu{Quelltext standardm��ig anzeigen} gew�hlt wurde, wird das Quelltext-Panel
+beim �ffnen des Eintrags-Editors als erstes angezeigt. Wenn Sie lieber
+den Quelltext bearbeiten als die anderen Panels zu benutzen, sollten
+Sie diese Option w�hlen.
+
+\tip{Wenn Ihre Datei Felder enth�lt, die \jabref{} nicht kennt,
+erscheinen diese im Quelltext-Panel.}
+
+\tip[Und noch ein Tipp: ]{Die \emph{PDF-} und \emph{URL}-Felder unterst�tzen
+Drag \& Drop. Sie k�nnen z.\,B. ein URL aus Ihrem Browser dort einf�gen.}
+
+
+\subsubsection*{�berpr�fung der Feldkonsistenz}
+
+Wenn der Inhalt eines Feldes ge�ndert wird, �berpr�ft \jabref{},
+ob der neue Inhalt akzeptiert werden kann. Bei Feldern, die von Bib\TeX{}
+genutzt werden, wird der Inhalt zum einen auf die richtige Klammerung
+mit geschweiften Klammern, aber auch auf die Benutzung des Zeichens
+\texttt{\#} hin �berpr�ft. Das >>hash<<-Symbol (im Deutschen oft
+>>Doppelkreuz<< oder >>Raute<< genannt) darf \emph{nur} paarweise
+benutzt werden, um damit den Namen eines Bib\TeX{}-Strings einzuschlie�en.
+Beachten Sie, dass \jabref{} nicht �berpr�ft, ob der angef�hrte String
+tats�chlich vorhanden ist (der Bib\TeX{}-Stil, den Sie benutzen, kann
+eine beliebige Anzahl von Strings definieren, die \jabref{} nicht
+kennt).
+
+Falls die Inhalte nicht akzeptabel sind, wird das Feld mit roter Farbe
+hinterlegt, was auf einen Fehler hindeutet. In diesem Fall werden
+die �nderungen nicht gespeichert.
+
+
+\subsection{Integrit�tspr�fung}
+
+\begin{quote}
+\emph{Erreichbar �ber das Men� \menu{Extras}} \msep{} \emph{\menu{�berpr�fung der Integrit�t}.}
+\end{quote}
+Mit dieser Funktion �berpr�ft \jabref{} alle Eintr�ge auf deren G�ltigkeit
+und versucht Fehler aufzudecken. Mit dem \menu{�berpr�fen}-Button
+kann der Vorgang gestartet werden. Es wird eine Liste mit Hinweisen
+(Info-Icon) und m�glichen Fehlern (Ausrufezeichen-Icon) sowie dem
+entsprechenden Bib\TeX{}-Key erstellt. Wenn Sie einen Hinweis ausw�hlen,
+erscheint der Inhalt des Feldes, das beanstandet wird. Sie k�nnen
+nun den Feldinhalt ver�ndern und die Ver�nderungen mit Klick auf die
+Schaltfl�che \menu{�bernehmen} speichern.
+
+
+\subsection{Bib\TeX{}-Keys}
+
+Damit man sich in einem \LaTeX{}-Dokument auf einen Literaturverweis
+beziehen kann, braucht man einen eindeutigen Bib\TeX{}-Key. Eindeutig
+hei�t, dass er nur einmal vergeben sein darf. Es wird nach Gro�"~
+und Kleinschreibung unterschieden, \texttt{Yared1998} ist also nicht
+identisch mit \texttt{yared1998}. \jabref{} bietet einige M�glichkeiten,
+um auch bei gr��eren Datenbanken den �berblick �ber die Bib\TeX{}-Keys
+nicht zu verlieren.
+
+\tip{Falls Sie in einem \LaTeX{}-Dokument mehrere Bib\TeX{}-Dateien
+einbinden, m�ssen Sie selbst darauf achten, dass in den unterschiedlichen
+Dateien nicht mehrmals derselbe Bib\TeX{}-Key vergeben ist. Nutzen
+Sie deshalb am besten die Funktion \menu{Extras} \msep{} \menu{Neue Teildatei aus AUX-Datei}.}
+
+Der einfachste Weg, einen eindeutigen Bib\TeX{}-Key zu bekommen, ist
+das automatische Erzeugen, das Sie mit der Tastenkombination STRG-G
+oder mit dem Zauberstab-Button im Eintrags-Editor veranlassen k�nnen.
+Falls Sie sich nicht im Eintrags-Editor befinden, werden mit Hilfe
+von STRG-G oder dem Zauberstab-Button aus der Men�leiste f�r alle
+Eintr�ge der Datei Bib\TeX{}-Keys erzeugt. Falls dabei Keys �berschrieben
+werden, gibt \jabref{} eine Warnmeldung aus.
+
+Wie die Bib\TeX{}-Keys aussehen, die \jabref{} automatisch generiert,
+und wie Sie dieses Aussehen ver�ndern k�nnen, erfahren Sie unter Abschnitt~\ref{LabelPatterns}.
+
+
+\subsection{Suchfunktionen}
+
+\begin{quote}
+\label{SearchHelp}\emph{STRG-F �ffnet oder aktiviert den Suchdialog.
+Dr�ckt man mehrmals auf STRG-F, so werden die verschiedenen Suchmodi
+ausgew�hlt. Mit STRG-SHIFT-F �ffnet oder aktiviert man den Suchdialog
+und w�hlt gleichzeitig die direkte Suche aus. Bei der direkten Suche
+springt man mit STRG-F oder STRG-SHIFT-F zum n�chsten Treffer.}
+\end{quote}
+Es gibt drei verschiedene Suchmethoden in \jabref{}: die direkte
+Suche, die Markier-Suche und die Sortier-Suche.
+
+
+\subsubsection*{Direkte Suche}
+
+Bei der direkten Suche sucht \jabref{} unmittelbar, wenn Sie einen
+Buchstaben eingeben. Die Statuszeile informiert Sie �ber den Sucherfolg.
+Mit STRG-F oder STRG-SHIFT-F wird zum n�chsten Vorkommen des aktuellen
+Suchbegriffs gesprungen. Falls es keine weiteren Vorkommen gibt, informiert
+die Statuszeile dar�ber. Bei erneuter Wiederholung startet die Suche
+vom Anfang der Datei. Die Suchreihenfolge richtet sich nach der aktuellen
+Sortierung Ihrer Datei. Um die direkte Suche zu verlassen, dr�cken
+Sie ESC oder klicken Sie auf \menu{Zur�cksetzen}.
+
+
+\subsubsection*{Markier-Suche}
+
+Wenn Sie die Suchmethode \emph{Markieren} w�hlen, sucht das Programm
+in Ihrer Datei nach allen Vorkommen ihres Suchbegriffs, sobald Sie
+auf ENTER dr�cken. Die Treffer werden indirekt markiert, d.\,h. alle
+Nicht-Treffer werden grau hinterlegt. Haben Sie zus�tzlich die Option
+\menu{Treffer ausw�hlen} aktiviert (im \menu{Einstellungen}-Men�
+des Suchdialogs), dann werden die Treffer ausgew�hlt.
+
+
+\subsubsection*{Sortier-Suche}
+
+Die Suche mit der Methode \emph{Oben einsortieren} ist �hnlich wie
+die Suche mit Markierung, nur dass die Treffer automatisch an den
+Anfang der Tabelle sortiert werden. Eintr�ge, die nicht mit dem Suchbegriff
+�bereinstimmen, werden unter den Treffern aufgelistet und zus�tzlich
+grau hinterlegt. Um die Anzeige der Suchergebnisse abzuschalten, dr�cken
+Sie ESC oder klicken auf \emph{Zur�cksetzen}.
+
+\tip{Suchen Sie mit der Option \menu{Treffer ausw�hlen} und dr�cken
+anschlie�end STRG-M, so haben Sie alle Treffer markiert (vgl. Abschnitt~\ref{MarkingHelp}:
+Markieren von Eintr�gen) und k�nnen z.\,B. eine weitere Suche durchf�hren,
+ohne die bisherigen Ergebnisse zu >>verlieren<<.}
+
+
+\subsubsection*{Feldbezeichner und logische Operatoren}
+
+\label{SearchHelp_advanced}Um nur einige bestimmte Felder zu durchsuchen
+und\slash{}oder logische Operatoren im Suchbegriff zu benutzen, wird
+eine spezielle Syntax zur Verf�gung gestellt. Um beispielsweise nach
+Eintr�gen mit dem Autor >>Miller<< zu suchen, geben Sie
+
+\begin{lyxcode}
+author~=~miller
+\end{lyxcode}
+in das Suchfeld ein. \emph{(Achtung! Das funktioniert nicht bei der
+direkten Suche!)} Falls der Suchbegriff Leerzeichen enth�lt, schlie�en
+Sie ihn in Anf�hrungszeichen ein. Benutzen Sie \emph{nie} Leerzeichen
+in dem Feldbezeichner. Mehrere Feldbezeichner werden durch >>|<<
+voneinander getrennt. Um beispielsweise nach Eintr�gen �ber Karl den
+Gro�en zu suchen, geben Sie folgendes ein:
+
+\begin{lyxcode}
+title|keywords~=~\char`\"{}Karl~der~Gro�e\char`\"{}
+\end{lyxcode}
+Sie k�nnen die logischen Operatoren AND, OR und NOT sowie Klammern
+verwenden:
+
+\begin{lyxcode}
+(author~=~miller~OR~title|keywords~=~\char`\"{}Karl~der~Gro�e\char`\"{})~
+
+AND~NOT~author~=~brown
+\end{lyxcode}
+\ldots{} sucht beispielsweise nach Eintr�gen, in denen entweder der
+Autor >>Miller<< hei�t oder im \emph{title}- oder \emph{keywords}-Feld
+der Begriff >>Karl der Gro�e<< steht; gleichzeitig werden die Eintr�ge
+mit dem Autor >>Brown<< nicht angezeigt.
+
+Das \texttt{=}-Zeichen ist eigentlich eine Abk�rzung f�r >>enth�lt<<
+\emph{(contains)}. Wenn man nach genauen Treffern suchen m�chte, muss
+man \texttt{==} oder \texttt{matches} (>>�bereinstimmen<<) eingeben.
+\texttt{!=} sucht nach Eintr�gen, bei denen der Suchbegriff \emph{nicht}
+enthalten ist. Um nach Eintr�gen eines bestimmten Typs zu suchen,
+gibt es ein Pseudofeld namens \emph{entrytype}:
+
+\begin{lyxcode}
+entrytype~=~thesis
+\end{lyxcode}
+\ldots{} findet Eintr�ge, deren Typ (wie in der Spalte \emph{Entrytype}
+dargestellt) das Wort >>thesis<< enth�lt (z.\,B. >>phdthesis<<
+und >>mastersthesis<<). Ebenso erlaubt das Pseudofeld \emph{bibtexkey}
+die Suche nach Bib\TeX{}-Keys, z.\,B.:
+
+\begin{lyxcode}
+bibtexkey~=~miller2005
+\end{lyxcode}
+
+\subsubsection*{Suchoptionen}
+
+Der \menu{Einstellungen}-Button im Suchdialog �ffnet ein Men�, in
+dem man mehrere Optionen (de)aktivieren kann: das Beachten von Gro�-
+und Kleinschreibung, das Nutzen regul�rer Ausdr�cke sowie das Ausw�hlen
+der Suchergebnisse.
+
+
+\subsection{Gruppen}
+
+Mit Gruppen k�nnen Sie Ihre Bib\TeX{}-Datei in einer Baumstruktur
+anordnen, vergleichbar mit einer Dateistruktur in Ordnern und Unterordnern.
+Die beiden Hauptunterschiede sind:
+
+\begin{enumerate}
+\item W�hrend eine Datei auf einer Festplatte immer in genau einem Ordner
+abgelegt ist, kann ein Literatureintrag in \jabref{} mehreren Gruppen
+angeh�ren.
+\item Gruppen benutzen bestimmte Kriterien, um ihren Inhalt dynamisch zu
+bestimmen. Neue Eintr�ge, die den Kriterien einer Gruppe entsprechen,
+geh�ren automatisch zu dieser Gruppe. Diese Funktionalit�t gibt es
+nicht in �blichen Dateisystemen, wohl aber in einigen E-Mail-Programmen
+(z.\,B. Thunderbird und Opera).
+\end{enumerate}
+Wenn Sie eine Gruppe ausw�hlen, werden die Eintr�ge dieser Gruppe
+angezeigt. Wenn Sie mehrere Gruppen ausw�hlen, werden entweder die
+Eintr�ge angezeigt, die in einer der Gruppen sind (Vereinigung), oder
+solche, die in allen Gruppen vorhanden sind (Schnittmenge)~-- das
+h�ngt von Ihren Einstellungen ab. All dies wird im Folgenden detailliert
+erl�utert.
+
+Gruppendefinitionen sind dateispezifisch; sie werden als \texttt{@COMMENT}-Block
+in der \texttt{bib}-Datei gespeichert und von allen Benutzern gemeinsam
+benutzt. (K�nftige Versionen von \jabref{} werden m�glicherweise
+benutzerabh�ngige Gruppen unterst�tzen.)
+
+
+\subsubsection*{Die Gruppenansicht}
+
+Die Gruppenansicht wird im linken Bereich des Bildschirms angezeigt.
+Sie kann mit der Tastenkombination STRG-SHIFT-G oder dem Gruppen-Button
+in der Toolbar ein- und ausgeblendet werden. Die Gruppenansicht verf�gt
+�ber mehrere Schaltfl�chen, aber die meisten Funktionen werden �ber
+das Kontextmen� angesteuert (also mit der rechten Maustaste). Drag\,\&\,Drop
+wird ebenfalls unterst�tzt.
+
+
+\subsection*{Einige kurze Beispiele}
+
+Sie m�chten vielleicht~\ldots{}
+
+\begin{itemize}
+\item [\ldots]\textbf{einfach nur eine Gruppe anlegen und ihr einige Eintr�ge
+zuordnen}
+
+
+Vergewissern Sie sich, dass die Gruppenansicht eingeschaltet ist.
+Dr�cken Sie auf den Button \menu{Neue Gruppe}, geben einen Namen
+f�r die Gruppe ein und dr�cken \menu{OK}. Sie k�nnen alle Einstellungen
+auf ihren Standardwerten belassen. Jetzt w�hlen Sie die Eintr�ge aus,
+die der Gruppe zugeordnet werden sollen, und ziehen diese mit der
+Maus auf die Gruppe oder w�hlen \menu{Zu Gruppe hinzuf�gen} aus dem
+Kontextmen�. Jetzt k�nnen Sie die Gruppe anklicken, um sich ihren
+Inhalt anzeigen zu lassen (das sollten die Eintr�ge sein, die Sie
+gerade hinzugef�gt haben).
+
+\item [\ldots]\textbf{das Feld} \textbf{\emph{keywords}} \textbf{benutzen,
+um die Eintr�ge zu gruppieren}
+
+
+Stellen Sie sicher, dass die Gruppenansicht aktiviert ist. Dr�cken
+Sie auf den Button \menu{Neue Gruppe}, geben einen Namen f�r die
+Gruppe ein und w�hlen die Option \menu{Dynamisches Gruppieren der Eintr�ge anhand eines Stichworts in einem Feld}.
+Geben Sie das Stichwort, nach dem gesucht werden soll, ein und dr�cken
+\menu{OK}. Jetzt k�nnen Sie die Gruppe anklicken, um sich ihren Inhalt
+anzeigen zu lassen (das sollten alle Eintr�ge sein, deren \emph{keywords}-Feld
+das Stichwort enth�lt, das Sie angegeben haben).
+
+\item [\ldots]\textbf{einen frei w�hlbaren Suchausdruck verwenden, um eine
+Gruppe zu definieren}
+
+
+Stellen Sie sicher, dass die Gruppenansicht aktiviert ist. Dr�cken
+Sie auf den Button \menu{Neue Gruppe}, geben einen Namen f�r die
+Gruppe ein und w�hlen die Option \menu{Dynamisches Gruppieren der Eintr�ge anhand eines beliebigen Suchausdrucks}.
+Geben Sie \texttt{author=smith} als Suchausdruck ein (ersetzen Sie
+\texttt{smith} mit einem Namen, der wirklich in Ihrer Datei vorkommt)
+und klicken \menu{OK}. Jetzt k�nnen Sie die Gruppe anklicken, um
+sich ihren Inhalt anzeigen zu lassen (das sollten alle Eintr�ge sein,
+deren \emph{author}-Feld den Namen beinhaltet, den Sie angegeben haben).
+
+\item [\ldots]\textbf{mehrere Gruppen kombinieren }
+
+
+Erstellen sie zwei unterschiedliche Gruppen (z.\,B. so wie oben beschrieben).
+Klicken Sie auf den Button \menu{Einstellungen} in der Gruppenansicht
+und w�hlen \menu{Vereinigung}. Jetzt w�hlen Sie beide Gruppen aus
+(dazu klicken Sie auf eine Gruppe und anschlie�end bei gedr�ckter
+STRG-Taste auf die andere Gruppe). Sie sollten jetzt alle Eintr�ge
+sehen, die in einer der beiden Gruppen aufgef�hrt sind. Klicken Sie
+noch einmal auf \menu{Einstellungen} und w�hlen \menu{Schnittmenge}
+aus. Nun sollten Sie nur die Eintr�ge sehen, die in beiden Gruppen
+enthalten sind (das k�nnen auch keine sein, oder aber genau dieselben
+Eintr�ge wie zuvor, sofern beide Gruppen dieselben Eintr�ge enthalten).
+
+\item [\ldots]\textbf{sehen, welche Gruppen sich �berschneiden}
+
+
+Mit \jabref{} k�nnen Sie ganz einfach herausfinden, welche Gruppen
+sich mit den aktuell ausgew�hlten Gruppen �berschneiden (d.\,h. welche
+Gruppen zumindest einen Eintrag enthalten, der auch in der aktuell
+ausgew�hlten Gruppe ist). Klicken Sie auf \menu{Einstellungen} und
+aktivieren die Option \menu{Sich �berschneidende Gruppen markieren}.
+W�hlen Sie dann eine Gruppe, die sich mit anderen �berschneidet. Diese
+anderen Gruppen sollten nun markiert sein.
+
+\end{itemize}
+
+\subsubsection*{Arten von Gruppen}
+
+In \jabref{}~1.8 gibt es vier verschiedene Arten von Gruppen:
+
+\begin{enumerate}
+\item Die Gruppe \emph{Alle Eintr�ge}, die~-- wie der Name vermuten l�sst~--
+alle Eintr�ge beinhaltet, ist immer vorhanden und kann weder ver�ndert
+noch gel�scht werden.
+\item \emph{Statische Gruppen} verhalten sich wie Ordner auf einer Festplatte
+und beinhalten nur die Eintr�ge, die Sie ihnen explizit zuweisen.
+\item \emph{Dynamische Gruppen basierend auf einem Stichwort} beinhalten
+Eintr�ge, die in einem bestimmten Bib\TeX{}-Feld (z.\,B. \emph{keywords})
+ein bestimmtes Stichwort (z.\,B. \emph{elektrisch}) aufweisen. Diese
+Methode ben�tigt kein manuelles Zuweisen der Eintr�ge, sondern nutzt
+die bereits in der Datei vorhandenen Informationen. Wenn alle Eintr�ge
+in Ihrer Datenbank passende Stichw�rter haben, k�nnte diese Art von
+Gruppe die beste Wahl f�r Sie sein.
+\item \emph{Dynamische Gruppen basierend auf einer freien Suche} beinhalten
+Eintr�ge, die mit einem bestimmten Suchausdruck �bereinstimmen. Dabei
+wird dieselbe Syntax verwendet wie beim Suchen (siehe Abschnitt~\ref{SearchHelp}).
+Diese Syntax (die auf S.\,\pageref{SearchHelp_advanced} genauer
+beschrieben wird) unterst�tzt logische Operatoren (AND, OR, NOT) und
+erlaubt es, in einem oder mehreren Bib\TeX{}-Feldern zu suchen. Dadurch
+ist eine flexiblere Definition von Gruppen m�glich als mit einer Stichwortsuche
+(z.\,B. \texttt{author=smith AND title=elektrisch}).
+\end{enumerate}
+Jede Gruppe, die Sie erstellen, ist von einer der drei letztgenannten
+Arten. Der Dialog \menu{Gruppe bearbeiten}, der mit einem Doppelklick
+auf eine Gruppe aufgerufen wird, zeigt eine kurze Beschreibung der
+ausgew�hlten Gruppe.
+
+
+\subsubsection*{Gruppenstrukturen, Erstellen und L�schen von Gruppen}
+
+Die Gruppen sind~-- vergleichbar mit Datei-Ordnern~-- in einer Baumansicht
+strukturiert, in der die Gruppe \emph{Alle Eintr�ge} das Stammelement
+ist. Mit einem Rechtsklick auf eine Gruppe k�nnen Sie dem Baum eine
+neue Gruppe hinzuf�gen, entweder auf derselben Ebene wie die ausgew�hlte
+Gruppe oder als ihre Untergruppe. Der Button \menu{Neue Gruppe} erzeugt
+eine neue Untergruppe der Gruppe \emph{Alle Eintr�ge}, egal ob Sie
+gerade Gruppen ausgew�hlt haben oder nicht. Im Kontextmen� k�nnen
+Sie auch Gruppen und\slash{}oder Untergruppen l�schen, Untergruppen
+alphabetisch sortieren oder Gruppen an eine andere Stelle des Baums
+verschieben. Letzteres k�nnen Sie auch mit Drag\,\&\,Drop machen,
+allerdings mit der Einschr�nkung, dass bei Drag\,\&\,Drop die Reihenfolge
+der Untergruppen einer Gruppe nicht ver�ndert werden kann.
+
+Die Funktionen \menu{R�ckg�ngig} und \menu{Wiederholen} werden f�r
+alle Bearbeitungsschritte unterst�tzt.
+
+
+\paragraph*{Statische Gruppen}
+
+Statische Gruppen werden nur durch manuelles Zuweisen von Eintr�gen
+>>gef�ttert<<. Nachdem Sie eine statische Gruppe erstellt haben,
+w�hlen Sie die Eintr�ge aus, die Sie ihr zuweisen wollen, und nutzen
+entweder Drag\,\&\,Drop oder das Kontextmen� in der Tabelle, um
+die Zuweisung durchzuf�hren. Um Eintr�ge aus einer Gruppe zu entfernen,
+w�hlen Sie sie aus und benutzen das Kontextmen� in der Tabelle. Es
+k�nnen keine weiteren Optionen angegeben werden.
+
+Diese Methode des Gruppierens setzt voraus, dass alle Eintr�ge einen
+eindeutigen Bib\TeX{}-Key haben. Im Falle von fehlenden oder doppelten
+Bib\TeX{}-Keys kann das Zuweisen der betreffenden Eintr�ge in k�nftigen
+Sitzungen nicht korrekt wiederhergestellt werden.
+
+
+\paragraph*{Dynamische Gruppen}
+
+Der Inhalt einer dynamischen Gruppe wird von einer logischen Bedingung
+bestimmt. Nur Eintr�ge, die dieser Bedingung entsprechen, geh�ren
+zu dieser Gruppe. Diese Methode nutzt die bereits in der Datei vorhandenen
+Informationen und wird aktualisiert, sobald Sie Ver�nderungen in der
+Datei vornehmen. Es gibt zwei m�gliche Arten von Bedingungen:
+
+\begin{enumerate}
+\item Ein Feld nach einem Stichwort durchsuchen
+
+
+Diese Methode gruppiert Eintr�ge, bei denen ein bestimmtes Bib\TeX{}-Feld
+(z.\,B. \emph{keywords}) einen bestimmten Suchausdruck (z.\,B. \emph{elektrisch})
+enth�lt. Damit dies funktioniert, muss das Feld, nach dem sortiert
+wird, nat�rlich in jedem Eintrag vorhanden und sein Inhalt fehlerfrei
+sein. Das obige Beispiel w�rde alle Eintr�ge zu einer Gruppe zusammenfassen,
+die sich auf etwas Elektrisches beziehen. Benutzt man das Feld \emph{author},
+kann man sich Eintr�ge eines bestimmten Autors gruppieren lassen,
+usw. Die Suche ist als reine Textsuche oder mit einem regul�ren Ausdruck
+m�glich. Im ersten Fall erlaubt \jabref{} das manuelle Zuweisen zu
+und Entfernen aus einer Gruppe; dazu f�gt \jabref{} den Suchausdruck
+dem entsprechenden Feld zu bzw. entfernt ihn daraus. Das macht nur
+f�r das Feld \emph{keywords} oder f�r selbstdefinierte Felder Sinn,
+aber offensichtlich nicht f�r Felder wie \emph{author} oder \emph{year}.
+
+\item Einen freien Suchausdruck verwenden
+
+
+Diese Vorgehensweise ist ganz �hnlich wie die eben beschriebene, aber
+statt nur ein Feld nach einem Suchausdruck zu durchsuchen, kann hierbei
+die Syntax der Suche (siehe S.\,\pageref{SearchHelp_advanced}) angewendet
+werden, die logische Operatoren (AND, OR, NOT) und die Suche in mehreren
+Feldern gleichzeitig unterst�tzt. So fasst z.\,B. die Suchanfrage
+\texttt{keywords=Regression AND NOT keywords=linear} Eintr�ge, die
+sich mit nicht-linearer Regression besch�ftigen, zu einer Gruppe zusammen.
+
+\end{enumerate}
+In der Gruppenansicht werden dynamische Gruppen standardm��ig \emph{kursiv}
+dargestellt. Dies kann unter \menu{Optionen} \msep{} \menu{Einstellungen}
+\msep{} \menu{Gruppen} abgestellt werden.
+
+
+\paragraph*{Hierarchischer Kontext}
+
+Standardm��ig ist eine Gruppe \emph{unabh�ngig} von ihrer Position
+im Gruppenbaum. Ist eine Gruppe ausgew�hlt, wird nur der Inhalt dieser
+Gruppe angezeigt. Es ist jedoch~-- besonders beim Verwenden dynamischer
+Gruppen~-- oft n�tzlich, eine Untergruppe zu erstellen, die \emph{ihre
+Obergruppe verfeinert}.%
+\footnote{In \jabref{}~1.8.1 sind die entsprechenden Optionen noch nicht ins
+Deutsche �bersetzt. Gemeint sind hier \emph{refining (sub-)groups}.%
+} Wenn diese Untergruppe ausgew�hlt wird, werden alle Eintr�ge dieser
+Gruppe und ihrer Obergruppe angezeigt. Erstellen Sie z.\,B. eine
+Obergrupe, die Eintr�ge mit dem Stichwort \emph{Verteilung} enth�lt,
+sowie eine verfeinernde Untergruppe mit Eintr�gen, die das Stichwort
+\emph{Gau�} enthalten. Wenn Sie nun die Untergruppe ausw�hlen, werden
+alle Eintr�ge angezeigt, die beiden Bedingungen entsprechen, also
+alle, die mit Gau�'scher Verteilung zu tun haben. Indem Sie nun eine
+weitere Untergruppe f�r \emph{Laplace} anlegen, die dieselbe Obergruppe
+verfeinert, k�nnen Sie die Gruppierung einfach erweitern. Im Gruppenbaum
+haben solche Gruppen, die ihre Obergruppen verfeinern, ein spezielles
+Icon. (Dieses Verhalten kann in den Einstellungen abgestellt werden.)
+
+Das logische Gegenst�ck zu einer solchen verfeinernden Untergruppe
+ist eine Gruppe, die \emph{ihre Untergruppen ber�cksichtigt}.%
+\footnote{Im Englischen \emph{including (super-)groups}.%
+} Wird sie ausgew�hlt, werden nicht nur die Eintr�ge dieser Gruppe,
+sondern auch diejenigen aller Untergruppen angezeigt. Im Gruppenbaum
+hat auch diese Art von Gruppen ein spezielles Icon. (Dieses Verhalten
+kann in den Einstellungen abgestellt werden.)
+
+
+\subsubsection*{Eintr�ge einer Gruppe anzeigen, mehrere Gruppen kombinieren}
+
+Wenn Sie eine Gruppe ausw�hlen, werden die Eintr�ge, die dieser Gruppe
+zugeordnet sind, hervorgehoben und~-- je nach Einstellung (die mit
+einem Klick auf den \menu{Einstellungen}-Button vorgenommen werden
+kann)~-- an den Anfang der Tabelle verschoben und\slash{}oder ausgew�hlt.
+Diese Optionen entsprechen denen f�r die normale Suche (siehe Abschnitt~\ref{SearchHelp}).
+
+Wenn Sie meherere Gruppen ausw�hlen (indem Sie die STRG-Taste gedr�ckt
+halten und mehrere Gruppen anklicken), wird~-- je nach Einstellung~--
+entweder die Vereinigung oder die Schnittmenge ihrer Inhalte angezeigt.
+Damit k�nnen mehrere Bedingungen schnell miteinander kombiniert werden.
+Ein Beispiel: Wenn Sie eine statische Gruppe namens \emph{Sehr wichtig}
+haben, in der alle sehr wichtigen Eintr�ge sind, k�nnen Sie sich die
+sehr wichtigen Eintr�ge jeder anderen Gruppe anzeigen lassen, indem
+Sie beide Gruppen ausw�hlen (dazu muss \menu{Schnittmenge} in den
+Einstellungen aktiviert sein).
+
+
+\subsubsection*{Gruppen und Suche}
+
+Wenn der Inhalt einer oder mehrerer Gruppen angezeigt wird, k�nnen
+Sie eine Suche innerhalb dieser Eintr�ge durchf�hren. Benutzen Sie
+dazu die normalen Suchfunktionen (siehe Abschnitt~\ref{SearchHelp}).
+
+
+\subsubsection*{Sich �berschneidende Gruppen markieren}
+
+Der \menu{Einstellungen}-Button bietet eine Option zum Markieren
+von sich �berschneidenden Gruppen. Wenn diese Option aktiviert ist
+und Sie eine (oder mehrere) Gruppe(n) ausw�hlen, werden alle Gruppen
+markiert, die mindestens einen Eintrag enthalten, der auch der ausgew�hlten
+Gruppe zugeordnet ist. Damit k�nnen Sie schnell �berschneidungen zwischen
+den Eintr�gen verschiedener Gruppen erkennen. Sie k�nnten beispielsweise
+eine Gruppe mit dem Namen \emph{lesen} erstellen, die alle Eintr�ge
+enth�lt, die sie lesen wollen. Sobald Sie nun eine Gruppe ausw�hlen,
+wird die Gruppe \emph{lesen} markiert, sofern die ausgew�hlte Gruppe
+Eintr�ge enth�lt, die Sie noch lesen wollten.
+
+
+\subsubsection*{Erweiterte Funktionen}
+
+Wenn Sie sich mit dem oben beschriebenen Gruppenkonzept vertraut gemacht
+haben, k�nnten die folgenden erweiterten Funktionen n�tzlich sein.
+
+
+\paragraph*{Dynamische Gruppen automatisch erstellen}
+
+Mit einem Klick auf den Button \menu{Automatisch Gruppen f�r die Datei anlegen}
+k�nnen Sie ganz schnell passende Gruppen f�r Ihre Datei erzeugen.
+Diese Funktion sammelt alle W�rter eines bestimmten Felds Ihrer Wahl
+und erstellt eine Gruppe f�r jedes Wort. Das ist zum Beispiel n�tzlich,
+wenn Ihre Datei geeignete Stichworte f�r alle Eintr�ge enth�lt. Mit
+dem automatischen Erstellen von Gruppen basierend auf dem Feld \emph{keywords}
+k�nnen Sie also ohne gro�en Aufwand ein Grundger�st von Gruppen anlegen.
+
+Sie k�nnen auch Buchstaben angeben, die ignoriert werden sollen, z.\,B.
+Kommas, die zwischen einzelnen Stichworten stehen. Diese werden als
+Worttrenner behandelt und nicht als Teile des Wortes selbst. Dieser
+Schritt ist wichtig, damit kombinierte Stichworte wie etwa \emph{Gau�'sche
+Verteilung} als semantische Einheit interpretiert werden k�nnen. (Sie
+k�nnen diese Option allerdings nicht verwenden, um ganze W�rter zu
+ignorieren. Sie m�ssen stattdessen die Gruppen, die Sie nicht wollen,
+nach dem automatischen Erstellen von Hand l�schen.)
+
+
+\paragraph*{Ansicht aktualisieren}
+
+Der \menu{Aktualisieren}-Button in der Gruppenansicht aktualisiert
+die Tabelle in Bezug auf die aktuell ausgew�hlten Gruppen. Normalerweise
+erfolgt dies automatisch, aber in seltenen F�llen (z.\,B. nach einem
+R�ckg�ngig- oder Wiederholen-Vorgang, der mit Gruppen zusammenh�ngt)
+ist ein h�ndisches Aktualisieren n�tig.
+
+
+\paragraph*{Verfeinernde Untergruppen und einbeziehende Obergruppen mischen\protect%
+\footnote{In \jabref{}~1.8.1 sind die entsprechenden Optionen noch nicht ins
+Deutsche �bersetzt. Gemeint sind hier \emph{refining (sub-)groups}
+und \emph{including (super-)groups}.%
+}}
+
+Wenn eine verfeinernde Gruppe die Untergruppe von einer Gruppe ist,
+die ihre Untergruppen ber�cksichtigt~-- also sozusagen die Geschwister
+der verfeinernden Gruppe~--, dann werden diese Geschwister ignoriert,
+sobald die verfeinernde Gruppe ausgew�hlt wird.
+
+
+\subsection{Markieren von Eintr�gen}
+
+\begin{quote}
+\label{MarkingHelp}\emph{Mit der Tastenkombination STRG-M k�nnen
+Sie Eintr�ge markieren und diese Markierung mit STRG-SHIFT-M wieder
+aufheben. Diese Aktionen sind auch im Men� \menu{Bearbeiten} zu finden.}
+\end{quote}
+Das Markieren ist nicht dasselbe wie das Ausw�hlen eines Eintrags.
+Markierte Eintr�ge verhalten sich in zweierlei Hinsicht anders als
+die restlichen Eintr�ge:
+
+\begin{enumerate}
+\item Markierte Eintr�ge werden immer mit einem gelben Hintergrund in der
+Tabelle angezeigt.
+\item Markierte Eintr�ge werden an den Anfang der Eintragsliste verschoben,
+falls Ihre Tabelle nicht nach Gruppen oder aufgrund einer Suche sortiert
+ist.
+\end{enumerate}
+Wenn Sie Ihre Datei speichern, werden die Markierungen beibehalten.
+Das Markieren von Eintr�gen ist z.\,B. n�tzlich, wenn Sie verschiedene
+Suchvorg�nge durchf�hren wollen, ohne das erste Suchergebnis zu verlieren,
+oder wenn Sie sich merken wollen, welche Artikel oder B�cher Sie noch
+einmal genauer ansehen m�ssen.
+
+
+\subsection{String-Editor}
+
+\label{StringEditorHelp}
+
+\begin{quote}
+\emph{Zugriff �ber das Men� \menu{BibTeX}} \msep{} \emph{\menu{Strings bearbeiten}
+oder durch Klick auf die Schaltfl�che \menu{Strings bearbeiten}.}
+\end{quote}
+\emph{Strings} sind das Bib\TeX{}-�quivalent zu Konstanten in einer
+Programmiersprache. Jeder String wird durch einen eindeutigen \emph{Namen}
+und einen \emph{Inhalt} festgelegt. Der Name kann an anderer Stelle
+in der Datei benutzt werden, um den Inhalt wiederzugeben.
+
+Ein Beispiel: Wenn viele Eintr�ge aus einer Zeitschrift stammen, deren
+Abk�rzung schwer zu behalten ist, wie etwa >>J. Theor. Biol.<< (Journal
+of Theroretical Biology), k�nnte ein String mit dem Namen >>JTB<<
+angelegt werden, um den Namen der Zeitschrift zu repr�sentieren. Statt
+nun in jedem Eintrag den exakten Namen der Zeitschrift einzutragen,
+gen�gt die Zeichenfolge \texttt{\#JTB\#} im Feld \emph{journal}, und
+es ist sichergestellt, dass der Name jedesmal in identischer Schreibweise
+ausgegeben wird.
+
+Der Verweis auf einen String kann an jeder Stelle in einem beliebigen
+Feld erscheinen, wobei der Name des Strings immer von einem Paar \texttt{\#}-Zeichen
+eingeschlossen werden muss. Diese Syntax gilt nur f�r \jabref{} und
+weicht ein wenig von der Bib\TeX{}-Syntax ab, die erzeugt wird, wenn
+Sie Ihre Datei speichern.
+
+In derselben Weise kann man auch im Inhalt eines Strings auf einen
+anderen String verweisen, vorausgesetzt, dass der String, auf den
+verwiesen wird, bereits \emph{vorher} definiert ist.
+
+W�hrend die Reihenfolge der Strings in Ihrer Bib\TeX{}-Datei in einigen
+F�llen wichtig ist, brauchen Sie sich bei der Benutzung von \jabref{}
+dar�ber keine Gedanken zu machen. Die Strings werden in alphabetischer
+Reihenfolge im String-Editor aufgelistet und in derselben Reihenfolge
+gespeichert, au�er wenn eine andere Reihenfolge von Bib\TeX{} verlangt
+wird.
+
+
+\subsection{Wortauswahl verwalten}
+
+\label{ContentSelectorHelp}Diese Funktion erm�glicht es, eine Auswahl
+von oft benutzten W�rtern oder Phrasen zu speichern. In der Standardeinstellung
+ist sie f�r die Felder \emph{journal}, \emph{keywords} und \emph{publisher}
+aktiviert, aber Sie k�nnen die Funktion auch in anderen Feldern verwenden,
+indem Sie diese Felder im oberen Teil des Dialogs \menu{Extras} \msep{}
+\menu{Wortauswahl verwalten} hinzuf�gen.
+
+Die Wortauswahl gilt nur f�r die jeweilige Datei und wird daher zusammen
+mit den Literaturangaben in der Bib\TeX{}-Datei gespeichert. Jedes
+Feld mit Wortauswahl erh�lt im Eintrags-Editor einen gesonderten Bereich
+mit einer Auswahlliste und der Schaltfl�che \menu{Verwalten}. Wenn
+Sie die Auswahlliste mit der Maus anklicken, erscheint eine Liste
+der f�r dieses Feld verf�gbaren W�rter. Sobald Sie auf das gew�nschte
+Wort klicken, wird es in das entsprechende Feld geschrieben.
+
+Um ein neues Wort hinzuzuf�gen, schreiben Sie es einfach in das Auswahlfeld
+(�ber der Schaltfl�che \menu{Verwalten}) und dr�cken ENTER. Im Dialog
+\menu{Verwalten} k�nnen Sie hinzugef�gte W�rter auch wieder l�schen.
+
+
+\subsection{Import und Export}
+
+
+\subsubsection*{Import-Kontrollfenster}
+
+\label{ImportInspectionDialog}Beim Importieren neuer Eintr�ge aus
+einem unterst�tzten Format oder beim Herunterladen von Eintr�gen aus
+dem Internet werden diese Eintr�ge zun�chst im Import-Kontrollfenster
+gezeigt. Zu diesem Zeitpunkt wurden noch keine Eintr�ge zu einer ge�ffneten
+Datei hinzugef�gt.
+
+Im Kontrollfenster k�nnen Sie Eintr�ge entfernen, die nicht �bernommen
+werden sollen, und einige einfache Arbeiten durchf�hren wie etwa das
+Generieren von Bib\TeX{}-Keys f�r die Eintr�ge oder das Zuordnen von
+Eintr�gen zu Gruppen. Wenn Sie in eine bestehende Datei importieren,
+ist es oftmals leichter, diese Arbeiten durchzuf�hren, bevor die neuen
+Eintr�ge zwischen die bereits bestehenden sortiert wurden.
+
+
+\subsubsection*{\jabref{} $\to$~EndNote}
+
+\begin{quote}
+\label{EndnoteFilters}\emph{\jabref{} kann Dateien so exportieren,
+dass EndNote sie lesen kann. Um diese Funktion zu nutzen, w�hlen Sie
+\menu{Datei}} \msep{} \emph{\menu{Exportieren}} \msep{} \emph{\menu{Endnote}
+und w�hlen dann den Namen der Export-Datei.}
+\end{quote}
+Der Standard-EndNote-Importfilter kann nicht richtig mit mehreren
+Autoren oder Editoren umgehen. Es gibt zwei M�glichkeiten, um diese
+Schwierigkeit zu umgehen:
+
+\begin{enumerate}
+\item Benutzen Sie den eingebauten Filter und bessern Sie die Datei sp�ter
+aus.
+
+
+Um die Datei in EndNote zu �ffnen, erstellen Sie eine neue Datei oder
+�ffnen eine bestehende Datei in EndNote. Dann w�hlen Sie \menu{Datei}
+\msep{} \menu{Importieren}, klicken mit der Maus auf \menu{Datei w�hlen},
+w�hlen die aus \jabref{} exportierte Datei aus und dr�cken auf \menu{Ausw�hlen}.
+Anschlie�end dr�cken Sie auf \menu{Import Optionen} und w�hlen \menu{EndNote Import}.
+Mit einem Klick auf \menu{Importieren} starten Sie den Importvorgang.
+Anschlie�end gehen Sie zum Men�punkt \menu{Bearbeiten} \msep{} \menu{Text �ndern}
+und �ndern \emph{Any Field} in \emph{Author}. Geben Sie >>~and~<<
+in das Suchfeld ein (ohne Anf�hrungszeichen) sowie ein RETURN-Zeichen
+in das Feld �ndern (Option-Return unter Mac OS X, STRG-Return unter
+Windows XP). Dann klicken Sie auf \menu{�ndern}. Wiederholen Sie
+das Ganze f�r das Feld \emph{Secondary Author} (Zweiter Autor).
+
+\item Installieren Sie den \emph{EndNote Import from JabRef Filter}.
+
+
+Folgen Sie den Anweisungen im Abschnitt >>Erweiterte Benutzung<<
+(siehe unten, Seite~\pageref{EndNote_erweitert}). Um die Datei in
+EndNote zu �ffnen, erstellen Sie eine neue Datei oder �ffnen eine
+bestehende Datei in EndNote. Dann w�hlen Sie \menu{Datei} \msep{}
+\menu{Importieren}, klicken auf \menu{Datei w�hlen}, w�hlen die
+exportierte Datei aus und dr�cken auf \menu{Ausw�hlen}. Anschlie�end
+dr�cken Sie auf \menu{Import Optionen} und w�hlen \menu{EndNote Import from JabRef}.
+(Falls dieser Eintrag nicht erscheint, w�hlen Sie \menu{Weitere Filter}.
+Wenn er dann immer noch nicht erscheint, wurde der Filter nicht korrekt
+installiert.) Klicken Sie schlie�lich auf \menu{Importieren}, um
+den Importvorgang zu starten.
+
+\end{enumerate}
+Der EndNote Exportfilter ordnet Bib\TeX{}-Eintragstypen folgenden
+EndNote-Re\-fe\-renz\-ty\-pen zu:
+
+\medskip{}
+\begin{center}\begin{tabular}{ll}
+\textbf{Bib\TeX{}-Eintragstyp}&
+\textbf{Endnote-Referenztyp}\tabularnewline
+misc, other&
+Generic\tabularnewline
+unpublished&
+Manuscript\tabularnewline
+manual&
+Computer Program\tabularnewline
+article&
+Journal Article\tabularnewline
+book&
+Book\tabularnewline
+booklet&
+Personal Communication\tabularnewline
+inbook, incollection&
+Book Section\tabularnewline
+inproceedings&
+Conference Proceedings\tabularnewline
+techreport&
+Report\tabularnewline
+mastersthesis, phdthesis~&
+Thesis\tabularnewline
+\end{tabular} \end{center}
+\medskip{}
+
+\noindent In der Standardeinstellung geht der Exportfilter davon aus,
+dass Eintr�ge in den Feldern \emph{author} oder \emph{editor}, die
+geklammert sind, mehrere Autoren enthalten und ersetzt die Klammern
+durch ein angeh�ngtes Komma. Dadurch werden Eintr�ge, die \LaTeX{}-Befehle
+mit Klammern enthalten, als Eintrag mit mehreren Autoren gewertet
+und demzufolge unpassend formatiert.
+
+
+\subsubsection*{Erweiterte Benutzung: EndNote Extras}
+
+\label{EndNote_erweitert}Einige Felder, die von Bib\TeX{} genutzt
+werden, geh�ren nicht zu EndNotes vorgegebenen Referenztypen. W�hrend
+der Import in \jabref{} und der Export nach \jabref{} ohne ein �ndern
+der Referenztypen funktioniert, werden die Feldnamen in EndNote nicht
+korrekt dargestellt (z.\,B. wird das PDF-Feld \emph{Custom 1} hei�en
+statt \emph{pdf}). Dar�ber hinaus k�nnen diese Felder bei neuen Eintr�gen
+in EndNote nicht genutzt werden, weil sie nicht im Eintragsdialog
+erscheinen. Der vorgegebene EndNote-Importfilter kann dar�berhinaus
+das Feld \emph{author} nicht richtig analysieren. Der \emph{EndNote
+Import from JabRef Filter} kann dies. Au�erdem erkennt dieser Filter
+ein Feld \texttt{endnotereftype}, das die vorgegebene Zuordnung �berschreibt.
+Um den Filter zu installieren, extrahieren Sie die EndNote Extras
+(\menu{Datei} \msep{} \menu{Exportieren} \msep{} \menu{EndNote Filter-Set auspacken})
+und entpacken die Zip-Datei, die dabei erstellt wird. Dann folgen
+Sie den Angaben in der Datei \texttt{readme.txt}.
+
+
+\subsubsection*{EndNote $\to$~\jabref{}}
+
+EndNote hat einen Export-Stil Bib\TeX{}, der allerdings nicht alle
+Eintragstypen und Felder von Bib\TeX{} und auch nicht die zus�tzlich
+von \jabref{} genutzten Allgemeinen Felder (\emph{pdf}, \emph{owner},
+\emph{key} usw.) unterst�tzt. Falls Sie diese Felder nutzen wollen,
+extrahieren Sie die EndNote Extras (\menu{Datei} \msep{} \menu{Exportieren}
+\msep{} \menu{EndNote Filter-Set auspacken}), entpacken die Zip-Datei,
+die dabei erstellt wird und folgen den Anweisungenx in der Datei \texttt{readme.txt}.
+
+
+\subsubsection*{\jabref{} $\to$~ OpenOffice.org}
+
+\begin{quote}
+\label{OpenOfficeHelp}\menu{Datei} \msep{} \menu{Exportieren}
+\msep{} \menu{OpenOffice Calc}
+\end{quote}
+\jabref{} kann Ihre Datei in das OpenOffice.org-Tabellenkalkulationsformat
+exportieren. Die exportierte Tabelle besteht aus einem Arbeitsblatt,
+das die Eintr�ge in Reihen und die unterschiedlichen Felder in Spalten
+enth�lt. Die Tabelle ist kompatibel zu den Literaturverzeichnis-Funktionen
+von OpenOffice.org; Sie k�nnen die exportierte Tabelle unter \menu{Datenquellen}
+als Literaturdatenbank angeben.
+
+
+\subsubsection*{Klartext-Import}
+
+\begin{quote}
+\emph{Sie k�nnen aus einfachen Text-Dateien oder der Zwischenablage
+einen Importvorgang starten, indem Sie \menu{BibTeX}} \msep{} \emph{\menu{Neuer Eintrag aus Klartext}
+oder die Tastenkombination STRG-SHIFT-N w�hlen.}
+\end{quote}
+Dieser Dialog erm�glicht das schnelle Einf�gen von Eintr�gen aus normalem
+Text. W�hlen Sie zun�chst aus, welcher Eintragstyp erstellt werden
+soll. F�gen Sie dann einfach Text aus der Zwischenablage ein (mit
+dem Kontextmen� im Textfeld mit der Wasserzeichenschrift >>Text einf�gen<<
+oder �ber den Button \menu{Einf�gen}) oder w�hlen �ber den Button
+\menu{Datei �ffnen} eine Datei aus, die Sie in den Dialog laden wollen.
+
+Jetzt markieren Sie z.\,B. den Textbereich, der zum Titel des neuen
+Eintrags werden soll, und machen im rechten Teil des Dialogfensters
+im Bereich >>verf�gbare BibTeX Felder<< einen Doppelklick auf \emph{title}.
+So gehen Sie f�r alle weiteren Felder des neuen Eintrags vor. Sie
+k�nnen einem Feld nat�rlich auch mehrere Textbereiche zuordnen. Achten
+Sie dazu darauf, dass die Option \menu{anf�gen} aktiviert ist, ansonsten
+wird bei jedem neuen Zuweisen von Textbereichen das Feld �berschrieben
+(Option \menu{�berschreiben}).
+
+Bereits zugewiesene Textteile werden im Tab \menu{Importtext} blau
+hervorgehoben. Um zu kontrollieren, welche Textbereiche Sie einem
+bestimmten Bib\TeX{}-Feld zugewiesen haben, w�hlen Sie das Feld im
+rechten Bereich aus; der zugeordnete Text wird nun rot hervorgehoben.
+
+Sie k�nnen sich das Ergebnis des Importvorgangs jederzeit im Tab \menu{BibTeX Quelltext}
+des Importdialogs ansehen. Hier k�nnen keine �nderungen vorgenommen
+werden; das ist erst m�glich, sobald der Text tats�chlich importiert
+und ein neuer Eintrag angelegt wurde. Auf m�gliche Fehler werden Sie
+im Tab \menu{Hinweise und Warnungen} aufmerksam gemacht.
+
+Haben Sie alle Textstellen den gew�nschten Bib\TeX{}-Feldern zugewiesen,
+klicken Sie auf die Schaltfl�che \menu{�bernehmen}. Nun erstellt
+\jabref{} den neuen Eintrag, der allerdings noch keinen Bib\TeX{}-Key
+hat.
+
+
+\subsection{Links zu externen Dateien}
+
+\label{ExternalFiles}Mit \jabref{} k�nnen Sie Ihre Eintr�ge mit
+den entsprechenden PDF- oder PS-Dateien, die sich auf Ihrem Computer
+befinden, verlinken. Ebenso ist es m�glich, Dateien im Internet �ber
+ein URL oder DOI zu verlinken.
+
+
+\subsubsection*{Externe Betrachter einrichten}
+
+\jabref{} ben�tigt Informationen dar�ber, welche Programme es f�r
+PDF- und PS-Dateien und Internetseiten benutzen soll. In der Standardeinstellung
+werden sie auf Werte gesetzt, die wahrscheinlich zu Ihrem Betriebssystem
+passen, so dass eine gute Chance besteht, dass Sie diese Werte nicht
+zu ver�ndern brauchen.
+
+\begin{quote}
+\emph{Um die Einstellungen der externen Programme zu �ndern, �ffnen
+Sie den Unterpunkt \menu{Externe Programme} im Dialog \menu{Optionen}}
+\msep{} \emph{\menu{Einstellungen}.}
+\end{quote}
+
+\subsubsection*{Externe Dateien oder Links �ffnen}
+
+Es gibt verschiedene M�glichkeiten, wie man externe Dateien oder Internetseiten
+aus \jabref{} �ffnen kann. Im Eintrags-Editor k�nnen Sie einfach
+auf das Textfeld, das ein DOI oder URL enth�lt, doppelklicken. In
+der Tabellenansicht k�nnen Sie einen Eintrag ausw�hlen und die Men�eintr�ge
+(unter \menu{Extras}), die Tastenkombinationen (in der Standardeinstellung
+F4 f�r PDF/PS und F3 f�r DOI/URL) oder das Kontextmen� (mit der rechten
+Maustaste) benutzen, um die Datei oder Internetseite zu �ffnen. Schlie�lich
+k�nnen Sie auch auf ein PDF-, PS-, URL- oder DOI-Icon in der Tabelle
+klicken.
+
+In der Standardeinstellung zeigt die Tabellenansicht zwei Spalten
+mit Icons f�r die Eintr�ge, die mit externen Dateien oder URLs verlinkt
+sind. Beide Spalten k�nnen im Unterpunkt \menu{Tabellenansicht} des
+Dialogs \menu{Optionen} \msep{} \menu{Einstellungen} ausgeblendet
+werden. Die zweite Spalte zeigt Icons f�r PDF- oder PS-Dateien (nur
+PDF, wenn beide vorhanden sind), die dritte Spalte zeigt Icons f�r
+URL oder DOI (nur URL, wenn beide vorhanden sind).
+
+
+\subsubsection*{Der Standard-Ordner f�r PDF-Dateien}
+
+PDF-Dateien erhalten von \jabref{} eine >>Spezialbehandlung<<,
+um das Verlinken mit den entsprechenden Eintr�gen so einfach wie m�glich
+zu gestalten. Um diese >>Spezialbehandlung<< nutzen zu k�nnen, m�ssen
+Sie im Unterpunkt \menu{Externe Programme} des Dialogs \menu{Optionen}
+\msep{} \menu{Einstellungen} einen Ordner als Standard-Ordner f�r
+Ihre PDF-Dateien angeben. Alle PDF-Dateien, die in diesem Ordner oder
+einem Unterordner gespeichert sind, werden mit einer relativen Pfadangabe
+referenziert, so dass Sie problemlos PDF-Verzeichnisse verschieben
+oder mit mehreren Benutzern von verschiedenen Netzwerkarbeitspl�tzen
+aus an derselben Datei arbeiten k�nnen.
+
+Wenn Sie Ihren PDF-Dateien dann noch Namen geben, die mit dem Bib\TeX{}-Key
+des entsprechenden Eintrags �bereinstimmen (plus \texttt{.pdf} im
+Dateinamen), sucht \jabref{} in Ihrem Standard-PDF-Ordner und dessen
+Unterordnern nach der richtigen PDF-Datei. Sobald die korrekt benannte
+PDF-Datei sich dort befindet, klicken Sie auf die Schaltfl�che \menu{Auto}
+neben dem PDF-Feld im Eintrags-Editor. Wenn die PDF-Datei gefunden
+wird, wird das Feld entsprechend gesetzt.
+
+Wenn Sie eine PDF-Datei wie beschrieben benennen, k�nnen Sie sie auch
+�ffnen, ohne das PDF-Feld �berhaupt zu benutzen. Der Nachteil ist
+in diesem Fall allerdings, dass das PDF-Icon in der Tabellenansicht
+nicht angezeigt wird, solange das PDF-Feld leer bleibt.
+
+
+\subsection[JabRef und Online-Datenbanken]{\jabref{} und Online-Datenbanken}
+
+
+\subsubsection*{CiteSeer}
+
+\label{CiteSeerHelp}\jabref{} kann Informationen �ber eine bestimmte
+Literaturangabe aus der CiteSeer-Datenbank herunterladen. Um diesen
+Vorgang zu starten, f�gen Sie Ihrer Datei einen neuen Eintrag hinzu
+und belegen das Feld \emph{citeseerurl} mit einem Link zur entsprechenden
+Inhaltsseite auf CiteSeer. Das Feld \emph{citeseerurl} muss in einem
+der folgenden Formate eingegeben werden:
+
+\begin{lyxcode}
+http://citeseer.ist.psu.edu/DDDDDD{[}.html{]}\textrm{,~oder}
+
+oai:CiteSeerPSU:DDDDDD\textrm{,~oder}
+
+DDDDDD
+\end{lyxcode}
+wobei DDDDDD eine Ziffernfolge darstellt. Um diese Ziffernfolge f�r
+einen CiteSeer-Eintrag zu finden, gehen Sie auf die Dokumentseite
+der Literaturangabe des Formats \texttt{http://citeseer.ist.psu.edu/}\texttt{\emph{nameYearTitle}}\texttt{.html}
+und klicken den (Update)"=Link f�r diese Literaturangabe. Die URL
+f�r den Update-Link beinhaltet die numerische ID f�r diese Literaturangabe.
+
+Sobald Sie das Feld \emph{citeseerurl} belegt haben, k�nnen Sie die
+CiteSeer-Felder herunterladen, indem Sie \menu{BibTeX} \msep{} \menu{Felder von CiteSeer importieren}
+ausw�hlen. Achten Sie darauf, dass Sie die Zeile(n) ausgew�hlt haben,
+die Sie aktualisieren wollen.
+
+Mit einem Set von Literaturangaben k�nnen Sie eine Liste von Dokumenten
+generieren, die die Elemente dieses Sets zitieren. Dazu muss jede
+Literaturangabe in einer Datei ein \emph{citeseerurl}-Feld mit dem
+eben beschriebenen Format haben.%
+\footnote{Hinweis des �bersetzers (DW): Offen gesagt habe ich diesen Absatz
+nicht wirklich verstanden, was daran liegen mag, dass ich CiteSeer
+nicht kenne und deshalb auch die Funktionsweise nicht nachvollziehen
+kann. F�r Hinweise, Erkl�rungen oder eine bessere �bersetzung w�re
+ich deshalb dankbar.%
+}
+
+
+\subsubsection*{Medline}
+
+\begin{quote}
+\label{MedlineHelp}\jabref{} kann Literaturangaben von der Medline-Datenbank
+herunterladen. Um diese Funktion zu nutzen, w�hlen Sie \menu{Extras}
+\msep{} \menu{Medline abrufen}, so dass der Medline-Dialog im linken
+Seitenfeld erscheint.
+\end{quote}
+Es gibt zwei M�glichkeiten, die Auswahl der Eintr�ge vorzunehmen,
+die heruntergeladen werden sollen:
+
+\begin{enumerate}
+\item Geben Sie eine oder mehr Medline IDs (getrennt durch Komma/Semikolon)
+in das Textfeld ein.
+\item Geben Sie Namen oder W�rter ein, nach denen gesucht werden soll. Sie
+k�nnen dazu die Operatoren \texttt{AND} und \texttt{OR} sowie Klammern
+benutzen, um Ihren Suchbegriff zu verfeinern.
+\end{enumerate}
+In beiden F�llen dr�cken Sie dann ENTER oder die Schaltfl�che \menu{Abrufen}.
+Wenn Sie eine Textsuche durchf�hren, wird Ihnen die Anzahl der gefundenen
+Eintr�ge angezeigt, und Sie k�nnen w�hlen, wie viele Sie herunterladen
+m�chten.
+
+Die abgerufenen Eintr�ge werden Ihrer zu diesem Zeitpunkt aktivierten
+Datei zugeordnet.
+
+
+\subsubsection*{Benutzung eines Proxy-Servers}
+
+Wenn Sie einen HTTP-Proxy-Server benutzen m�ssen, �bergeben Sie den
+Servernamen und die Portnummer an Java. Diese Umgebungseinstellungen
+sind dokumentiert unter \url{http://java.sun.com/j2se/1.4.2/docs/guide/net/properties.html}
+
+\begin{lyxcode}
+java~-Dhttp.proxyHost=\char`\"{}hostname\char`\"{}
+
+-Dhttp.proxyPort=\char`\"{}portnumber\char`\"{}
+\end{lyxcode}
+
+\subsection[JabRef mit mehreren Benutzern verwenden]{\jabref{} mit mehreren Benutzern verwenden}
+
+\jabref{} bietet einige Funktionen, die besonders dann von Nutzen
+sind, wenn eine Datenbank von mehreren Benutzern~-- z.\,B. �ber
+ein Netzwerk~-- bearbeitet wird. Das sind vor allem die Felder \emph{owner}
+und \emph{timestamp}.
+
+
+\subsubsection*{Zeitstempel \emph{(timestamp)}}
+
+\begin{quote}
+\label{TimeStampHelp}\emph{Die Benutzung des Zeitstempels kann unter
+\menu{Einstellungen}} \msep{} \emph{\menu{Allgemeines} an- und
+abgestellt sowie ver�ndert werden.}
+\end{quote}
+\jabref{} kann automatisch das Feld \emph{timestamp} setzen, das
+das Datum enth�lt, an dem der Eintrag zur Datei hinzugef�gt wurde.
+Die Formatierung des Zeitstempels wird von einem Ausdruck mit Bezeichnern
+bestimmt, die die Position verschiedener Bestandteile des Datums angeben.
+Es folgen einige der verf�gbaren Bezeichner (die Beispiele in Klammern
+beziehen sich auf Mittwoch, den 14. September 2005, 17:45 Uhr):
+
+\begin{labeling}{00.00.0000}
+\item [\texttt{yy}]Jahr (05)
+\item [\texttt{yyyy}]Jahr (2005)
+\item [\texttt{MM}]Monat (09)
+\item [\texttt{dd}]Tag (14)
+\item [\texttt{HH}]Stunde (17)
+\item [\texttt{mm}]Minute (45)
+\end{labeling}
+Diese Bezeichner k�nnen mit Interpunktion und Leerzeichen kombiniert
+werden. Hier einige Beispiele:
+
+\begin{quote}
+\texttt{yyyy.MM.dd} $\to$ 2005.09.14
+
+\texttt{yy-MM-dd} $\to$ 05-09-14
+
+\texttt{yyyy.MM.dd~HH:mm} $\to$ 2005.09.14 17:45
+\end{quote}
+
+\subsubsection*{Besitzer \emph{(owner)}}
+
+\label{OwnerHelp}\jabref{} kann allen neuen Eintr�gen, die zu einer
+Datei hinzugef�gt oder in sie importiert werden, Ihren Benutzernamen
+beigeben. Diese Funktion k�nnen Sie im Men� \menu{Einstellungen}
+\msep{} \menu{Allgemein} ein- und ausschalten. Dort k�nnen Sie auch
+den Namen angeben, der in den Eintr�gen erscheinen soll.
+
+In der Standardeinstellung wird Ihr (System-)Benutzername verwendet.
+Der Name wird in dem Feld \emph{owner} eingetragen, das in der Standardeinstellung
+im Tab \emph{General fields} des Eintragseditors angezeigt wird.
+
+
+\subsection[JabRef von der Kommandozeile]{\jabref{} von der Kommandozeile}
+
+\label{CommandLine}Obwohl \jabref{} in erster Linie ein Programm
+mit grafischer Benutzeroberfl�che ist, bietet es einige n�tzliche
+Optionen f�r die Kommandozeile und kann sogar Dateikonvertierungen
+durchf�hren, ohne die grafische Benutzeroberfl�che zu �ffnen.
+
+Sie k�nnen eine oder mehrere Bib\TeX{}-Dateien laden, indem Sie auf
+der Kommandozeile die entsprechenden Dateinamen auflisten. Achten
+Sie darauf, alle gew�nschten Optionen anzugeben, bevor Sie die Dateinamen
+anf�gen. Au�erdem m�ssen Sie sich vergewissern, dass der erste Dateiname
+nicht als Argument einer Option missverstanden werden kann~-- falls
+eine Bool'sche Option wie \texttt{-n} oder \texttt{-l} direkt vor
+einem Dateinamen steht, m�ssen Sie also \texttt{true} als Argument
+angeben. Das Beispielkommando:
+
+\begin{lyxcode}
+jabref~-o~filetoexport.xml,docbook~-n~true~original.bib
+\end{lyxcode}
+l�dt die Datei \texttt{original.bib}, exportiert sie in das Docbook-Format,
+speichert sie unter dem Namen \texttt{filetoexport.xml} und unterdr�ckt
+das Laden der grafischen Oberfl�che. Das Word \emph{true} verhindert,
+dass der Dateiname als Argument der Option \texttt{-n} interpretiert
+wird.
+
+
+\subsubsection*{Kommandozeilen-Optionen}
+
+Im folgenden werden die wichtigsten Optionen und Befehle f�r die Kommandozeile
+vorgestellt.
+
+\begin{itemize}
+\item Hilfe: \texttt{-h}
+
+
+Diese Option veranlasst \jabref{}, eine Zusammenfassung der Kommandozeilen-Optionen
+anzuzeigen und das Programm unmittelbar darauf zu schlie�en.
+
+\item Kein GUI-Modus: \texttt{-n}
+
+
+Diese Option unterdr�ckt sowohl das \jabref{}-Fenster als auch den
+Er�ffnungsbildschirm, der normalerweise beim Programmstart angezeigt
+wird. Das Programm wird beendet, sobald die Kommandozeilen-Optionen
+abgearbeitet wurden.
+
+Diese Option ist n�tzlich, um Dateikonvertierungen von der Kommandozeile
+oder mit Hilfe eines Scripts durchzuf�hren.
+
+\item Sitzung laden: \texttt{-l}
+
+
+Diese Option veranlasst \jabref{}, eine gespeicherte Sitzung zu laden,
+sofern eine vorhanden ist, bevor sich das Hauptfenster �ffnet.
+
+\item Datei importieren: \texttt{-i Dateiname{[},Importformat{]}}
+
+
+Bei dieser Option importiert oder l�dt \jabref{} eine bestimmte Datei.
+Wenn nur ein Dateiname angegeben wird oder ein Komma und ein {*}-Zeichen
+hinter dem Dateinamen stehen, versucht \jabref{}, das Dateiformat
+automatisch zu erkennen. Das sollte bei allen Bib\TeX{}-Dateien ebenso
+funktionieren wie bei Dateien, die in einem der von \jabref{} unterst�tzten
+Importformate vorliegen. Wenn dem Dateinamen ein Komma und ein Importformat
+folgen, wird der angegebene Importfilter benutzt. Mit der Option \texttt{-h}
+k�nnen Sie sich eine Liste der verf�gbaren Importformate anzeigen
+lassen.
+
+Wenn Sie zus�tzlich eine Export-Option angeben, wird der Import immer
+zuerst ausgef�hrt, bevor die importierte oder geladene Datei an den
+Exportfilter �bergeben wird. Falls die grafische Oberfl�che nicht
+mit der Option \texttt{-n} unterdr�ckt wird, werden alle geladenen
+oder importierten Dateien im Hauptfenster von \jabref{} angezeigt.
+
+Die Option \texttt{-i} kann nur einmal angegeben werden und nimmt
+als Argument maximal eine Datei.
+
+\item Datei exportieren: \texttt{-o Dateiname{[},Exportformat{]}}
+
+
+Diese Option veranlasst \jabref{}, eine Datei zu speichern oder zu
+exportieren, die von derselben Kommandozeile geladen oder importiert
+wurde. Wenn eine Datei mit der Option \texttt{-i} importiert wurde,
+wird diese Datei exportiert. Ansonsten wird die Datei exportiert,
+die \emph{zuletzt}~-- ohne die Option \texttt{-i}~-- angegeben (und
+erfolgreich geladen) wurde.
+
+Wird nur ein Dateiname angegeben, so wird diese Datei im Bib\TeX{}-Format
+gespeichert. Wenn dem Dateinamen ein Komma und ein Exportformat folgen,
+wird der angegebene Exportfilter benutzt. Auf diese Weise wird auch
+ein benutzerdefinierter Exportfilter angewendet; wenn der Name sowohl
+auf einen Standard-Exportfilter, als auch auf einen benutzerdefinierten
+Exportfilter zutrifft, wird der benutzerdefinierte verwendet.
+
+Mit der Option \texttt{-h} k�nnen Sie sich eine Liste der verf�gbaren
+Exportformate anzeigen lassen.
+
+Falls die Option \texttt{-n} nicht aufgerufen wurde, wird jeder Exportvorgang
+durchgef�hrt, bevor das \jabref{}-Fenster ge�ffnet wird. Dort werden
+dann die importierten Dateien angezeigt.
+
+Die Option \texttt{-o} kann nur einmal angegeben werden und nimmt
+als Argument maximal eine Datei.
+
+\item Einstellungen exportieren: \texttt{-x Dateiname}
+
+
+Mit dieser Option k�nnen Sie \jabref{} veranlassen, alle Benutzer-Einstellungen
+in eine XML-Datei zu speichern. Nach dem Export startet \jabref{}
+normal.
+
+\item Einstellungen importieren: \texttt{-p Dateiname}
+
+
+Mit dieser Option importiert \jabref{} Benutzer-Einstellungen, die
+mit der Option \texttt{-x} exportiert wurden. Nach dem Import startet
+\jabref{} normal.
+
+\item Nur benutzte Eintr�ge exportieren: \texttt{-a Dateiname{[}.aux{]},neueBibDatei{[}.bib{]}}
+
+
+Manchmal ist es n�tzlich, eine Bib\TeX{}-Datei zu haben, die nur die
+benutzten Eintr�ge enth�lt. Eine Liste dieser benutzten Eintr�ge findet
+sich in einer .aux-Datei (sobald Sie \LaTeX{} aufgerufen haben). \jabref{}
+kann diese Datei analysieren, um eine neue Bib\TeX{}-Datei zu erstellen,
+die nur die bekannten und benutzten Eintr�ge enth�lt. Das bedeutet,
+dass ein Eintrag, der in der Standard-Bib\TeX{}-Datei nicht definiert
+ist, auch nicht in die neue Datei geschrieben werden kann.
+
+\end{itemize}
+
+\section{Anpassung}
+
+
+\subsection{Eintragstypen}
+
+\label{CustomEntriesHelp}
+
+\begin{quote}
+\emph{Um Eintragstypen anzupassen, w�hlen Sie den Men�punkt \menu{Optionen}}
+\msep{} \emph{\menu{Eintragstypen anpassen}.}
+\end{quote}
+Wenn Sie einen Eintragstyp anpassen, definieren Sie sowohl sein Erscheinungsbild
+im Eintragseditor als auch die Bedingungen, nach denen \jabref{}
+einen Eintrag als vollst�ndig akzeptiert. Sie k�nnen die bestehenden
+Eintragstypen ver�ndern und neue hinzuf�gen.
+
+Beachten Sie, dass in diesem Dialog keine �nderungen gespeichert werden,
+solange Sie nicht auf \menu{�bernehmen} oder \menu{OK} klicken.
+Wenn Sie \menu{Abbrechen} anklicken oder einfach den Dialog schlie�en,
+gehen die bislang nicht �bernommenen �nderungen verloren.
+
+
+\subsubsection*{Der Dialog \menu{Eintragstypen anpassen}}
+
+Der Dialog \menu{Eintragstypen anpassen} ist in drei Hauptbereiche
+unterteilt. Im linken Bereich k�nnen Sie den Eintragstyp ausw�hlen,
+den Sie bearbeiten wollen, und neue Eintragstypen hinzuf�gen. Im mittleren
+Bereich werden die Einstellungen f�r die ben�tigten Felder des ausgew�hlten
+Eintragstyps vorgenommen und im rechten Bereich diejenigen der optionalen
+Felder.
+
+
+\subsubsection*{Eintragstypen hinzuf�gen und l�schen}
+
+Die derzeit verf�gbaren Eintragstypen werden im linken Bereich des
+Dialogfensters aufgelistet. Wenn Sie einen Eintragstyp ausw�hlen,
+werden die anderen Bereiche aktualisiert und zeigen die ben�tigten
+und optionalen Felder dieses Eintragstyps.
+
+Um einen neuen Eintragstyp hinzuzuf�gen, geben Sie einfach seinen
+Namen in das Textfeld unter der Typliste ein und klicken \menu{Hinzuf�gen}.
+Der neue Eintragstyp wird zur Liste hinzugef�gt und zur Bearbeitung
+ausgew�hlt.
+
+Um einen eigenen Eintragstyp zu entfernen, w�hlen Sie ihn aus und
+klicken auf \menu{L�schen}. Dieser Vorgang ist nur f�r eigene Eintragstypen
+verf�gbar, die nicht nur Abwandlungen der Standard-Typen sind. Die
+Standard-Eintragstypen k�nnen nicht gel�scht werden.
+
+Um einem Eintragstyp seinen Standardwert zur�ckzugeben, w�hlen Sie
+ihn aus und dr�cken auf \menu{Standard}. Dieser Vorgang ist nur f�r
+Standard-Typen verf�gbar, die bearbeitet wurden.
+
+
+\subsubsection*{Eintragstypen bearbeiten}
+
+Wenn ein Eintragstyp ausgew�hlt ist, werden die derzeitigen ben�tigten
+und optionalen Felder im mittleren und rechten Bereich des Dialogfensters
+aufgelistet. Das Vorgehen beim Bearbeiten dieser Listen ist f�r die
+ben�tigten und optionalen Felder identisch.
+
+Um ein neues Feld hinzuzuf�gen, bearbeiten Sie das Textfeld unterhalb
+der Liste oder w�hlen einen Feldnamen aus dem Dropdown-Men� und klicken
+auf \menu{Hinzuf�gen}. Der gew�hlte Feldname erscheint am Ende der
+Liste.
+
+Um eines oder mehrere Felder zu l�schen, w�hlen Sie sie in der Liste
+aus und klicken auf \menu{L�schen}. Die Reihenfolge der Felder k�nnen
+Sie �ndern, indem Sie einen Feldnamen ausw�hlen und die Pfeiltasten
+benutzen, um das Feld nach oben oder nach unten zu verschieben.
+
+Es gibt eine Beschr�nkung beim Anpassen der Eintragstypen; bestimmte
+Typen haben eine und/oder-Bedingung in ihren ben�tigten Feldern. Ein
+\emph{book}-Eintrag ist beispielsweise komplett, wenn entweder das
+Feld \emph{author} oder \emph{editor} oder beide gesetzt sind. Diese
+Art von Bedingung kann in einem angepassten Eintragstyp nicht realisiert
+werden.
+
+
+\subsection{Allgemeine Felder festlegen}
+
+\label{GeneralFields}Sie k�nnen dem Eintragseditor eine beliebige
+Anzahl von Tabs hinzuf�gen, die bei allen Eintragstypen sichtbar sind.
+W�hlen Sie dazu den Men�eintrag \menu{Optionen} \msep{} \menu{Allgemeine Felder festlegen}.
+
+Jede Zeile repr�sentiert einen Tab. Der Anfang der Zeile steht f�r
+den Namen des Tabs, gefolgt von einem Doppelpunkt. Anschlie�end listen
+Sie die einzelnen Felder auf, die der Tab enthalten soll, und trennen
+sie jeweils durch ein Semikolon.
+
+Das Beispiel
+
+\begin{lyxcode}
+Allgemeine~Felder:url;keywords;doi;pdf
+
+Zusammenfassung:abstract;annote
+\end{lyxcode}
+ergibt somit einen Tab mit dem Namen >>Allgemeine Felder<<, der
+die Felder \emph{url}, \emph{keywords}, \emph{doi} und \emph{pdf}
+enth�lt, sowie einen zweiten Tab namens >>Zusammenfassung<< mit
+den Feldern \emph{abstract} und \emph{annote}.
+
+
+\subsection{Automatische Erstellung von Bib\TeX{}-Keys}
+
+\begin{quote}
+\label{LabelPatterns}Im Tab \menu{Key-Muster} des Dialogs \menu{Einstellungen}
+kann man die Felder bestimmen, die zur automatischen Generierung der
+Bib\TeX{}-Keys herangezogen werden.
+\end{quote}
+Standardm��ig verwendet \jabref{} ein vorgegebenes Muster (default
+pattern) zur Generierung von Bib\TeX{}-Keys, das Keys wie z.\,B.
+\texttt{Yared1998} erzeugt. Falls der Bib\TeX{}-Key in der ge�ffneten
+Datei nicht eindeutig sein sollte, wird einer der Buchstaben a-z angef�gt,
+bis ein eindeutiger Key gefunden ist. Dementsprechend k�nnten die
+Labels wie folgt aussehen:
+
+\begin{lyxcode}
+Yared1998
+
+Yared1998a
+
+Yared1998b
+
+\textrm{\ldots{}}
+
+\end{lyxcode}
+\jabref{} verwendet Feldmarken, um das Aussehen der Bib\TeX{}-Keys
+zu bestimmen. Das Key-Muster kann f�r jeden der vorgegebenen Eintragstypen
+bestimmt werden. Es kann beliebigen Text enthalten, unabh�ngig von
+und zus�tzlich zu den Feldmarken, die angeben, dass ein bestimmtes
+Feld des Eintrags an dieser Stelle des Keys eingef�gt werden soll.
+Eine Feldmarke besteht gew�hnlich aus dem Feldnamen in eckigen Klammern,
+z.\,B. \texttt{{[}volume{]}}. Wenn dieses Feld zum Zeitpunkt der
+Erstellung des Keys leer ist, wird kein Text eingef�gt.
+
+Es gibt au�erdem mehrere spezielle Feldmarken, die nur einen bestimmten
+Teil aus einem Feld extrahieren. Sie werden unten aufgelistet. Nat�rlich
+k�nnen Sie auch neue spezielle Feldmarken vorschlagen.
+
+
+\subsubsection*{Spezielle Feldmarken}
+
+\begin{labeling}{veryveryveryshorttitle}
+\item [\texttt{{[}auth{]}}]Der Nachname des ersten Autors.
+\item [\texttt{{[}authors{]}}]Die Nachnamen aller Autoren.
+\item [\texttt{{[}authorsN{]}}]Die Nachnamen von bis zu N Autoren. Falls
+es mehr Autoren gibt, wird EtAl angeh�ngt.
+\item [\texttt{{[}authIniN{]}}]Der Anfang des Nachnamens von jedem Autoren,
+wobei nicht mehr als N Buchstaben verwendet werden.
+\item [\texttt{{[}authorIni{]}}]Die ersten 5 Buchstaben des Nachnamens
+des ersten Autors und die Initialen der Nachnamen der restlichen Autoren.
+\item [\texttt{{[}authN{]}}]Die ersten N Buchstaben des Nachnamens des
+ersten Autors.
+\item [\texttt{{[}authN\_M{]}}]Die ersten N Buchstaben des Nachnamens des
+M-ten Autors.
+\item [\texttt{{[}auth.auth.ea{]}}]Die Nachnamen der beiden ersten Autoren
+und \texttt{.ea}, falls es mehr als zwei Autoren sind.
+\item [\texttt{{[}authshort{]}}]Der Nachname bei einem Autor; der erste
+Buchstabe der Nachnamen von bis zu drei Autoren, falls mehr als ein
+Autor vorhanden ist. Ein Plus (+) wird angeh�ngt, falls es mehr als
+drei Autoren gibt.
+\end{labeling}
+
+\tip[Anmerkung:]{Falls es keinen Autor gibt (z.B. bei einem Buch mit Herausgeber), benutzen die genannten \texttt{{[}auth...{]}}-Feldmarken den oder die Herausgeber, die im editor-Feld angegeben wurden. Also werden die Herausgeber eines Buches ohne Autor f�r die Label-Erstellung wie Autoren behandelt. Falls Sie dieses Verhalten nicht w�nschen und die Feldmarke stattdessen bei einem leeren author-Feld zu nichts expandieren soll, m�ssen Sie stattdessen >>pureauth<< verwenden, z.B.: \texttt [...]
+
+\begin{labeling}{veryveryveryshorttitle}
+\item [\texttt{{[}edtr{]}}]Der Nachname des ersten Herausgebers.
+\item [\texttt{{[}editors{]}}]Die Nachnamen aller Herausgeber.
+\item [\texttt{{[}edtrIniN{]}}]Der Anfang des Nachnamens von jedem Herausgeber,
+wobei nicht mehr als N Buchstaben verwendet werden.
+\item [\texttt{{[}editorIni{]}}]Die ersten 5 Buchstaben des Nachnamens
+des Herausgebers und die Initialen der Nachnamen der restlichen Herausgeber.
+\item [\texttt{{[}edtrN{]}}]Die ersten N Buchstaben des Nachnamens des
+ersten Herausgebers.
+\item [\texttt{{[}edtrN\_M{]}}]Die ersten N Buchstaben des Nachnamens des
+M-ten Herausgebers.
+\item [\texttt{{[}edtr.edtr.ea{]}}]Der Nachname der ersten beiden Herausgeber
+und \texttt{.ea}, falls es mehr als zwei Herausgeber sind.
+\item [\texttt{{[}edtrshort{]}}]Der Nachname bei einem Herausgeber; der
+erste Buchstabe der Nachnamen von bis zu drei Herausgebern, falls
+mehr als ein Herausgeber vorhanden ist. Ein Plus (+) wird angeh�ngt,
+falls es mehr als drei Herausgeber gibt.
+\item [\texttt{{[}firstpage{]}}]Die erste Seitenzahl einer Ver�ffentlichung
+(pages).
+\item [\texttt{{[}lastpage{]}}]Die letzte Seitenzahl einer Ver�ffentlichung
+(pages).
+\item [\texttt{{[}shorttitle{]}}]Die ersten 3 Worte eines Titels (title).
+\item [\texttt{{[}shortyear{]}}]Die letzten 2 Ziffern des Jahrgangs (year).
+\item [\texttt{{[}veryshorttitle{]}}]Die ersten beiden Worte des Titels
+(title), wobei >>the<<, >>a<< und >>an<< ausgelassen werden.
+\end{labeling}
+Hinter einem Feldnamen (oder einem der oben aufgef�hrten Pseudo-Feldnamen)
+kann ein Modifikator stehen. Modifikatoren werden in der Reihenfolge
+angewendet, in der sie angegeben wurden.
+
+\begin{labeling}{00.00.0000}
+\item [\texttt{:abbr}]K�rzt den Text, der von einem Feldnamen oder speziellen
+Feldmarken gebildet wird. Nur der erste Buchstabe und weitere Buchstaben,
+die auf ein Leerzeichen folgen, werden ber�cksichtigt. Zum Beispiel
+w�rde \texttt{{[}journal:}~\\
+\texttt{abbr{]}} die Zeitschrift >>Jorunal of Fish Biology<< zu
+>>JoFB<< wandeln.
+\item [\texttt{:lower}]Wandelt den von der Feldmarke eingef�gten Text in
+Kleinbuchstaben. So wird beispielsweise bei \texttt{{[}auth:lower{]}}
+der Nachname des ersten Autors in Kleinbuchstaben ausgegeben.
+\end{labeling}
+Das Standard-Key-Muster, das Bib\TeX{}-Keys wie \texttt{Yared1998}
+erzeugt, ist \texttt{{[}auth{]}{[}year{]}}. Wenn Sie keine Key-Muster
+f�r einen bestimmten Eintragstyp angeben, wird dieses vorgegebene
+Muster verwendet. Sie k�nnen das vorgegebene Muster nat�rlich ebenfalls
+anpassen~-- seine Einstellung befindet sich �ber der Liste der Eintragstypen
+im Tab \menu{Key-Muster} des Dialogs \menu{Einstellungen}.
+
+Beachten Sie, dass \jabref{} Umlaute und Buchstaben mit Akzenten
+sowie das � beim Erstellen von Bib\TeX{}-Keys ver�ndert, um m�glichen
+Problemen vorzubeugen. Hierzu einige Beispiele:
+
+\begin{lyxcode}
+D�az~Iba�ez~$\to$~DiazIbanez
+
+Str�mb�ck~$\to$~Stroembaeck
+
+Wa�enhoven~$\to$~Wassenhoven
+
+\textrm{usw.}
+\end{lyxcode}
+
+\subsubsection*{Ersetzen eines Regul�ren Ausdrucks}
+
+Nachdem das Key-Muster angewendet wurde, um einen Bib\TeX{}-Key zu erstellen, k�nnen Sie den Key-Generator nach einem bestimmten Regul�ren Ausdruck suchen und ihn durch eine Zeichenfolge ersetzen lassen. Der Regul�re Ausdruck und die Zeichenfolge, die ihn ersetzen soll, werden in den Textfeldern unter der Liste der Key-Muster eingegeben. Falls das Feld zur Ersetzung des Regul�ren Ausdrucks leer ist, werden die mit der Suche �bereinstimmenden Regul�ren Ausdr�cke einfach gel�scht.
+
+\subsection{Erscheinungsbild}
+
+\begin{comment}
+fehlende Punkte:
+-- Tabellendarstellung
+-- Toolbar
+-- Panels
+\end{comment}
+\tip[Hinweis: ]{Dieser Abschnitt ist noch vorl�ufig. Es sind Beschreibungen zur Tabellendarstellung, zur Toolbar, den Panels und der Verwendung von Schriften geplant.}
+
+
+\subsubsection{Eintragsvorschau}
+
+\label{PreviewHelp}Die Eintragsvorschau wird mit denselben Mechanismen
+erstellt, die auch bei den Exportfiltern 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
+am unteren Bildschirmrand angezeigt wird.
+
+Aussehen und Inhalt der Vorschau k�nnen mit derselben Syntax ver�ndert
+werden, die f�r die Anpassung der Exportfilter verwendet wird (siehe
+Abschnitt~\ref{CustomExports}).
+
+\begin{comment}
+fehlende Punkte:
+-- Schriften
+\label{sub:Erscheinungsbild_Schriften}
+\end{comment}
+
+\subsection{Exportfilter}
+
+\label{CustomExports}Mit \jabref{} k�nnen Sie Ihre eigenen Exportfilter
+definieren und genau so wie die Standard-Exportfilter benutzen. Ein
+Exportfilter wird durch eine oder mehrere \emph{Layout-Dateien} definiert,
+die mittels eingebauter Formatierprogramme das Format der exportierten
+Dateien festlegen. Ihre Layout-Datei m�ssen Sie in einem separaten
+Texteditor erstellen.
+
+
+\subsubsection*{Hinzuf�gen eines Exportfilters}
+
+Die einzige Voraussetzung f�r einen Exportfilter ist, da� eine Datei
+mit der Endung \texttt{.layout} vorhanden ist. Um einen neuen, eigenen
+Exportfilter hinzuzuf�gen, �ffnen Sie das Dialogfenster \menu{Optionen}
+\msep{} \menu{Verwalte externe Exportfilter} und klicken auf die
+Schaltfl�che \menu{Neu}. Es �ffnet sich ein neues Fenster, in dem
+Sie einen Namen (der im Men� \menu{Datei} \msep{} \menu{Externe Exportfilter}
+angezeigt wird), eine Pfadangabe zur \texttt{.layout}-Datei und die
+gew�nschte Dateiendung f�r den Exportfilter angeben k�nnen. Wenn Sie
+den Exportfilter benutzen, wird diese Endung im Datei-Dialog automatisch
+vorgeschlagen.
+
+
+\subsubsection*{Das Erstellen des Exportfilters}
+
+Um einen Eindruck zu bekommen, wie Exportfilter auszusehen haben,
+suchen Sie am besten auf unserer Homepage nach dem Paket, das die
+Layout-Dateien der Standard-Exportfilter enth�lt.
+
+Nehmen wir einmal an, dass wir einen HTML-Exportfilter erstellen wollen.
+Der Exportfilter muss lediglich aus einer einzigen \texttt{.layout}-Datei
+bestehen, die in diesem Fall \texttt{html.layout} genannt werden k�nnte.
+Sie k�nnen dar�ber hinaus auch zwei Dateien mit den Namen \texttt{html.begin.layout}
+und \texttt{html.end.layout} anlegen. Die erste dieser beiden Dateien
+enth�lt den Kopfteil der Ausgabe, die zweite den Fu�teil. \jabref{}
+sucht jedes Mal, wenn der Exportfilter benutzt wird, nach diesen Dateien
+und f�gt sie~-- falls sie gefunden werden~-- w�rtlich vor bzw. nach
+den einzelnen Eintr�gen in die Ausgabe ein.
+
+\tip[]{Beachten Sie, dass sich diese Dateien in demselben Verzeichnis
+wie \texttt{html.layout} befinden und die Namensbestandteile \texttt{.begin}
+bzw. \texttt{.end} enthalten m�ssen.}
+
+\noindent In unserem Beispiel-Exportfilter k�nnten diese Dateien folgenderma�en
+aussehen:
+
+\begin{lyxcode}
+\textrm{html.begin.layout:}
+
+<HTML>
+
+<BODY~text=\char`\"{}\#275856\char`\"{}>
+
+<basefont~size=\char`\"{}4\char`\"{}~color=\char`\"{}\#2F4958\char`\"{}~face=\char`\"{}arial\char`\"{}>
+
+~
+
+\textrm{html.end.layout:}
+
+</BODY>
+
+</HTML>
+\end{lyxcode}
+Die Datei \texttt{html.layout} stellt die \emph{Standard}-Formatvorlage
+f�r den Export eines einzelnen Eintrags bereit. Falls Sie unterschiedliche
+Formatvorlagen f�r verschiedene Eintragstypen anwenden wollen, m�ssen
+Sie Eintrags-spezifische \texttt{.layout}-Dateien erstellen. Diese
+m�ssen sich ebenfalls in demselben Verzeichnis wie die Haupt-Layout-Datei
+befinden und den Namensbestandteil \texttt{.entrytype} enthalten.
+Der Name des Eintragstyps muss komplett in Kleinbuchstaben geschrieben
+werden. In unserem Beispiel wollen wir eine Formatvorlage f�r Eintr�ge
+des Typs \emph{book} haben, die in der Datei \texttt{html.book.layout}
+abgelegt wird. F�r eine Dissertation w�rden wir die Datei \texttt{html.phdthesis.layout}
+anlegen~-- und so weiter. Diese Dateien sind der Standard-Layout-Datei
+sehr �hnlich, nur dass sie lediglich f�r Eintr�ge des entsprechenden
+Typs genutzt werden. Achten Sie darauf, dass die Standard-Layout-Datei
+so allgemein gehalten wird, dass sie die meisten Eintragstypen abdeckt.
+
+
+\paragraph*{Das Format der Layout-Datei}
+
+Layout-Dateien werden mit einem einfachen markup-Format erstellt,
+bei dem die Kommandos mit einem >>backslash<< (\texttt{\textbackslash{}})
+eingeleitet werden. Alle Textbestandteile, die nicht als Kommando
+identifiziert werden, gelangen direkt in die Ausgabedatei.
+
+
+\paragraph*{Feldkommandos}
+
+Ein beliebiges Wort, vor dem ein backslash steht, z.\,B. \texttt{\textbackslash{}author},
+\texttt{\textbackslash{}editor,} \texttt{\textbackslash{}title} oder
+\texttt{\textbackslash{}year}, wird als Verweis auf das entsprechende
+Feld ausgewertet, das dann direkt in die Ausgabe kopiert wird.
+
+
+\paragraph*{Feldformatierer}
+
+Oft muss der Feldinhalt vor der Ausgabe verarbeitet werden. Dies wird
+mit Hilfe eines \emph{Feldformatierers} gemacht~-- einer java class,
+die eine Methode zur Verarbeitung des Feldinhaltes enth�lt.
+
+Ein Formatierer wird angewendet, indem man das Kommando \texttt{\textbackslash{}format}
+gefolgt vom Namen des Formatierers in eckigen Klammern und dem Feldnamen
+in geschweiften Klammern einf�gt, z.\,B.:
+
+\begin{lyxcode}
+\textbackslash{}format{[}ToLowerCase{]}\{\textbackslash{}author\}
+\end{lyxcode}
+Sie k�nnen auch mehrere Formatierer angeben, getrennt durch Kommas.
+Diese werden nacheinander aufgerufen, und zwar von links nach rechts.
+Das Kommando
+
+\begin{lyxcode}
+\textbackslash{}format{[}ToLowerCase,HTMLChars{]}\{\textbackslash{}author\}
+\end{lyxcode}
+ruft z.\,B. zun�chst den Formatierer \emph{ToLowerCase} auf, \emph{HTMLChars}
+formatiert anschlie�end das Ergebnis. Auf diese Weise k�nnen Sie eine
+beliebige Anzahl an Formatierern auflisten.
+
+\jabref{} bietet die folgenden Formatierer, wobei einige von anderen
+abh�ngen:
+
+\begin{labeling}{veryveryveryshorttitle}
+\item [\texttt{HTMLChars}]ersetzt \TeX{}-spezifische Sonderzeichen wie
+\texttt{\{\textbackslash{}\textasciicircum{}a\}} oder \texttt{\{\textbackslash{}\char`\"{}\{o\}\}}
+durch ihre HTML-Entsprechungen.
+\item [\texttt{XMLChars}]ersetzt \TeX{}-spezifische Sonderzeichen wie \texttt{\{\textbackslash{}\textasciicircum{}a\}}
+oder \texttt{\{\textbackslash{}\char`\"{}\{o\}\}} durch ihre XML-Entsprechungen.
+\item [\texttt{CreateDocBookAuthors}]formatiert das author-Feld im DocBook-Stil.
+\item [\texttt{AuthorFirstFirst}]formatiert die Felder \emph{author}/\emph{editor}
+mit den Vornamen zuerst.
+\item [\texttt{AuthorFirstFirstCommas}]formatiert die Felder \emph{author}/\emph{editor}
+mit den Vornamen zuerst und abgetrennt durch Kommas.
+\item [\texttt{AuthorLastFirst}]formatiert die Felder \emph{author}/\emph{editor}
+mit den Nachnamen zuerst.
+\item [\texttt{AuthorLastFirstAbbreviator}]k�rzt die Vornamen aller Autoren.
+Dieser Formatierer kann nur angewendet werden, wenn \texttt{AuthorLastFirst}
+bereits benutzt wurde.
+\item [\texttt{AuthorAndsReplacer}]ersetzt >>and<< zwischen den Namen
+durch >>;<<, zwischen den letzten beiden Autoren steht >>\&<<.
+\item [\texttt{AuthorAndsCommaReplacer}]ersetzt >>and<< zwischen den
+Namen durch ein Komma (,) sowie >>\&<< zwischen den beiden letzten.
+\item [\texttt{FormatPagesForHTML}]ersetzt >>\texttt{-{}-}<< durch >>\texttt{-}<<.
+\item [\texttt{FormatPagesForXML}]ersetzt >>\texttt{-{}-}<< durch einen
+XML en-dash (>>--<<).
+\item [\texttt{RemoveBrackets}]entfernt alle geschweiften Klammern (>>\{<<
+und >>\}<<).
+\item [\texttt{RemoveLatexCommands}]entfernt \LaTeX{} Kommandos wie \texttt{\textbackslash{}em},
+\texttt{\textbackslash{}textbf} etc. Zusammen mit \texttt{HTMLChars}
+oder \texttt{XMLChars} sollte dieser Formatierer zuletzt aufgerufen
+werden.
+\item [\texttt{ToLowerCase}]macht aus allen Buchstaben Kleinbuchstaben.
+\end{labeling}
+Falls keiner der verf�gbaren Formatierer das Ergebnis erzielt, das
+Sie erreichen m�chten, k�nnen Sie Ihren eigenen Formatierer hinzuf�gen,
+indem Sie das \texttt{net.sf.jabref.ex\allowbreak port.layout.LayoutFormatter}-Interface
+implementieren. Wenn Sie Ihre Klasse (class) in das Paket \texttt{net.sf.jabref.export.}\allowbreak \texttt{layout.format}
+einf�gen, k�nnen Sie den Formatierer mit seinem Klassennamen aufrufen,
+so wie auch die Standard-Formatierer. Ansonsten m�ssen Sie den Formatierer
+mit seinem vollen Namen aufrufen (inklusive Paketname). In jedem Fall
+muss der Formatierer in ihrem classpath sein, wenn Sie \jabref{}
+starten.
+
+
+\paragraph*{Bedingte Ausgabe}
+
+Manche statische Ausgabe macht nur Sinn, wenn ein bestimmtes Feld
+nicht leer ist. Wenn wir z.\,B. hinter den Namen der Editoren den
+Text \texttt{(Hrsg.)} haben wollen, brauchen wir Folgendes:
+
+\begin{lyxcode}
+\textbackslash{}format{[}HTMLChars,AuthorFirstFirst{]}\{\textbackslash{}editor\}~(Hrsg.)
+\end{lyxcode}
+Wenn nun aber das \emph{editor}-Feld leer ist~-- m�glicherweise ist
+es f�r den Eintrag, der exportiert werden soll, nicht erforderlich~--,
+dann w�rde das \texttt{(Hrsg.)} dennoch erscheinen. Das kann man mit
+den Kommandos \texttt{\textbackslash{}begin} und \texttt{\textbackslash{}end}
+verhindern:
+
+\begin{lyxcode}
+\textbackslash{}begin\{editor\}
+
+\textbackslash{}format{[}HTMLChars,AuthorFirstFirst{]}\{\textbackslash{}editor\}~(Hrsg.)
+
+\textbackslash{}end\{editor\}
+\end{lyxcode}
+Die Kommandos \texttt{\textbackslash{}begin} und \texttt{\textbackslash{}end}
+sorgen daf�r, dass der Text, den sie einschlie�en, nur dann ausgegeben
+wird, falls das Feld, auf das in den geschweiften Klammern verwiesen
+wird, f�r den zu exportierenden Eintrag definiert und damit nicht
+leer ist.
+
+\tip{Das Benutzen der Kommandos \texttt{\textbackslash{}begin} und
+\texttt{\textbackslash{}end} ist ein Schl�ssel zum Erstellen von Layout-Dateien,
+die mit einer Vielzahl von Eintragstypen umgehen k�nnen.}
+
+
+\paragraph*{Gruppierte Ausgabe}
+
+Wenn Sie Ihre Eintr�ge auf der Basis eines bestimmten Feldes gruppieren
+wollen, benutzen Sie die Kommandos f�r die gruppierte Ausgabe. Die
+gruppierte Ausgabe ist der bedingten Ausgabe sehr �hnlich, au�er dass
+der Text zwischen den Kommandos nur ausgegeben wird, wenn das Feld,
+auf das in den geschweiften Klammern verwiesen wird, unterschiedliche
+Werte enth�lt.
+
+Nehmen wir zum Beispiel an, dass wir die Ausgabe nach dem \emph{keyword}
+(Stichwort) gruppieren wollen. Bevor die Datei exportiert wird, m�ssen
+die Eintr�ge nach dem \emph{keyword} sortiert worden sein. Dann benutzen
+Sie die folgenden Kommandos, um nach \emph{keyword} zu gruppieren:
+
+\begin{lyxcode}
+\textbackslash{}begingroup\{keywords\}
+
+New~Category:~\textbackslash{}format{[}HTMLChars{]}\{\textbackslash{}keywords\}
+
+\textbackslash{}endgroup\{keywords\}
+\end{lyxcode}
+
+\subsubsection*{Teilen Sie Ihre Arbeit mit anderen}
+
+Mit externen Layout-Dateien ist es einfach, Ihre eigenen Export-Formate
+mit anderen Anwendern gemeinsam zu benutzen. Falls Sie einen Exportfilter
+f�r ein Format erstellen, das nicht von \jabref{} unterst�tzt wird,
+oder falls Sie einen bestehenden Exportfilter verbessern, m�chten
+wir Sie ermutigen, Ihre Arbeit auf der SourceForge.net-Seite bereitzustellen.
+Dasselbe gilt f�r Formatierklassen, die Sie schreiben. Wir w�rden
+uns freuen, eine Sammlung von bereitgestellten Layout-Dateien verteilen
+zu k�nnen oder die Standard-Export-Filter und Standard-Formatierer
+zu erweitern.
+
+
+\section{Externe Importfilter}
+
+\jabref{} bietet Ihnen die M�glichkeit, ganz �hnlich den Standard-Importern, eigene Importer 
+zu definieren und zu benutzen. Man definiert einen Importer durch eine oder mehrere Java
+\emph{Klassen}, die Dateiinhalte aus einem sogenannten \emph{Input stream} lesen
+und daraus Bib\TeX{}-Eintr�ge erzeugen. Sie k�nnen vorkompilierte Importer einbinden, die Sie vielleicht 
+von SourceForge erhalten haben (siehe Abschnitt >>Ihre Arbeit anderen zur Verf�gung stellen<<, 
+S.\,\pageref{subsec:Ihre-Arbeit}). Sie k�nnen auch
+mit Grundkenntnissen der Java-Programmierung eigene Importer f�r f�r Sie wichtige Referenzquellen 
+erstellen oder neue, verbesserte Versionen existierender Importer einbinden, ohne \jabref{} neu zu
+kompilieren.
+
+\paragraph*{Vorrangsregeln}
+
+Externe Importfilter haben Vorrang vor Standard-Importern. So k�nnen Sie mit Ihren Importern
+die existierenden in der automatischen Formaterkennung und an der Kommandozeile in \jabref{} �berschreiben.
+Externe Importfilter selbst sind dann nach Namen sortiert.
+
+\subsection{Einen externen Importfilter hinzuf�gen}
+
+Stellen Sie sicher, dass Sie den Importer in kompilierter Form haben (eine oder mehrere
+\texttt{.class} Dateien) und dass die Klassendateien
+in einer Verzeichnisstruktur entsprechend ihrer Package-Struktur liegen. 
+Um einen neuen externen Importfilter hinzuzuf�gen, �ffnen Sie den Dialog 
+\menu{Optionen} \msep{} \menu{Verwalte externe Importfilter}, und klicken Sie auf
+\menu{Aus Klassenpfad hinzuf�gen}. Ein Dateiauswahl-Fenster erscheint, 
+mit dem Sie den Klassenpfad des Importers w�hlen, dass hei�t den obersten Ordner,
+in dem die Package-Struktur Ihres Importers beginnt. In einem zweiten Dateiauswahl-Fenster
+w�hlen Sie die \emph{.class}-Datei Ihres Importers, die von \texttt{\textbackslash{}ImportFormat} abgeleitet
+ist. Wenn Sie \menu{Klasse ausw�hlen} klicken, erscheint Ihr neuer Importer
+in der Liste der externen Importfilter. Alle externen Importfilter erscheinen in den
+\jabref{}-Untermen�s \menu{Datei} \msep{} \menu{Importieren} \msep{} \menu{Externe Importfilter} und 
+\menu{Datei} \msep{} \menu{Importieren und Anh�ngen} \msep{} \menu{Externe Importfilter}.
+
+\tip[Bitte beachten Sie: ]{Wenn Sie die Klassen in ein anderes Verzeichnis verschieben,
+m�ssen Sie den Importer entfernen und neu hinzuf�gen. Wenn Sie einen Importfilter
+mit einem bereits vorhandenen Namen registrieren, ersetzt \jabref{} den vorhandenen
+externen Importfilter. Auch wenn es in manchen F�llen m�glich ist, einen schon registrierten
+Importer zu aktualisieren ohne \jabref{} neu zu starten (n�mlich dann,
+wenn der Importer nicht im Klassenpfad von \jabref{} ist), empfehlen wir, grunds�tzlich
+\jabref{} neu zu starten, wenn Sie ein Update eines externen Importers durchgef�hrt haben.
+Sie k�nnen auch Importer aus ZIP- oder JAR-Archiven registrieren, w�hlen Sie einfach
+\emph{\menu{Aus Archiv-Datei hinzuf�gen}}, dann das ZIP- oder JAR-Archiv und dann den Eintrag
+(Klassendatei), der den neuen Importer darstellt.}
+
+\subsection{Einen Importfilter entwickeln}
+
+Bitte schauen Sie auf unseren Download-Seiten nach Beispielen und n�tzlichen Dateien zur 
+Entwicklung Ihres Importfilters.
+
+\subsubsection{Ein einfaches Beispiel}
+
+Angenommen, wir wollen Dateien der folgenden Form importieren:
+\begin{lyxcode}
+1936;John Maynard Keynes;The General Theory of Employment, Interest and Money
+
+2003;Boldrin \& Levine;Case Against Intellectual Monopoly
+
+2004;ROBERT HUNT AND JAMES BESSEN;The Software Patent Experiment
+\end{lyxcode}
+
+\paragraph*{SimpleCsvImporter Erstellen}
+
+Erzeugen Sie in einem Text-Editor eine von \texttt{ImportFormat} abgeleitete Klasse,
+die die Methoden \texttt{getFormatName()}, 
+\texttt{isRecognizedFormat()}
+und \texttt{importEntries()} implementiert. Hier ein Beispiel:
+\begin{lyxcode}
+import java.io.*;
+
+import java.util.*;
+
+import net.sf.jabref.*;
+
+import net.sf.jabref.imports.ImportFormat;
+
+import net.sf.jabref.imports.ImportFormatReader;
+
+~
+
+public class SimpleCsvImporter extends ImportFormat {
+
+~
+
+  public String getFormatName() {
+
+    return "{}Simple CSV Importer";
+
+  }
+
+~
+
+  public boolean isRecognizedFormat(InputStream stream) throws IOException {
+
+    return true; // this is discouraged except for demonstration purposes
+
+  }
+  
+~
+
+  public List importEntries(InputStream stream) throws IOException {    
+
+  	ArrayList bibitems = new ArrayList();
+
+    BufferedReader in = new BufferedReader(ImportFormatReader.getReaderDefaultEncoding(stream));
+      
+~
+
+    String line = in.readLine();
+
+    while (line != null) {
+
+      if (!"{}"{}.equals(line.trim())) {
+
+        String[] fields = line.split(";");
+
+        BibtexEntry be = new BibtexEntry(Util.createNeutralId());
+
+        be.setType(BibtexEntryType.getType("techreport"));
+
+        be.setField("year", fields[0]);
+
+        be.setField("{}author", fields[1]);
+
+        be.setField("title", fields[2]);
+
+        bibitems.add(be);
+
+        line = in.readLine();
+
+      }     
+
+    }
+
+  	return bibitems;	  	
+
+  }
+
+}
+\end{lyxcode}
+
+\paragraph*{SimpleCsvImporter �bersetzen}
+
+Beachten Sie, dass die Beispielklasse im Default"=Package liegt. Angenommen, Sie haben
+sie unter \texttt{/meinpfad/SimpleCsvImporter.java} gespeichert. Nehmen wir weiter an,
+die Datei \texttt{JabRef-2.0.jar} ist im gleichen Verzeichnis wie
+\texttt{SimpleCsvImporter.java} und Java ist in Ihrem Kommandopfad. 
+Kompilieren Sie die Klasse mit JSDK 1.4 zum Beispiel mit folgendem Kommandozeilen"=Aufruf: 
+\begin{lyxcode}
+javac -classpath JabRef-2.0.jar SimpleCsvImporter.java
+\end{lyxcode}
+Nun sollte dort auch eine Datei \texttt{/mypath/SimpleCsvImporter.class} liegen.
+
+\paragraph*{SimpleCsvImporter registrieren}
+
+�ffnen Sie in \jabref{} \menu{Optionen} \msep{} \menu{Verwaltung externer Importfilter} und klicken Sie
+auf \menu{Aus Klassenpfad hinzuf�gen}. Navigieren Sie nach \texttt{/meinpfad} und 
+klicken Sie \menu{Klassenpfad ausw�hlen}. W�hlen Sie dann die Datei \texttt{SimpleCsvImporter.class}
+und klicken Sie \menu{Klasse ausw�hlen}. Ihr Importfilter sollte nun in der Liste der
+externen Importfilter unter dem Namen >>Simple CSV Importer<< erscheinen und,
+sobald Sie \menu{Schlie�en} gew�hlt haben, auch in den Untermen�s \menu{Datei} \msep{} \menu{Importieren} \msep{} 
+\menu{Externe Importfilter} und \menu{Datei} \msep{} \menu{Importieren und Anh�ngen} \msep{} \menu{Externe Importfilter} 
+des \jabref{}-Hauptfensters auftauchen.
+
+\subsection{Ihre Arbeit anderen zur Verf�gung stellen}
+\label{subsec:Ihre-Arbeit}
+Mit externen Importfiltern ist es recht einfach, Importfilter zwischen Nutzern auszutauschen und
+gemeinsam zu nutzen. Wenn Sie einen Importer f�r ein  Format schreiben, das \jabref{} noch nicht unterst�tzt, 
+oder einen Importer verbessern, bitten wir Sie, Ihre Ergebnisse auf unserer SourceForge.net 
+Seite zu ver�ffentlichen. Wir bieten gerne eine Sammlung eingereichter Importfilter an oder 
+f�gen sie unserer Auswahl an Standard-Importfiltern hinzu.
+
+
+\section{Tastenk�rzel}
+
+Die Men�s k�nnen alle �ber Tastenk�rzel angesteuert werden, die meisten
+Men�befehle ebenfalls. Das ist immer am unterstrichenen Buchstaben
+sichtbar.
+
+Es folgt ein �berblick �ber die wichtigsten Tastenk�rzel ohne Anspruch
+auf Vollst�ndigkeit~\ldots{}
+
+\begin{longtable}{p{66mm}p{33mm}}
+\textbf{Datei (Forts.)}&
+\tabularnewline
+\endhead
+\textbf{Datei}&
+\tabularnewline
+\endfirsthead
+Datei �ffnen&
+STRG-O\tabularnewline
+Datei speichern&
+STRG-S\tabularnewline
+Datei speichern unter~\ldots{}&
+STRG-SHIFT-S\tabularnewline
+Datei schlie�en&
+STRG-W\tabularnewline
+Sitzung speichern&
+F11\tabularnewline
+Sitzung laden&
+F12\tabularnewline
+\jabref{} beenden&
+STRG-Q\tabularnewline
+\end{longtable}
+
+\begin{longtable}{p{66mm}p{33mm}}
+\textbf{Bearbeiten (Forts.)}&
+\tabularnewline
+\endhead
+\textbf{Bearbeiten}&
+\tabularnewline
+\endfirsthead
+Neuer Eintrag&
+STRG-N\tabularnewline
+Neuer Eintrag -- Article&
+STRG-SHIFT-A\tabularnewline
+Neuer Eintrag -- Book&
+STRG-SHIFT-B\tabularnewline
+Neuer Eintrag -- Phdthesis&
+STRG-SHIFT-T\tabularnewline
+Neuer Eintrag -- Inbook&
+STRG-SHIFT-I\tabularnewline
+Neuer Eintrag -- Mastersthesis&
+STRG-SHIFT-M\tabularnewline
+Neuer Eintrag -- Proceedings&
+STRG-SHIFT-P\tabularnewline
+Neuer Eintrag -- Unpublished&
+STRG-SHIFT-U\tabularnewline
+Neuer Eintrag aus Klartext&
+STRG-SHIFT-N\tabularnewline
+Eintrag bearbeiten&
+STRG-E\tabularnewline
+Bib\TeX{}-Keys generieren&
+STRG-G\tabularnewline
+R�ckg�ngig&
+STRG-Y\tabularnewline
+Wiederholen&
+STRG-Z\tabularnewline
+Ausschneiden&
+STRG-X\tabularnewline
+Kopieren&
+STRG-C\tabularnewline
+Einf�gen&
+STRG-V\tabularnewline
+L�schen&
+Entf\tabularnewline
+Alles ausw�hlen&
+STRG-A\tabularnewline
+\texttt{\textbackslash{}cite\{BibTeX-Key\}} kopieren&
+STRG-K\tabularnewline
+Eintr�ge markieren&
+STRG-M\tabularnewline
+Markierung l�schen&
+STRG-SHIFT-M\tabularnewline
+Pr�ambel bearbeiten&
+STRG-P\tabularnewline
+Strings bearbeiten&
+STRG-T\tabularnewline
+\end{longtable}
+
+\begin{longtable}{p{66mm}p{33mm}}
+\textbf{Ansicht / Navigation (Forts.)}&
+\tabularnewline
+\endhead
+\textbf{Ansicht / Navigation}&
+\tabularnewline
+\endfirsthead
+Zur n�chsten ge�ffneten Datei springen&
+STRG-Bild ab\tabularnewline
+Zum vorherigen TAB springen&
+STRG-Bild auf\tabularnewline
+Gruppendialog ein-/ausblenden&
+STRG-SHIFT-G\tabularnewline
+Eintragsvorschau ein-/ausblenden&
+STRG-F9\tabularnewline
+Layout der Eintragsvorschau wechseln&
+F9\tabularnewline
+\end{longtable}
+
+\begin{longtable}{p{66mm}p{33mm}}
+\textbf{Externe Programme / Internet (Forts.)}&
+\tabularnewline
+\endhead
+\textbf{Externe Programme / Internet}&
+\tabularnewline
+\endfirsthead
+Literaturangaben in \LyX{} einf�gen&
+STRG-L\tabularnewline
+Literaturangaben in WinEdt einf�gen&
+STRG-SHIFT-W\tabularnewline
+URL/DOI �ffnen&
+F3\tabularnewline
+PDF/PS �ffnen&
+F4\tabularnewline
+PDF-Links synchronisieren&
+SHIFT-F4\tabularnewline
+PS-Links synchronisieren&
+STRG-F4\tabularnewline
+Medline abrufen&
+F5\tabularnewline
+CiteSeer abrufen&
+F6\tabularnewline
+Literaturangaben von CiteSeer abrufen&
+F7\tabularnewline
+\end{longtable}
+
+\begin{longtable}{p{66mm}p{33mm}}
+\textbf{Extras / Sonstiges (Forts.)}&
+\tabularnewline
+\endhead
+\textbf{Extras / Sonstiges}&
+\tabularnewline
+\endfirsthead
+Suchen&
+STRG-F\tabularnewline
+Weitersuchen&
+STRG-SHIFT-F\tabularnewline
+Suchen \& Ersetzen&
+STRG-R\tabularnewline
+Hilfe&
+F1\tabularnewline
+\end{longtable}
+
+
+\section{Entwicklung}
+
+\jabref{} ist ein \emph{Open Source} Projekt, das hei�t, dass jede(r)
+dazu beitragen kann, das Programm zu verbessern und weiterzuentwickeln.
+Wenn Sie Anregungen, W�nsche oder Fragen haben, ist die erste Anlaufstelle
+die \href{http://sourceforge.net/projects/jabref/}{Projektseite bei \emph{Sourceforge}}.
+Dort gibt es Foren, in denen Sie Ihre Fragen stellen k�nnen, und eine
+Mailingliste rund um \jabref{}. Auch Ihre W�nsche \emph{(Feature
+Requests)} und Fehlermeldungen \emph{(Bug Reports)} k�nnen Sie dort
+loswerden. Um sich direkt als Entwickler einzubringen, wenden Sie
+sich an einen der beiden Maintainer (Morten O. Alver und Nizar N.
+Batada)~-- die E-Mail-Adressen finden Sie auf der Projektseite bei
+\emph{Sourceforge}. Sie brauchen lediglich einen Sourceforge-Login,
+der dann f�r das Projekt freigeschaltet werden kann.
+
+
+\subsection{Beschr�nkungen und bekannte Probleme (Bugs)}
+
+\begin{quote}
+\emph{Dieses Handbuch befindet sich noch in der Entstehungsphase.
+Bitte sehen Sie auf der} \emph{\href{http://sourceforge.net/projects/jabref/}{Projektseite bei Sourceforge}
+nach, welche bekannten Probleme bei \jabref{} auftreten k�nnten.}
+\end{quote}
+
+\subsection[Die Zukunft von JabRef]{Die Zukunft von \jabref{}}
+
+Hier sollen einige Punkte aufgef�hrt werden, die in einer der n�chsten
+Versionen von \jabref{} verwirklicht werden k�nnten, z.\,B. die
+\emph{Anpassung der Tastenk�rzel}.
+
+
+\subsection{Danksagung}
+
+Neben den Entwicklern, die die Hilfe-Seiten des Programms geschrieben
+haben, m�chte ich Thomas Fritz f�r seine hilfreichen Tipps und
+Anregungen zum Handbuch danken.
+
+Seit den Anf�ngen als \emph{BibKeeper} und \emph{JBibtexManager} haben
+zahlreiche Personen dazu beigetragen, das \jabrefversion{} zu dem
+geworden ist, was es ist. Erster Dank geb�hrt nat�rlich den Initiatoren
+Morten O. Alver und Nizar N. Batada. Das Entwicklerteam (Michel Baylac,
+Guillaume Gardey, Cyrille d'Haese, Raik Nagel, Ellen Reitmayr, Michael
+Spiegel, Ulrik Stervbo, Dominik Wa�enhoven, Joerg K. Wegner, Michael
+Wrighton, Egon Willighagen und J�rg Zieren) dankt auch den Beitr�gen
+von Kolja Brix, Fr�d�ric Darboux, Fabrice Dessaint, Nathan Dunn, Alexis
+Gallagher, Sascha Hunold, Bernd Kalbfuss, Martin K�hmer, Jeffrey Kuhn,
+Alex Montgomery, John Relph, Moritz Ringler, Rudolf Seemann, Mike
+Smoot, Martin Stolle, David Weitzman und Seb Wills. Weiterer Dank
+geht an Samin Muhammad Ridwanul Karim und Stefan Robert.
+
+
+\subsection{Lizenz}
+
+\jabref{} ist frei verf�gbar unter den Bedingungen der \href{http://www.gnu.org/copyleft/gpl.html}{GNU Public License}.
+
+
+\subsubsection*{Benutzte Fremdsoftware}
+
+\jabref{} benutzt JGoodies Looks 1.2.2 und JGoodiesForms 1.0.4, das
+von \href{http://www.jgoodies.com}{JGoodies} unter den Bedingungen
+der \href{http://www.opensource.org/licenses/bsd-license.html}{BSD License}
+vertrieben wird. Au�erdem werden zwei zust�tzliche Klassen (SimpleInternalFrame and UIFSplitPane) von Karsten Lentzsch benutzt. Kommandozeilenbefehle werden geparst mit \href{http://ritopt.sourceforge.net}{RitOpt},
+das unter den Bedingungen der GNU Public License (Version 2) verf�gbar
+ist. \jabref{} verwendet f�r die Suche den ANTLR Parser Generator.
+ANTLR ist \emph{public domain software}~-- siehe \href{http://www.antlr.org/license.html}{http://www.antlr.org/license.html}
+f�r die Lizenzbedingungen. F�r die Darstellung und Filterung der Tabelle benutzt \jabref{} die \href{http://publicobject.com/glazedlists}{Glazed Lists library}, die unter den Bedingungen der \href{http://www.opensource.org/licenses/lgpl-license.php}{LGPL}
+(Lesser GNU Public License) vertrieben wird. \jabref{} benutzt dar�ber hinaus die \emph{threading
+library} Spin 1.3.1, die unter den Bedingungen der \href{http://www.opensource.org/licenses/lgpl-license.php}{LGPL} vertrieben wird. Das hier beschriebene
+Produkt beinhaltet Software, die von der \href{http://www.apache.org}{Apache Software Foundation}
+entwickelt wurde. Die Bibliotheken \emph{Commons Logging} und \emph{Commons
+HTTP Client} werden von \href{http://jakarta.apache.org}{The Jakarta Project}
+unter der \href{http://opensource.org/licenses/apachepl.php}{Apache Software Lizenz}
+(Version 1.1) vertrieben.
+
+Einige Icons sind von uns, aber die meisten stammen vom \href{http://www.eclipse.org}{Eclipse Projekt},
+das unter den Bedingungen der \href{http://www.opensource.org/licenses/cpl.php}{Common Public License}
+vertrieben wird, sowie vom \href{http://qt.osdn.org.ua}{QIcons Paket},
+das unter den Bedingungen der \href{http://www.gnu.org/copyleft/gpl.html}{GNU Public License}
+vertrieben wird.
+
+\begin{comment}
+M�glicherweise ans Ende eine FAQ anschlie�en
+-- Ich kann nicht programmieren, kann ich trotzdem zum Projekt beitragen?
+-- Wie installiere ich neue Schriften?
+   Siehe \ref{sub:Erscheinungsbild_Schriften}.
+\end{comment}
+\appendix
+\newpage
+\bibliographystyle{jurabib}
+\bibliography{JabRef-UserManual_de}
+
+
+
+\newpage
+\section*{Versionsgeschichte}
+
+\label{RevisionHistory}
+
+\subsection*{Version 0.3 (zu \jabref{} 2.0, Stand: 16.\,1.\,2006)}
+\begin{revhist}
+\item Abschnitt zur Erzeugung der Bib\TeX{}-Keys aktualisiert
+\item Neues Kapitel (>>Externe Importfilter<<), geschrieben von Andreas Rudert
+\item Einige kleinere �nderungen
+\end{revhist}
+
+\subsection*{Version 0.2 (6.\,12.\,2005)}
+%\renewcommand{\labelitemi}{}
+
+\begin{revhist}
+\item Lizenzbedingungen f�r das Handbuch hinzugef�gt
+\item von PDF~1.4 auf PDF~1.2 umgestellt
+\item mehrere kleinere �nderungen
+\end{revhist}
+
+\subsubsection*{Version 0.1 (16.\,11.\,2005)}
+\begin{revhist}
+\item Erstentwurf von Dominik Wa�enhoven, basierend
+auf dem unver�ffentlichten englischen \emph{Initial Draft} von Nizar Batada (20.\,2.\,2004)
+und den Hilfeseiten des Programms
+\end{revhist}
+
+\end{document}
\ No newline at end of file
diff --git a/src/help/de/JabRefHelp.html b/src/help/de/JabRefHelp.html
new file mode 100644
index 0000000..d421b2b
--- /dev/null
+++ b/src/help/de/JabRefHelp.html
@@ -0,0 +1,20 @@
+<HTML>
+
+<BODY text="#275856">
+
+<basefont size="4" color="#2F4958" face="arial">
+
+<H1>JabRef</H1>
+
+<P><strong>Anmerkung:</strong> Das Programm <em>BibTeX</em> wird in den Hilfedateien h�ufig erw�hnt. <em>BibTeX</em> ist ein Hilfsprogramm zur Erstellung bibliographischer Angaben in LaTeX-Dokumenten, das Oren Patashnik entwickelt hat. Dasselbe Dateiformat wird von CiteMaker benutzt, einem Hilfsprogramm zur Erstellung von Bibliographien mit Adobe FrameMaker.
+
+<P>JabRef ist ein Programm zur Verwaltung von <em>BibTeX</em>-Dateien. Es benutzt kein eigenes Dateiformat, d.h. dass Sie Ihre Dateien direkt im <em>BibTeX</em>-Format (Dateiendung .bib) laden und speichern. Sie k�nnen aber auch bibliographische Datenbanken in anderen Formaten in JabRef importieren. 
+
+<P>JabRef unterst�tzt Sortier- und Suchfunktionen, um einen �berblick �ber den Inhalt Ihrer Datei zu bekommen. Sie k�nnen der Datei ganz einfach neue Eintr�ge hinzuf�gen, ohne sich daran erinnern zu m�ssen, welche Informationen ben�tigt werden. Au�erdem kann JabRef <em>BibTeX</em> keys automatisch generieren. 
+JabRef ist sehr n�tzlich, wenn Sie <em>BibTeX</em> oder CiteMaker benutzen, kann aber auch f�r diejenigen sinnvoll sein, die andere Bibliographie-Systeme benutzen oder schlicht und einfach ihre Literaturquellen organisieren wollen.
+
+<P>
+<a href="BaseFrameHelp.html">Das Hauptfenster von JabRef</a>
+
+</BODY>
+</HTML>
diff --git a/src/help/de/LabelPatterns.html b/src/help/de/LabelPatterns.html
new file mode 100644
index 0000000..886cd22
--- /dev/null
+++ b/src/help/de/LabelPatterns.html
@@ -0,0 +1,89 @@
+<HTML>
+
+<BODY text="#275856">
+
+<basefont size="4" color="#2F4958" face="arial">
+
+<H1>Anpassen der automatischen Erstellung von BibTeX-Keys</H1>
+
+Im Tab "Key-Muster" im Dialog "Einstellungen" kann man  die Felder bestimmen, die
+zur automatischen Generierung der BibTeX-Labels (bibtexkey) herangezogen werden.
+Das Muster kann für jeden der vorgegebenen Eintragstypen bestimmt werden.
+<P>
+<h2>Key-Muster</h2>
+Das Muster kann beliebigen Text enthalten, unabhängig von und zusätzlich zu
+den Feldmarken, die angeben, dass ein bestimmtes Feld des Eintrags an dieser Stelle des
+Keys eingefügt werden soll. Eine Feldmarke besteht gewöhnlich aus dem
+Feldnamen in eckigen Klammern, z.B. <b>[volume]</b>. Wenn dieses Feld zum Zeitpunkt
+der Erstellung des Keys leer ist, wird kein Text eingefügt.
+<P>
+Es gibt außerdem mehrere spezielle Feldmarken, die nur einen bestimmten Teil aus einem
+Feld extrahieren. Sie werden unten aufgelistet. Natürlich können Sie auch neue
+spezielle Feldmarken vorschlagen.
+
+<P>
+Spezielle Feldmarken:
+<ul>
+<li><b>[<code>auth</code>]</b>: Der Nachname des ersten Autors.<BR>
+<li><b>[<code>authors</code>]</b>: Die Nachnamen aller Autoren.<BR>
+<li><b>[<code>authorsN</code>]</b>: Die Nachnamen von bis zu N Autoren. Falls es mehr Autoren gibt, wird EtAl angehängt.<BR>
+<li><b>[<code>authIniN</code>]</b>: Der Anfang des Nachnamens von jedem Autoren,
+	wobei nicht mehr als N Buchstaben verwendet werden.<BR>
+<li><b>[<code>authorIni</code>]</b>: Die ersten 5 Buchstaben des Nachnamens des ersten Autors
+	und die Initialen der Nachnamen der restlichen Autoren.<BR>
+<li><b>[<code>authN</code>]</b>: Die ersten N Buchstaben des Nachnamens des ersten Autors.<BR>
+<li><b>[<code>authN_M</code>]</b>: Die ersten N Buchstaben des Nachnamens des M. Autors.<BR>
+<li><b>[<code>auth.auth.ea</code>]</b>: Die Nachnamen der beiden ersten Autoren und ".ea", falls
+	es mehr als zwei Autoren sind.<BR>
+<li><b>[<code>authshort</code>]</b>: Der Nachname bei einem Autor; der erste Buchstabe der Nachnamen von bis zu drei Autoren, falls mehr als ein Autor vorhanden ist. Ein Plus (+) wird angehängt, falls es mehr als drei Autoren gibt.<BR></ul>
+<b>Anmerkung:</b>Falls es keinen Autor gibt (z.B. bei einem Buch mit Herausgeber), benutzen die genannten [auth...]-Feldmarken den oder die Herausgeber, die im editor-Feld angegeben wurden. Also werden die Herausgeber eines Buches ohne Autor für die Label-Erstellung wie Autoren behandelt. Falls Sie dieses Verhalten nicht wünschen und die Feldmarke stattdessen bei einem leeren author-Feld zu nichts expandieren soll, müssen Sie <b>pureauth</b> statt <b>auth</b> verwenden, z. [...]
+<ul>
+<li><b>[<code>edtr</code>]</b>: Der Nachname des ersten Editors.<BR>
+<li><b>[<code>editors</code>]</b>: Die Nachnamen aller Editoren.<BR>
+<li><b>[<code>edtrIniN</code>]</b>: Der Anfang des Nachnamens von jedem Editor,
+	wobei nicht mehr als N Buchstaben verwendet werden.<BR>
+<li><b>[<code>editorIni</code>]</b>: Die ersten 5 Buchstaben des Nachnamens des Editors
+	und die Initialen der Nachnamen der restlichen Editoren.<BR>
+<li><b>[<code>edtrN</code>]</b>: Die ersten N Buchstaben des Nachnamens des ersten Editors.<BR>
+<li><b>[<code>edtrN_M</code>]</b>: Die ersten N Buchstaben des Nachnamens des M. Editors.<BR>
+<li><b>[<code>edtr.edtr.ea</code>]</b>: Der Nachname der ersten beiden Editoren
+	und ".ea", falls es mehr als zwei Editoren sind.<BR>
+<li><b>[<code>edtrshort</code>]</b>: Der Nachname bei einem Editor; der erste Buchstabe der Nachnamen von bis zu drei Editoren, falls mehr als ein Editor vorhanden ist. Ein Plus (+) wird angehängt, falls es mehr als drei Editoren gibt.<BR>
+<li><b>[<code>firstpage</code>]</b>: Die erste Seitenzahl einer Veröffentlichung (pages).<BR>
+<li><b>[<code>lastpage</code>]</b>: Die letzte Seitenzahl einer Veröffentlichung (pages).<BR>
+<li><b>[<code>shorttitle</code>]</b>: Die ersten 3 Worte eines Titels (title).<BR>
+<li><b>[<code>shortyear</code>]</b>: Die letzten 2 Ziffern des Jahrgangs (year).<BR>
+<li><b>[<code>veryshorttitle</code>]</b>: Die ersten beiden Worte des Titels (title), wobei 'the', 'a' und
+	'an' ausgelassen werden.<BR>
+ </ul>
+
+<P>
+Hinter einem Feldnamen (oder einem der oben aufgeführten Pseudo-Feldnamen) kann ein
+Modifikator stehen. Modifikatoren werden in der Reihenfolge angewendet, in der sie angegeben wurden.
+<ul>
+<li><b>:abbr</b>: Kürzt den Text, der von einem Feldnamen oder speziellen Feldmarken gebildet wird. Nur der erste Buchstabe und weitere Buchstaben, die auf ein Leerzeichen folgen, werden berücksichtigt. Zum Beispiel würde <b>[journal:abbr]</b> die Zeitschrift "Jorunal of Fish Biology" zu "JoFB" wandeln.<br>
+<li><b>:lower</b>: Wandelt den von der Feldmarke eingefügten Text in Kleinbuchstaben. So wird beispielsweise bei <b>[auth:lower]</b> der Nachname des ersten Autors in Kleinbuchstaben ausgegeben.
+<P>
+Wenn Sie keine Key-Muster für einen bestimmten Eintragstyp angeben, wird das vorgegebene
+Muster (default pattern) verwendet. Sie können das vorgegebene Muster natürlich ebenfalls
+anpassen - seine Einstellung befindet sich über der Liste der Eintragstypen im Tab <b>Key-Muster</b>
+des Dialogs <b>Einstellungen</b>.
+
+<P>
+Das vorgegebene Key-Muster ist [auth][year], das Keys wie z.B. <code>Yared1998</code> generiert.
+Falls der Key in der geöffneten Datei nicht eindeutig sein sollte, wird einer der Buchstaben
+a-z angefügt, bis ein eindeutiger Key gefunden ist. Dementsprechend könnten die Labels
+wie folgt aussehen:
+
+<blockquote> <code>Yared1998</code><BR> <code>Yared1998a</code><BR>
+<code>Yared1998b</code> </blockquote>
+
+<h2>Ersetzen eines Regulären Ausdrucks</h2>
+
+Nachdem das Key-Muster angewendet wurde, um einen BibTeX-Key zu erstellen, können Sie den Key-Generator nach einem bestimmten Regulären Ausdruck suchen und ihn durch eine Zeichenfolge ersetzen lassen. Der Reguläre Ausdruck und die Zeichenfolge, die ihn ersetzen soll, werden in den Textfeldern unter der Liste der Key-Muster eingegeben.
+
+Falls das Feld zur Ersetzung des Regulären Ausdrucks leer ist, werden die mit der Suche übereinstimmenden Regulären Ausdrücke einfach gelöscht.
+
+</font>
+</BODY>
+</HTML>
\ No newline at end of file
diff --git a/src/help/de/MarkingHelp.html b/src/help/de/MarkingHelp.html
new file mode 100644
index 0000000..b8fda43
--- /dev/null
+++ b/src/help/de/MarkingHelp.html
@@ -0,0 +1,24 @@
+<HTML>
+
+<BODY text="#275856">
+<basefont size="4" color="#2F4958" face="arial">
+
+<H1>Einträge markieren</H1>
+
+Mit der Tastenkombination STRG-M können Sie Einträge <em>markieren</em> und diese
+Markierung mit STRG-SHIFT-M wieder aufheben. Diese Aktionen sind auch im Menü "Bearbeiten" zu finden.
+
+<p>Das Markieren ist nicht dasselbe wie das Auswählen eines Eintrags. Markierte Einträge verhalten
+sich in zweierlei Hinsicht anders als die restlichen Einträge:
+<ol>
+	<li>Markierte Einträge werden immer mit einem gelben Hintergrund in der Tabelle angezeigt.</li>
+	<li>Markierte Einträge werden an den Anfang der Eintragsliste verschoben, falls Ihre Tabelle
+	nicht nach Gruppen oder aufgrund einer Suche sortiert ist.</li>
+</ol>
+
+<p>Wenn Sie Ihre Datei speichern, werden die Markierungen beibehalten.
+
+<p>Das Markieren von Einträgen ist z.B. nützlich, wenn Sie verschiedene Suchvorgänge durchführen wollen,
+ohne das erste Suchergebnis zu verlieren, oder wenn Sie sich merken wollen, welche Artikel oder Bücher Sie 
+noch einmal genauer ansehen müssen.
+</HTML>
diff --git a/src/help/de/MedlineHelp.html b/src/help/de/MedlineHelp.html
new file mode 100644
index 0000000..a299758
--- /dev/null
+++ b/src/help/de/MedlineHelp.html
@@ -0,0 +1,34 @@
+<HTML>
+
+<BODY text="#275856">
+<basefont size="4" color="#2F4958" face="arial">
+
+<H1>Einträge von Medline abrufen</H1>
+
+JabRef kann Literaturangaben von der Medline-Datenbank herunterladen. Um diese Funktion
+zu nutzen, wählen Sie <b>Extras -> Medline abrufen</b>, so dass der Medline-Dialog
+im linken Seitenfeld erscheint.
+<P>
+Es gibt zwei Möglichkeiten, die Auswahl der Einträge vorzunehmen, die heruntergeladen werden sollen:
+
+<ol>
+<li> Geben Sie eine oder mehr Medline IDs (getrennt durch Komma/Semikolon) in das Textfeld ein.
+<li> Geben Sie Namen oder Wörter ein, nach denen gesucht werden soll. Sie können dazu die Operatoren
+<em>and</em> und <em>or</em> sowie Klammern benutzen, um Ihren Suchbegriff zu verfeinern.
+</ol>
+
+In beiden Fällen drücken Sie dann <b>Enter</b> oder die Schaltfläche <b>Abrufen</b>.
+Wenn Sie eine Textsuche durchführen, wird Ihnen die Anzahl der gefundenen Einträge angezeigt, und
+Sie können wählen, wie viele Sie herunterladen möchten.
+
+<p>Die abgerufenen Einträge werden Ihrer zu diesem Zeitpunkt aktivierten Datei zugeordnet.
+
+<H2>Benutzung eines Proxy-Servers</H2>
+
+Wenn Sie einen HTTP-Proxy-Server benutzen müssen, übergeben Sie den Servernamen und die Portnummer
+an Java. Diese Umgebungseinstellungen sind dokumentiert unter
+ <p> http://java.sun.com/j2se/1.4.2/docs/guide/net/properties.html
+
+<p><code>java -Dhttp.proxyHost="hostname" -Dhttp.proxyPort="portnumber"</code>
+
+</HTML>
diff --git a/src/help/de/OpenOfficeHelp.html b/src/help/de/OpenOfficeHelp.html
new file mode 100644
index 0000000..24544a0
--- /dev/null
+++ b/src/help/de/OpenOfficeHelp.html
@@ -0,0 +1,46 @@
+<HTML>
+
+<BODY text="#275856">
+<basefont size="4" color="#2F4958" face="arial">
+
+<H1>JabRef-Bibliographien in OpenOffice.org benutzen</H1>
+
+JabRef kann Ihre Datei sowohl in das OpenOffice.org 1.1 <b>.sxc</b>-Tabellenkalkulationsformat als auch in das OpenDocument <b>.ods</b>-Tabellenkalkulationsformat, das von OpenOffice.org 2.0 benutzt wird, exportieren.
+<p>
+In beiden fällen besteht die exportierte Tabelle aus einem Arbeitsblatt, das die Einträge in Reihen
+und die unterschiedlichen Felder in Spalten enthält. Die Reihenfolge und Bennung der Spalten ist kompatibel
+zu den Literaturverzeichnis-Funktionen von OpenOffice.org (OOo 1.1: <b>.sxc</b>, OOo 2.0: <b>.ods</b>).
+
+<h2>Die exportierte Datei als Bibliographiedatenbank in OpenOffice 2.0 (oder neuer) benutzen</h2>
+Gehen Sie folgendermaßen vor, um eine Tabelle, die von JabRef exportiert wurde, als Bibliographiedatenbank in OpenOffice.org zu benutzen:
+
+<ul>
+    <li>Exportieren Sie Ihre Datenbank in das <b>.ods</b> -Format</li>
+    <li>Starten Sie OpenOffice.org</li>
+    <li>Wählen Sie <b>Extras -> Optionen -> OpenOffice.org Base -> Datenbanken</b></li>
+    <li>Bearbeiten Sie die <i>Bibliography</i>-Datenbank und ändern ihren Namen z.B. in <i>Bibliographie-alt</i></li>
+    <li>Schließen Sie das Fenster <b>Optionen</b> und gehen Sie zu <b>Datei -> Neu -> Datenbank</b></li>
+    <li>Wählen Sie <b>Verbindung zu einer bestehenden Datenbank herstellen</b>, wählen <b>Tabellendokument</b> als
+    Datenbanktyp und wählen die <b>.ods</b>-Datei, die Sie exportiert haben</li>
+    <li>Klicken Sie auf <b>Fertig stellen</b> und wählen den Namen <i>Bibliography</i> im Speicherdialog</li>
+</ul>
+Anschließend wählen Sie <b>Extras -> Literaturdatenbank</b>. Ihre Datenbank sollte nun angezeigt werden.
+<p>
+
+<h2>Eine exportierte Datei als Datenbank in OpenOffice 1.1.x benutzen</h2>
+
+ <ul>
+    <li>Exportieren Sie Ihre Datei in das <b>.sxc</b>-Format</li>
+    <li>Starten Sie OpenOffice.org</li>
+    <li>Wählen Sie <b>Extras -> Datenquellen</b></li>
+    <li>Wählen Sie die <i>Bibliography</i>-Datei und ändern ihren Namen z.B. in <i>Bibliographie-alt</i></li>. Drücken Sie <b>Anwenden</b>.
+    <li>Klicken Sie <b>Neue Datenquelle</b>. Ein neuer Eintrag erscheint. Ändern Sie den Namen zu
+        <i>Bibliography</i>.</li>
+     <li>Ändern Sie den <b>Dateityp</b> zu <b>Tabelle</b>. Klicken Sie den <b>...</b>-Button
+     in der Zeile <b>Datenquellen URL</b>. Wählen Sie die <b>.sxc</b>-Datei, die Sie exportiert haben.</li>
+     <li>Klicken Sie auf <b>OK</b>, um das Fenster <b>Datenquellen</b> zu schließen.</li>
+</ul>
+Anschließend wählen Sie <b>Extras -> Literaturdatenbank</b>.
+Ihre Datenbank sollte nun angezeigt werden.
+
+</HTML>
\ No newline at end of file
diff --git a/src/help/de/OwnerHelp.html b/src/help/de/OwnerHelp.html
new file mode 100644
index 0000000..7e06a07
--- /dev/null
+++ b/src/help/de/OwnerHelp.html
@@ -0,0 +1,16 @@
+<HTML>
+
+<BODY text="#275856">
+<basefont size="4" color="#2F4958" face="arial">
+
+<H1>Das 'Besitzer' (owner) Feld</H1>
+
+JabRef kann allen neuen Einträgen, die zu einer Datei hinzugefügt oder in sie importiert werden,
+Ihren Benutzernamen beigeben. Dieses Feature können Sie im Menü <b>Einstellungen -> Allgemein</b>
+ein- und ausschalten. Dort können Sie auch den Namen angeben, der in den Einträgen erscheinen soll.
+In der Standardeinstellung wird Ihr (System-)Benutzername verwendet.
+
+<p>Der Name wird in dem Feld 'owner' eingetragen, das in der Standardeinstellung im Tab <b>General fields</b>
+des Eintragseditors angezeigt wird.
+
+</HTML>
diff --git a/src/help/de/PreviewHelp.html b/src/help/de/PreviewHelp.html
new file mode 100644
index 0000000..3515df0
--- /dev/null
+++ b/src/help/de/PreviewHelp.html
@@ -0,0 +1,12 @@
+<HTML>
+
+<BODY text="#275856">
+<basefont size="4" color="#2F4958" face="arial">
+
+<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.
+
+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.
+
+</HTML>
\ No newline at end of file
diff --git a/src/help/de/SearchHelp.html b/src/help/de/SearchHelp.html
new file mode 100644
index 0000000..e83cb36
--- /dev/null
+++ b/src/help/de/SearchHelp.html
@@ -0,0 +1,56 @@
+<HTML>
+
+<BODY text="#275856">
+<basefont size="4" color="#2F4958" face="arial">
+
+<H1>Suchfunktionen</H1>
+
+Es gibt drei verschiedene Suchmethoden in JabRef.
+
+<p>
+<em>STRG-F</em> öffnet oder aktiviert den Suchdialog. Drückt man mehrmals auf <em>STRG-F</em>, so werden die verschiedenen Suchmodi ausgewählt. Bei der direkten Suche springt man mit <em>STRG-F</em> zum nächsten Treffer.
+<p>
+<em>STRG-SHIFT-F</em> öffnet oder aktiviert den Suchdialog und wählt die direkte Suche aus. Bei der direkten Suche springt man mit <em>STRG-SHIFT-F</em> ebenfalls zum nächsten Treffer.
+
+<H2>Direkte Suche</H2>
+
+Bei der direkten Suche sucht das Programm sofort, sobald Sie einen Buchstaben eingeben. Die Statuszeile informiert Sie über den Sucherfolg. Mit den Tastaturkürzeln wird das Programm dazu veranlasst, nach dem nächsten Vorkommen des aktuellen Suchbegriffs zu suchen. Falls es keine weiteren Vorkommen gibt, informiert die Statuszeile sie darüber. Bei erneuter Wiederholung startet die Suche vom Anfang der Datei. Die Suchreihenfolge richtet sich nach der aktuellen Sortierun [...]
+
+<H2>Suche mit Markierung</H2>
+
+Wenn Sie die Suchoption "Markieren" wählen, sucht das Programm in Ihrer Datei nach allen Vorkommen ihres Suchbegriffs, sobald Sie auf ENTER drücken. Alle Treffer werden ausgewählt.
+
+<H2>Float-Suche</H2>
+
+Die Suche mit der Option "Float" ist ähnlich wie die Suche mit Markierung, nur dass die Treffer nicht ausgewählt, sondern an den Anfang der Tabelle sortiert werden. Einträge, die nicht mit dem Suchbegriff übereinstimmen, werden unter den Treffern aufgelistet und zusätzlich grau hinterlegt. Um die Anzeige der Suchergebnisse abzuschalten, drücken Sie ESC oder klicken auf "Zurücksetzen".
+
+<a name="advanced"><H2>Feldbezeichner und logische Operatoren</H2></a>
+
+Um nur einige bestimmte Felder zu durchsuchen und/oder logische Operatoren im Suchbegriff zu benutzen, wird eine spezielle Syntax zur Verfügung gestellt. Um beispielsweise nach Einträgen mit dem Autor "Miller" zu suchen, geben Sie
+<p>
+author = miller
+<p>
+in das Suchfeld ein (Achtung! Das funktioniert nicht bei der direkten Suche!). Falls der Suchbegriff Leerzeichen enthält, schließen Sie ihn in Anführungszeichen ein. Benutzen Sie <i>nie</i> Leerzeichen in dem Feldbezeichner. Um beispielsweise nach Einträgen über Karl den Großen zu suchen, geben Sie folgendes ein:
+<p>
+title|keywords = "Karl der Große"
+<p>
+Sie können "and", "or", "not" und Klammern verwenden:
+<p>
+(author = miller or title|keywords = "Karl der Große") and not author = brown
+<p>
+... sucht nach Einträgen, in denen entweder der Autor "Miller" heißt oder im title- oder keywords-Feld der Begriff "Karl der Große" steht; gleichzeitig werden die Einträge mit dem Autor "Brown" nicht angezeigt.
+<p>
+Das "="-Zeichen ist eigentlich eine Abkürzung für "enthält" ("contains"). Wenn man nach genauen Treffern suchen möchte, muss man "==" oder "matches" ("übereinstimmen") eingeben. "!=" sucht nach Einträgen, bei denen der Suchbegriff <i>nicht</i> enthalten ist. Die Auswahl von Feldern, die durchsucht werden sollen (benötigte, optionale, allgemeine Felder), wird ignoriert, wenn man im Suchausdruck Feldbezeichner verwendet. Um nach Einträgen eines besti [...]
+<p>
+entrytype = thesis
+<p>
+… findet z.B. Einträge, deren Typ (wie in der Spalte "Entrytype" dargestellt) das Wort "thesis" enthält (z.B. "phdthesis" und "mastersthesis"). Ebenso erlaubt das Pseudofeld "bibtexkey" die Suche nach BibTeX keys, z.B.:
+<p>
+bibtexkey = miller2005
+
+<H2>Suchoptionen</H2>
+
+Der <em>Einstellungen</em>-Knopf öffnet ein Menü mit mehreren Optionen: das Beachten von Groß- und Kleinschreibung, das Nutzen regulärer Ausdrücke sowie das Auswählen der Suchergebnisse in der Tabelle.
+
+</BODY>
+</HTML>
\ No newline at end of file
diff --git a/src/help/de/ShortIntegrityCheck.html b/src/help/de/ShortIntegrityCheck.html
new file mode 100644
index 0000000..18f9d5a
--- /dev/null
+++ b/src/help/de/ShortIntegrityCheck.html
@@ -0,0 +1,8 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<body>
+<basefont size="-1" color="#2F4958" face="arial">
+Die Integritätsprüfung überprüft alle Einträge auf
+deren Gültigkeit und versucht Fehler aufzudecken. Mit dem
+"Überprüfen" Button kann der Vorgang gestartet werden.
+</body></html>
\ No newline at end of file
diff --git a/src/help/de/ShortPlainImport.html b/src/help/de/ShortPlainImport.html
new file mode 100644
index 0000000..fb9e476
--- /dev/null
+++ b/src/help/de/ShortPlainImport.html
@@ -0,0 +1,8 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<body>
+<basefont size="-1" color="#2F4958" face="arial">
+Dieser Dialog ermöglicht das schnelle Einfügen von Einträgen
+aus normalen Text. Die gewünschten Textstellen werden markiert und
+z.B. durch Doppelklick einem selektierten BibTeX Eintrag zugeordnet.
+</body></html>
\ No newline at end of file
diff --git a/src/help/de/StringEditorHelp.html b/src/help/de/StringEditorHelp.html
new file mode 100644
index 0000000..6f9d796
--- /dev/null
+++ b/src/help/de/StringEditorHelp.html
@@ -0,0 +1,41 @@
+<HTML>
+
+<BODY text="#275856">
+<basefont size="4" color="#2F4958" face="arial">
+
+<H1>Der String-Editor</H1>
+<em>Zugriff über das Menü <b>BibTeX -> Strings bearbeiten</b>
+oder durch Klick auf die Schaltfläche <b>Strings bearbeiten</b></em>.
+
+<P>
+<em>Strings</em> sind das <em>BibTeX</em>-Äquivalent zu Konstanten in einer
+Programmiersprache. Jeder String wird durch einen eindeutigen <em>Namen</em> und einen
+<em>Inhalt</em> festgelegt. Der Name kann an anderer Stelle in der Datei benutzt werden,
+um den Inhalt wiederzugeben.
+
+<P>
+Ein Beispiel: Wenn viele Einträge aus einer Zeitschrift stammen, deren Abkürzung
+schwer zu behalten ist, wie etwa 'J. Theor. Biol.' (Journal of
+Theroretical Biology), könnte ein String mit dem Namen 'JTB' angelegt werden,
+um den Namen der Zeitschrift zu repräsentieren. Statt nun in jedem Eintrag den
+exakten Namen der Zeitschrift einzutragen, genügt die Zeichenfolge <code>#JTB#</code> im Feld
+<em>journal</em>, und es ist sichergestellt, dass der Name jedesmal in identischer Schreibweise
+ausgegeben wird.
+
+<P>
+Der Verweis auf einen String kann an jeder Stelle in einem beliebigen Feld erscheinen, wobei
+der Name des Strings immer von einem Paar '#'-Zeichen eingeschlossen werden muss. Diese Syntax
+gilt nur für JabRef und weicht ein wenig von der <em>BibTeX</em>-Syntax ab, die erzeugt wird,
+wenn Sie Ihre Datei speichern.
+
+<P>
+In derselben Weise kann man auch im Inhalt eines Strings auf einen anderen String verweisen, 
+vorausgesetzt, dass der String, auf den verwiesen wird, bereits <em>vorher</em> definiert ist.
+
+<p>Während die Reihenfolge der Strings in Ihrer BibTeX-Datei in einigen Fällen wichtig ist,
+brauchen Sie sich bei der Benutzung von JabRef darüber keine Gedanken zu machen. Die Strings
+werden in alphabetischer Reihenfolge im String-Editor aufgelistet und in derselben Reihenfolge gespeichert,
+außer wenn eine andere Reihenfolge von BibTeX verlangt wird.
+
+</BODY>
+</HTML>
\ No newline at end of file
diff --git a/src/help/de/TimeStampHelp.html b/src/help/de/TimeStampHelp.html
new file mode 100644
index 0000000..f626295
--- /dev/null
+++ b/src/help/de/TimeStampHelp.html
@@ -0,0 +1,35 @@
+<HTML>
+
+<BODY text="#275856">
+<basefont size="4" color="#2F4958" face="arial">
+
+<H1>Zeitstempel</H1>
+
+Die Benutzung des Zeitstempels kann unter <b>Einstellungen -> Allgemeines</b> an- und abgestellt sowie verändert werden.
+
+<p>JabRef kann automatisch ein Feld setzen, das das Datum enthält, an dem der Eintrag zur Datei hinzugefügt wurde.
+
+<H2>Formatierung</H2>
+
+Die Formatierung des Zeitstempels wird von einem Ausdruck mit Bezeichnern bestimmt, die die Position verschiedener Bestandteile des Datums angeben.
+<p>
+Hier einige der verfügbaren Bezeichner (die Beispiele in Klammern beziehen sich auf Mittwoch, den 14. September 2005, 17:45 Uhr):
+<ul>
+    <li><b>yy</b>: Jahr (05)</li>
+    <li><b>yyyy</b>: Jahr (2005)</li>
+    <li><b>MM</b>: Monat (09)</li>
+    <li><b>dd</b>: Tag (14)</li>
+    <li><b>HH</b>: Stunde (17)</li>
+    <li><b>mm</b>: Minute (45)</li>
+</ul>
+
+Diese Bezeichner können mit Interpunktion und Leerzeichen kombiniert werden. Hier einige Beispiele:
+
+<ul>
+<li><b>yyyy.MM.dd</b> ergibt <b>2005.09.14</b></li>
+<li><b>yy.MM.dd</b> ergibt <b>05.09.14</b></li>
+<li><b>yyyy.MM.dd HH:mm</b> ergibt <b>2005.09.14 17:45</b></li>
+</ul>
+
+</BODY>
+</HTML>
\ No newline at end of file
diff --git a/src/help/fr/About.html b/src/help/fr/About.html
new file mode 100644
index 0000000..7281b27
--- /dev/null
+++ b/src/help/fr/About.html
@@ -0,0 +1,91 @@
+<HTML>
+
+<BODY text="#275856">
+<basefont size="4" color="#2F4958" face="arial">
+<CENTER>
+<H1>JabRef version @version@</H1>
+
+(c) 2006
+
+
+<P>
+JabRef est librement distribuable selon les termes de la 
+<a href="License.html">GNU Public License</a>, version 2.
+
+<H2>Développeurs :</H2>
+Morten O. Alver<BR>
+Nizar N. Batada<BR>
+Michel Baylac<BR>
+Guillaume Gardey<BR>
+Cyrille d'Haese<BR>
+Raik Nagel<BR>
+Ellen Reitmayr<BR>
+Andreas Rudert<BR>    
+Michael Spiegel<BR>
+Ulrik Stervbo<BR>
+Dominik Waßenhoven<BR>
+Joerg K. Wegner<BR>
+Michael Wrighton<BR>
+Egon Willighagen <BR>
+Jörg Zieren<BR>
+
+<H2>Contributions de :</H2>
+Kolja Brix<BR>
+Frédéric Darboux<BR>
+Fabrice Dessaint<BR>
+Nathan Dunn<BR>
+Brian van Essen<br>    
+Alexis Gallagher<BR>
+Sascha Hunold<BR>
+Bernd Kalbfuss<BR>
+Martin Kähmer<BR>
+Jeffrey Kuhn<BR>
+Alex Montgomery<BR>
+John Relph<BR>
+Moritz Ringler<BR>
+Rudolf Seemann<BR>
+Toralf Senger<br>    
+Mike Smoot<BR>
+Martin Stolle<BR>
+David Weitzman<BR>
+Seb Wills<BR>
+
+<H2>Remerciements à :</H2>
+Samin Muhammad Ridwanul Karim<BR>
+Stefan Robert<BR>
+
+<H2>Logiciels tiers utilisés :</H2>
+JabRef utilise JGoodies Looks 1.2.2 et JGoodies Forms 1.0.4, distribués par JGoodies
+(<code>http://www.jgoodies.com</code>) selon les termes de la License BSD (voir
+<code>http://www.opensource.org/licenses/bsd-license.html</code> pour plus de détails).
+<P>
+Deux classes additionnelles sont aussi incluses (SimpleInternalFrame et UIFSplitPane), de Karsten
+Lentzsch, qui sont distribuées sous <A HREF="jgoodies.html">ces termes</A>.
+
+<P>
+Les options de la ligne de commande sont traitées en utilisant RitOpt (<code>http://ritopt.sourceforge.net</code>). RitOpt
+est distribuée selon les termes de la  <a href="License.html">GNU Public License</a>,
+version 2.
+<P>
+JabRef utilise le générateur d'analyseur syntaxique ANTLR pour interpréter les chaînes de recherche. ANTLR est un logiciel du domaine public
+ - voir <code>http://www.antlr.org/license.html</code> pour les termes de la license.
+<p>
+Pour la présentation de la table et le filtrage, JabRef utilise la bibliothèque Glazed Lists
+(<code>http://publicobject.com/glazedlists</code>), qui est distribuée sous la license "Lesser GNU Public License".
+<P>
+JabRef utilise aussi la bibliothèque de threading Spin 1.3.1, qui est distribuée selon les termes de la Lesser GNU Public License.
+<P>
+Ce produit inclut des logiciels développés par Apache Software
+Foundation (http://www.apache.org/). Les bibliothèques Commons Logging et
+Commons HTTP Client sont distribués par The Jakarta Project
+(<code>http://jakarta.apache.org</code>) sous la License Apache Software, Version 1.1. Voir le fichier inclus
+<code>apache-license.txt</code> ou
+<code>http://opensource.org/licenses/apachepl.php</code> pour plus de détails.
+
+<P>
+Certains icônes sont de notre facture, mais la plupart viennent soit du projet Eclipse  (<code>http://www.eclipse.org</code>),
+distribués sous la <a href="cpl-v10.html">Common Public License</a>, soit du paquetage  QIcons (<code>http://qt.osdn.org.ua</code>), qui est distribué selon les termes de la <a href="License.html">GNU Public License</a>.
+
+</CENTER>
+</BODY>
+</HTML>
diff --git a/src/help/fr/BaseFrameHelp.html b/src/help/fr/BaseFrameHelp.html
new file mode 100644
index 0000000..214064a
--- /dev/null
+++ b/src/help/fr/BaseFrameHelp.html
@@ -0,0 +1,94 @@
+<HTML>
+
+<BODY text="#275856">
+
+<basefont size="4" color="#2F4958" face="arial">
+
+<H1>La fenêtre principale de JabRef</H1>
+
+<em>Note :</em> La plupart des menus dont il est question dans les
+paragraphes suivants ont des raccourcis claviers, et beaucoup sont accessibles
+depuis la barre d'outils. Les raccourcis clavier sont affichés dans les menus
+déroulants.
+
+<p>
+Ceci est la fenêtre principale à partir de laquelle vous travaillez avec vos
+bases de données. En dessous de la barre de menus et de la barre d'outils se
+trouve un panneau à onglets contenant un onglet pour chacune de vos
+bases de données actuellement ouvertes. Quand vous sélectionnez un de ces
+onglets, un tableau apparaît, listant toutes les entrées de la base de
+données, ainsi qu'une sélection configurable de leurs champs.
+<ul>
+<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>Les champs peuvent être édités directement dans le tableau, en cliquant
+simplement dans la cellule et en tapant le contenu
+(ce mode d'édition est possible uniquement si "Autoriser l'édition dans les cellules
+du tableau" est cochée dans <strong>Options -->
+Préférences --> Général</strong>).
+Double-cliquez dans la cellule pour utiliser un mode d'édition plus puissant. 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>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
+doit être redimensionné pour s'ajuster à la fenêtre. Sélectionnez cette option
+pour toujours voir l'ensemble du tableau, et désélectionner là pour permettre
+l'affichage de plus d'informations.</li>
+<li>Les codes de couleurs vous aident à visualiser l'état
+de votre base de données. Les cellules sont colorées de la
+façon suivante :
+  <ul>
+  <li>Une cellule <font color="red">rouge</font> dans la colonne
+  la plus à gauche signale une entrée incomplète.</li>
+  <li>Une cellule <font color="#909000">jaune</font> dans la colonne
+  la plus à gauche signale une entrée qui ne définit pas par elle-même
+  l'ensemble des champs requis, mais qui contient un renvoi.</li>
+  <li>Une cellule <font color="blue">bleue</font> correspond à un champ requis.</li>
+  <li>Une cellule <font color="green">verte</font> correspond à un champ optionnel.</li>
+  <li>Une cellule sans couleur correspond à un champ qui n'est pas utilisé
+  par le programme <em>BibTeX</em> pour ce type d'entrée. Le champ peut cependant
+  être édité dans JabRef.</li>
+  </ul>
+</li>
+Les codes de couleurs peuvent être modifiés dans la fenêtre de dialogue
+<strong>Préférences</strong>. 
+
+</ul>
+
+<H2>Ajouter une nouvelle entrée</H2>
+Il y a plusieurs façons d'ajouter une nouvelle entrée. L'activation du menu
+<strong>BibTeX/ Nouvelle entrée</strong> affiche une fenêtre de dialogue où vous pouvez
+choisir le type d'entrée à partir d'une liste. Pour éviter cette fenêtre
+de dialogue, vous pouvez utilisez le menu <strong>BibTeX/ Nouvelle entrée...</strong>
+ainsi que des raccourcis clavier pour les types les plus courants.
+
+<P>Lorsqu'une nouvelle entrée est ajoutée, par défaut, une 
+<a href="EntryEditorHelp.html">fenêtre d'édition</a> s'ouvre. Ce comportement
+peut être modifié dans la fenêtre de dialogue <strong>Préférences</strong>.
+<P><em>Note :</em> Nous vous recommandons fortement d'apprendre les
+raccourcis clavier des types d'entrées que vous utilisez le plus souvent,
+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 dans la colonne la plus à gauche sur la ligne
+correspondante à l'entrée, ou sélectionner l'entrée et appuyez sur ENTER.
+Si "Autoriser l'édition dans les cellules du tableau" n'est pas coché
+dans la fenêtre de dialogue <strong>Options -->
+Préférences --> Général</strong>, un double-clic n'importe
+où sur la ligne correspondant à l'entrée ouvrira la fenêtre d'édition.
+
+<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 
+façon que dans un éditeur de texte, à une exception près : pour
+référencer une chaîne, entourer le nom de la chaîne avec le caractère #,
+tel que dans :<BR>
+  '#jan# 1997',<BR>
+ce qui sera interprété comme la chaîne nommée 'jan' suivie de '1997'.
+<P>Voir aussi : <a href="StringEditorHelp.html">Editeur de chaîne</a>.
+
+</font>
+
+</BODY>
+</HTML>
diff --git a/src/help/fr/BibtexHelp.html b/src/help/fr/BibtexHelp.html
new file mode 100644
index 0000000..ab4dc1f
--- /dev/null
+++ b/src/help/fr/BibtexHelp.html
@@ -0,0 +1,50 @@
+<HTML>
+
+<BODY text="#275856">
+<basefont size="4" color="#2F4958" face="arial">
+
+<H1>A propos de <em>BibTeX</em></H1>
+
+JabRef vous aide à travailler avec vos bases de données <em>BibTeX</em>,
+mais certaines règles doivent être gardées à l'esprit lorsque vous
+éditez vos entrées afin le traitement correct de vos bases de données par le programme <em>BibTeX</em>.
+
+<H2>Les champs <em>BibTeX</em></H2>
+
+Il y a un grand nombre de champs possibles dans <em>BibTeX</em>, et
+quelques champs en plus que vous pouvez paramétrer dans JabRef.
+
+<P>
+Généralement, vous pouvez utiliser des commandes LaTeX à l'intérieur
+de champs contenant du texte. <em>BibTeX</em> formatera automatiquement
+vos listes de références et les champs qui sont inclus dans ces
+listes seront mis en majuscules/minuscules selon votre style bibliographique. Pour être certain que certains caractères restent en majuscules, encadrez-les
+par des accolades, comme dans le mot {B}elgique.
+
+<P>
+Notes à propos de certains types de champs :
+<ul>
+<li><em>Author</em> : Ce champ doit contenir la liste complète
+des auteurs de votre entrée. Les noms sont séparés par le mot
+<em>and</em> même s'il y a plus de deux auteurs. Chaque nom peut
+être écrit indifféremment selon une des deux formes suivantes :<br>
+ Donald E. Knuth <em>ou</em> Knuth, Donald E.<br>
+ Eddie van Halen <em>ou</em> van Halen, Eddie<br>
+
+La seconde forme doit être utilisée pour les auteurs qui ont des noms
+composés (afin de différencier entre prénoms et noms).
+ 
+<li><em>Editor</em> : Ce champ est analogue au champ <em>author</em>.
+
+<li><em>Year</em> : Année de la publication. Ce champ est requis pour
+la plupart des types d'entrées. 
+
+<li><em>Bibtexkey</em> : C'est une chaîne unique utilisée pour référencer
+l'entrée dans les documents LaTeX. Notez que lorsque vous référencez une entrée
+dans LaTeX, la clef doit respecter la casse (majuscules/minuscules) de la chaîne
+de référence.
+
+</ul>
+
+
+</HTML>
diff --git a/src/help/fr/CiteSeerHelp.html b/src/help/fr/CiteSeerHelp.html
new file mode 100644
index 0000000..cce9a83
--- /dev/null
+++ b/src/help/fr/CiteSeerHelp.html
@@ -0,0 +1,43 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html lang="fr-fr"><head></head>
+
+<body style="color: rgb(39, 88, 86); direction: ltr;">
+<basefont size="4" color="#2F4958" face="arial">
+
+<h1>Récupération depuis CiteSeer</h1>
+<h2>Récupération d'une entrée depuis CiteSeer</h2>
+
+<p>
+JabRef peut récupérer de l'information sur une entrée particulière à partir de la base de données CiteSeer. Pour initier ce processus, ajoutez une nouvelle entrée dans votre base de données et renseignez le champ citeseerurl avec un lien vers la page de contenu sur CiteSeer. Le champ citeseerurl doit être rempli avec l'un des formats suivants :
+</p>
+<p>
+http://citeseer.ist.psu.edu/DDDDDD[.html], or <br>
+oai:CiteSeerPSU:DDDDDD, or <br>
+DDDDDD
+</p>
+<p>
+où DDDDD est une séquence de chiffres. Pour trouver la séquence de chiffres (DDDDD) pour une entrée CiteSeer, allez sur la page contenant le document cité avec l'adresse http://citeseer.ist.psu.edu/<i>nomAnnéeTitre</i>.html et cliquez sur le lien (update) pour cette citation. L'URL pour le lien update devrait contenir l'ID numérique de la citation.
+</p>
+<p>
+Une fois que vous avez renseigné le champ citeseerurl, vous pouvez télécharger les champs sur CiteSeer en sélectionnant le menu <b>BibTeX -> Importer les champs depuis CiteSeer</b>. Vérifier que vous avez bien sélectionné la (les) lignes(s) que vous voulez mettre à jour.
+</p>
+
+<h2>Génération d'une base de citations</h2>
+
+<p>
+A partir d'une série de références, vous pouvez générer une liste de documents qui citent les éléments de cette liste. Pour faciliter cette opération, chaque citation de la base de données doit avoir son champ citeseerurl rempli selon l'un des formats indiqués dans <b>Récupération d'une entrée depuis CiteSeer</b>. Pour réaliser cette opération, sélectionnez <b>Outils -> Recherc [...]
+</p>
+
+<h2>Utilisation d'un serveur proxy</h2>
+
+<p>
+Si vous avez besoin d'utiliser un serveur de proxy, passez le nom du serveur et le numéro de port au lancement de java. Ces paramètres d'environnement sont documentés sur
+</p>
+<p>
+http://java.sun.com/j2se/1.4.2/docs/guide/net/properties.html
+</p>
+<p>
+<code>java -Dhttp.proxyHost="hostname" -Dhttp.proxyPort="portnumber"</code>
+</p>
+</body>
+</html>
diff --git a/src/help/fr/CommandLine.html b/src/help/fr/CommandLine.html
new file mode 100644
index 0000000..b2a7919
--- /dev/null
+++ b/src/help/fr/CommandLine.html
@@ -0,0 +1,116 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html lang="fr-fr"><head></head>
+
+<body style="color: rgb(39, 88, 86); direction: ltr;">
+<basefont size="4" color="#2F4958" face="arial">
+<h1>Les options de la ligne de commande</h1>
+
+Bien que JabRef soit d'abord une application graphique, il offre
+plusieurs options pour la ligne de commande qui peuvent être
+utiles et qui peuvent réaliser des opérations de
+conversion de fichiers sans avoir à ouvrir l'interface
+graphique.
+<p>Vous pouvez
+spécifier le chargement d'un ou de plusieurs fichiers BibTeX
+en indiquant simplement leurs noms. Prenez la précaution de
+spécifier l'ensemble des options avant la liste des
+fichiers. Vous devez toujours vérifier que le premier nom de
+fichier ne sera pas compris comme l'argument d'une option - cela
+veut simplement dire que si une option de type logique comme <code>-n</code> ou <code>-l</code>
+précède immédiatement un nom de
+fichier, il faut ajouter le mot "true" comme argument. Par
+exemple, la commande </p>
+<p><code>jabref -o filetoexport.xml,docbook -n true original.bib</code>
+
+</p>
+<p> va charger correctement le fichier <code>original.bib</code> et l'exporter au format docbook dans le fichier <code>filetoexport.xml</code> sans afficher l'interface graphique. Le mot <em>true</em> évite que le nom de fichier ne soit interpréter comme un argument de l'option <code>-n</code>
+
+</p>
+<h2>Aide : -h</h2>
+
+Cette option demande à JabRef d'afficher un
+résumé des options possibles avec la ligne de
+commande et de quitter immédiatement.
+<h2>No-GUI mode : -n</h2>
+Cette
+option supprime le lancement de l'interface graphique et du logo JabRef
+qui apparaît normalement au démarrage de l'application. Elle
+permet la sortie du programme immédiatement après
+l'exécution des autres options.
+
+<p>Cette option est particulièrement utile pour réaliser
+des opérations de conversion à partir de la ligne de
+commande ou dans un script.</p>
+
+<h2>Chargement d'une session : -l</h2>
+
+Cette option demande à JabRef de charger la session
+sauvegardée, si elle existe, avant d'ouvrir la
+fenêtre principale.<br>
+
+<h2>Importation de fichier : -i nomdefichier[,format]</h2>
+
+Cette option demande à JabRef d'importer ou de charger le
+fichier indiqué. Si on n'indique que le nom du fichier, il
+est chargé comme un fichier BibTeX. Si le fichier est suivi
+d'une virgule et d'un format d'importation, le filtre d'importation
+correspondant est utilisé. Utilisez l'option <code>-h</code> pour obtenir la liste des formats d'importations disponibles.<br>
+
+<br>
+
+Si une option de sortie est ajoutée, l'importation aura
+toujours lieu avant et le fichier importé ou
+chargé sera ensuite converti selon le format d'exportation.
+Si l'interface graphique (GUI) n'est pas supprimée avec
+l'option <code>-n</code>, les fichiers importés ou chargés seront affichés dans la fenêtre principale.<br>
+
+<br>
+
+L'option <code>-i</code>  ne peut être spécifiée qu'une seule fois et pour un seul fichier.<br>
+
+<h2>Exportation de fichier : -o nomdefichier[,format]</h2>
+
+Cette option demande à JabRef de sauvegarder ou d'exporter
+un fichier chargé ou importé par la
+même commande ligne. Si le fichier importé l'est
+via une option <code>-i</code>, alors la
+base de données sera exportée. Autrement, le
+fichier spécifié (et chargé avec
+succès) sans l'option <code>-i</code> sera exporté. <br>
+<br>
+Si seul le nom du fichier est indiqué, il est sauvegardé
+au format BibTeX. Si le fichier est suivi par une virgule et un format
+d'exportation, le filtre d'exportation demandé sera
+utilisé. Un filtre d'exportation personnel peut ainsi être
+utilisé et sera systématiquement
+préféré au style d'exportation standard de
+même nom.<br>
+<br>
+Utilisez l'option <code>-h</code> pour avoir la liste des formats disponibles.<br>
+<br>
+Si l'option <code>-n</code> n'a pas été
+utilisée, les opérations d'exportation sont faites avant
+l'ouverture de la fenêtre JabRef et la base importée ou
+chargée sera présente dans la fenêtre principale.<br>
+<br>
+L'option <code>-o</code> ne peut être utilisée qu'une seule fois et pour un seul fichier.<br>
+<h2>Exportation des préférences : -x nomdefichier</h2>
+Cette option indique à JabRef d'exporter sous forme d'un
+fichier .xml, l'ensemble des préférences de
+l'utilisateur. Après l'exportation, JabRef est lancé
+normalement.<br>
+<h2>Importation des préférences : -p nomdefichier</h2>
+Cette option indique à JabRef d'importer les
+préférences de l'utilisateur préalablement
+exportées avec l'option <code>-x</code>. Après l'importation, JabRef démarre normalement.<br>
+<h2>Exportation des entrées utilisées : -a nomdefichier[.aux],nouvelleBaseBib[.bib]</h2>
+Il est quelques fois utile d'avoir un fichier BibTeX qui ne contienne
+que les références BibTeX utilisées. Une liste de
+ces entrées utilisées est stockée dans un fichier
+.aux. JabRef peut analyser ce fichier pour générer
+un nouveau fichier BibTeX qui ne contiendra que les entrées
+connues et utilisées. Cela veut dire que si une entrée
+n'est pas définie dans le fichier BibTeX courant, elle ne sera
+pas intégrée dans le nouveau fichier.
+
+</body></html>
diff --git a/src/help/fr/ContentSelectorHelp.html b/src/help/fr/ContentSelectorHelp.html
new file mode 100644
index 0000000..b953d82
--- /dev/null
+++ b/src/help/fr/ContentSelectorHelp.html
@@ -0,0 +1,24 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html lang="fr-fr">
+<head>
+    <title>Sélecteur de mots</title>
+  </head>
+
+<body style="color: rgb(39, 88, 86); direction: ltr;">
+<basefont size="4" color="#2F4958" face="arial">
+
+<h1>Sélecteur de contenu de champ</h1>
+
+<p>
+Cette opération vous permet d'enregistrer une sélection de mots et de phrases que vous utilisez souvent dans votre base de données. Par défaut, c'est possible avec les champs <em>Journal</em>, <em>Keywords</em> et <em>Publisher</em> mais vous pouvez aussi ajouter des sélecteurs à d'autres champs, en utilisant la partie supérieure de la fenêtre <i>Gérer les sélecteurs</i> (menu <strong> Outils --> Gérer les s&eacu [...]
+</p>
+
+<p>
+La sélection des mots est spécifique à la base de données et sauvegardée avec vos références dans le fichier .bib.
+</p>
+
+<p>
+Pour ajouter un nouveau mot, vous pouvez simplement l'écrire dans la boite de sélection des mots et appuyer sur la touche Enter. A partir de la fenêtre <i>Gérer les sélecteurs</i>, vous pouvez aussi supprimer les mots que vous avez ajoutés.
+</p>
+</body>
+</html>
diff --git a/src/help/fr/Contents.html b/src/help/fr/Contents.html
new file mode 100644
index 0000000..239bd7f
--- /dev/null
+++ b/src/help/fr/Contents.html
@@ -0,0 +1,47 @@
+<HTML>
+
+    <BODY text="#275856">
+    <basefont size="4" color="#2F4958" face="arial">
+
+    <H1>Contenu de l'aide</H1>
+
+    <a href="HelpHelp.html">A propos de la fenêtre d'aide</a><br>
+    <a href="JabRefHelp.html">Informations générales</a><br>
+    <p>
+    <a href="BibtexHelp.html">Aide sur <em>BibTeX</em></a><br>
+    <a href="CommandLine.html">Options de la ligne de commande</a><br>
+    <a href="CustomExports.html">Filtres d'exportation personnalisés</a><br>
+    <a href="CustomImports.html">Filtres d'importation personnalisés</a><br>
+    <a href="LabelPatterns.html">Personnalisation du générateur de clefs BibTeX</a><br>
+    <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="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="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="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="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>
+
+
+
+
+
+
+
+
+
+
+
+
+</HTML>
diff --git a/src/help/fr/CustomEntriesHelp.html b/src/help/fr/CustomEntriesHelp.html
new file mode 100644
index 0000000..5fc1536
--- /dev/null
+++ b/src/help/fr/CustomEntriesHelp.html
@@ -0,0 +1,80 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+  <head>
+    <title>Personnaliser les types d'entrées</title>
+  </head>
+
+  <BODY text="#275856">
+    <basefont size="4" color="#2F4958" face="arial">
+
+    <h1>Personnaliser les types d'entrées</h1>
+    <p>
+    Pour accéder à cette fonction, cliquez sur le menu 
+    <strong>Options --> Personnaliser les types d'entrées</strong>.
+    <p>
+    Lors de la personnalisation d'un type d'entrée, vous définissez à la fois son apparence
+    dans l'éditeur d'entrées et ce qui est nécessaire pour que JabRef considère une entrée comme
+    complète. Vous pouvez aussi bien changer les types d'entrée existants qu'en définir de nouveaux.
+    <p>
+    
+    Notez qu'aucune des modifications que vous effectuez dans cette fenêtre ne sera stockée tant
+    que vous n'aurez pas cliqué sur <b>Apply</b> ou <b>OK</b>. Si vous cliquez sur <b>Cancel</b>
+    ou si vous fermez simplement la fenêtre, les changements non-appliqués seront perdus.
+    
+    <h2>Utiliser la fenêtre de personnalisation des entrées</h2> 
+    
+La fenêtre de personnalisation des entrées est divisée en 3 panneaux principaux.
+Le panneau de gauche vous permet de sélectionner l'entrée à modifier, et d'en
+ajouter de nouvelles. Le panneau central est utilisé pour paramétrer les champs requis
+du type d'entrée sélectionné. Le panneau de droite est utilisé pour paramétrer les
+champs optionnels du type d'entrée sélectionné.
+
+
+<h3>Ajouter et supprimer des types d'entrées</h3>
+
+<p>Les types d'entrées actuellement disponibles sont listés dans le panneau de gauche.
+Lorsque vous sélectionnez un type d'entrée, les autres panneaux sont mis à jour afin
+d'afficher les champs requis et optionnels pour ce type d'entrée.
+
+<p>Pour ajouter un nouveau type d'entrées, vous devez entrer son nom dans le
+champ de texte situé sous la liste des types et cliquer sur <b>Ajouter</b>
+Le nouveau type d'entrées sera ajouté à la liste et sélectionné pour pouvoir être
+modifié.
+
+<p>Pour supprimer un type d'entrées personnalisé, sélectionnez-le et cliquez sur
+<b>Supprimer</b>. Cette opération n'est possible que pour les types d'entrées
+personnalisés qui ne sont pas de simples modifications des types standards. Il n'est
+pas possible de supprimer les types standards.
+
+
+<p>Pour qu'un type standard modifié reprenne ses valeurs par défaut, sélectionnez-le et 
+cliquez sur <b>Défaut</b>. Cette opération n'est possible que pour les types d'entrées
+personnalisés qui modifient un type standard.
+
+
+<h2>Editer les types d'entrées</h2>
+
+
+Quand un type d'entrées est sélectionné, ses champs requis et optionnels sont listés dans
+les panneaux du centre et de droite. La méthode d'édition des listes de champs est la même
+pour les champs requis et optionnels.
+
+
+<p>Pour ajouter un nouveau champ, éditez le champ de texte situé sous la liste,
+ou sélectionnez un nom de champ à partir du menu déroulant, puis cliquez sur 
+<b>Ajouter</b>. Le nom du champ sélectionné sera ajouté à la fin de la liste.
+
+<p>Pour supprimer un ou plusieurs champs, sélectionnez-les dans la liste et cliquez
+sur <b>Supprimer</b>.
+
+<p>Pour changer l'ordre des champs, sélectionner le nom d'un champ et cliquer sur les boutons
+en forme de flèches pour le déplacer vers le haut ou vers le bas de la liste.
+
+Il y a une limitation à la personnalisation des entrées ; certains
+types ont une condition "et/ou" dans les champs requis. Par exemple, 
+une entrée <em>book</em> est complète lorsque au moins un des champs
+<em>author</em> ou <em>editor</em> est rempli. Ce type de condition
+ne peut pas être introduite dans une entrée personnalisée.
+
+  </body>
+</html>
diff --git a/src/help/fr/CustomExports.html b/src/help/fr/CustomExports.html
new file mode 100644
index 0000000..df7a6fb
--- /dev/null
+++ b/src/help/fr/CustomExports.html
@@ -0,0 +1,176 @@
+<HTML>
+
+<BODY text="#275856">
+<basefont size="4" color="#2F4958" face="arial">
+
+<h1>Filtres d'exportation personnalisés</h1>
+
+<p>
+JabRef vous permet de définir et d'utiliser vos propres filtres d'exportation de la même manière que les filtres d'exportation standards. Un filtre d'exportation est défini par un ou plusieurs <i>fichiers gabarit</i> qui, avec l'aide d'un certain nombre de routines internes de formatage, définissent le format des fichiers exportés. Vos fichiers gabarit doivent être préparés avec un éditeur de texte à l'exté [...]
+</p>
+
+<h2>Ajout d'un filtre d'exportation personnalisé </h2>
+
+<p>
+La seule obligation pour avoir un filtre d'exportation valide est l'existence d'un fichier avec l'extension <b>.layout</b>. Pour ajouter un nouveau filtre d'exportation, on utilise le menu <b>Options -> Gérer les exportations personnalisées</b>, et on clique sur <b>Ajouter nouvelle</b>. Une nouvelle boite de dialogue apparaît et vous permet de spécifier un nom pour le nouveau filtre d'exportation (ce nom apparaîtra dans le menu <b>Fichier -> Exportation p [...]
+</p>
+
+<h2>Création d'un filtre d'exportation</h2>
+
+<p>
+Pour voir des exemples de constitution de filtres d'exportation, recherchez le répertoire contenant les fichiers gabarit des filtres d'exportation standards sur notre page de téléchargement.
+</p>
+
+<h3>Les fichiers gabarit</h3>
+
+<p>
+On suppose que l'on veut créer un filtre d'exportation pour une sortie HTML.
+</p>
+
+<p>
+Bien que le filtre d'exportation ne nécessite qu'un seul fichier <b>.layout</b>, qui dans ce cas pourrait s'appeler <i>html.layout</i>, vous pouvez désirer ajouter deux autres fichiers appelés <i>html.begin.layout</i> et <i>html.end.layout</i>. Le premier contient le début de la sortie et le dernier la fin. JabRef recherche ces deux fichiers quelque soit le fichier d'exportation utilisé et, s'il les trouve, les recopie tel quel dans la sortie avant et a [...]
+</p>
+
+<p>
+Il faut noter que ces fichiers doivent être dans le même répertoire que le fichier <i>html.layout</i>, et que leur nom doit comporter <b>.begin</b> pour l'un et <b>.end</b> pour l'autre.
+</p>
+
+<p>
+Dans notre exemple de fichier d'exportation, cela pourrait ressembler à 
+</p>
+
+<p>
+<i>html.begin.layout</i> :<br>
+<code>
+<HTML><br>
+  <BODY> text="#275856"><br>
+<basefont size="4" color="#2F4958" face="arial">
+</code>
+</p>
+
+<p>
+<i>html.end.layout</i> :<br>
+<code>
+</BODY><br>
+  </HTML>
+</code>
+</p>
+
+<p>
+Le fichier <i>html.layout</i> fournit le gabarit par défaut pour l'exportation  d'une seule entrée. Si vous devez utiliser différents gabarits pour les différentes entrées, vous pouvez le faire en ajoutant des fichiers <b>.layout</b> spécifiques.
+Les fichiers doivent aussi être dans le même répertoire que le gabarit principal et ils sont nommés en insérant <b>.entrytype</b> dans le nom du fichier gabarit principal. Le nom de l'entrée doit être en minuscules.
+Dans notre exemple, on peut vouloir ajouter un gabarit différent pour les livres et cela se fera via le fichier <i>html.book.layout</i>. Pour une thèse, on ajoutera le fichier <i>html.phdthesis.layout</i>.
+Ces fichiers sont similaires au gabarit principal, si ce n'est qu'ils sont utilisés pour des entrées spécifiques. A noter que le gabarit général peut aisément être créé suffisamment général pour être utilisable avec la plupart des entrées dans la majorité des filtres d'exportation.
+</p>
+
+<h3>Le format des fichiers gabarit</h3>
+
+<p>
+Les fichiers gabarit utilisent un simple langage de balisage dans lequel les commandes sont identifiées par l'antislash (\) les précédant. Tout texte non identifié comme faisant partie d'une entrée est recopié tel quel dans le fichier de sortie.
+</p>
+
+<h3>Les commandes relatives aux champs</h3>
+
+<p>
+Les mots précédés d'un antislash, par exemple <code>\author</code>, <code>\editor</code>, <code>\title</code> ou <code>\year</code>, sont interprétés comme des références aux champs correspondants et le contenu du champ est copié directement dans la sortie.
+</p>
+
+<h3>Les formateurs de champs</h3>
+
+<p>
+Souvent, on a besoin de faire subir au contenu d'un champ un pré-traitement avant de le copier dans le fichier de sortie. Cela est réalisé en utilisant un <i>formateur de champ</i> - une classe java contenant une seule méthode qui manipule le contenu du champ.
+</p>
+
+<p>
+Le formateur est utilisé en insérant la commande <code>\format</code> suivie du nom du formateur entre crochets et du nom du champ entre accolades, par exemple
+</p>
+<p>
+<code>\format[ToLowerCase]{\author}</code>
+</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 : 
+</p>
+<p>
+<code>\format[ToLowerCase,HTMLChars]{\author}</code>
+</p>
+<p>
+va d'abord appliqué le formateur <b>ToLowerCase</b> puis <b>HTMLChars</b> sur le résultat. Vous pouvez lister un nombre arbitraire de formateurs de cette manière.
+</p>
+
+<p>Le paramètre des formateurs, entre les accolades, n'est pas obligatoirement une commande de champ. Vous pouvez y insérer du texte normal, qui sera alors passé aux formateurs au lieu des contenues de tout champ [NdT : pas sûr d'avoir bien compris...]. Cela peut-être utile avec certains formateurs, par exemple le formateur CurrentDate (voir ci-dessous).
+</p>
+
+<p>
+JabRef fournit les formateurs suivants, certains d'entre eux dépendant d'autres formateurs :
+</p>
+
+<ul>
+<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, 
+<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>FormatPagesForHTML</code> : remplace "--" par "-".
+  <li><code>FormatPagesForXML</code> : remplace "--" par un tiret XML.
+<li><code>RemoveBrackets</code> : supprime toutes les accolades "{" ou "}".
+<li><code>RemoveLatexCommands</code> : supprime toutes les commandes LaTeX comme <code>\em</code>, <code>\textbf</code>, etc. Lorsqu'il est utilisé avec <code>HTMLChars</code> ou <code>XMLChars</code>, ce formateur doit être appelé en dernier.
+<li><code>ToLowerCase</code> : bascule tous les caractères en minuscules.
+</ul>
+
+<p>
+Si aucun des formateurs disponibles ne peut faire ce que vous désirez, vous pouvez ajouter le votre à l'interface <code> net.sf.jabref.export.layout.LayoutFormatter</code>. Si vous insérez votre propre classe dans <code>net.sf.jabref.export.layout.format</code>, vous pouvez appeler votre formateur en utilisant son nom de classe, comme pour les formateurs standards. Sinon, vous devez appeler le formateur par son nom complet (incluant le nom du package). Dans les deux  [...]
+</p>
+
+<h3>Les sorties conditionnelles</h3>
+<p>
+Certaines informations dans les sorties ne prennent de sens que si un certain champ est utilisé. Par exemple, disons que l'on veuille faire suivre le nom de l'éditeur par le texte <code>(Ed.)</code>. Cela peut être réalisé avec le code suivant :
+</p>
+
+<p>
+<code>\format[HTMLChars,AuthorFirstFirst]{\editor} (Ed.)</code>
+</p>
+
+<p>
+Cependant, si le champs <code>editor</code> n'a pas été renseigné - il n'a pas de sens pour l'entrée exportée - le texte <code>(Ed.)</code> doit être ignoré. Cela peut être effectué en utilisant les commandes <code>\begin</code> et <code>\end</code> :
+</p>
+
+<p>
+<code>\begin{editor}<br>\format[HTMLChars,AuthorFirstFirst]{\editor} (Ed.)
+<br>\end{editor}</code>
+</p>
+
+<p>Les commandes <code>\begin</code> et <code>\end</code> assure que le texte contenu entre les deux commandes ne sera imprimé que si et seulement si le champ spécifié entre accolades est renseigné dans l'entrée que l'on veut exporter.
+</p>
+
+<p>
+<b>Note :</b> L'utilisation des commandes <code>\begin</code> et <code>\end</code> est une manière astucieuse de créer des gabarits qui sont communs à une grande variété d'entrées.
+</p>
+
+<h3>Les sorties groupées</h3>
+
+<p>
+Si vous désirez séparer vos entrées en groupes basés sur un certain champ, vous pouvez utiliser les commandes de sorties groupées. La sortie groupée est assez similaire aux sorties conditionnelles, excepté que le texte spécifié n'est imprimé que si le champ indiqué dans les accolades change de valeur.
+</p>
+
+<p>
+Par exemple, on suppose que l'on désire faire des groupes à partir de mots-clefs. Avant l'exportation, on s'assure que les entrées sont triées selon les mots-clefs. Ensuite, on utilise les commandes suivantes pour les grouper par mot-clefs :
+</p>
+<p>
+<code>\begingroup{keywords}New Category: \format[HTMLChars]{\keywords}
+<br>	\endgroup{keywords}</code>
+</p>
+
+<h2>Partage de votre travail </h2>
+
+<p>
+Avec les fichiers gabarit externes, il est relativement simple de partager des formats d'exportation entre utilisateurs. Si vous écrivez un filtre d'exportation pour un format non supporté par JabRef, ou si vous améliorez un filtre déjà existant, nous vous encourageons à déposer votre travail sur notre page SourceForge.net. La même chose est possible pour les nouvelles classes de formateur que vous avez écrites. Nous serons he [...]
+</p>
+</body>
+</html>
diff --git a/src/help/fr/CustomImports.html b/src/help/fr/CustomImports.html
new file mode 100644
index 0000000..278ed75
--- /dev/null
+++ b/src/help/fr/CustomImports.html
@@ -0,0 +1,95 @@
+<HTML>
+
+<BODY text="#275856">
+<basefont size="4" color="#2F4958" face="arial">
+
+<H1>Filtres d'importation personnalisés</H1>
+
+<p>JabRef vous permet de définir et d'utiliser vos propres formats d'importation, d'une façon très similaire aux filtres d'importation standard qui sont définis. Un filtre d'importation est défini par une ou plusieurs <i>classes</i> Java qui analyse le contenu d'un fichier à partir d'un flux d'entrée et crée des entrées BibTeX. Ainsi, avec un peu de programmation de base en Java, vous pouvez ajouter un format d'importation co [...]
+
+<p>Les formats d'importation personnalisés sont prioritaires sur les formats d'importation standard. De cette façon, vous pouvez remplacer les formats d'importations existants pour les fonctions d'auto-détection et de ligne de commande de JabRef. Les formats d'importation personnalisés sont classés par nom.
+
+<H2>Ajouter un filtre d'importation personnalisé</H2>
+
+<p>Assurez-vous que vous avez un filtre d'importation personnalisé compilé (un ou plusieurs fichiers <code>.class</code> sont décrits ci-dessous) et que les fichiers de classe soient dans la structure des répertoires selon la structure de leur paquetage. Pour ajouter un nouveau filtre d'importation personnalisé, ouvrez la boîte de dialogue <b>Options -> Gérer les importations personnalisées</b>, et cliquer <b>Ajouter à partir  [...]
+Un sélectionneur de fichier apparaîtra, vous permettant de sélectionner le chemin de classe de votre filtre d'importation, c'est à dire le répertoire où se trouve le répertoire supérieur de votre structure de paquetage. Dans un second sélectionneur de fichier vous sélectionnez votre fichier de classe de filtre d'importation, lequel doit dériver de <code>ImportFormat</code> [NdT : pas tout compris...]. En cli [...]
+<b>Sélectionner une nouvelle sous-classe de format d'importation</b>, votre nouveau filtre d'importation apparaîtra dans la liste des filtres d'importation personnalisés. Tous les filtres d'importations personnalisés apparaîtront dans le menu <b>Fichier -> Importer -> 
+Filtres d'importation personnalisés</b> et <b>Fichier -> Importer et joindre -> Filtres d'importation personnalisés</b> de la fenêtre de JabRef.</p>
+
+
+
+<p>S'il vous plaît, notez que si vous déplacer la classe vers un autre répertoire, vous aurez à supprimer et à ré-ajouter le filtre d'importation. Si vous ajouter un filtre d'importation personnalisé sous un nom qui existe déjà, le filtre d'importation existant sera remplacé. De plus, dans certains cas, il est possible de mettre à jour un filtre d'importation personnalisé existant sans redémarrer Ja [...]
+
+
+<H2>Créer un filtre d'importation</H2>
+
+Pour des exemples et quelques fichiers utiles sur la façon de construire vos propres filtres d'importation, consulter s'il vous plaît la page de téléchargement.
+
+
+<H3>Un exemple simple</H3>
+
+<p>Supposons que vous vouliez importer des fichiers de la forme suivante :
+<pre>
+1936;John Maynard Keynes;The General Theory of Employment, Interest and Money
+2003;Boldrin & Levine;Case Against Intellectual Monopoly
+2004;ROBERT HUNT AND JAMES BESSEN;The Software Patent Experiment
+</pre></p>
+
+<p>Dans votre outil de développement ou éditeur de texte préféré, créez une classe dérivée de <code>ImportFormat</code> qui implémente les méthodes <code>getFormatName()</code>, <code>isRecognizedFormat</code>
+and <code>importEntries()</code>. En voici un exemple :
+<pre>
+import java.io.*;
+import java.util.*;
+import net.sf.jabref.*;
+import net.sf.jabref.imports.ImportFormat;
+import net.sf.jabref.imports.ImportFormatReader;
+
+public class SimpleCsvImporter extends ImportFormat {
+
+  public String getFormatName() {
+    return "Simple CSV Importer";
+  }
+
+  public boolean isRecognizedFormat(InputStream stream) throws IOException {
+    return true; // ceci est déconseillé sauf pour les besoins de la démonstration
+  }
+  
+  public List importEntries(InputStream stream) throws IOException {    
+  	ArrayList bibitems = new ArrayList();
+    BufferedReader in = new BufferedReader(ImportFormatReader.getReaderDefaultEncoding(stream));
+      
+    String line = in.readLine();
+    while (line != null) {
+      if (!"".equals(line.trim())) {
+        String[] fields = line.split(";");
+        BibtexEntry be = new BibtexEntry(Util.createNeutralId());
+        be.setType(BibtexEntryType.getType("techreport"));
+        be.setField("year", fields[0]);
+        be.setField("author", fields[1]);
+        be.setField("title", fields[2]);
+        bibitems.add(be);
+        line = in.readLine();
+      }     
+    }
+  	return bibitems;	  	
+  }
+}
+</pre></p>
+
+<p>Notez que l'exemple est dans le paquetage par défaut. Supposez que vous l'avez sauvé sous <code>/mypath/SimpleCsvImporter.java</code>. Supposez aussi que JabRef-2.0.jar est dans le même répertoire que <code>SimpleCsvImporter.java</code> et que Java est dans votre chemin d'exécutables. 
+Compilez-le en utilisant par exemple JSDK 1.4 avec
+<pre>
+javac -classpath JabRef-2.0.jar SimpleCsvImporter.java
+</pre>
+A présent il doit y avoir un fichier <code>/mypath/SimpleCsvImporter.class</code>.</p>
+
+<p>Dans JabRef, ouvrez <b>Options -> Gérer les importations personnalisées</b>, et cliquez sur <b>Ajouter à partir du répertoire</b>.
+Aller dans <code>/mypath</code> et cliquer le bouton <b>Sélectionner...</b>. Sélectionnez 
+<code>SimpleCsvImporter.class</code> et cliquer sur le bouton <b>Sélectionner...</b>.
+Votre filtre d'importation devrait maintenant apparaître dans la liste des filtres d'importation personnalisés sous le nom "Simple CSV Importer" et, après avoir cliqué sur <b>Fermer</b>, aussi dans les menus <b>Fichier -> Importer -> Filtres d'importation personnalisés</b> et <b>Fichier -> Importer et joindre -> Filtres d'importation personnalisés</b> de la fenêtre de JabRef.</p>
+
+<H2>Partager votre travail</H2>
+
+Avec des fichiers de filtres d'importation personnalisés, il est vraiment simple de partager des formats d'importation personnalisés entre utilisateurs. Si vous écrivez un filtre d'importation pour un format non supporté par JabRef, ou l'amélioration d'un filtre existant, nous vous encourageons à soumettre votre travail sur notre page SourceForge.net. Nous serons heureux de distribuer la collection des fichiers d'importation soumis, ou d'en ajout [...]
+
+</HTML>
diff --git a/src/help/fr/EndNoteFilters.html b/src/help/fr/EndNoteFilters.html
new file mode 100644
index 0000000..2a59500
--- /dev/null
+++ b/src/help/fr/EndNoteFilters.html
@@ -0,0 +1,127 @@
+<HTML>
+
+<BODY text="#275856">
+<basefont size="4" color="#2F4958" face="arial">
+
+<h1>Filtre d'exportation EndNote</h1>
+
+<h2>Exportation à partir de JabRef</h2>
+
+JabRef peut exporter des bases de données dans des fichiers
+lisibles par EndNote. Pour utiliser cette fonction,
+choisissez <b>Fichier -> Exporter -> EndNote</b>, et
+spécifiez le nom du fichier d'exportation.
+
+<h2>Importer dans EndNote</h2>
+
+Le fichier par défaut d'importation d'EndNote ne traite
+pas proprement les auteurs ou les éditeurs multiples. 
+Il y a deux façons de contourner cela :
+
+<ol>
+
+<li>Utiliser le filtre interne et corriger ensuite le fichier.
+Pour ouvrir le fichier dans EndNote, créez une nouvelle base de
+données ou ouvrez une ancienne base de données dans EndNote.
+Ensuite, sélectionnez <b>Fichier -> Importer</b>, cliquer
+sur <b>Choisir le filtre</b>, puis sélectionnez le fichier
+exporté et cliquez sur <b>Choisir</b>. Cliquez sur 
+<b>Options d'importation</b> et sélectionnez
+<b>Importation EndNote</b>.  Cliquez sur <b>Importer</b> pour
+démarrer l'importation. Après l'importation, sélectionnez
+<b>Edition-> Changer le texte</b>. Changez <b>N'importe
+quel champ</b> en <b>Author</b>. Entrez " and " à l'intérieur
+du champ de recherche (sans les guillemets). Entrez un 
+retour chariot dans le champ Remplacer
+(option-return pour Mac OS X, ctrl-return pour Windows
+XP). Cliquez sur <b>Remplacer</b>. Répétez avec le champ
+<b>Secondary Author</b>. [NdT: difficile à traduire sans
+avoir EndNote... oui]
+
+<li>Installer le <i>filtre d'importation d'EndNote depuis
+JabRef</i> dans le <i>EndNote Extras</i>. Suivez les instructions
+dans la section <i>Utilisation avancée</i> ci-dessous.
+Pour ouvrir le fichier dans EndNote, créez une nouvelle base
+de données ou ouvrez une ancienne base de données dans EndNote.
+Ensuite, sélectionnez <b>Fichier -> Importer</b>, cliquez
+sur <b>Choisir le filtre</b>, puis sélectionnez le fichier
+exporté et cliquez sur <b>Choisir</b>. Cliquez sur 
+<b>Options d'importation</b> et sélectionnez
+<b>Filtre d'importation d'EndNote depuis
+JabRef</b> (s'il n'est pas présent, sélectionnez Autres
+filtres. S'il n'apparaît toujours pas, il n'a pas été installé
+correctement). Cliquer sur <b>Importer</b> pour démarrer
+l'importation.
+
+</ol>
+
+<h2>Notes</h2>
+
+Le filtre d'exportation EndNote fait correspondre les types
+d'entrées BibTeX avec les types de référence d'EndNote de la
+façon suivante :
+
+<pre>
+Type d'entrée BibTeX -> Type de référence d'EndNote
+---------------------------------------------------
+misc, other -> Generic
+unpublished -> Manuscript
+manual -> Computer Program
+article -> Journal Article
+book -> Book
+booklet -> Personal Communication
+inbook,incollection -> Book Section
+inproceedings -> Conference Proceedings
+techreport -> Report
+mastersthesis, phdthesis -> Thesis
+</pre>
+
+<h2>Auteurs collectifs</h2>
+
+Par défaut, le filtre d'exportation suppose que le contenu 
+des champs author ou editor qui sont dans des accolades
+sont des auteurs collectifs et remplace les accolades par
+une virgule. Cependant, cela signifie que les champs qui
+contiennent du code LaTeX entre accolades seront supposés
+être des auteurs collectifs et seront donc improprement
+formatés.
+
+<H2>Utilisation avancée : Suppléments EndNote</h2>
+
+<h3>Installation du filtre d'importation d'EndNote depuis JabRef</h3>
+
+Le filtre par défaut d'importation d'EndNote ne traite pas 
+correctement les auteurs. Le filtre d'importation d'EndNote depuis
+JabRef le fait proprement. De plus, ce filtre reconnaîtra 
+un champ EndNotereftype qui supplantera la table des correspondances
+par défaut. Pour installer ce filtre, extraire les suppléments
+pour EndNote (<b>Fichier ->  Exporter - > Décompacter la série de
+filtres EndNote</b>) et décompresser le fichier Zip qui est crée.
+Ensuite, suivez les instructions du fichier readme.txt.<p>
+
+<h3>Modification des types de référence d'EndNote</h3>
+
+Plusieurs champs utilisés par BibTeX ne font pas partie
+des Types de Référence par défaut d'EndNote. Alors que
+l'importation depuis JabRef et l'exportation à partir
+de JabRef fonctionneront correctement sans modifier
+les types de références, les noms de champs ne seront
+pas affichés correctement dans EndNote (par exemple,
+une fenêtre d'entrée appellera le champ PDF
+<i>"Custom 1"</i> au lieu de <i>"pdf"</i>. De plus,
+puisque ces champs n'apparaîtront pas dans la fenêtre
+d'édition, ces champs ne pourront pas être ajoutés à
+de nouvelles entrées dans EndNote. Pour modifier les
+Types de Références d'EndNote, extrayez les Suppléments
+EndNote et suivez les instructions du fichier readme.txt.<p>
+
+<h3>Exportation vers JabRef</h3> 
+
+EndNote est fourni avec un style d'exportation BibTeX. 
+Cependant, il ne prend pas en compte tous les types et les champs BibTeX
+et ne prend pas non plus en compte les Champs Généraux additionnels supportés
+par JabRef (<i>pdf, owner, key,</i> etc.). Si vous souhaitez
+que ces champs soient pris en compte, extrayez les Suppléments EndNote
+et suivez les instructions du fichier readme.txt.<p>
+
+</HTML>
diff --git a/src/help/fr/EntryEditorHelp.html b/src/help/fr/EntryEditorHelp.html
new file mode 100644
index 0000000..fd44951
--- /dev/null
+++ b/src/help/fr/EntryEditorHelp.html
@@ -0,0 +1,114 @@
+<HTML>
+
+<BODY text="#275856">
+<basefont size="4" color="#2F4958" face="arial">
+
+<H1>L'éditeur d'entrées</H1>
+
+<em>On l'ouvre à partir de la fenêtre principale en double-cliquant
+sur la colonne la plus à gauche de l'entrée (en double-cliquant n'importe
+où sur la ligne de l'entrée si "Autoriser l'édition dans les cellules
+du tableau" n'est pas cochée dans <strong>Options --> Préférences --> Général</strong>),
+ou en appuyant sur ENTER. L'éditeur d'entrées se ferme en appuyant sur ESC.</em>
+<P>
+Dans l'éditeur d'entrées, vous pouvez spécifier toutes les informations pertinentes
+pour une entrée donnée. L'éditeur d'entrées vérifie le type de votre entrée et 
+affiche tous les champs qui sont requis ou optionnels pour que <em>BibTeX</em>
+traite l'entrée. De plus, il y a plusieurs champs, appelés <em>Champs
+généraux</em>, qui sont communs à tous les types d'entrées.
+
+<P>Vous pouvez personnaliser complètement les champs qui doivent être considérés comme
+requis ou optionnel pour chaque type d'entrée, ainsi que les champs apparaissant dans
+l'onglet Champs généraux. Voir <a href="CustomEntriesHelp.html">Personnaliser les types
+d'entrées</a> pour plus d'informations à ce sujet.
+
+<P>Pour des informations sur la façon de remplir les champs,
+voir <a href="BibtexHelp.html">Aide sur BibTeX</a>.
+
+<H2>Le panneau à onglets de l'éditeur d'entrées</H2>
+
+L'éditeur d'entrée contient cinq onglets :
+<em>Champs requis</em>, <em>Champs optionnels</em>,
+<em>Champs généraux</em>, <em>Abstract</em>
+et <em>Source BibTeX</em>. Les onglets <em>Champs généraux</em> et
+<em>Abstract</em> peuvent être personnalisés (voir <a href="GeneralFields.html">Personnalisation des champs généraux</a> pour plus de détails). A l'intérieur des trois premiers onglets, TAB et SHIFT-TAB sont utilisés pour naviguer entre les champs de texte.
+
+<P>Naviguez entre les onglets en cliquant sur les onglets
+ou en utilisant les combinaisons de touches suivantes pour vous déplacer
+vers la gauche ou la droite : CTRL-TAB ou CTRL-PLUS
+affiche l'onglet à droite, et CTRL-SHIFT-TAB ou CTRL-MOINS
+affiche l'onglet à gauche. Vous pouvez aussi afficher l'entrée précédente ou
+suivante en appuyant respectivement sur CTRL-SHIFT-DOWN ou
+CTRL-SHIFT-UP, ainsi qu'en cliquant sur les boutons de la barre
+d'outils de l'éditeur d'entrées.
+
+<P>L'onglet <em>Source BibTeX</em> montre comment l'entrée
+apparaîtra lorsque la base de données sera sauvegardée au format
+<em>BibTeX</em>. Si vous le souhaitez, vous pouvez éditer la source
+<em>BibTeX</em> directement dans cet onglet. Lorsque vous changez
+d'onglet, que vous appuyez sur CTRL-S ou que vous fermez
+l'éditeur d'entrées, JabRef essayera de traiter le contenu de l'onglet
+<em>Source BibTeX</em>. S'il y a des problèmes, vous
+en serez informé ; vous pourrez alors éditer à nouveau votre
+entrée ou rétablir son contenu initial.
+
+Si <strong>Par défaut, afficher l'onglet Source BibTeX</strong>
+est coché dans les options <strong>Général</strong> de la fenêtre de
+dialogue <strong>Préférences</strong>, l'onglet <em>Source
+BibTeX</em> sera affiché par défaut chaque fois que l'éditeur d'entrées
+sera ouvert. Si vous préférez éditer la source au lieu d'utiliser
+les quatre autres onglets, vous devez cocher
+cette option.
+
+<P><strong>Astuce :</strong> Si votre base contient des champs que JabRef
+ne connaît pas, ils seront visibles dans l'onglet <em>Source
+BibTeX</em>.
+
+<P><strong>Astuce :</strong> les champs <I>pdf</I> et <I>url</I>
+supportent les opérations de Glisser-Déplacer. 
+Vous pouvez faire glisser une url depuis votre navigateur. 
+Ensuite, vous aurez le choix entre insérer l'URL et 
+téléchargé le fichier.
+
+<H2>Vérification de la cohérence des champs</H2>
+Quand le contenu d'un champ est modifié, JabRef vérifie que le nouveau
+contenu est acceptable. Pour les champs qui sont utilisés par
+<em>BibTeX</em>, le contenu est vérifié par rapport à l'utilisation
+du caractére '#'. Le symbole dièse doit <em>toujours</em> être
+utilisé par paires, encadrant le nom d'une chaîne <em>BibTeX</em> 
+existante. Notez que JabRef ne vérifie pas si la chaîne <em>BibTeX</em>
+est vraiment définie (ce n'est pas trivial, puisque le style
+<em>BibTeX</em> que vous utilisez peut définir une série
+arbitraire de chaînes dont JabRef n'a pas connaissance).
+<P>
+Si le contenu n'est pas valide, le champ sera affiché en rouge,
+indiquant ainsi une erreur. Dans ce cas, le changement ne 
+sera pas sauvé.
+
+<!--<H2>Word/name autocompletion</H2>
+The entry editor offers autocompletion of words. In the Preferences dialog
+you can enable or disable autocompletion, and choose for which fields
+autocompletion is active.
+<P>With autocompletion, JabRef records all words that appear in
+each of the chosen fields throughout your database. Whenever you write
+the beginning of one of these words, it will be suggested visually. To
+ignore the suggestion, simply write on. To accept the suggestion,
+either press <em>ENTER</em> or use your arrow keys or other keys to
+remove the selection box around the suggested characters.
+<P><em>Note:</em> the words considered for suggestion are only the ones
+appearing in the same field in entries of the same database as the one you
+are editing. There are many ways to realise this kind of feature, and if you feel
+it should have been implemented differently, we'd like to hear your suggestions!
+
+<H2>Copy <em>bibtex</em> key</H2>
+Pressing CTRL-K or the 'key' button causes the <em>bibtex</em> key for your entry
+to be copied to the clipboard.
+-->
+<H2>Génération automatique des clefs <em>BibTeX</em></H2>
+Appuyez sur CTRL-G ou sur le bouton 'Créer la clef BibTeX' (la baguette magique)
+pour générer automatiquement une clef <em>BibTeX</em> à partir du contenu des champs requis.
+
+<p>
+Pour plus d'informations sur la façon dont JabRef génère les clefs <em>BibTeX</em>, voir <a href="LabelPatterns.html">Personnalisation du générateur de clefs BibTeX</a>.
+</BODY>
+</HTML>
diff --git a/src/help/fr/ExternalFiles.html b/src/help/fr/ExternalFiles.html
new file mode 100644
index 0000000..ac80369
--- /dev/null
+++ b/src/help/fr/ExternalFiles.html
@@ -0,0 +1,67 @@
+<HTML>
+
+<BODY text="#275856">
+<basefont size="4" color="#2F4958" face="arial">
+
+<H1>Les liens PDF/PS/URL/DOI dans JabRef</H1>
+
+JabRef vous permet de lier vos entrées avec des fichiers PDF ou PS stockés
+sur votre ordinateur, ainsi que de créer des liens vers des documents sur
+internet par l'intermédiaire d'une URL ou d'un identifiant DOI.
+
+<H2>Configurer les visionneurs externes</H2>
+
+Le programme doit savoir quels visionneurs externes utiliser pour les fichiers
+PDF et PS ainsi que pour les pages internet. Ils sont par défaut configurés
+avec des valeurs qui fonctionnent probablement avec votre système d'exploitation ;
+aussi, il est très possible que vous n'ayez pas besoin de changer ces valeurs
+<p>Pour changer la configuration des visionneurs externes, allez dans le menu
+<b>Options/ Préférences -> Général</b>.
+
+<H2>Ouvrir des fichiers externes ou des liens</H2>
+
+Il y a plusieurs façons d'ouvrir un fichier externe ou une page internet.
+Dans l'éditeur d'entrées, vous pouvez double-cliquer sur le texte du champ
+contenant le nom du fichier, le DOI ou l'URL. Dans le tableau des entrées,
+vous pouvez sélectionner une entrée et utiliser le menu (<b>Outils/ Ouvrir
+PS ou PDF</b> et <b>Outils/ Ouvrir URL ou DOI</b>), le raccourci clavier
+ou le menu contextuel (avec un clic droit). Enfin, vous pouvez cliquer
+sur les icônes PDF, PS, URL ou DOI de la barre d'outils.
+
+<P>Par défaut, le tableau des entrées contient deux colonnes dans
+lesquelles des icônes s'affichent pour les entrées possédant un lien
+vers un fichier externe ou une URL. La seconde colonne du tableau
+montre les icônes qui ouvrent les fichiers PDF et PS (uniquement
+le fichier PDF si les deux fichiers sont présents), 
+et la troisième colonne montre les icônes
+ouvrant les URL et les DOI (uniquement l'URL si les deux liens sont
+présents). Vous ouvrez le fichier ou la page internet en cliquant
+sur une de ces icônes. Vous pouvez désactiver n'importe laquelle de ces
+fonctions en utilisant le menu <b>Options/ Préférences -> Table des
+entrées</b>. 
+
+<H2>Le répertoire PDF principal</H2>
+
+Les fichiers PDF ont un traitement particulier afin de les relier aussi
+facilement que possible à vos entrées. Pour bénéficier de cette fonction,
+vous devez définir un répertoire comme répertoire PDF principal dans
+le menu <b>Options -> Préférences -> Programmes externes</b>.
+Tous les fichiers PDF qui sont stockés dans ou en dessous de ce répertoire
+seront référencés par un chemin relatif. Il vous sera ainsi facile 
+de déplacer le répertoire PDF principal ou de partager votre base de données
+avec d'autres utilisateurs situés en des points différents du réseau.
+
+<P>De plus, si vous donnez à vos fichiers PDF des noms qui correspondent à
+la clef BibTeX des entrées (plus '.pdf'), JabRef sera capable de rechercher
+dans le répertoire PDF principal et ses sous-répertoires le bon fichier PDF.
+Lorsqu'un fichier PDF (nommé correctement) est dans le répertoire,
+vous accéder à cette fonction en cliquant sur le bouton 'Auto' situé à
+coté du champ PDF de l'éditeur d'entrées. Si le fichier PDF est trouvé,
+le champ sera immédiatement rempli.
+
+<P>Si vous nommez le PDF comme mentionné ci-dessus, vous pourrez aussi
+ouvrir le fichier PDF sans configurer préalablement le champ PDF.
+Cependant, dans ce cas, l'icône PDF n'apparaîtra pas dans le tableau
+des entrées.
+
+</HTML>
diff --git a/src/help/fr/GeneralFields.html b/src/help/fr/GeneralFields.html
new file mode 100644
index 0000000..9775d51
--- /dev/null
+++ b/src/help/fr/GeneralFields.html
@@ -0,0 +1,25 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html lang="fr-fr"><head></head>
+
+<body style="color: rgb(39, 88, 86); direction: ltr;">
+<basefont size="4" color="#2F4958" face="arial">
+<h1>Personnalisation des champs généraux</h1>
+
+<p>
+Vous pouvez ajouter un nombre arbitraire d'onglets dans l'éditeur d'entrées. Ceux-ci seront alors présents pour tous les types d'entrées. Pour personnaliser ces onglets, allez dans "Options -> Configurer les champs généraux".
+</p>
+<p>
+Vous devez spécifier un onglet par ligne. La ligne doit commencer par le nom de l'onglet suivi par 2 points (:) puis par les champs séparés par un point-virgule (;), devant être contenus. 
+</p>
+<p>
+Exemple :
+</p>
+<code>
+General:url;keyword;doi;pdf<BR>
+Abstract:abstract;annote
+</code>
+<p>
+produit un onglet appelé "General" contenant les champs url, keywords, doi et pdf et un onglet appelé "Abstract" contenant les champs abstract et annote.
+</p>
+  </body>
+</html>
diff --git a/src/help/fr/GroupsHelp.html b/src/help/fr/GroupsHelp.html
new file mode 100644
index 0000000..5e5cb55
--- /dev/null
+++ b/src/help/fr/GroupsHelp.html
@@ -0,0 +1,136 @@
+<HTML>
+
+<BODY text="#275856">
+<basefont size="4" color="#2F4958" face="arial">
+
+
+<H1>Les groupes</H1>
+
+Les groupes permettent de structurer une base de données BibTeX selon une arborescence rappelant l'organisation des fichiers sur un disque dur dans des répertoires et sous-répertoires. Les deux principales différences sont :
+
+<ul>
+<li> Alors qu'un fichier est toujours localisé dans un seul répertoire, une entrée peut être incluse dans plus d'un groupe.
+<li> Les groupes peuvent utiliser certains critères pour définir dynamiquement leur contenu. Les nouvelles entrées qui correspondent à ses critères sont automatiquement incluses à ces groupes. Cette caractéristique n'est pas disponible dans les systèmes de fichiers habituels, mais est présente dans certains logiciels de messagerie électronique (tel que Thunderbird et Opera).
+</ul>
+
+Sélectionner un groupe montre les entrées contenues dans ce groupe. Sélectionner plusieurs groupes montre les entrées contenues dans au moins un des groupes (union) ou dans tous les groupes (intersection), selon le paramétrage actuel. Tout ceci est expliqué en détail ci-dessous.
+<p>
+Les définitions de groupes sont spécifiques à chaque base de données ; Elles sont sauvées comme un bloc <tt>@COMMENT</tt> dans le fichier <tt>.bib</tt> et sont communes à tous les utilisateurs (des futures versions de JabRef pourrait supporter des groupes dépendants des utilisateurs).
+
+<H2>Interface</H2>
+
+L'interface des groupes se trouve dans le panneau latéral sur la gauche de l'écran. Il peut être affiché ou masqué en appuyant sur <tt>CTRL-SHIFT-G</tt> ou sur le bouton des groupes dans la barre d'outils. L'interface a plusieurs boutons, mais la plupart des fonctions sont accessibles par un menu contextuel ("clic droit"). La fonction Glisser-Déplacer est aussi disponible.
+<p>
+
+<table cellspacing=0 cellpadding=5 border=0 bgcolor=#c0ffc0>
+<tr><td>
+<h2>Quelques exemples rapides</h2>
+
+Vous pourriez vouloir...
+
+<h3>...uniquement créer un groupe et lui assigner quelques entrées.</h3>
+
+Assurez-vous que l'interface des groupes est visible. Appuyez sur le bouton <b>Nouveau Groupe</b>, entrez un nom pour ce groupe puis appuyez sur OK en conservant les valeurs par défaut. Maintenant, sélectionnez les entrées qui doivent être assignées à ce groupe et utiliser un Glisser-Déplacer vers le groupe, ou l'option <b>Ajouter au groupe</b> du menu contextuel. Enfin, sélectionnez le groupe pour voir son contenu (qui doit correspo [...]
+
+<h3>...utiliser le champ <tt>keywords</tt> pour grouper les entrées</h3>
+
+Assurez-vous que l'interface des groupes est visible. Appuyez sur le bouton <b>Nouveau Groupe</b>, entrez un nom pour ce groupe et sélectionner l'option qui groupe dynamiquement les entrées en cherchant un mot-clef dans un champ. Entrez le mot-clef à rechercher, puis cliquer sur OK. Enfin, sélectionnez le groupe pour voir son contenu (qui doit correspondre aux entrées dont le champ <tt>keywords</tt> contient le mot-clef que vous avez spécifié).
+
+<h3>...utiliser une expression de recherche de forme libre pour définir un groupe</h3>
+
+Assurez-vous que l'interface des groupes est visible. Appuyez sur le bouton <b>Nouveau Groupe</b>, entrez un nom pour ce groupe et sélectionner l'option qui groupe dynamiquement les entrées en utilisant une expression de recherche de forme libre. Entrez <tt>author=smith</tt> comme expression de recherche (remplacez <tt>smith</tt> avec un nom d'auteur présent dans votre base et cliquez sur OK. Enfin, sélectionnez le groupe pour voir son contenu (qui doit corres [...]
+
+<h3>...combiner plusieurs groupes</h3>
+
+Créez deux groupes différents (par exemple, tel que décrit ci-dessus). Cliquez sur le bouton <b>Paramètres</b> et assurez-vous que <b>Union</b> est sélectionné. Maintenant, sélectionnez les deux groupes. Vous devriez voir uniquement les entrées appartenant aux deux groupes (ce qui peut en faire aucune ou exactement les mêmes entrées que précédemment si les deux groupes contiennent les mêmes entrées).
+
+<h3>...identifier les groupes se chevauchant</h3>
+
+JabRef vous permet d'identifier facilement les groupes qui se chevauchent parmi les groupes actuellement sélectionnés (c-à-d ceux qui contiennent au moins une entrée qui est aussi contenu dans les groupes actuellement sélectionnés). Cliquez sur le bouton <b>Paramètres</b> et activé l'option pour montrer les groupes qui se chevauchent. Ensuite sélectionnez un groupe qui chevauche d'autres groupes. Les autres groupes devraient  [...]
+
+</tr></td>
+</table>
+<p>
+
+<H2>Les types de groupes</H2>
+
+Dans JabRef 1.8, il y a quatre types de groupes différents :
+
+<ol>
+<li> Le groupe <b>Toutes les entrées</b>, qui -- comme son nom le suggère -- contient toutes les entrées, est toujours présent et ne peut pas être édité ou supprimé.
+<li> <b>Les groupes manuels</b> se comportent comme les répertoires d'un disque et contiennent uniquement les entrées que vous leur avez explicitement assignées. 
+<li> <b>Les groupes dynamiques basés sur la recherche d'un mot-clef</b> contiennent des entrées pour lesquelles un champ BibTeX donné (par ex. <tt>keywords</tt>) contient un certain mot-clef (par ex. <tt>électrique</tt>). Cette méthode ne nécessite pas d'assignation manuelle des entrées, mais utilise les informations qui sont déjà présentes dans la base de données. Si toutes les entrées de votre base de d [...]
+<li> <b>Les groupes dynamiques basés sur des expressions de recherche de forme libre</b> contiennent les entrées qui correspondent à l'expression de recherche spécifiée et suivant la même syntaxe que <a href="SearchHelp.html">l'interface de recherche</a> dans le panneau latéral. Cette <a href="SearchHelp.html#advanced">syntaxe</a> supportent les opérateurs logiques (<tt>AND</tt>, <tt>OR</tt>, <tt>NOT</tt>) et permet de spécifi [...]
+</ol>
+
+Chaque groupe que vous créez fait partie de ces trois derniers types. La fenêtre d'édition des groupes, qui s'ouvre en double-cliquant sur un groupe, montre une description succincte (en français de tous les jours) de la définition du groupe sélectionné/édité. 
+
+<H2>La structure des groupes, créer et supprimer des groupes</H2>
+
+Comme pour les répertoires, les groupes sont structurés selon une arborescence, avec le groupe <b>Toutes les entrées</b> à la racine. En faisant un clic droit sur un groupe, vous pouvez ajoutez un nouveau groupe à l'arbre, soit au même niveau que le groupe sélectionné, soit comme un sous-groupe. Le bouton <b>Nouveau groupe</b> vous permet de créer un nouveau sous-groupe au groupe <b>Toutes les entrées</b>, quelque soit  [...]
+<p>
+Annuler et Répéter fonctionnent pour toutes les éditions.
+
+<H3>Les groupes manuels</h3>
+
+Les groupes manuels sont alimentés uniquement par l'assignation explicite des entrées. Après avoir créer un groupe manuel, vous sélectionnez les entrées à lui assigner et utilisez soit un Glisser-Déplacer soit le menu contextuel de la table des entrées. Il n'y a pas d'options à configurer.
+<p>
+Cette méthode de groupement nécessite que toutes les entrées aient une clef BibTeX unique. Dans le cas de clefs BibTeX manquantes ou dupliquées, l'assignation de ces entrées ne pourra pas être correctement rétablie lors de futures sessions.
+
+<H3>Les groupes dynamiques</h3>
+
+Le contenu d'un groupe dynamique est défini par une condition logique. Uniquement les entrées qui remplissent cette condition sont contenues dans le groupe. Cette méthode utilise des informations stockées dans la base de données elle-même et s'actualise dynamiquement dés que la base de données est modifiée.
+<p>
+Deux types de conditions logiques peuvent être utilisées :
+<dl>
+<dt><b>Recherche d'un mot-clef dans un champ</b></dt>
+<dd>
+Cette méthode groupe les entrées dans lesquelles un champ BibTeX spécifié (par ex. <tt>keywords</tt>) contient le terme de recherche spécifié (par ex. <tt>électrique</tt>). Evidemment, pour que cela fonctionne, le champ doit être présent dans toutes les entrées et son contenu doit être pertinent. L'exemple ci-dessus regroupera toutes les entrées qui font références à électrique.  [...]
+</dd>
+<dt><b>Utiliser une expression de recherche de forme libre</b></dt>
+<dd>
+Ceci est similaire à ce qui est décrit ci-dessus mais, au lieu de rechercher dans un seul champ pour un unique terme de recherche, la <a href="SearchHelp.html#advanced">syntaxe des expressions de recherche</a>  peut être utilisées, autorisant l'emploi d'opérateurs logiques (<tt>AND</tt>, <tt>OR</tt>, <tt>NOT</tt>) et permettant les recherches sur plusieurs champs BibTeX. Par exemple, l'expression de recherche <tt>keywords=régression and not keywor [...]
+</dd>
+</dl>
+
+Dans le panneau des groupes, les groupes dynamiques sont par défaut affichés en <i>italique</i>. Cela peut être modifié dans les préférences [NdT: où ça ?].
+
+<h3>Contexte hiérarchique</h3>
+
+Par défaut, un groupe est <b>indépendant</b> de sa position dans l'arbre des groupes : lorsqu'il est sélectionné, uniquement son contenu est affiché. Cependant, particulièrement lors de l'utilisation de groupes dynamiques, il est souvent utile de définir un sous-groupe qui <b>raffine son sur-groupe</b>, c-à-d que, lorsqu'il est sélectionné, les entrées contenues dans les deux groupes sont affichées.  [...]
+<p>
+Le complément logique au groupe raffinant est un groupe qui <b>inclut ses sous-groupes</b>, c-é-d qu'en le sélectionnant, ce ne sont pas uniquement les propres entrées du groupe mais aussi les entrées de ses sous-groupes qui sont affichées. Dans l'arbre des groupes, ce type de groupe possède un icône spécial (cela peut-être annulé dans les préférences).
+
+<h2>Afficher les entrées d'un groupe, combiner plusieurs groupes</H2>
+
+Sélectionner un groupe montre les entrées contenues dans ce groupe en les surlignant et, selon le paramétrage (accessible en cliquant sur le bouton <b>Paramètres</b>), les déplacent au sommet de la liste et/ou les sélectionnent. Ces options sont identiques à celles disponibles habituellement pour la recherche.
+<p>
+Quand plusieurs groupes sont sélectionnés, soit l'union soit l'intersection de leurs contenus est affiché en fonction de paramétrage choisi. Cela permet de combiner rapidement plusieurs conditions. Par exemple, si vous avez un groupe manuel <tt>Extrêmement Important</tt> auquel vous assignez toutes les entrées extrêmement importantes, vous pouvez voir les entrées extrêmement importantes dans tout autre groupe en sélection [...]
+
+<h2>Groupes et recherche</h2>
+
+Lors de l'affichage de contenu d'un ou plusieurs groupes, une recherche peut être effectuée à l'intérieur de ce contenu en utilisant la technique de recherche habituelle.
+
+<h2>Surligner les groupes se chevauchant</h2>
+
+Le bouton <b>Paramètres</b> offre une option de surlignement des groupes se chevauchant. Si elle est activée, lors de la sélection d'un ou plusieurs groupes, tous les groupes contenant au moins une des entrées appartenant au(x) groupe(s) sélectionné(s) sont surlignés. Cela identifie rapidement les chevauchements entre les contenus des groupes. Vous pourriez, par exemple, créer un groupe <tt>A lire</tt> qui contient toutes les entr&e [...]
+
+<h2>Caractéristiques avancées</h2>
+
+Une fois que vous maîtriserez les concepts de groupe décrits ci-dessus, les caractéristiques avancées suivantes pourraient vous être utile.
+
+<h3>Création automatique de groupes dynamiques</h3>
+
+En cliquant sur le bouton <b>Créer automatiquement des groupes pour la base de données</b> (les trois "+" jaunes-orangés), vous pouvez facilement créer une série de groupes pertinents pour votre base de données. Ce dispositif collectera tous les mots trouvés dans le champ que vous aurez spécifié et créera un groupe pour chaque mot. C'est utile si, par exemple, votre base contient des mots-clefs pertinents for toutes le [...]
+<p>
+Vous pouvez aussi spécifiés des caractères à ignorer, par exemple les virgules utilisées entre les mots-clefs. Ils seront traités comme des séparateurs de mots et non comme en faisant partie. Cette étape est importante pour que les mots-clefs composés tels que <tt>distribution de Laplace</tt> soient reconnus comme une unique entité sémantique (vous ne pouvez pas utiliser cette option pour supprimer des mots comp [...]
+
+<h3>Rafraîchir l'affichage des groupes</h3>
+
+Le bouton <b>Rafraîchir</b> met à jour la table des entrées pour refléter la sélection actuelle des groupes. Habituellement, cela s'effectue automatiquement, mais, dans quelques occasions (par exemple après un Annuler/Répéter en rapport avec les groupes), un rafraîchissement manuel est nécessaire.
+
+<h3>Combiner des groupes raffinants avec des groupes incluants</h3>
+
+Si un groupe raffinant est le sous-groupe d'un groupe qui inclue ses sous-groupes -- les frères du groupe raffinant --, les frères sont ignorés quand le groupe raffinant est sélectionné.
+
+</HTML> 
\ No newline at end of file
diff --git a/src/help/fr/HelpHelp.html b/src/help/fr/HelpHelp.html
new file mode 100644
index 0000000..f29ab2a
--- /dev/null
+++ b/src/help/fr/HelpHelp.html
@@ -0,0 +1,30 @@
+<HTML>
+
+<BODY text="#275856">
+<basefont size="4" color="#2F4958" face="arial">
+
+<H1>La fenêtre d'aide</H1>
+<em>S'ouvre en cliquant sur le bouton d'aide ou en appuyant sur F1.</em>
+<P>
+La fenêtre d'aide est conçue pour fournir des informations sur l'utilisation de JabRef.
+
+<H2>Naviguer entre les fichiers d'aide</H2>
+
+La fenêtre d'aide est en fait un navigateur HTML simplifié, et les fichiers d'aide
+sont des fichiers HTML standard.
+<P>
+A l'ouverture, la fenêtre d'aide affichera des fichiers différents
+selon la fenêtre à partir de laquelle elle est lancée. Si ce fichier
+n'explique pas les points qui vous intéressent, le bouton <em>Contenu</em>
+de la barre d'outils vous affichera la liste des fichiers d'aide disponibles.
+
+<P>
+De plus, la barre d'outils contient des boutons de navigation pour afficher
+les fichiers précédents et suivants. Ils sont similaires aux boutons
+<em>Précédent</em> et <em>Suivant</em> d'un navigateur internet standard.
+Les raccourcis clavier pour la navigation sont CTRL-SHIFT et la flèche gauche
+pour <em>Précédent</em>, CTRL-SHIFT et la flèche droite pour <em>Suivant</em>.
+
+<P>
+La fenêtre d'aide se ferme en pressant ESCAPE.
+</HTML>
diff --git a/src/help/fr/ImportInspectionDialog.html b/src/help/fr/ImportInspectionDialog.html
new file mode 100644
index 0000000..5ed3343
--- /dev/null
+++ b/src/help/fr/ImportInspectionDialog.html
@@ -0,0 +1,19 @@
+<HTML>
+
+<BODY text="#275856">
+<basefont size="4" color="#2F4958" face="arial">
+
+<h1>Fenêtre de vérification des importations</h1>
+
+<p>
+Quand vous importez de nouvelles entrées à partir d'un format de référence connu, ou que vous récupérez des entrées directement sur internet, elles sont tout d'abord affichées dans une fenêtre pour leur vérification. A ce moment, aucune des entrées n'a encore été ajoutée à la base de données actuellement ouverte (si une base est ouverte).
+</p>
+
+
+<P>La fenêtre de vérification vous permet de supprimer les entrées que vous ne voulez pas garder et d'effectuer des opérations simples telles que la générations des clefs BibTeX pour ces entrées ou leur ajout à des <a href="GroupsHelp.html">groupes</a>. Si vous les importez dans une base de données existante, il est souvent plus facile d'effectuer ces opérations avant que les nouvelles entrées soient insér [...]
+</p>
+
+
+
+
+</HTML>
diff --git a/src/help/fr/JabRefHelp.html b/src/help/fr/JabRefHelp.html
new file mode 100644
index 0000000..1fb13cc
--- /dev/null
+++ b/src/help/fr/JabRefHelp.html
@@ -0,0 +1,34 @@
+<HTML>
+
+<BODY text="#275856">
+
+<basefont size="4" color="#2F4958" face="arial">
+
+<H1>JabRef</H1>
+
+<P><strong>Note :</strong> Le programme <em>BibTeX</em> est mentionné de nombreuses fois
+dans ces fichiers d'aide. <em>BibTeX</em> est un utilitaire pour la génération
+de références bibliographiques dans les documents LaTeX, créé par Oren
+Patashnik. Le même format de base de données est aussi utilisé par CiteMaker,
+un utilitaire pour la génération de bibliographie d'Adobe FrameMaker.
+
+<P>JabRef est un programme permettant l'exploitation des bases de données <em>BibTeX</em>.
+Ce programme n'utilise aucun format de fichier interne, ce qui signifie
+qu'habituellement vous ouvrez et sauvez vos bases de données directement
+dans le format .bib de <em>BibTeX</em>. Cependant, vous pouvez aussi importer
+dans JabRef d'autres formats de bases de données bibliographiques.
+
+<P>JabRef possède des fonctionnalités de tri et de recherche afin
+de vous donner une vue d'ensemble du contenu de vos bases de données. Vous
+pouvez facilement ajouter de nouvelles entrées à vos bases de données
+sans avoir à vous souvenir des informations requises, et les clefs
+<em>BibTeX</em> peuvent être générées automatiquement. JabRef sera surtout
+utile aux utilisateurs de <em>BibTeX</em> ou CiteMaker, mais il peut aussi
+être utile à ceux qui se servent d'autres systèmes de référencements ou
+qui veulent simplement organiser leurs sources bibliographiques.
+
+<P>
+<a href="BaseFrameHelp.html">La fenêtre principale de JabRef</a>
+
+</BODY>
+</HTML>
diff --git a/src/help/fr/JournalAbbreviations.html b/src/help/fr/JournalAbbreviations.html
new file mode 100644
index 0000000..c061693
--- /dev/null
+++ b/src/help/fr/JournalAbbreviations.html
@@ -0,0 +1,52 @@
+<HTML>
+
+<BODY text="#275856">
+<basefont size="4" color="#2F4958" face="arial">
+
+<H1>Abréviations des journaux</H1>
+
+Cette fonction peut être configurée dans <b>Outils -> Gérer les abréviations de journaux</b>.
+
+<p>JabRef peut basculer automatiquement les noms de journaux entre leurs formes abrégées et non abrégées si les noms sont contenus dans une de vos listes de journaux. Vous pouvez utiliser plusieurs listes, chacune étant un fichier texte sauvé sur votre disque dur.
+
+<H2>Utiliser cette fonction</H2>
+<p>
+La conversion de noms de journaux peut être effectuée depuis l'éditeur d'entrées ou depuis le menu <b>Outils</b>. Dans l'éditeur d'entrées, vous trouverez un bouton nommé <i>Type d'abréviation</i> dans le champ <i>journal</i>.
+Cliquer sur ce bouton changera le mode d'affichage du nom du journal. Trois modes sont possibles :
+<ul>
+    <li>Nom complet, par exemple "Aquacultural Engineering"</li>
+    <li>Abréviation ISO, par exemple "Aquacult. Eng."</li>
+    <li>Abréviation MEDLINE, par exemple "Aquacult Eng"</li>
+</ul>
+Si le nom du journal actuel n'est pas trouvé dans la liste des journaux, le champ ne sera pas modifié.
+
+<p>
+Pour convertir en une seule fois les noms de journaux de beaucoup d'entrées, vous pouvez sélectionner ces entrées et choisir <b>Outils -> Abréger les noms de journaux (ISO)</b>, <b>Outils -> Abréger les noms de journaux (MEDLINE)</b> ou <b>Outils -> Développer les noms des journaux</b>. Ces deux actions abrégeront ou développeront les noms de journaux pour toutes les entrées sélectionnées dont le nom de journal  [...]
+
+<h2>Paramétrer vos listes de journaux</h2>
+
+Vous pouvez avoir plusieurs listes de journaux, toutes sous la forme de fichiers externes liés depuis JabRef. La liste par défaut peut être éditée depuis JabRef.
+
+<H3>Votre liste personnelle des abréviations de journaux</H3>
+
+Votre liste personnelle de journaux est gérée dans la partie supérieure de la fenêtre <b>Gérer les abréviations de journaux</b>.
+Pour commencer à construire votre liste d'abréviations de journaux, choisissez <i>Nouveau fichier</i>, et entrez manuellement le nom du fichier ou utilisez le bouton <i>Naviguer</i>. Si vous disposez déjà d'un fichier que vous souhaitez utiliser comme point de départ, choisissez <i>Fichier existant</i> et utilisez le bouton <i>Naviguer</i> pour choisir le fichier. La table sera mise à jour pour tenir compte du contenu de la liste sélection [...]
+
+<p>La table et les boutons d'outils à sa droite vous permettent d'ajouter, de supprimer et d'éditer les entrées de journaux. Pour chaque entrée, vous devez fournir le nom complet du journal et son abréviation ISO (par exemple "Aquacultural Engineering" et "Aquacult. Eng."). Pour éditer une entrée, double-cliquez sur sa ligne dans la table.
+
+<p>Une fois que vous avez cliqué sur <i>OK</i>, si vous avez sélectionné un fichier et que la table contient au moins une entrée, le contenu de la table sera stocké dans le fichier sélectionné, et la liste des journaux de JabRef sera mise à jour.
+
+<h3>Listes externes de journaux</h3>
+
+En plus de votre liste personnelle, vous pouvez relier plusieurs listes externes. Ces liens peuvent être paramétré dans la partie inférieure de la fenêtre <b>Gérer les abréviations de journaux</b>. Les listes externes sont similaires à la liste personnelle - la seule différence est que JabRef ne fournit pas d'interface pour éditer les listes externes.
+<p>
+Pour ajouter une nouvelle liste externe, cliquez sur le bouton <b>+</b>. Cela ajoutera une nouvelle entrée à l'interface. Ensuite, utilisez soit le bouton <i>Naviguer</i> soit le bouton  <i>Télécharger</i> situé à coté d'une des entrées de la partie inférieure de la fenêtre.
+    <ul>
+    <li>Le bouton <i>Naviguer</i> vous permet de sélectionner un fichier existant sur votre ordinateur.</li>
+    <li>Le bouton <i>Télécharger</i> vous permet de télécharger une liste depuis l'internet en entrant une URL, de la stocker dans un fichier local sur votre ordinateur et de la lier comme une liste de journaux depuis JabRef. L'URL sera par défaut l'adresse de la liste de journaux disponible depuis la page web de JabRef. Cette liste est incomplète mais pourra être améliorée dans le futur.</li>
+    </ul>
+
+Toute entrée dans votre liste personnelle de journaux sera prioritaire devant une entrée ayant le même nom complet dans l'une des listes externes. De même, les listes externes sont prioritaires selon l'ordre dans lequel elles sont listées.
+
+</BODY>
+</HTML>
diff --git a/src/help/fr/LabelPatterns.html b/src/help/fr/LabelPatterns.html
new file mode 100644
index 0000000..1524dde
--- /dev/null
+++ b/src/help/fr/LabelPatterns.html
@@ -0,0 +1,80 @@
+<HTML>
+
+<BODY text="#275856">
+
+<basefont size="4" color="#2F4958" face="arial">
+
+<H1>Personnalisation du générateur de clefs BibTeX</H1>
+
+<p>
+Dans le menu 'Paramétrage des clefs' de la fenêtre Préférences, on peut indiquer les champs à utiliser pour la génération automatique des clefs BibTeX. La définition peut être faite pour chacune des entrées standards.
+</p>
+
+<p>
+La définition peut contenir n'importe quel texte au choix ainsi que des marqueurs de champs qui indiquent les champs particuliers de l'entrée utilisés et leur position dans la clef. Un marqueur de champ est constitué généralement du nom du champ entre crochets, par ex. <b>[volume]</b>. Si le champ n'est pas défini dans l'entrée lorsque la clef est générée, aucun texte n'est inséré dans la clef.
+</p>
+
+<p>
+Plusieurs marqueurs de champs spéciaux sont fournis et permettent l'extraction d'une partie du contenu d'un champ. Ils sont donnés ci-dessous. Vous pouvez librement suggérer de nouveaux marqueurs de champs spéciaux.
+</p>
+
+<p>
+Les marqueurs de champs spéciaux :
+</p>
+
+<ul>
+<li><b>[<code>auth</code>]</b> : Le nom du premier auteur<BR>
+<li><b>[<code>authors</code>]</b> : Le nom de tous les auteurs<BR>
+<li><b>[<code>authorsN</code>]</b>: Les noms des N premiers auteurs. S'il y a plus d'auteurs, "EtAl" est ajouté.<BR>
+<li><b>[<code>authIniN</code>]</b> : Les N premières lettres (ou moins) du nom de chacun des auteurs.<BR>
+<li><b>[<code>authorIni</code>]</b> : Les 5 premières lettres du nom du premier auteur et les initiales du nom des auteurs restants<BR>
+<li><b>[<code>authN</code>]</b> : Les N premières lettres du premier auteur.<BR>
+<li><b>[<code>authN_M</code>]</b> : Les N premières lettres du nom des M premiers auteurs.<BR>
+<li><b>[<code>auth.auth.ea</code>]</b> : Le nom des deux premiers auteurs suivi de ".ea" lorsqu'ils sont plus de deux.<BR>
+<li><b>[<code>authshort</code>]</b> : Le nom s'il n'y a qu'un seul auteur. Jusqu'à trois auteurs, le premier caractère du nom de chacun d'eux. Au delà de trois auteurs, le caractère plus (+) est ajouté.<BR>
+</ul>
+<b>Note :</b> S'il n'y a pas d'auteur (dans le cas d'un livre �dit�), alors tous les marqueurs <b><code>[auth...]</code></b> ci-dessus utiliseront l'�diteur(s) (s'il y en a) comme alternative. Ainsi l'�diteur(s) d'un livre sans auteur sera trait� comme l'auteur(s) pour la g�n�ration des clefs.
+Si vous ne d�sirez pas ce comportement, c'est � dire si vous voulez un marqueur qui soit vide s'il n'y a pas d'auteur, utilisez le code <b><code>pureauth</code></b> au lieu du code <b><code>auth</code></b> dans les marqueurs ci-dessus. Par exemple, <b><code>[pureauth]</code></b> ou <b><code>[pureauthors3]</code></b>.
+<ul>
+<li><b>[<code>edtr</code>]</b> : Le nom du premier éditeur<BR>
+<li><b>[<code>edtrIniN</code>]</b> : Les N premières lettres du nom de chaque éditeur<BR>
+<li><b>[<code>editors</code>]</b> : Le nom des chacun des éditeurs<BR>
+<li><b>[<code>editorIni</code>]</b> : Les cinq premières lettres du nom du premier éditeur suivi des initiales du nom des éditeurs restants.<BR>
+<li><b>[<code>edtrN</code>]</b> : Les N premières lettres du nom du premier éditeur<BR>
+<li><b>[<code>edtrN_M</code>]</b> : Les N premières lettres du nom des M premiers éditeurs.<BR>
+<li><b>[<code>edtr.edtr.ea</code>]</b> : Le nom des deux premiers éditeurs suivi de ".ea" lorsqu'ils sont plus de deux.<BR>
+<li><b>[<code>edtrshort</code>]</b> : Le nom s'il n'y a qu'un seul éditeur. Jusqu'à trois éditeurs, le premier caractère du nom de chacun d'eux. Au delà de trois éditeurs, le caractère plus (+) est ajouté.<BR>
+<li><b>[<code>firstpage</code>]</b> : Le numéro de la première page de la publication<BR>
+<li><b>[<code>lastpage</code>]</b> : Le numéro de la dernière page de la publication<BR>
+<li><b>[<code>shorttitle</code>]</b> : Les 3 premiers mots du titre<BR>
+<li><b>[<code>shortyear</code>]</b> : Les 2 derniers chiffres de l'année de publication<BR>
+<li><b>[<code>veryshorttitle</code>]</b> : Le premier mot du titre qui ne soit pas 'the', 'a', 'an'.<BR>
+</ul>
+ 
+ <p>
+ Un nom de champs (ou celui de l'un des pseudo-champs vu au dessus) peut, de façon optionnelle, être suivi par un ou plusieurs modificateurs. Les modificateurs sont appliqués dans l'ordre
+où ils sont spécifiés.
+<ul>
+ <li><b>:abbr</b>: Abrège le texte produit par le nom du champ ou un marqueur de champ spécial.
+ Uniquement le premier caractère et les caractères suivant un espace seront inclus. Par exemple, <b>[journal:abbr]</b> abrègera "Journal of Fish Biology" en "JoFB".<br>
+<li><b>:lower</b>, force le texte inséré par le marqueur de champ à être en minuscules. Par exemple, <b>[auth:lower]</b> bascule le nom du premier auteur en minuscules.
+</ul>
+
+<P>
+Si vous n'avez pas défini de modèle de clef pour un type d'entrées donné, le <b>Modèle de clef par
+défaut</b> sera utilisé. Vous pouvez changer le modèle par défaut - son paramétrage se
+trouve au-dessus de la liste des types d'entrées dans la section 
+<b>Paramétrage des clefs</b> de la fenêtre <b>Préférences</b>.
+
+<P>
+La clef utilisée par défaut est [auth][year]; elle produit des clefs du type <code>Yared1998</code>. Si la clef n'est pas unique dans la base de donnée, elle est modifiée par l'ajout d'une des lettres de a à z et ceci jusqu'a ce quelle soit unique. De cette façon, les étiquettes ressemblent à :
+</p>
+
+<blockquote> 
+<code>Yared1998</code><BR> 
+<code>Yared1998a</code><BR>
+<code>Yared1998b</code> 
+</blockquote>
+
+</body>
+</html>
diff --git a/src/help/fr/MarkingHelp.html b/src/help/fr/MarkingHelp.html
new file mode 100644
index 0000000..a857237
--- /dev/null
+++ b/src/help/fr/MarkingHelp.html
@@ -0,0 +1,26 @@
+<HTML>
+
+<BODY text="#275856">
+<basefont size="4" color="#2F4958" face="arial">
+
+<H1>Etiqueter les entrées</H1>
+
+Vous avez la possibilité d'<em>étiqueter</em> des entrées. Les raccourcis
+claviers sont CTRL-M et CTRL-SHIFT-M pour, respectivement, étiqueter et
+désétiqueter les entrées sélectionnées. Vous pouvez aussi accéder à ces actions
+en utilisant le menu <b>Edition</b>.
+
+<p>Noter qu'étiqueter des entrées n'est pas la même chose que les sélectionner.
+Les entrées étiquetées se comportent différemment des autres, et ce de deux façons.
+Premièrement, elles sont toujours affichées avec un fond jaune dans le tableau
+des entrées. Deuxièmement, elles seront affichées en haut de la liste des entrées,
+et ce tant que votre table n'est pas triée selon des groupes ou par une recherche
+flottante.
+
+<p>Sauver votre base de données préservera l'étiquetage.
+
+<p>Les entrées étiquetées vous seront utiles si, par exemple, vous avez besoin
+de faire plusieurs recherches sans perdre vos premiers résultats, ou si vous avez
+besoin de vous souvenir des articles ou des livres auxquels il faut que vous
+prêtiez attention.
+</HTML>
diff --git a/src/help/fr/MedlineHelp.html b/src/help/fr/MedlineHelp.html
new file mode 100644
index 0000000..ac44a86
--- /dev/null
+++ b/src/help/fr/MedlineHelp.html
@@ -0,0 +1,43 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html lang="fr-fr"><head></head>
+
+<body style="color: rgb(39, 88, 86); direction: ltr;">
+<basefont size="4" color="#2F4958" face="arial">
+
+<h1>Récupération d'entrées depuis Medline</h1>
+
+<p>
+JabRef peut télécharger des citations depuis la base de données Medline. Pour réaliser cette opération, sélectionnez <b>Outils -> Recherche Medline</b> et vous verrez apparaître l'interface de Medline dans le panneau latéral.
+</p>
+
+<p>
+Il y a deux manières d'indiquer les entrées à télécharger :
+</p>
+
+<ol>
+<li> Entrez un ou plusieurs ID Medline (séparés par des virgules/points-virgules) dans le champ texte
+<li> Entrez une série de noms et/ou de mots à rechercher. Vous pouvez utiliser les opérateurs <em>and</em> et <em>or</em> et les parenthèses pour raffiner l'expression de votre recherche.
+</ol>
+
+<p>
+Dans les deux cas, appuyez sur la touche <b>Enter</b> ou sur le bouton <b>Rechercher</b>. Si vous utilisez une recherche de texte, vous serez informé du nombre d'entrées trouvées et vous pourrez choisir le nombre d'entrées à télécharger.
+</p>
+
+<p>
+Les entrées recherchées seront ajoutées à votre base de données active.
+</p>
+
+<h2>Utilisation d'un serveur proxy</h2>
+
+<p>
+Si vous avez besoin d'utiliser un serveur de proxy, passez le nom du serveur et le numéro de port au lancement de java. Ces paramètres d'environnement sont documentés sur
+</p>
+<p>
+http://java.sun.com/j2se/1.4.2/docs/guide/net/properties.html
+</p>
+<p>
+<code>java -Dhttp.proxyHost="hostname" -Dhttp.proxyPort="portnumber"</code>
+</p>
+</p>
+</body>
+</html>
diff --git a/src/help/fr/OpenOfficeHelp.html b/src/help/fr/OpenOfficeHelp.html
new file mode 100644
index 0000000..ac78a75
--- /dev/null
+++ b/src/help/fr/OpenOfficeHelp.html
@@ -0,0 +1,45 @@
+<HTML>
+
+<BODY text="#275856">
+<basefont size="4" color="#2F4958" face="arial">
+
+
+<H1>Utiliser les bibliographies JabRef dans OpenOffice.org</H1>
+
+JabRef peut exporter votre base de données dans le format de tableur OpenOffice.org 1.1 <b>.sxc</b> ainsi que dans le format OpenDocument <b>.ods</b> utilisé par OpenOffice.org 2.0.
+<p>
+Dans les deux cas, la table exportée contiendra une feuille de calcul, listant les entrées selon les lignes et les différents champs en colonnes. L'ordre et les noms des colonnes sont configurés pour être compatible avec les fonctions bibliographiques d'OpenOffice.org (OOo 1.1 dans le cas d'une exportation au format <b>.sxc</b>, et OOo 2.0 pour une exportation au format <b>.ods</b>).
+
+<h2>Utiliser le fichier exporté comme une base de données dans OpenOffice 2.0 et supérieur</h2>
+
+Suivez les étapes suivantes pour configurer une feuille de calcul exportée par JabRef comme une base de données bibliographique dans OpenOffice.org :
+<ul>
+    <li>Exporter votre base en utilisant le format <b>.ods</b></li>
+    <li>Démarrer OpenOffice.org Writer</li>
+    <li>Choisir <b>Outils -> Options -> OpenOffice.org Base -> Base de données</b></li>
+    <li>�diter la base de données <i>Bibliography</i>, et lui donner un autre nom, tel que
+          <i>Bibliography-old</i></li>
+    <li>Fermer la fenêtre <b>Options</b> et choisir <b>Fichier -> Nouveau -> Base de données</b></li>
+    <li>Choisir <b>Se connecter à une base de données existante</b>, sélectionner <b>Classeur</b> comme type de base de données, cliquer sur <b>Suivant</b> et choisir le fichier <b>.ods</b> que vous avez exporté.</li>
+    <li>Cliquer sur <b>Terminer</b>, puis choisir le nom <i>Bibliographie</i> quand demandé.</li>
+</ul>                                       
+Après avoir effectué ces étapes, choisir <b>Outils -> Base de données bibliographique</b>. Votre base de données devrait maintenant s'afficher.
+<p>
+
+<h2>Utiliser le fichier exporté comme une base de données bibliographique dans OpenOffice 1.1.x</h2>
+
+ <ul>
+    <li>Exporter votre base de données vers le format <b>.sxc</b></li>
+    <li>Démarrer OpenOffice.org Texte</li>
+    <li>Choisir <b>Outils -> Sources de données...</b></li>
+    <li>Sélectionner la base de données <i>Bibliography</i> et lui donner un autre nom, tel que 
+     <i>Bibliography-old</i>. Cliquer sur <b>Appliquer</b>.</li>
+    <li>Cliquer sur <b>Nouvelle source de données</b>. Une nouvelle entrée apparaît. La renommer 
+        <i>Bibliography</i>.</li>
+     <li>Changer le <b>type de BD</b> en <b>Classeur</b>. Cliquer le bouton <b>...</b> 
+     au bout de la ligne <b>URL de la source de données</b>. Choisir le fichier <b>.sxc</b> que vous avez exporté.</li>
+     <li>Cliquer sur <b>OK</b> pour fermer la fenêtre <b>Gestion des sources de données</b>.</li>
+</ul>
+Après avoir effectué ces étapes, choisir <b>Outils -> Base de données bibliographique</b>. Votre base de données devrait maintenant s'afficher.
+
+</HTML>
diff --git a/src/help/fr/OwnerHelp.html b/src/help/fr/OwnerHelp.html
new file mode 100644
index 0000000..844acd5
--- /dev/null
+++ b/src/help/fr/OwnerHelp.html
@@ -0,0 +1,16 @@
+<HTML>
+
+<BODY text="#275856">
+<basefont size="4" color="#2F4958" face="arial">
+
+<H1>Le champ 'owner' (propriétaire)</H1>
+
+JabRef peut éventuellement signer toutes les nouvelles entrées ajoutées ou importées
+dans une base de données avec votre nom.
+Vous pouvez activer ou désactiver cette fonction dans le menu
+<b>Options/ Préférences -> Général</b>, et vous pouvez aussi changer le nom utilisé pour
+signer vos entrées. Le nom utilisé par défaut est votre nom d'utilisateur.
+
+<p>Ce nom sera ajouté dans un champ nommé 'owner', qui, par défaut, est visible
+dans l'onglet <b>Champs Généraux</b> de l'éditeur d'entrées.
+</HTML>
diff --git a/src/help/fr/PreviewHelp.html b/src/help/fr/PreviewHelp.html
new file mode 100644
index 0000000..f396b63
--- /dev/null
+++ b/src/help/fr/PreviewHelp.html
@@ -0,0 +1,17 @@
+<HTML>
+
+<BODY text="#275856">
+<basefont size="4" color="#2F4958" face="arial">
+
+<H1>Configuration de l'aperçu des entrées</H1>
+
+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.
+
+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>.
+
+</HTML>
diff --git a/src/help/fr/RemoteHelp.html b/src/help/fr/RemoteHelp.html
new file mode 100644
index 0000000..365ddeb
--- /dev/null
+++ b/src/help/fr/RemoteHelp.html
@@ -0,0 +1,34 @@
+<HTML>
+
+<BODY text="#275856">
+<basefont size="4" color="#2F4958" face="arial">
+
+<H1>Accès à distance</H1>
+
+Cette fonction peut être activée et configurée dans <b>Préférences -> Avancé</b>.
+
+<p><i>Notez qu'activer cette fonction sous Windows XP SP2 (et probablement d'autres configurations)
+peut afficher une boîte de message disant que certaines fonctions du programme ont été bloquées
+par le pare-feu de Windows. Vous pouvez en toute sécurité dire au pare-feu de continuer à bloquer ;
+le pare-feu n'interférera pas avec l'accès à distance de JabRef.</i>
+
+<p>Si l'accès à distance est activé, JabRef se mettra à écouter un port spécifique lors de son démarrage.
+Cela signifie que les autres applications peuvent envoyer des informations à JabRef à travers ce port.
+JabRef n'acceptera que des connexions locales, afin d'éviter le risque d'interférence à partir de l'extérieur.
+
+<p>
+La réservation du port permet à une seconde instance de JabRef de découvrir
+qu'une première instance tourne déjà.
+Dans ce cas, à moins qu'elle soit spécifiquement configurée pour tourner en mode autonome, la
+seconde instance de JabRef passera ses options de sa ligne de commande à la première instance en utilisant
+le port, puis se terminera immédiatement.
+
+<p>La première instance de JabRef lira les options de la ligne de commande et effectuera
+les actions indiquées, tel que la lecture ou l'importation d'un fichier, ou la fusion
+d'un fichier avec la base de données actuellement affichée. Si un fichier est importé
+en utilisant l'option de ligne de commande <code>--importToOpen</code>, les entrées importées
+seront ajoutées à la base de données actuellement affichée. Si aucune base de données n'est
+ouverte, une nouvelle base sera créée.
+
+</BODY>
+</HTML> 
\ No newline at end of file
diff --git a/src/help/fr/SearchHelp.html b/src/help/fr/SearchHelp.html
new file mode 100644
index 0000000..f16e31d
--- /dev/null
+++ b/src/help/fr/SearchHelp.html
@@ -0,0 +1,87 @@
+<HTML>
+
+<BODY text="#275856">
+<basefont size="4" color="#2F4958" face="arial">
+
+<H1>Recherche</H1>
+
+Il y a trois modes différents de recherche dans JabRef.
+
+<p>
+<em>CTRL-F</em> ouvre ou active l'interface de recherche. Appuyer 
+sur <em>CTRL-F</em> plusieurs fois modifie le mode de recherche.
+En recherche incrémentale, <em>CTRL-F</em> affiche
+l'occurrence suivante de la chaîne à rechercher.
+<p>
+<em>CTRL-SHIFT-F</em> ouvre ou active l'interface de recherche, et
+sélectionne la recherche incrémentale. En recherche incrémentale, appuyer
+sur  <em>CTRL-SHIFT-F</em> affiche aussi l'occurrence suivante de la chaîne
+à rechercher.
+
+
+<H2>Recherche incrémentale</H2>
+
+En recherche incrémentale, le programme effectue une recherche chaque
+fois qu'une lettre est tapée. La ligne de statut vous informe
+du résultat de cette recherche. Entrez le raccourci clavier
+de la recherche affiche l'occurrence suivante de la chaîne à rechercher.
+Si aucune autre occurrence ne peut être trouvée, la ligne de statut vous
+en informe. Répétez alors la recherche fera redémarrer la recherche
+au début. L'ordre de recherche se fait toujours selon l'ordre de tri
+actuel de votre base de données. Pour quitter la recherche incrémentale,
+appuyez sur ESC ou cliquez sur "Vider".
+
+<H2>Recherche normale</H2>
+
+Dans une recherche normale, le programme recherche dans votre base les occurrences de votre chaîne de recherche, après que vous ayez appuyé sur Entrée. Toutes les entrées qui ne correspondent pas sont masquées, ne laissant apparaître que les entrées correspondant aux critères. Pour ne plus afficher les résultats de la recherche, appuyez sur ESC ou cliquer sur "Vider".
+
+<a name="advanced"><H2>Spécification des champs, opérateurs logiques</H2>
+
+Afin de rechercher uniquement des champs spécifiques et/ou
+d'inclure des opérateurs logiques dans l'expression à rechercher,
+une syntaxe particulière est disponible. Par exemple, pour 
+rechercher les entrées dont l'auteur est "Miller", entrez (excepté
+en mode de recherche incrémentale) :
+<p>
+author = miller
+<p>
+A la fois la spécification du champ et le terme à rechercher
+peuvent être des expressions régulières. Si un terme à rechercher
+contient des espaces, le mettre entre guillemets. Il ne faut
+<i>jamais</i> utiliser d'espace dans la spécification du champ !
+
+Par exemple, pour rechercher les entrées à propos de traitement
+d'images, entrez :
+<p>
+title|keywords = "traitement d'images"
+<p>
+Vous pouvez utiliser "and", "or", "not", et les parenthèses
+de la façon habituelle :
+<p>
+(author = miller or title|keywords = "traitement d'images") and not author = brown
+<p>
+En fait, le signe "=" signifie "contient". La recherche d'une correspondance exacte
+est possible en utilisant "matches" ou "==". Utilisez "!=" pour tester si le terme à
+rechercher n'est <i>pas</i> contenu dans le champ (un équivalent de "not ...
+contains ..."). 
+
+Si vous spécifiez un type de champ dans l'expression à rechercher, la sélection des types de champs (requis, optionels, généraux)
+apparaissant dans les paramètres de recherche n'est pas prise en compte.
+Pour chercher des entrées d'un certain type,
+un pseudo-champ nommé "entrytype" est disponible :
+<p>
+entrytype = thesis
+<p>
+recherchera les entrées dont le type (tel qu'affiché dans la colonne "Entrytype")
+contient le mot "thesis" (et qui sera donc "phdthesis" ou "mastersthesis"). Le pseudo-champ "bibtexkey" permet de rechercher dans les clefs de citation, tel que :
+ <p>
+ bibtexkey = miller2005
+
+
+<H2>Paramètres de recherche</H2>
+
+Le bouton <em>Paramètres</em> ouvre un menu qui permet de basculer en mode "sensible à la casse", d'utiliser des expressions régulières lors de la recherche, et de définir si les résultats de la recherche doivent être sélectionnés dans la table.
+
+
+</BODY>
+</HTML> 
diff --git a/src/help/fr/ShortIntegrityCheck.html b/src/help/fr/ShortIntegrityCheck.html
new file mode 100644
index 0000000..a48b991
--- /dev/null
+++ b/src/help/fr/ShortIntegrityCheck.html
@@ -0,0 +1,8 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<body>
+<basefont size="-1" color="#2F4958" face="arial">
+La vérification d'intégrité est un processus qui
+recherche des indices de champs BibTeX mal remplis."Démarrer"
+est le bouton pour lancer la vérification. 
+</body></html>
\ No newline at end of file
diff --git a/src/help/fr/ShortPlainImport.html b/src/help/fr/ShortPlainImport.html
new file mode 100644
index 0000000..089692c
--- /dev/null
+++ b/src/help/fr/ShortPlainImport.html
@@ -0,0 +1,9 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<body>
+<basefont size="-1" color="#2F4958" face="arial">
+Ceci est simplement une fenêtre de copier-coller. Commencez par
+charger ou coller du texte dans la zone de saisie de texte. Ensuite,
+vous pouvez sélectionner des portions de texte et les attribuer
+à des champs BibTeX.
+</body></html>
\ No newline at end of file
diff --git a/src/help/fr/StringEditorHelp.html b/src/help/fr/StringEditorHelp.html
new file mode 100644
index 0000000..bd1d74a
--- /dev/null
+++ b/src/help/fr/StringEditorHelp.html
@@ -0,0 +1,43 @@
+<HTML>
+
+<BODY text="#275856">
+<basefont size="4" color="#2F4958" face="arial">
+
+<H1>L'éditeur de chaîne</H1>
+<em>On l'ouvre à partir de la fenêtre principale par le menu <em>BibTeX -> Editer les chaînes</em> ou
+en appuyant sur un des icônes de la barre d'outils.
+Le raccourci clavier est CTRL-T.</em>
+<P>
+Les <em>chaînes</em> sont l'équivalent <em>BibTeX</em> des constantes dans 
+un langage de programmation. Chaque chaîne est définie par un <em>nom</em> 
+unique et un <em>contenu</em>. Dans votre base de données, ce nom peut être
+utilisé pour représenter ce contenu.
+
+<P>
+Par exemple, si beaucoup d'entrées sont d'un journal dont l'abréviation
+est difficile à mémoriser, tel que 'J. Theor. Biol.' (Journal of
+Theroretical Biology), une chaîne nommée JTB peut être définie pour
+représenter le nom de ce journal. Au lieu de taper le nom exact du journal
+dans chaque entrée, les caractères '#JTB#' sont entrés (sans les guillemets)
+dans le champ <em>journal</em> de chaque entrée, assurant ainsi que le nom
+du journal est écrit de la même façon à chaque fois.
+
+<P>
+Une telle chaîne peut apparaître n'importe où, dans n'importe quel
+champ, en incluant le nom de la chaîne entre une paire de caractères '#'.
+Cette syntaxe est spécifique à JabRef et diffère légèrement de la notation
+<em>BibTeX</em> qui est utilisée quand vous sauvez votre base de données.
+
+<P>
+Une chaîne peut être incluse dans le contenu d'une autre chaîne (chaîne
+incluante), à la condition que la chaîne incluse soit définie
+<em>avant</em> la chaîne incluante. 
+
+<p>Alors que l'ordre des chaînes dans votre fichier BibTeX est important dans certains cas, 
+vous n'avez pas à vous en préoccuper quand vous utilisez JabRef. Dans l'éditeur de chaînes,
+les chaînes seront affichées selon l'ordre alphabétique et stockée dans le même ordre,
+excepté quand BibTeX aura besoin d'un ordre différent.
+
+
+</BODY>
+</HTML>
diff --git a/src/help/fr/TimeStampHelp.html b/src/help/fr/TimeStampHelp.html
new file mode 100644
index 0000000..d92ebbe
--- /dev/null
+++ b/src/help/fr/TimeStampHelp.html
@@ -0,0 +1,40 @@
+<HTML>
+
+<BODY text="#275856">
+<basefont size="4" color="#2F4958" face="arial">
+
+<H1>Horodatage des entrées</H1>
+
+Cette fonction peut être activée et configurée sous <b>Préférences -> Général</b>.
+
+<p>JabRef peut automatiquement insérer un champ qui contient la date à laquelle
+une entrée a été ajoutée à la base de données.
+
+
+<H2>Mise en forme</H2>
+
+Le format d'horodatage est déterminé par une chaîne contenant des codes qui indiquent
+la position des différentes parties de la date. 
+  	 <p>
+  	 Voici certains des codes disponibles (exemples donnés entre parenthèses pour le 
+  	 mercredi 14 septembre 2005 à 17h45) :
+  	 <ul>
+  	     <li><b>yy</b>: année (05)</li>
+  	     <li><b>yyyy</b>: année (2005)</li>
+  	     <li><b>MM</b>: mois (09)</li>
+  	     <li><b>dd</b>: jour du mois (14)</li>
+  	     <li><b>HH</b>: heure du jour (17)</li>
+  	     <li><b>mm</b>: minute de l'heure (45)</li>
+  	 </ul>
+  	 
+  	 Ces codes peuvent être combinés avec des ponctuations et des espaces. Quelques exemples :
+  	 
+  	 <ul>
+  	 <li><b>yyyy.MM.dd</b> donne <b>2005.09.14</b></li>
+  	 <li><b>yy.MM.dd</b> donne <b>05.09.14</b></li>
+  	 <li><b>yyyy.MM.dd HH:mm</b> donne <b>2005.09.14 17:45</b></li>
+  	 </ul>
+
+
+</BODY>
+</HTML>
diff --git a/src/help/jgoodies.html b/src/help/jgoodies.html
new file mode 100644
index 0000000..0cd9fb9
--- /dev/null
+++ b/src/help/jgoodies.html
@@ -0,0 +1,25 @@
+Copyright (c) 2003 JGoodies Karsten Lentzsch. All Rights Reserved.
+<p>
+Redistribution and use in source and binary forms, with or without 
+modification, are permitted provided that the following conditions are met:
+<ul>
+<li>Redistributions of source code must retain the above copyright notice, 
+this list of conditions and the following disclaimer. 
+<li>Redistributions in binary form must reproduce the above copyright notice, 
+this list of conditions and the following disclaimer in the documentation 
+and/or other materials provided with the distribution. 
+<li>Neither the name of JGoodies Karsten Lentzsch nor the names of 
+its contributors may be used to endorse or promote products derived 
+from this software without specific prior written permission. 
+</ul>   
+<P>THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 
+PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
\ No newline at end of file
diff --git a/src/help/no/ShortPlainImport.html b/src/help/no/ShortPlainImport.html
new file mode 100644
index 0000000..8c5f3e2
--- /dev/null
+++ b/src/help/no/ShortPlainImport.html
@@ -0,0 +1,8 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<body>
+<basefont size="-1" color="#2F4958" face="arial">
+Dette er et enkelt klipp-og-lim-vindu. Først last inn eller kopier
+tekst til inndatafeltet. Deretter kan du merke tekst og tildele den til
+et BibTeX-felt.
+</body></html>
\ No newline at end of file
diff --git a/src/images/Close.gif b/src/images/Close.gif
new file mode 100644
index 0000000..f53ee93
Binary files /dev/null and b/src/images/Close.gif differ
diff --git a/src/images/CopyKey.gif b/src/images/CopyKey.gif
new file mode 100755
index 0000000..f81c64a
Binary files /dev/null and b/src/images/CopyKey.gif differ
diff --git a/src/images/Hourglass.png b/src/images/Hourglass.png
new file mode 100644
index 0000000..d93cadd
Binary files /dev/null and b/src/images/Hourglass.png differ
diff --git a/src/images/JabRef-Logo-small.gif b/src/images/JabRef-Logo-small.gif
new file mode 100644
index 0000000..2efd2e0
Binary files /dev/null and b/src/images/JabRef-Logo-small.gif differ
diff --git a/src/images/JabRef-Logo.icns b/src/images/JabRef-Logo.icns
new file mode 100644
index 0000000..7f30a50
Binary files /dev/null and b/src/images/JabRef-Logo.icns differ
diff --git a/src/images/JabRef-icon.png b/src/images/JabRef-icon.png
new file mode 100644
index 0000000..4ea527b
Binary files /dev/null and b/src/images/JabRef-icon.png differ
diff --git a/src/images/absIcon.png b/src/images/absIcon.png
new file mode 100644
index 0000000..f249fda
Binary files /dev/null and b/src/images/absIcon.png differ
diff --git a/src/images/addtsk_tsk.gif b/src/images/addtsk_tsk.gif
new file mode 100644
index 0000000..dad7260
Binary files /dev/null and b/src/images/addtsk_tsk.gif differ
diff --git a/src/images/backward_nav.gif b/src/images/backward_nav.gif
new file mode 100644
index 0000000..740419b
Binary files /dev/null and b/src/images/backward_nav.gif differ
diff --git a/src/images/close_view.gif b/src/images/close_view.gif
new file mode 100644
index 0000000..1aca259
Binary files /dev/null and b/src/images/close_view.gif differ
diff --git a/src/images/completeItem.png b/src/images/completeItem.png
new file mode 100644
index 0000000..5eeadc7
Binary files /dev/null and b/src/images/completeItem.png differ
diff --git a/src/images/configure2.png b/src/images/configure2.png
new file mode 100644
index 0000000..9df41c4
Binary files /dev/null and b/src/images/configure2.png differ
diff --git a/src/images/contents2.png b/src/images/contents2.png
new file mode 100644
index 0000000..2d94894
Binary files /dev/null and b/src/images/contents2.png differ
diff --git a/src/images/copy_edit.gif b/src/images/copy_edit.gif
new file mode 100644
index 0000000..4274b07
Binary files /dev/null and b/src/images/copy_edit.gif differ
diff --git a/src/images/cut_edit.gif b/src/images/cut_edit.gif
new file mode 100644
index 0000000..eb948b9
Binary files /dev/null and b/src/images/cut_edit.gif differ
diff --git a/src/images/defaults_ps.gif b/src/images/defaults_ps.gif
new file mode 100644
index 0000000..5e1e78a
Binary files /dev/null and b/src/images/defaults_ps.gif differ
diff --git a/src/images/delete_edit.gif b/src/images/delete_edit.gif
new file mode 100644
index 0000000..6f64766
Binary files /dev/null and b/src/images/delete_edit.gif differ
diff --git a/src/images/doismall.png b/src/images/doismall.png
new file mode 100644
index 0000000..3c9595b
Binary files /dev/null and b/src/images/doismall.png differ
diff --git a/src/images/duplicate.png b/src/images/duplicate.png
new file mode 100644
index 0000000..5599a18
Binary files /dev/null and b/src/images/duplicate.png differ
diff --git a/src/images/editcopy.png b/src/images/editcopy.png
new file mode 100644
index 0000000..313bd9b
Binary files /dev/null and b/src/images/editcopy.png differ
diff --git a/src/images/editcut.png b/src/images/editcut.png
new file mode 100644
index 0000000..af88212
Binary files /dev/null and b/src/images/editcut.png differ
diff --git a/src/images/editdelete.png b/src/images/editdelete.png
new file mode 100644
index 0000000..d073c87
Binary files /dev/null and b/src/images/editdelete.png differ
diff --git a/src/images/editpaste.png b/src/images/editpaste.png
new file mode 100644
index 0000000..cba1f23
Binary files /dev/null and b/src/images/editpaste.png differ
diff --git a/src/images/edittsk_tsk.gif b/src/images/edittsk_tsk.gif
new file mode 100644
index 0000000..a1ca3e7
Binary files /dev/null and b/src/images/edittsk_tsk.gif differ
diff --git a/src/images/emacs.png b/src/images/emacs.png
new file mode 100644
index 0000000..c86092f
Binary files /dev/null and b/src/images/emacs.png differ
diff --git a/src/images/exclamation.gif b/src/images/exclamation.gif
new file mode 100644
index 0000000..586ed8e
Binary files /dev/null and b/src/images/exclamation.gif differ
diff --git a/src/images/fileclose.png b/src/images/fileclose.png
new file mode 100644
index 0000000..033326f
Binary files /dev/null and b/src/images/fileclose.png differ
diff --git a/src/images/fileclose2.png b/src/images/fileclose2.png
new file mode 100644
index 0000000..c1e5f4d
Binary files /dev/null and b/src/images/fileclose2.png differ
diff --git a/src/images/fldr_obj.gif b/src/images/fldr_obj.gif
new file mode 100644
index 0000000..a9c7773
Binary files /dev/null and b/src/images/fldr_obj.gif differ
diff --git a/src/images/forward_nav.gif b/src/images/forward_nav.gif
new file mode 100644
index 0000000..7a1511d
Binary files /dev/null and b/src/images/forward_nav.gif differ
diff --git a/src/images/g_icon.gif b/src/images/g_icon.gif
new file mode 100755
index 0000000..3f4f73f
Binary files /dev/null and b/src/images/g_icon.gif differ
diff --git a/src/images/genIcon.png b/src/images/genIcon.png
new file mode 100644
index 0000000..5bedaa2
Binary files /dev/null and b/src/images/genIcon.png differ
diff --git a/src/images/goto.png b/src/images/goto.png
new file mode 100644
index 0000000..58cc31c
Binary files /dev/null and b/src/images/goto.png differ
diff --git a/src/images/groupIncluding.png b/src/images/groupIncluding.png
new file mode 100644
index 0000000..6e72101
Binary files /dev/null and b/src/images/groupIncluding.png differ
diff --git a/src/images/groupRefining.png b/src/images/groupRefining.png
new file mode 100644
index 0000000..2ba0a26
Binary files /dev/null and b/src/images/groupRefining.png differ
diff --git a/src/images/groupsHighlightAll.png b/src/images/groupsHighlightAll.png
new file mode 100644
index 0000000..374c20e
Binary files /dev/null and b/src/images/groupsHighlightAll.png differ
diff --git a/src/images/groupsHighlightAny.png b/src/images/groupsHighlightAny.png
new file mode 100644
index 0000000..e1f73a5
Binary files /dev/null and b/src/images/groupsHighlightAny.png differ
diff --git a/src/images/incomplete.png b/src/images/incomplete.png
new file mode 100644
index 0000000..e77ff14
Binary files /dev/null and b/src/images/incomplete.png differ
diff --git a/src/images/integrity.png b/src/images/integrity.png
new file mode 100644
index 0000000..4343947
Binary files /dev/null and b/src/images/integrity.png differ
diff --git a/src/images/jabref-2.0-splash.png b/src/images/jabref-2.0-splash.png
new file mode 100644
index 0000000..e295337
Binary files /dev/null and b/src/images/jabref-2.0-splash.png differ
diff --git a/src/images/lyx2.png b/src/images/lyx2.png
new file mode 100644
index 0000000..4162b77
Binary files /dev/null and b/src/images/lyx2.png differ
diff --git a/src/images/mark.png b/src/images/mark.png
new file mode 100644
index 0000000..fc64fc1
Binary files /dev/null and b/src/images/mark.png differ
diff --git a/src/images/messageFail.png b/src/images/messageFail.png
new file mode 100644
index 0000000..474f63f
Binary files /dev/null and b/src/images/messageFail.png differ
diff --git a/src/images/messageInfo.png b/src/images/messageInfo.png
new file mode 100644
index 0000000..ecdc991
Binary files /dev/null and b/src/images/messageInfo.png differ
diff --git a/src/images/messageWarn.png b/src/images/messageWarn.png
new file mode 100755
index 0000000..55a6f01
Binary files /dev/null and b/src/images/messageWarn.png differ
diff --git a/src/images/minus.gif b/src/images/minus.gif
new file mode 100644
index 0000000..a81eba1
Binary files /dev/null and b/src/images/minus.gif differ
diff --git a/src/images/newBibFile.png b/src/images/newBibFile.png
new file mode 100644
index 0000000..a669555
Binary files /dev/null and b/src/images/newBibFile.png differ
diff --git a/src/images/new_page.gif b/src/images/new_page.gif
new file mode 100644
index 0000000..41c3958
Binary files /dev/null and b/src/images/new_page.gif differ
diff --git a/src/images/new_wiz.gif b/src/images/new_wiz.gif
new file mode 100644
index 0000000..bf683ca
Binary files /dev/null and b/src/images/new_wiz.gif differ
diff --git a/src/images/next_nav.gif b/src/images/next_nav.gif
new file mode 100644
index 0000000..8392f33
Binary files /dev/null and b/src/images/next_nav.gif differ
diff --git a/src/images/o_icon.gif b/src/images/o_icon.gif
new file mode 100755
index 0000000..22cd977
Binary files /dev/null and b/src/images/o_icon.gif differ
diff --git a/src/images/optIcon.png b/src/images/optIcon.png
new file mode 100644
index 0000000..64562b3
Binary files /dev/null and b/src/images/optIcon.png differ
diff --git a/src/images/paste_edit.gif b/src/images/paste_edit.gif
new file mode 100644
index 0000000..75e0ab2
Binary files /dev/null and b/src/images/paste_edit.gif differ
diff --git a/src/images/pdf.png b/src/images/pdf.png
new file mode 100644
index 0000000..d5eab07
Binary files /dev/null and b/src/images/pdf.png differ
diff --git a/src/images/pdf_small.gif b/src/images/pdf_small.gif
new file mode 100644
index 0000000..2228bc9
Binary files /dev/null and b/src/images/pdf_small.gif differ
diff --git a/src/images/plus.gif b/src/images/plus.gif
new file mode 100644
index 0000000..c123ba7
Binary files /dev/null and b/src/images/plus.gif differ
diff --git a/src/images/postscript.png b/src/images/postscript.png
new file mode 100644
index 0000000..5065c98
Binary files /dev/null and b/src/images/postscript.png differ
diff --git a/src/images/preamble.png b/src/images/preamble.png
new file mode 100644
index 0000000..3b5eb35
Binary files /dev/null and b/src/images/preamble.png differ
diff --git a/src/images/prev_nav.gif b/src/images/prev_nav.gif
new file mode 100644
index 0000000..9b278e6
Binary files /dev/null and b/src/images/prev_nav.gif differ
diff --git a/src/images/preview.png b/src/images/preview.png
new file mode 100644
index 0000000..a8aa6b3
Binary files /dev/null and b/src/images/preview.png differ
diff --git a/src/images/queue.png b/src/images/queue.png
new file mode 100644
index 0000000..d75a53b
Binary files /dev/null and b/src/images/queue.png differ
diff --git a/src/images/r_icon.gif b/src/images/r_icon.gif
new file mode 100755
index 0000000..5fea573
Binary files /dev/null and b/src/images/r_icon.gif differ
diff --git a/src/images/redo_edit.gif b/src/images/redo_edit.gif
new file mode 100644
index 0000000..01ce578
Binary files /dev/null and b/src/images/redo_edit.gif differ
diff --git a/src/images/refresh_nav.gif b/src/images/refresh_nav.gif
new file mode 100644
index 0000000..a063c23
Binary files /dev/null and b/src/images/refresh_nav.gif differ
diff --git a/src/images/reqIcon.png b/src/images/reqIcon.png
new file mode 100644
index 0000000..5d2439c
Binary files /dev/null and b/src/images/reqIcon.png differ
diff --git a/src/images/run.png b/src/images/run.png
new file mode 100644
index 0000000..3662b07
Binary files /dev/null and b/src/images/run.png differ
diff --git a/src/images/save_edit.gif b/src/images/save_edit.gif
new file mode 100644
index 0000000..698d9a2
Binary files /dev/null and b/src/images/save_edit.gif differ
diff --git a/src/images/saveas_edit.gif b/src/images/saveas_edit.gif
new file mode 100644
index 0000000..76549a1
Binary files /dev/null and b/src/images/saveas_edit.gif differ
diff --git a/src/images/search.gif b/src/images/search.gif
new file mode 100644
index 0000000..6dc3ebe
Binary files /dev/null and b/src/images/search.gif differ
diff --git a/src/images/showerr_tsk.gif b/src/images/showerr_tsk.gif
new file mode 100644
index 0000000..c2bfdd6
Binary files /dev/null and b/src/images/showerr_tsk.gif differ
diff --git a/src/images/strings.png b/src/images/strings.png
new file mode 100644
index 0000000..8717f06
Binary files /dev/null and b/src/images/strings.png differ
diff --git a/src/images/toc_closed.gif b/src/images/toc_closed.gif
new file mode 100644
index 0000000..e5bc046
Binary files /dev/null and b/src/images/toc_closed.gif differ
diff --git a/src/images/undo_edit.gif b/src/images/undo_edit.gif
new file mode 100644
index 0000000..570c61c
Binary files /dev/null and b/src/images/undo_edit.gif differ
diff --git a/src/images/unmark.png b/src/images/unmark.png
new file mode 100644
index 0000000..553ad17
Binary files /dev/null and b/src/images/unmark.png differ
diff --git a/src/images/up_nav.gif b/src/images/up_nav.gif
new file mode 100644
index 0000000..6877784
Binary files /dev/null and b/src/images/up_nav.gif differ
diff --git a/src/images/view.gif b/src/images/view.gif
new file mode 100644
index 0000000..6d8d1be
Binary files /dev/null and b/src/images/view.gif differ
diff --git a/src/images/viewsource.gif b/src/images/viewsource.gif
new file mode 100644
index 0000000..3ef9a2e
Binary files /dev/null and b/src/images/viewsource.gif differ
diff --git a/src/images/window_nofullscreen.png b/src/images/window_nofullscreen.png
new file mode 100644
index 0000000..6383f31
Binary files /dev/null and b/src/images/window_nofullscreen.png differ
diff --git a/src/images/winedt.png b/src/images/winedt.png
new file mode 100644
index 0000000..320320b
Binary files /dev/null and b/src/images/winedt.png differ
diff --git a/src/images/wizard.png b/src/images/wizard.png
new file mode 100644
index 0000000..2474c19
Binary files /dev/null and b/src/images/wizard.png differ
diff --git a/src/images/wrongItem.png b/src/images/wrongItem.png
new file mode 100644
index 0000000..8b2f1eb
Binary files /dev/null and b/src/images/wrongItem.png differ
diff --git a/src/images/www.png b/src/images/www.png
new file mode 100644
index 0000000..8ee63b8
Binary files /dev/null and b/src/images/www.png differ
diff --git a/src/images/wwwciteseer.png b/src/images/wwwciteseer.png
new file mode 100644
index 0000000..82c8038
Binary files /dev/null and b/src/images/wwwciteseer.png differ
diff --git a/src/java/Eclipse_formatter.xml b/src/java/Eclipse_formatter.xml
new file mode 100644
index 0000000..fc7f74a
--- /dev/null
+++ b/src/java/Eclipse_formatter.xml
@@ -0,0 +1,186 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<profiles version="6">
+<profile name="JabRef" version="6">
+<setting id="comment_clear_blank_lines" value="false"/>
+<setting id="comment_format_comments" value="true"/>
+<setting id="comment_format_header" value="false"/>
+<setting id="comment_format_html" value="true"/>
+<setting id="comment_format_source_code" value="true"/>
+<setting id="comment_indent_parameter_description" value="true"/>
+<setting id="comment_indent_root_tags" value="true"/>
+<setting id="comment_line_length" value="80"/>
+<setting id="comment_new_line_for_parameter" value="true"/>
+<setting id="comment_separate_root_tags" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.align_type_members_on_columns" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_binary_expression" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_compact_if" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_conditional_expression" value="80"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_multiple_fields" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_imports" value="1"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_package" value="1"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_field" value="1"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration" value="1"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_imports" value="1"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_member_type" value="0"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_method" value="1"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk" value="1"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_package" value="0"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations" value="1"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_array_initializer" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block_in_case" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_method_declaration" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_switch" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_type_declaration" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.compact_else_if" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.continuation_indentation" value="2"/>
+<setting id="org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer" value="2"/>
+<setting id="org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_block" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_body" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_binary_operator" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_unary_operator" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_binary_operator" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_unary_operator" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.lineSplit" value="80"/>
+<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body" value="0"/>
+<setting id="org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve" value="1"/>
+<setting id="org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.tabulation.char" value="space"/>
+<setting id="org.eclipse.jdt.core.formatter.tabulation.size" value="2"/>
+</profile>
+</profiles>
diff --git a/src/java/com/jgoodies/uif_lite/component/UIFSplitPane.java b/src/java/com/jgoodies/uif_lite/component/UIFSplitPane.java
new file mode 100644
index 0000000..953d737
--- /dev/null
+++ b/src/java/com/jgoodies/uif_lite/component/UIFSplitPane.java
@@ -0,0 +1,270 @@
+/*
+ * Copyright (c) 2003, 2004 JGoodies Karsten Lentzsch. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ * 
+ *  o Redistributions of source code must retain the above copyright notice, 
+ *    this list of conditions and the following disclaimer. 
+ *     
+ *  o Redistributions in binary form must reproduce the above copyright notice, 
+ *    this list of conditions and the following disclaimer in the documentation 
+ *    and/or other materials provided with the distribution. 
+ *     
+ *  o Neither the name of JGoodies Karsten Lentzsch nor the names of 
+ *    its contributors may be used to endorse or promote products derived 
+ *    from this software without specific prior written permission. 
+ *     
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+package com.jgoodies.uif_lite.component;
+
+import java.awt.Component;
+
+import javax.swing.JButton;
+import javax.swing.JSplitPane;
+import javax.swing.UIManager;
+import javax.swing.border.Border;
+import javax.swing.border.EmptyBorder;
+import javax.swing.plaf.SplitPaneUI;
+import javax.swing.plaf.basic.BasicSplitPaneUI;
+
+/**
+ * A <code>JSplitPane</code> subclass that can try to remove the divider border. 
+ * Useful if the splitted components render their own borders.
+ * Note that this feature is not supported by all look&feels.
+ * Some look&feel implementation will always show a divider border, 
+ * and conversely, others will never show a divider border.
+ * 
+ * @author Karsten Lentzsch
+ * @version $Revision: 1.2 $
+ * 
+ * @see javax.swing.plaf.basic.BasicSplitPaneUI
+ */
+
+public final class UIFSplitPane extends JSplitPane {
+    
+    /**
+     * Holds the name of the bound property that tries to show or hide
+     * the split pane's divider border.
+     * 
+     * @see #isDividerBorderVisible()
+     * @see #setDividerBorderVisible(boolean)
+     */
+    public static final String PROPERTYNAME_DIVIDER_BORDER_VISIBLE = 
+        "dividerBorderVisible";
+    
+    /**
+     * Holds an empty border that is reused for the split pane itself
+     * and the divider.
+     */
+    private static final Border EMPTY_BORDER = new EmptyBorder(0, 0, 0, 0);
+    
+    /**
+     * Determines whether the divider border shall be removed when
+     * the UI is updated.
+     * 
+     * @see #isDividerBorderVisible()
+     * @see #setDividerBorderVisible(boolean) 
+     */
+    private boolean dividerBorderVisible;
+
+   
+    // Instance Creation *****************************************************
+    
+    /**
+     * Constructs a <code>UIFSplitPane</code> configured to arrange the child
+     * components side-by-side horizontally with no continuous 
+     * layout, using two buttons for the components.
+     */
+    public UIFSplitPane() {
+        this(JSplitPane.HORIZONTAL_SPLIT, false,
+                new JButton(UIManager.getString("SplitPane.leftButtonText")),
+                new JButton(UIManager.getString("SplitPane.rightButtonText")));
+    }
+
+
+    /**
+     * Constructs a <code>UIFSplitPane</code> configured with the
+     * specified orientation and no continuous layout.
+     *
+     * @param newOrientation  <code>JSplitPane.HORIZONTAL_SPLIT</code> or
+     *                        <code>JSplitPane.VERTICAL_SPLIT</code>
+     * @throws IllegalArgumentException if <code>orientation</code>
+     *		is not one of HORIZONTAL_SPLIT or VERTICAL_SPLIT.
+     */
+    public UIFSplitPane(int newOrientation) {
+        this(newOrientation, false);
+    }
+
+
+    /**
+     * Constructs a <code>UIFSplitPane</code> with the specified
+     * orientation and redrawing style.
+     *
+     * @param newOrientation  <code>JSplitPane.HORIZONTAL_SPLIT</code> or
+     *                        <code>JSplitPane.VERTICAL_SPLIT</code>
+     * @param newContinuousLayout  a boolean, true for the components to 
+     *        redraw continuously as the divider changes position, false
+     *        to wait until the divider position stops changing to redraw
+     * @throws IllegalArgumentException if <code>orientation</code>
+     *		is not one of HORIZONTAL_SPLIT or VERTICAL_SPLIT
+     */
+    public UIFSplitPane(int newOrientation,
+                      boolean newContinuousLayout) {
+        this(newOrientation, newContinuousLayout, null, null);
+    }
+
+
+    /**
+     * Constructs a <code>UIFSplitPane</code> with the specified orientation
+     * and the given componenents.
+     * 
+     * @param orientation  <code>JSplitPane.HORIZONTAL_SPLIT</code> or
+     *                        <code>JSplitPane.VERTICAL_SPLIT</code>
+     * @param leftComponent the <code>Component</code> that will
+     *    appear on the left of a horizontally-split pane, 
+     *    or at the top of a vertically-split pane
+     * @param rightComponent the <code>Component</code> that will
+     *    appear on the right of a horizontally-split pane, 
+     *    or at the bottom of a	vertically-split pane
+     * @throws IllegalArgumentException if <code>orientation</code>
+     *    is not one of: HORIZONTAL_SPLIT or VERTICAL_SPLIT
+     */
+    public UIFSplitPane(int orientation,
+                         Component leftComponent,
+                         Component rightComponent) {
+        this(orientation, false, leftComponent, rightComponent);
+    }
+    
+    
+    /**
+     * Constructs a <code>UIFSplitPane</code> with the specified orientation,
+     * redrawing style, and given components.
+     *
+     * @param orientation  <code>JSplitPane.HORIZONTAL_SPLIT</code> or
+     *                        <code>JSplitPane.VERTICAL_SPLIT</code>
+     * @param continuousLayout  a boolean, true for the components to 
+     *        redraw continuously as the divider changes position, false
+     *        to wait until the divider position stops changing to redraw
+     * @param leftComponent the <code>Component</code> that will
+     *		appear on the left
+     *        	of a horizontally-split pane, or at the top of a
+     *        	vertically-split pane
+     * @param rightComponent the <code>Component</code> that will
+     *		appear on the right
+     *        	of a horizontally-split pane, or at the bottom of a
+     *        	vertically-split pane
+     * @throws IllegalArgumentException if <code>orientation</code>
+     *		is not one of HORIZONTAL_SPLIT or VERTICAL_SPLIT
+     */
+    public UIFSplitPane(int orientation,
+                      boolean continuousLayout,
+                      Component leftComponent,
+                      Component rightComponent){
+        super(orientation, continuousLayout, leftComponent, rightComponent);
+        dividerBorderVisible = false;
+    }
+    
+    
+    /**
+     * Constructs a <code>UIFSplitPane</code>, 
+     * i.e. a <code>JSplitPane</code> that has no borders.
+     * Also disabled the one touch exandable property.
+     * 
+     * @param orientation  <code>JSplitPane.HORIZONTAL_SPLIT</code> or
+     *                        <code>JSplitPane.VERTICAL_SPLIT</code>
+     * @param leftComponent the <code>Component</code> that will
+     *    appear on the left of a horizontally-split pane, 
+     *    or at the top of a vertically-split pane
+     * @param rightComponent the <code>Component</code> that will
+     *    appear on the right of a horizontally-split pane, 
+     *    or at the bottom of a	vertically-split pane
+     * @throws IllegalArgumentException if <code>orientation</code>
+     *    is not one of: HORIZONTAL_SPLIT or VERTICAL_SPLIT
+     */
+    public static UIFSplitPane createStrippedSplitPane(
+             int orientation,
+             Component leftComponent,
+             Component rightComponent) {
+        UIFSplitPane split = new UIFSplitPane(orientation, leftComponent, rightComponent);
+        split.setBorder(EMPTY_BORDER);
+        split.setOneTouchExpandable(false);
+        return split;
+    }
+    
+    
+    // Accessing Properties **************************************************
+    
+    /**
+     * Checks and answers whether the divider border shall be visible 
+     * or invisible. 
+     * Note that this feature is not supported by all look&feels.
+     * Some look&feel implementation will always show a divider border, 
+     * and conversely, others will never show a divider border.
+     * 
+     * @return the desired (but potentially inaccurate) divider border visiblity
+     */
+    public boolean isDividerBorderVisible() {
+        return dividerBorderVisible;
+    }
+    
+    
+    /**
+     * Makes the divider border visible or invisible.
+     * Note that this feature is not supported by all look&feels.
+     * Some look&feel implementation will always show a divider border, 
+     * and conversely, others will never show a divider border.
+     * 
+     * @param newVisibility   true for visible, false for invisible
+     */
+    public void setDividerBorderVisible(boolean newVisibility) {
+        boolean oldVisibility = isDividerBorderVisible();
+        if (oldVisibility == newVisibility)
+            return;
+        dividerBorderVisible = newVisibility;
+        firePropertyChange(PROPERTYNAME_DIVIDER_BORDER_VISIBLE, 
+                           oldVisibility, 
+                           newVisibility);
+    }
+    
+
+    // Changing the Divider Border Visibility *********************************
+    
+    /**
+     * Updates the UI and sets an empty divider border. The divider border
+     * may be restored by a L&F at UI installation time. And so, we
+     * try to reset it each time the UI is changed.
+     */
+    public void updateUI() {
+        super.updateUI();
+        if (!isDividerBorderVisible())
+            setEmptyDividerBorder();
+    }
+    
+
+    /**
+     * Sets an empty divider border if and only if the UI is 
+     * an instance of <code>BasicSplitPaneUI</code>.
+     */
+    private void setEmptyDividerBorder() {
+        SplitPaneUI splitPaneUI = getUI();
+        if (splitPaneUI instanceof BasicSplitPaneUI) {
+            BasicSplitPaneUI basicUI = (BasicSplitPaneUI) splitPaneUI;
+            basicUI.getDivider().setBorder(EMPTY_BORDER);
+        }
+    }
+    
+    
+}
\ No newline at end of file
diff --git a/src/java/com/jgoodies/uif_lite/panel/SimpleInternalFrame.java b/src/java/com/jgoodies/uif_lite/panel/SimpleInternalFrame.java
new file mode 100644
index 0000000..7abbe72
--- /dev/null
+++ b/src/java/com/jgoodies/uif_lite/panel/SimpleInternalFrame.java
@@ -0,0 +1,474 @@
+/*
+ * Copyright (c) 2003 JGoodies Karsten Lentzsch. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ * 
+ *  o Redistributions of source code must retain the above copyright notice, 
+ *    this list of conditions and the following disclaimer. 
+ *     
+ *  o Redistributions in binary form must reproduce the above copyright notice, 
+ *    this list of conditions and the following disclaimer in the documentation 
+ *    and/or other materials provided with the distribution. 
+ *     
+ *  o Neither the name of JGoodies Karsten Lentzsch nor the names of 
+ *    its contributors may be used to endorse or promote products derived 
+ *    from this software without specific prior written permission. 
+ *     
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+package com.jgoodies.uif_lite.panel;
+
+import java.awt.*;
+
+import javax.swing.*;
+import javax.swing.border.AbstractBorder;
+
+import com.jgoodies.plaf.LookUtils;
+
+/** 
+ * A <code>JPanel</code> subclass that has a drop shadow border and 
+ * that provides a header with icon, title and tool bar.<p>
+ * 
+ * This class can be used to replace the <code>JInternalFrame</code>,
+ * for use outside of a <code>JDesktopPane</code>. 
+ * The <code>SimpleInternalFrame</code> is less flexible but often
+ * more usable; it avoids overlapping windows and scales well 
+ * up to IDE size.
+ * Several customers have reported that they and their clients feel 
+ * much better with both the appearance and the UI feel.<p>
+ * 
+ * The SimpleInternalFrame provides the following bound properties:
+ * <i>frameIcon, title, toolBar, content, selected.</i><p>
+ * 
+ * By default the SimpleInternalFrame is in <i>selected</i> state.
+ * If you don't do anything, multiple simple internal frames will
+ * be displayed as selected.
+ * 
+ * @author Karsten Lentzsch
+ * @version $Revision: 1.3 $
+ * 
+ * @see    javax.swing.JInternalFrame
+ * @see    javax.swing.JDesktopPane
+ */
+
+public class SimpleInternalFrame extends JPanel {
+
+    private JLabel          titleLabel;
+    private GradientPanel   gradientPanel;
+    private JPanel          headerPanel;
+    private boolean        isSelected;
+    
+    
+    // Instance Creation ****************************************************
+
+    /**
+     * Constructs a <code>SimpleInternalFrame</code> with the specified title.
+     * 
+     * @param title       the initial title
+     */
+    public SimpleInternalFrame(String title) {
+        this(null, title, null, null);
+    }
+    
+    
+    /**
+     * Constructs a <code>SimpleInternalFrame</code> with the specified 
+     * icon, and title.
+     * 
+     * @param icon        the initial icon
+     * @param title       the initial title
+     */
+    public SimpleInternalFrame(Icon icon, String title) {
+        this(icon, title, null, null);
+    }
+
+    
+    /**
+     * Constructs a <code>SimpleInternalFrame</code> with the specified 
+     * title, tool bar, and content panel.
+     * 
+     * @param title       the initial title
+     * @param bar         the initial tool bar
+     * @param content     the initial content pane
+     */
+    public SimpleInternalFrame(String title, JToolBar bar, JComponent content) {
+        this(null, title, bar, content);
+    }
+    
+
+    /**
+     * Constructs a <code>SimpleInternalFrame</code> with the specified 
+     * icon, title, tool bar, and content panel.
+     * 
+     * @param icon        the initial icon
+     * @param title       the initial title
+     * @param bar         the initial tool bar
+     * @param content     the initial content pane
+     */
+    public SimpleInternalFrame(
+        Icon icon,
+        String title,
+        JToolBar bar,
+        JComponent content) {
+        super(new BorderLayout());
+        this.isSelected = false;
+        this.titleLabel = new JLabel(title, icon, SwingConstants.LEADING);
+        JPanel top = buildHeader(titleLabel, bar);
+
+        add(top, BorderLayout.NORTH);
+        if (content != null) {
+            setContent(content);
+        }
+        setBorder(new ShadowBorder());
+        setSelected(true);
+        updateHeader();
+    }
+
+    
+    // Public API ***********************************************************
+
+    /**
+     * Returns the frame's icon.
+     * 
+     * @return the frame's icon
+     */
+    public Icon getFrameIcon() {
+        return titleLabel.getIcon();
+    }
+    
+
+    /**
+     * Sets a new frame icon.
+     * 
+     * @param newIcon   the icon to be set
+     */
+    public void setFrameIcon(Icon newIcon) {
+        Icon oldIcon = getFrameIcon();
+        titleLabel.setIcon(newIcon);
+        firePropertyChange("frameIcon", oldIcon, newIcon);
+    }
+    
+
+    /**
+     * Returns the frame's title text.
+     * 
+     * @return String   the current title text
+     */
+    public String getTitle() {
+        return titleLabel.getText();
+    }
+    
+    
+    /**
+     * Sets a new title text.
+     * 
+     * @param newText  the title text tp be set
+     */
+    public void setTitle(String newText) {
+        String oldText = getTitle();
+        titleLabel.setText(newText);
+        firePropertyChange("title", oldText, newText);
+    }
+    
+    
+    /**
+     * Returns the current toolbar, null if none has been set before.
+     * 
+     * @return the current toolbar - if any
+     */
+    public JToolBar getToolBar() {
+        return headerPanel.getComponentCount() > 1
+            ? (JToolBar) headerPanel.getComponent(1)
+            : null;
+    }
+    
+
+    /**
+     * Sets a new tool bar in the header.
+     * 
+     * @param newToolBar the tool bar to be set in the header
+     */
+    public void setToolBar(JToolBar newToolBar) {
+        JToolBar oldToolBar = getToolBar();
+        if (oldToolBar == newToolBar) {
+            return;
+        }
+        if (oldToolBar != null) {
+            headerPanel.remove(oldToolBar);
+        }
+        if (newToolBar != null) {
+            newToolBar.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
+            headerPanel.add(newToolBar, BorderLayout.EAST);
+        }
+        updateHeader();
+        firePropertyChange("toolBar", oldToolBar, newToolBar);
+    }
+
+    
+    /**
+     * Returns the content - null, if none has been set.
+     * 
+     * @return the current content
+     */
+    public Component getContent() {
+        return hasContent() ? getComponent(1) : null;
+    }
+    
+    
+    /**
+     * Sets a new panel content; replaces any existing content, if existing.
+     * 
+     * @param newContent   the panel's new content
+     */
+    public void setContent(Component newContent) {
+        Component oldContent = getContent();
+        if (hasContent()) {
+            remove(oldContent);
+        }
+        add(newContent, BorderLayout.CENTER);
+        firePropertyChange("content", oldContent, newContent);
+    }
+    
+
+    /**
+     * Answers if the panel is currently selected (or in other words active)
+     * or not. In the selected state, the header background will be
+     * rendered differently.
+     * 
+     * @return boolean  a boolean, where true means the frame is selected 
+     *                  (currently active) and false means it is not  
+     */
+    public boolean isSelected() {
+        return isSelected;
+    }
+    
+    
+    /**
+     * This panel draws its title bar differently if it is selected,
+     * which may be used to indicate to the user that this panel
+     * has the focus, or should get more attention than other
+     * simple internal frames.
+     *
+     * @param newValue  a boolean, where true means the frame is selected 
+     *                  (currently active) and false means it is not
+     */
+    public void setSelected(boolean newValue) {
+        boolean oldValue = isSelected();
+        isSelected = newValue;
+        updateHeader();
+        firePropertyChange("selected", oldValue, newValue);
+    }
+    
+
+    // Building *************************************************************
+
+    /**
+     * Creates and answers the header panel, that consists of:
+     * an icon, a title label, a tool bar, and a gradient background.
+     * 
+     * @param label   the label to paint the icon and text
+     * @param bar     the panel's tool bar
+     * @return the panel's built header area
+     */
+    private JPanel buildHeader(JLabel label, JToolBar bar) {
+        gradientPanel =
+            new GradientPanel(new BorderLayout(), getHeaderBackground());
+        label.setOpaque(false);
+
+        gradientPanel.add(label, BorderLayout.WEST);
+        gradientPanel.setBorder(BorderFactory.createEmptyBorder(3, 4, 3, 1));
+
+        headerPanel = new JPanel(new BorderLayout());
+        headerPanel.add(gradientPanel, BorderLayout.CENTER);
+        setToolBar(bar);
+        headerPanel.setBorder(new RaisedHeaderBorder());
+        headerPanel.setOpaque(false);
+        return headerPanel;
+    }
+
+    /**
+     * Updates the header.
+     */
+    private void updateHeader() {
+        gradientPanel.setBackground(getHeaderBackground());
+        gradientPanel.setOpaque(isSelected());
+        titleLabel.setForeground(getTextForeground(isSelected()));
+        headerPanel.repaint();
+    }
+    
+
+    /**
+     * Updates the UI. In addition to the superclass behavior, we need
+     * to update the header component.
+     */
+    public void updateUI() {
+        super.updateUI();
+        if (titleLabel != null) {
+            updateHeader();
+        }
+    }
+
+
+    // Helper Code **********************************************************
+
+    /**
+     * Checks and answers if the panel has a content component set.
+     * 
+     * @return true if the panel has a content, false if it's empty
+     */
+    private boolean hasContent() {
+        return getComponentCount() > 1;
+    }
+    
+    /**
+     * Determines and answers the header's text foreground color.
+     * Tries to lookup a special color from the L&F.
+     * In case it is absent, it uses the standard internal frame forground.
+     * 
+     * @param selected   true to lookup the active color, false for the inactive
+     * @return the color of the foreground text
+     */
+    protected Color getTextForeground(boolean selected) {
+        Color c =
+            UIManager.getColor(
+                selected
+                    ? "SimpleInternalFrame.activeTitleForeground"
+                    : "SimpleInternalFrame.inactiveTitleForeground");
+        if (c != null) {
+            return c;
+        }
+        return UIManager.getColor(
+            selected 
+                ? "InternalFrame.activeTitleForeground" 
+                : "Label.foreground");
+
+    }
+
+    /**
+     * Determines and answers the header's background color.
+     * Tries to lookup a special color from the L&F.
+     * In case it is absent, it uses the standard internal frame background.
+     * 
+     * @return the color of the header's background
+     */
+    protected Color getHeaderBackground() {
+        
+        Color c =
+            UIManager.getColor("SimpleInternalFrame.activeTitleBackground");
+        if (c != null)
+            return c;
+        if (LookUtils.IS_LAF_WINDOWS_XP_ENABLED)
+            c = UIManager.getColor("InternalFrame.activeTitleGradient");
+        return c != null
+            ? c
+            : UIManager.getColor("InternalFrame.activeTitleBackground");
+    }
+
+
+    // Helper Classes *******************************************************
+
+    // A custom border for the raised header pseudo 3D effect.
+    private static class RaisedHeaderBorder extends AbstractBorder {
+
+        private static final Insets INSETS = new Insets(1, 1, 1, 0);
+
+        public Insets getBorderInsets(Component c) { return INSETS; }
+
+        public void paintBorder(Component c, Graphics g,
+            int x, int y, int w, int h) {
+                
+            g.translate(x, y);
+            g.setColor(UIManager.getColor("controlLtHighlight"));
+            g.fillRect(0, 0,   w, 1);
+            g.fillRect(0, 1,   1, h-1);
+            g.setColor(UIManager.getColor("controlShadow"));
+            g.fillRect(0, h-1, w, 1);
+            g.translate(-x, -y);
+        }
+    }
+
+    // A custom border that has a shadow on the right and lower sides.
+    private static class ShadowBorder extends AbstractBorder {
+
+        private static final Insets INSETS = new Insets(1, 1, 3, 3);
+
+        public Insets getBorderInsets(Component c) { return INSETS; }
+
+        public void paintBorder(Component c, Graphics g,
+            int x, int y, int w, int h) {
+                
+            Color shadow        = UIManager.getColor("controlShadow");
+            if (shadow == null) {
+                shadow = Color.GRAY;
+            }
+            Color lightShadow   = new Color(shadow.getRed(), 
+                                            shadow.getGreen(), 
+                                            shadow.getBlue(), 
+                                            170);
+            Color lighterShadow = new Color(shadow.getRed(),
+                                            shadow.getGreen(),
+                                            shadow.getBlue(),
+                                            70);
+            g.translate(x, y);
+            
+            g.setColor(shadow);
+            g.fillRect(0, 0, w - 3, 1);
+            g.fillRect(0, 0, 1, h - 3);
+            g.fillRect(w - 3, 1, 1, h - 3);
+            g.fillRect(1, h - 3, w - 3, 1);
+            // Shadow line 1
+            g.setColor(lightShadow);
+            g.fillRect(w - 3, 0, 1, 1);
+            g.fillRect(0, h - 3, 1, 1);
+            g.fillRect(w - 2, 1, 1, h - 3);
+            g.fillRect(1, h - 2, w - 3, 1);
+            // Shadow line2
+            g.setColor(lighterShadow);
+            g.fillRect(w - 2, 0, 1, 1);
+            g.fillRect(0, h - 2, 1, 1);
+            g.fillRect(w-2, h-2, 1, 1);
+            g.fillRect(w - 1, 1, 1, h - 2);
+            g.fillRect(1, h - 1, w - 2, 1);
+            g.translate(-x, -y);
+        }
+    }
+
+    // A panel with a horizontal gradient background.
+    private static class GradientPanel extends JPanel {
+        
+        private GradientPanel(LayoutManager lm, Color background) {
+            super(lm);
+            setBackground(background);
+        }
+
+        public void paintComponent(Graphics g) {
+            super.paintComponent(g);
+            if (!isOpaque()) {
+                return;
+            }
+            Color control = UIManager.getColor("control");
+            int width  = getWidth();
+            int height = getHeight();
+
+            Graphics2D g2 = (Graphics2D) g;
+            Paint storedPaint = g2.getPaint();
+            g2.setPaint(
+                new GradientPaint(0, 0, getBackground(), width, 0, control));
+            g2.fillRect(0, 0, width, height);
+            g2.setPaint(storedPaint);
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/src/java/gnu/dtools/ritopt/ArrayOption.java b/src/java/gnu/dtools/ritopt/ArrayOption.java
new file mode 100644
index 0000000..cdb5d65
--- /dev/null
+++ b/src/java/gnu/dtools/ritopt/ArrayOption.java
@@ -0,0 +1,82 @@
+package gnu.dtools.ritopt;
+
+/**
+ * ArrayOption.java
+ *
+ * Version:
+ *    $Id: ArrayOption.java,v 1.1 2004/05/20 20:45:47 mortenalver Exp $
+ */
+
+/**
+ * The principal base class used to register option variables that
+ * represent arrays or Collections. Array options are useful for
+ * options which represent path lists or file specifications.<p>
+ *
+ * The preferred derived sub-class implementation is to provide a constructor
+ * with a single array parameter to allow for simple registration. For
+ * example, an ArrayOption derived class for int arrays should
+ * implement the following constructor and accessor.
+ *
+ * <pre>
+ *   MyIntArrayOption( int array[] );
+ *   int[] getValue();
+ * </pre>
+ *
+ * Although this has no affect on option processing, following this
+ * philosophy for the public interfaces make it easier for the programmer to
+ * use your source code.
+ *
+ * <hr>
+ *
+ * <pre>
+ * Copyright (C) Damian Ryan Eads, 2001. All Rights Reserved.
+ *
+ * ritopt 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.
+
+ * ritopt is distributed in the hope that 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 ritopt; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * </pre>
+ *
+ * @author Damian Ryan Eads
+ */
+
+public abstract class ArrayOption extends Option implements OptionArrayable {
+
+    /**
+     * Builds and initializes ArrayOption class members, and invokes
+     * the Option constructor.
+     */
+
+    public ArrayOption() {
+	super();
+    }
+
+    /**
+     * Get an ArrayOption in array form. If the option value is an array of
+     * primitive values, references to wrapper objects are returned.
+     *
+     * @return An array of objects representing the option's value.
+     */
+
+    public abstract Object[] getObjectArray();
+
+    /**
+     * Get a list of objects representing the elements of this array option.
+     *
+     * @return A list of objects representing the option's value.
+     */
+
+    public java.util.List getObjectList() {
+	return java.util.Arrays.asList( getObjectArray() );
+    }
+} /** ArrayOption */
+
diff --git a/src/java/gnu/dtools/ritopt/BooleanOption.java b/src/java/gnu/dtools/ritopt/BooleanOption.java
new file mode 100644
index 0000000..2f2f194
--- /dev/null
+++ b/src/java/gnu/dtools/ritopt/BooleanOption.java
@@ -0,0 +1,245 @@
+package gnu.dtools.ritopt;
+
+/**
+ * BooleanOption.java
+ *
+ * Version:
+ *     $Id: BooleanOption.java,v 1.2 2005/11/08 04:53:27 mortenalver Exp $
+ */
+
+/**
+ * This class is used for options with boolean values. There are several
+ * ways to invoke a boolean option at the command line.<p>
+ *
+ * For example, a plus (true) or minus (false) sign directly after the short
+ * or long option may be used.<p>
+ * <pre>
+ *  myprogram -a+ -b- --longa+ --longb-
+ * </pre>
+ * The following keywords may be used to invoke an option using the assignment
+ * form.
+ * <ul>
+ *  <li>+
+ *  <li>-
+ *  <li>true
+ *  <li>false
+ *  <li>yes
+ *  <li>no
+ *  <li>on
+ *  <li>off
+ *  <li>activated
+ *  <li>not activated
+ *  <li>active
+ *  <li>inactive
+ * </ul>
+ * To invoke an option using assignment form where <value> is the <value> of
+ * the option, use the following syntax.<p>
+ * <pre>
+ *  myprogram -a=<keyword> -b <keyword> --longa=<keyword> --longb=<keyword>
+ * </pre>
+ * Invoking a boolean option without using any of the aforementioned
+ * keywords and forms will set the option to true by default.
+ *
+ * <hr>
+ *
+ * <pre>
+ * Copyright (C) Damian Ryan Eads, 2001. All Rights Reserved.
+ *
+ * ritopt 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.
+
+ * ritopt is distributed in the hope that 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 ritopt; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * </pre>
+ *
+ * @author Damian Eads
+ */
+
+public class BooleanOption extends Option {
+
+    /**
+     * The value of the boolean option.
+     */
+
+    private boolean value;
+
+    /**
+     * Constructs a boolean option that is initially false.
+     */
+
+    public BooleanOption() {
+	this( false );
+    }
+
+    /**
+     * Constructs a boolean option by copying the boolean option passed.
+     *
+     * @param op     The boolean option to copy.
+     */
+
+    public BooleanOption( BooleanOption op ) {
+	super( op );
+	op.value = op.getValue();
+    }
+
+    /**
+     * Constructs a boolean option initialized with the value passed.
+     *
+     * @param value    The initial value of this boolean option.
+     */
+
+    public BooleanOption( boolean value ) {
+	this( value, null );
+    }
+
+    /**
+     * Constructs a boolean option initialized with the value and
+     * long option passed.
+     *
+     * @param value      The initial value of this boolean option.
+     * @param longOption The long option associated with this option.
+     */
+
+    public BooleanOption( boolean value, String longOption ) {
+	this( value, longOption, '\0' );
+    }
+
+    /**
+     * Constructs a boolean option initialized with the value and short
+     * option passed.
+     *
+     * @param value       The initial value of this boolean option.
+     * @param shortOption The short option associated with this option.
+     */
+
+    public BooleanOption( boolean value, char shortOption ) {
+	this( value, null, shortOption );
+    }
+
+    /**
+     * Constructs a boolean option initialized with the value, short
+     * and long option passed.
+     *
+     * @param shortOption The short option associated with this option.
+     * @param longOption  The long option associated with this option.
+     * @param value       The initial value of this boolean option.
+     */
+
+    public BooleanOption( boolean value, String longOption, char shortOption ) {
+	super( longOption, shortOption );
+	this.value = value;
+    }
+
+    /**
+     * Return the value as an object.
+     *
+     * @return This value as an option.
+     */
+
+    public Object getObject() {
+	return Boolean.valueOf(value);
+    }
+
+    /**
+     * Modify this option based on a string representation. Acceptable values
+     * are +, -, true, false, yes, no, on, off, activated, not activated,
+     * active, and inactive.
+     *
+     * @param     value String representation of the object.
+     * @exception OptionModificationException Thrown if an error occurs
+     *                                  during modification of an option.
+     */
+
+    public void modify( String value ) throws OptionModificationException {
+	String val = value.toUpperCase();
+	this.value = false;
+	if ( val.equals( "+" ) || val.equals( "TRUE" ) ||
+	     val.equals( "YES" ) || val.equals( "ON" ) ||
+	     val.equals( "ACTIVATED" ) || val.equals( "ACTIVE" ) ) {
+	    this.value = true;
+	}
+	else if ( val.equals( "-" ) || val.equals( "FALSE" ) ||
+		  val.equals( "NO" ) || val.equals( "OFF" ) ||
+		  val.equals( "NOT ACTIVATED" ) ||
+		  val.equals( "INACTIVE" ) ) {
+	    this.value = false;
+	}
+	else {
+	    throw new OptionModificationException( "Error. A boolean value of\n+/-/true/false/yes/no/on/off/activated/not activated/active/inactive must be\nspecified, not '" + value + "'." );
+	}
+    }
+
+    /**
+     * Modify this option based on a string representation. Acceptable values
+     * are +, -, true, false, yes, no, on, off, activated, not activated,
+     * active, inactive.
+     *
+     * @param     value String representation of the object.
+     * @exception OptionModificationException Thrown if an error occurs
+     *                                  during modification of an option.
+     */
+
+    public void setValue( String value ) throws OptionModificationException {
+	modify( value );
+    }
+
+    /**
+     * Modify this option using a boolean value.
+     *
+     * @param     value A boolean value.
+     */
+
+    public void setValue( boolean value ) {
+	this.value = value;
+    }
+
+    /**
+     * Return this option as a boolean.
+     *
+     * @return This option as a boolean.
+     */
+
+    public boolean getValue() {
+	return value;
+    }
+
+    /**
+     * Return this option as a string.
+     *
+     * @return This option as a string.
+     */
+
+    public String getStringValue() {
+	return ( value ) ? "TRUE" : "FALSE";
+    }
+
+    /**
+     * Returns the type name of this option. For a BooleanOption, "BOOLEAN"
+     * is returned.
+     *
+     * @return The type name of this option.
+     */
+
+    public String getTypeName() {
+	return "BOOLEAN";
+    }
+
+    /**
+     * Returns a string representation of this object.
+     *
+     * @return A string representation of this object.
+     */
+
+    public String toString() {
+	return getStringValue();
+    }
+
+} /** BooleanOption */
diff --git a/src/java/gnu/dtools/ritopt/ByteOption.java b/src/java/gnu/dtools/ritopt/ByteOption.java
new file mode 100644
index 0000000..c6c000a
--- /dev/null
+++ b/src/java/gnu/dtools/ritopt/ByteOption.java
@@ -0,0 +1,203 @@
+package gnu.dtools.ritopt;
+
+/**
+ * ByteOption.java
+ *
+ * Version:
+ *     $Id: ByteOption.java,v 1.1 2004/05/20 20:45:47 mortenalver Exp $
+ */
+
+/**
+ * This class is used for options with byte values.
+ *
+ * <hr>
+ *
+ * <pre>
+ * Copyright (C) Damian Ryan Eads, 2001. All Rights Reserved.
+ *
+ * ritopt 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.
+
+ * ritopt is distributed in the hope that 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 ritopt; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * </pre>
+ *
+ * @author Damian Eads
+ */
+
+public class ByteOption extends Option {
+
+    /**
+     * The value of this byte option.
+     */
+
+    private byte value;
+
+    /**
+     * Constructs a byte option that is set to the null character.
+     */
+
+    public ByteOption() {
+	this( (byte)0 );
+    }
+
+    /**
+     * Constructs a byte option by copying the byte option passed.
+     *
+     * @param op     The byte option to copy.
+     */
+
+    public ByteOption( ByteOption op ) {
+	super( op );
+	op.value = op.getValue();
+    }
+
+    /**
+     * Constructs a byte option initialized with the value passed.
+     *
+     * @param value    The initial value of this byte option.
+     */
+
+    public ByteOption( byte value ) {
+	this( value, null );
+    }
+
+    /**
+     * Constructs a byte option initialized with the value and
+     * long option passed.
+     *
+     * @param value      The initial value of this byte option.
+     * @param longOption The long option associated with this option.
+     */
+
+    public ByteOption( byte value, String longOption ) {
+	this( value, longOption, '\0' );
+    }
+
+    /**
+     * Constructs a byte option initialized with the value and short
+     * option passed.
+     *
+     * @param shortOption The short option associated with this option.
+     * @param value       The initial value of this byte option.
+     */
+
+    public ByteOption( byte value, char shortOption ) {
+	this( value, null, shortOption );
+    }
+
+    /**
+     * Constructs a byte option initialized with the value, short
+     * and long option passed.
+     *
+     * @param shortOption The short option associated with this option.
+     * @param longOption  The long option associated with this option.
+     * @param value       The initial value of this byte option.
+     */
+
+    public ByteOption( byte value, String longOption, char shortOption ) {
+	super( longOption, shortOption );
+	this.value = value;
+    }
+
+    /**
+     * Return the value as an object.
+     *
+     * @return This value as an option.
+     */
+
+    public Object getObject() {
+	return new Byte( value );
+    }
+
+    /**
+     * Modify this option based on a string representation.
+     *
+     * @param     value String representation of the object.
+     * @exception OptionModificationException Thrown if an error occurs
+     *                                  during modification of an option.
+     */
+
+    public void modify( String value ) throws OptionModificationException {
+	try {
+	    this.value = Byte.parseByte( value );
+	}
+	catch ( NumberFormatException e ) {
+	    throw new OptionModificationException( "Error. A byte must be"
+						   + " specified, not '"
+						   + value + "'." );
+	}
+    }
+
+    /**
+     * Modify this option based on a string representation.
+     *
+     * @param     value String representation of the object.
+     * @exception OptionModificationException Thrown if an error occurs
+     *                                  during modification of an option.
+     */
+
+    public void setValue( String value ) throws OptionModificationException {
+	modify( value );
+    }
+
+    /**
+     * Modify this option using a byte value.
+     *
+     * @param     value A byte value.
+     */
+
+    public void setValue( byte value ) {
+	this.value = value;
+    }
+
+    /**
+     * Return this option as a boolean.
+     *
+     * @return This option as a boolean.
+     */
+
+    public byte getValue() {
+	return value;
+    }
+
+    /**
+     * Return this option as a string.
+     *
+     * @return This option as a string.
+     */
+
+    public String getStringValue() {
+	return Byte.toString( value );
+    }
+
+    /**
+     * Returns the type name of this option. For a ByteOption, "BYTE"
+     * is returned.
+     *
+     * @return The type name of this option.
+     */
+
+    public String getTypeName() {
+	return "BYTE";
+    }
+
+    /**
+     * Returns a string representation of this object.
+     *
+     * @return A string representation of this object.
+     */
+
+    public String toString() {
+	return getStringValue();
+    }
+
+} /** ByteOption */
diff --git a/src/java/gnu/dtools/ritopt/CharOption.java b/src/java/gnu/dtools/ritopt/CharOption.java
new file mode 100644
index 0000000..94c25ae
--- /dev/null
+++ b/src/java/gnu/dtools/ritopt/CharOption.java
@@ -0,0 +1,196 @@
+package gnu.dtools.ritopt;
+
+/**
+ * CharOption.java
+ *
+ * Version:
+ *    $Id: CharOption.java,v 1.1 2004/05/20 20:45:47 mortenalver Exp $
+ */
+
+/**
+ * This class is used for options with character values.
+ *
+ * <hr>
+ *
+ * <pre>
+ * Copyright (C) Damian Ryan Eads, 2001. All Rights Reserved.
+ *
+ * ritopt 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.
+
+ * ritopt is distributed in the hope that 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 ritopt; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * </pre>
+ *
+ * @author Damian Eads
+ */
+
+public class CharOption extends Option {
+
+    /**
+     * The value of this character option.
+     */
+
+    private char value;
+
+    /**
+     * Constructs a character option that is set to the space character.
+     */
+
+    public CharOption() {
+	this( ' ' );
+    }
+
+    /**
+     * Constructs a character option by copying the character option passed.
+     *
+     * @param op     The character option to copy.
+     */
+
+    public CharOption( CharOption op ) {
+	super( op );
+	op.value = op.getValue();
+    }
+
+    /**
+     * Constructs a character option initialized with the value passed.
+     *
+     * @param value    The initial value of this character option.
+     */
+
+    public CharOption( char value ) {
+	this( value, null );
+    }
+
+    /**
+     * Constructs a character option initialized with the value and
+     * long option passed.
+     *
+     * @param value      The initial value of this character option.
+     * @param longOption The long option associated with character option.
+     */
+
+    public CharOption( char value, String longOption ) {
+	this( value, longOption, '\0' );
+    }
+
+    /**
+     * Constructs a character option initialized with the value and
+     * short option passed.
+     *
+     * @param value       The initial value of this character option.
+     * @param shortOption The short option associated with this option.
+     */
+
+    public CharOption( char value, char shortOption ) {
+	this( value, null, shortOption );
+    }
+
+    /**
+     * Constructs a character option initialized with the value, short
+     * and long option passed.
+     *
+     * @param shortOption The short option associated with this option.
+     * @param longOption  The long option associated with this option.
+     * @param value       The initial value of this character option.
+     */
+
+    public CharOption( char value, String longOption, char shortOption ) {
+	super( longOption, shortOption );
+	this.value = value;
+    }
+
+    /**
+     * Return the value as an object.
+     *
+     * @return This value as an option.
+     */
+
+    public Object getObject() {
+	return new Character( value );
+    }
+
+    /**
+     * Modify this option based on a string representation.
+     *
+     * @param     value String representation of the object.
+     * @exception OptionModificationException Thrown if an error occurs
+     *                                  during modification of an option.
+     */
+
+    public void modify( String value ) throws OptionModificationException {
+	this.value = ( value.length() > 0 ) ? value.charAt( 0 ) : ' ';
+    }
+
+    /**
+     * Modify this option based on a string representation.
+     *
+     * @param     value String representation of the object.
+     * @exception OptionModificationException Thrown if an error occurs
+     *                                  during modification of an option.
+     */
+
+    public void setValue( String value ) throws OptionModificationException {
+	modify( value );
+    }
+
+    /**
+     * Modify this option using a character value.
+     *
+     * @param     value A character value.
+     */
+
+    public void setValue( char value ) {
+	this.value = value;
+    }
+
+    /**
+     * Return this option as a character.
+     *
+     * @return This option as a character.
+     */
+
+    public char getValue() {
+	return value;
+    }
+
+    /**
+     * Return this option as a string.
+     *
+     * @return This option as a string.
+     */
+
+    public String getStringValue() {
+	return "" + value;
+    }
+
+    /**
+     * Returns the type name of this option. For a ByteOption, "BYTE"
+     * is returned.
+     *
+     * @return The type name of this option.
+     */
+
+    public String getTypeName() {
+	return "CHAR";
+    }
+
+    /**
+     * Returns a string representation of this object.
+     *
+     * @return A string representation of this object.
+     */
+
+    public String toString() {
+	return getStringValue();
+    }
+
+} /** CharOption */
diff --git a/src/java/gnu/dtools/ritopt/DoubleOption.java b/src/java/gnu/dtools/ritopt/DoubleOption.java
new file mode 100644
index 0000000..5ecb10d
--- /dev/null
+++ b/src/java/gnu/dtools/ritopt/DoubleOption.java
@@ -0,0 +1,203 @@
+package gnu.dtools.ritopt;
+
+/**
+ * DoubleOption.java
+ *
+ * Version:
+ *    $Id: DoubleOption.java,v 1.1 2004/05/20 20:45:47 mortenalver Exp $
+ */
+
+/**
+ * This class is used for options with double values.
+ *
+ * <hr>
+ *
+ * <pre>
+ * Copyright (C) Damian Ryan Eads, 2001. All Rights Reserved.
+ *
+ * ritopt 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.
+
+ * ritopt is distributed in the hope that 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 ritopt; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * </pre>
+ *
+ * @author Damian Eads
+ */
+
+public class DoubleOption extends Option {
+
+    /**
+     * The value of this double option.
+     */
+
+    private double value;
+
+    /**
+     * Constructs a double option that is initially set to zero.
+     */
+
+    public DoubleOption() {
+	this( 0.0 );
+    }
+
+    /**
+     * Constructs a double option by copying the double option passed.
+     *
+     * @param op     The character option to copy.
+     */
+
+    public DoubleOption( DoubleOption op ) {
+	super( op );
+	op.value = op.getValue();
+    }
+
+    /**
+     * Constructs a double option initialized with the value passed.
+     *
+     * @param value    The initial value of this double option.
+     */
+
+    public DoubleOption( double value ) {
+	this( value, null );
+    }
+
+    /**
+     * Constructs a double option initialized with the value and
+     * long option passed.
+     *
+     * @param value      The initial value of this double option.
+     * @param longOption The long option associated with double option.
+     */
+
+    public DoubleOption( double value, String longOption ) {
+	this( value, longOption, '\0' );
+    }
+
+    /**
+     * Constructs a character option initialized with the value and
+     * short option passed.
+     *
+     * @param value       The initial value of this double option.
+     * @param shortOption The short option associated with this option.
+     */
+
+    public DoubleOption( double value, char shortOption ) {
+	this( value, null, shortOption );
+    }
+
+    /**
+     * Constructs a double option initialized with the value, short
+     * and long option passed.
+     *
+     * @param shortOption The short option associated with this option.
+     * @param longOption  The long option associated with this option.
+     * @param value       The initial value of this double option.
+     */
+
+    public DoubleOption( double value, String longOption, char shortOption ) {
+	super( longOption, shortOption );
+	this.value = value;
+    }
+
+    /**
+     * Return the value as an object.
+     *
+     * @return This value as an option.
+     */
+
+    public Object getObject() {
+	return new Double( value );
+    }
+
+    /**
+     * Modify this option based on a string representation.
+     *
+     * @param     value String representation of the object.
+     * @exception OptionModificationException Thrown if an error occurs
+     *                                  during modification of an option.
+     */
+
+    public void modify( String value ) throws OptionModificationException {
+	try {
+	    this.value = Double.parseDouble( value );
+	}
+	catch ( NumberFormatException e ) {
+	    throw new OptionModificationException( "Error. A double must be"
+						   + " specified, not '"
+						   + value + "'." );
+	}
+    }
+
+    /**
+     * Modify this option based on a string representation.
+     *
+     * @param     value String representation of the object.
+     * @exception OptionModificationException Thrown if an error occurs
+     *                                  during modification of an option.
+     */
+
+    public void setValue( String value ) throws OptionModificationException {
+	modify( value );
+    }
+
+    /**
+     * Modify this option using a double value.
+     *
+     * @param     value A double value.
+     */
+
+    public void setValue( double value ) {
+	this.value = value;
+    }
+
+    /**
+     * Return this option as a double.
+     *
+     * @return This option as a double.
+     */
+
+    public double getValue() {
+	return value;
+    }
+
+    /**
+     * Return this option as a string.
+     *
+     * @return This option as a string.
+     */
+
+    public String getStringValue() {
+	return Double.toString( value );
+    }
+
+    /**
+     * Returns the type name of this option. For a DoubleOption, "DOUBLE"
+     * is returned.
+     *
+     * @return The type name of this option.
+     */
+
+    public String getTypeName() {
+	return "DOUBLE";
+    }
+
+    /**
+     * Returns a string representation of this object.
+     *
+     * @return A string representation of this object.
+     */
+
+    public String toString() {
+	return getStringValue();
+    }
+
+} /** DoubleOption */
diff --git a/src/java/gnu/dtools/ritopt/FloatOption.java b/src/java/gnu/dtools/ritopt/FloatOption.java
new file mode 100644
index 0000000..fe81521
--- /dev/null
+++ b/src/java/gnu/dtools/ritopt/FloatOption.java
@@ -0,0 +1,203 @@
+package gnu.dtools.ritopt;
+
+/**
+ * FloatOption.java
+ *
+ * Version:
+ *    $Id: FloatOption.java,v 1.1 2004/05/20 20:45:47 mortenalver Exp $
+ */
+
+/**
+ * This class is used for options with float values.
+ *
+ * <hr>
+ *
+ * <pre>
+ * Copyright (C) Damian Ryan Eads, 2001. All Rights Reserved.
+ *
+ * ritopt 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.
+
+ * ritopt is distributed in the hope that 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 ritopt; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * </pre>
+ *
+ * @author Damian Eads
+ */
+
+public class FloatOption extends Option {
+
+    /**
+     * The value of this float option.
+     */
+
+    private float value;
+
+    /**
+     * Constructs a float option that is initially set to zero.
+     */
+
+    public FloatOption() {
+	this( 0.0f );
+    }
+
+    /**
+     * Constructs a float option by copying the float option passed.
+     *
+     * @param op     The character option to copy.
+     */
+
+    public FloatOption( FloatOption op ) {
+	super( op );
+	op.value = op.getValue();
+    }
+
+    /**
+     * Constructs a float option initialized with the value passed.
+     *
+     * @param value    The initial value of this float option.
+     */
+
+    public FloatOption( float value ) {
+	this( value, null );
+    }
+
+    /**
+     * Constructs a float option initialized with the value and
+     * long option passed.
+     *
+     * @param value      The initial value of this float option.
+     * @param longOption The long option associated with float option.
+     */
+
+    public FloatOption( float value, String longOption ) {
+	this( value, longOption, '\0' );
+    }
+
+    /**
+     * Constructs a character option initialized with the value and
+     * short option passed.
+     *
+     * @param value       The initial value of this float option.
+     * @param shortOption The short option associated with this option.
+     */
+
+    public FloatOption( float value, char shortOption ) {
+	this( value, null, shortOption );
+    }
+
+    /**
+     * Constructs a float option initialized with the value, short
+     * and long option passed.
+     *
+     * @param shortOption The short option associated with this option.
+     * @param longOption  The long option associated with this option.
+     * @param value       The initial value of this float option.
+     */
+
+    public FloatOption( float value, String longOption, char shortOption ) {
+	super( longOption, shortOption );
+	this.value = value;
+    }
+
+    /**
+     * Return the value as an object.
+     *
+     * @return This value as an option.
+     */
+
+    public Object getObject() {
+	return new Float( value );
+    }
+
+    /**
+     * Modify this option based on a string representation.
+     *
+     * @param     value String representation of the object.
+     * @exception OptionModificationException Thrown if an error occurs
+     *                                  during modification of an option.
+     */
+
+    public void modify( String value ) throws OptionModificationException {
+	try {
+	    this.value = Float.parseFloat( value );
+	}
+	catch ( NumberFormatException e ) {
+	    throw new OptionModificationException( "Error. A float must be"
+						   + " specified, not '"
+						   + value + "'." );
+	}
+    }
+
+    /**
+     * Modify this option based on a string representation.
+     *
+     * @param     value String representation of the object.
+     * @exception OptionModificationException Thrown if an error occurs
+     *                                  during modification of an option.
+     */
+
+    public void setValue( String value ) throws OptionModificationException {
+	modify( value );
+    }
+
+    /**
+     * Modify this option using a float value.
+     *
+     * @param     value A float value.
+     */
+
+    public void setValue( float value ) {
+	this.value = value;
+    }
+
+    /**
+     * Return this option as a float.
+     *
+     * @return This option as a float.
+     */
+
+    public float getValue() {
+	return value;
+    }
+
+    /**
+     * Return this option as a string.
+     *
+     * @return This option as a string.
+     */
+
+    public String getStringValue() {
+	return Float.toString( value );
+    }
+
+    /**
+     * Returns the type name of this option. For a FloatOption, "FLOAT"
+     * is returned.
+     *
+     * @return The type name of this option.
+     */
+
+    public String getTypeName() {
+	return "FLOAT";
+    }
+
+    /**
+     * Returns a string representation of this object.
+     *
+     * @return A string representation of this object.
+     */
+
+    public String toString() {
+	return getStringValue();
+    }
+
+}
diff --git a/src/java/gnu/dtools/ritopt/IntOption.java b/src/java/gnu/dtools/ritopt/IntOption.java
new file mode 100644
index 0000000..4879853
--- /dev/null
+++ b/src/java/gnu/dtools/ritopt/IntOption.java
@@ -0,0 +1,204 @@
+package gnu.dtools.ritopt;
+
+/**
+ * IntOption.java
+ *
+ * Version:
+ *    $Id: IntOption.java,v 1.1 2004/05/20 20:45:47 mortenalver Exp $
+ */
+
+/**
+ * This class is used for options with integer values.
+ *
+ * <pre>
+ *
+ * <hr>
+ *
+ * Copyright (C) Damian Ryan Eads, 2001. All Rights Reserved.
+ *
+ * ritopt 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.
+
+ * ritopt is distributed in the hope that 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 ritopt; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * </pre>
+ *
+ * @author Damian Eads
+ */
+
+public class IntOption extends Option {
+
+    /**
+     * The value of this integer option.
+     */
+
+    private int value;
+
+    /**
+     * Constructs an integer option that is initially set to zero.
+     */
+
+    public IntOption() {
+	this( 0 );
+    }
+
+    /**
+     * Constructs an integer option by copying the integer option passed.
+     *
+     * @param op     The character option to copy.
+     */
+
+    public IntOption( IntOption op ) {
+	super( op );
+	op.value = op.getValue();
+    }
+
+    /**
+     * Constructs an integer option initialized with the value passed.
+     *
+     * @param value    The initial value of this integer option.
+     */
+
+    public IntOption( int value ) {
+	this( value, null );
+    }
+
+    /**
+     * Constructs an integer option initialized with the value and
+     * long option passed.
+     *
+     * @param value      The initial value of this integer option.
+     * @param longOption The long option associated with integer option.
+     */
+
+    public IntOption( int value, String longOption ) {
+	this( value, longOption, '\0' );
+    }
+
+    /**
+     * Constructs a character option initialized with the value and
+     * short option passed.
+     *
+     * @param value       The initial value of this integer option.
+     * @param shortOption The short option associated with this option.
+     */
+
+    public IntOption( int value, char shortOption ) {
+	this( value, null, shortOption );
+    }
+
+    /**
+     * Constructs an integer option initialized with the value, short
+     * and long option passed.
+     *
+     * @param shortOption The short option associated with this option.
+     * @param longOption  The long option associated with this option.
+     * @param value       The initial value of this integer option.
+     */
+
+    public IntOption( int value, String longOption, char shortOption ) {
+	super( longOption, shortOption );
+	this.value = value;
+    }
+
+    /**
+     * Return the value as an object.
+     *
+     * @return This value as an option.
+     */
+
+    public Object getObject() {
+	return new Integer( value );
+    }
+
+    /**
+     * Modify this option based on a string representation.
+     *
+     * @param     value String representation of the object.
+     * @exception OptionModificationException Thrown if an error occurs
+     *                                  during modification of an option.
+     */
+
+    public void modify( String value ) throws OptionModificationException {
+	try {
+	    this.value = Integer.parseInt( value );
+	}
+	catch ( NumberFormatException e ) {
+	    throw new OptionModificationException( "Error. An integer must be"
+						   + " specified, not '"
+						   + value + "'." );
+	}
+    }
+
+    /**
+     * Modify this option based on a string representation.
+     *
+     * @param     value String representation of the object.
+     * @exception OptionModificationException Thrown if an error occurs
+     *                                  during modification of an option.
+     */
+
+    public void setValue( String value ) throws OptionModificationException {
+	modify( value );
+    }
+
+    /**
+     * Modify this option using an integer value.
+     *
+     * @param     value an integer value.
+     */
+
+    public void setValue( int value ) {
+	this.value = value;
+    }
+
+    /**
+     * Return this option as an integer.
+     *
+     * @return This option as an integer.
+     */
+
+    public int getValue() {
+	return value;
+    }
+
+    /**
+     * Return this option as a string.
+     *
+     * @return This option as a string.
+     */
+
+    public String getStringValue() {
+	return Integer.toString( value );
+    }
+
+    /**
+     * Returns the type name of this option. For an IntegerOption, "INTEGER"
+     * is returned.
+     *
+     * @return The type name of this option.
+     */
+
+    public String getTypeName() {
+	return "INTEGER";
+    }
+
+    /**
+     * Returns a string representation of this object.
+     *
+     * @return A string representation of this object.
+     */
+
+    public String toString() {
+	return getStringValue();
+    }
+
+}
diff --git a/src/java/gnu/dtools/ritopt/LongOption.java b/src/java/gnu/dtools/ritopt/LongOption.java
new file mode 100644
index 0000000..87e3119
--- /dev/null
+++ b/src/java/gnu/dtools/ritopt/LongOption.java
@@ -0,0 +1,203 @@
+package gnu.dtools.ritopt;
+
+/**
+ * LongOption.java
+ *
+ * Version:
+ *    $Id: LongOption.java,v 1.1 2004/05/20 20:45:47 mortenalver Exp $
+ */
+
+/**
+ * This class is used for options with long values.
+ *
+ * <hr>
+ *
+ * <pre>
+ * Copyright (C) Damian Ryan Eads, 2001. All Rights Reserved.
+ *
+ * ritopt 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.
+
+ * ritopt is distributed in the hope that 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 ritopt; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * </pre>
+ *
+ * @author Damian Eads
+ */
+
+public class LongOption extends Option {
+
+    /**
+     * The value of this long option.
+     */
+
+    private long value;
+
+    /**
+     * Constructs a long option that is initially set to zero.
+     */
+
+    public LongOption() {
+	this( (long)0 );
+    }
+
+    /**
+     * Constructs a long option by copying the long option passed.
+     *
+     * @param op     The character option to copy.
+     */
+
+    public LongOption( LongOption op ) {
+	super( op );
+	op.value = op.getValue();
+    }
+
+    /**
+     * Constructs a long option initialized with the value passed.
+     *
+     * @param value    The initial value of this long option.
+     */
+
+    public LongOption( long value ) {
+	this( value, null );
+    }
+
+    /**
+     * Constructs a long option initialized with the value and
+     * long option passed.
+     *
+     * @param value      The initial value of this long option.
+     * @param longOption The long option associated with long option.
+     */
+
+    public LongOption( long value, String longOption ) {
+	this( value, longOption, '\0' );
+    }
+
+    /**
+     * Constructs a character option initialized with the value and
+     * short option passed.
+     *
+     * @param value       The initial value of this long option.
+     * @param shortOption The short option associated with this option.
+     */
+
+    public LongOption( long value, char shortOption ) {
+	this( value, null, shortOption );
+    }
+
+    /**
+     * Constructs a long option initialized with the value, short
+     * and long option passed.
+     *
+     * @param shortOption The short option associated with this option.
+     * @param longOption  The long option associated with this option.
+     * @param value       The initial value of this long option.
+     */
+
+    public LongOption( long value, String longOption, char shortOption ) {
+	super( longOption, shortOption );
+	this.value = value;
+    }
+
+    /**
+     * Return the value as an object.
+     *
+     * @return This value as an option.
+     */
+
+    public Object getObject() {
+	return new Long( value );
+    }
+
+    /**
+     * Modify this option based on a string representation.
+     *
+     * @param     value String representation of the object.
+     * @exception OptionModificationException Thrown if an error occurs
+     *                                  during modification of an option.
+     */
+
+    public void modify( String value ) throws OptionModificationException {
+	try {
+	    this.value = Long.parseLong( value );
+	}
+	catch ( NumberFormatException e ) {
+	    throw new OptionModificationException( "Error. A long must be"
+						   + " specified, not '"
+						   + value + "'." );
+	}
+    }
+
+    /**
+     * Modify this option based on a string representation.
+     *
+     * @param     value String representation of the object.
+     * @exception OptionModificationException Thrown if an error occurs
+     *                                  during modification of an option.
+     */
+
+    public void setValue( String value ) throws OptionModificationException {
+	modify( value );
+    }
+
+    /**
+     * Modify this option using a long value.
+     *
+     * @param     value A long value.
+     */
+
+    public void setValue( long value ) {
+	this.value = value;
+    }
+
+    /**
+     * Return this option as a long.
+     *
+     * @return This option as a long.
+     */
+
+    public long getValue() {
+	return value;
+    }
+
+    /**
+     * Return this option as a string.
+     *
+     * @return This option as a string.
+     */
+
+    public String getStringValue() {
+	return Long.toString( value );
+    }
+
+    /**
+     * Returns the type name of this option. For a LongOption, "LONG"
+     * is returned.
+     *
+     * @return The type name of this option.
+     */
+
+    public String getTypeName() {
+	return "LONG";
+    }
+
+    /**
+     * Returns a string representation of this object.
+     *
+     * @return A string representation of this object.
+     */
+
+    public String toString() {
+	return getStringValue();
+    }
+
+} /** LongOption */
diff --git a/src/java/gnu/dtools/ritopt/NotifyOption.java b/src/java/gnu/dtools/ritopt/NotifyOption.java
new file mode 100644
index 0000000..37c12bc
--- /dev/null
+++ b/src/java/gnu/dtools/ritopt/NotifyOption.java
@@ -0,0 +1,318 @@
+package gnu.dtools.ritopt;
+
+/**
+ * The NotifyOption class is used to register options that when invoked
+ * notify a listener. This provides an interface for event-driven
+ * options processing. In order for a class to be notified, it must implement
+ * the OptionListener interface.<p>
+ *
+ * When the option is invoked, the corresponding short, long, and option
+ * values are put in an OptionEvent object, and passed to all registered
+ * listeners.<p>
+ *
+ * A class must implement the OptionListener interface in order to receive
+ * notification of option events.<p>
+ *
+ * For a more detailed explanation please refer to the tutorial. The following
+ * is a simple example of how a NotifyOption is used.
+ * <pre>
+ *
+ * import gnu.dtools.ritopt.*;
+ *
+ * public class TellMe implements OptionListener {
+ *
+ *    public static void main( String args[] ) {
+ *       TellMe m = new TellMe();
+ *       Options processor = new Options();
+ *       NotifyOption say = new NotifyOption( m );
+ *       processor.register( "say", 's', say );
+ *       processor.process();
+ *    }
+ *
+ *    public void optionInvoked( OptionEvent e ) {
+ *       if ( e.getCommand().equals( "say" ) ) {
+ *           String say = e.getValue();
+ *           if ( Utility.trim( say ).length() == 0 ) say = "nothing";
+ *           System.err.println( "You told me to say " + nothing + "." );
+ *       }
+ *    }
+ * }
+ *
+ * cookies at crazymonster$ javac TellMe.java
+ * cookies at crazymonster$ java TellMe
+ * cookies at crazymonster$ java TellMe
+ * cookies at crazymonster$ java TellMe --say -s
+ * You told me to say nothing.
+ * You told me to say nothing.
+ * cookies at crazymonster$ java TellMe --say hello
+ * You told me to say hello.
+ * cookies at crazymonster$ java TellMe --say "I'm sorry"
+ * You told me to say I'm sorry.
+ * cookies at crazymonster$ java TellMe --say="not until tomorrow" -s "I'm crazy"
+ * You told me to say not until tomorrow.
+ * You told me to say I'm crazy.
+ * </pre>
+ *
+ * <hr>
+ *
+ * <pre>
+ * Copyright (C) Damian Ryan Eads, 2001. All Rights Reserved.
+ *
+ * ritopt 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.
+
+ * ritopt is distributed in the hope that 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 ritopt; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * </pre>
+ *
+ * @author Damian Eads
+ */
+
+public class NotifyOption extends Option implements OptionNotifier {
+
+    /**
+     * The current value of the notify option.
+     */
+
+    private String value = "";
+
+    /**
+     * The default command if a command is not specified.
+     */
+
+    private String command = "Default";
+
+    /**
+     * A list of listeners to notify whenever a modification event occurs.
+     */
+
+    private java.util.List listeners;
+
+    /**
+     * Construct a NotifyOption with an empty list of listeners. Set the
+     * initial value to null.
+     */
+
+    public NotifyOption() {
+	this( "" );
+    }
+
+    /**
+     * Construct a NotifyOption and register the passed listener.
+     *
+     * @param listener    The listener to register.
+     */
+
+    public NotifyOption( OptionListener listener ) {
+	this( listener, "Default" );
+    }
+
+    /**
+     * Construct a NotifyOption and register the passed listener. Initialize
+     * the command to the value passed.
+     *
+     * @param listener    The listener to register.
+     * @param command     The value of the command.
+     */
+
+    public NotifyOption( OptionListener listener, String command ) {
+	this( listener, command, "" );
+    }
+
+    /**
+     * Construct a NotifyOption and register the passed listener. Initialize
+     * the command to the value passed.
+     *
+     * @param listener    The listener to register.
+     * @param command     The value of the command.
+     * @param value       The default value of the option.
+     */
+
+    public NotifyOption( OptionListener listener, String command,
+			 String value ) {
+	this( value );
+	this.command = command;
+	listeners.add( listener );
+    }
+
+    /**
+     * Construct a NotifyOption by copying the NotifyOption passed.
+     *
+     * @param op   The notify option to copy.
+     */
+
+    public NotifyOption( NotifyOption op ) {
+	super( op );
+	op.value = op.getValue();
+	listeners = new java.util.ArrayList( op.listeners );
+    }
+
+    /**
+     * Construct a NotifyOption, and initialize its default value to the
+     * value passed.
+     *
+     * @param value   The default value of this option.
+     */
+
+    public NotifyOption( String value ) {
+	this( value, null );
+    }
+
+    /**
+     * Constructs a NotifyOption option initialized with the value and
+     * long option passed.
+     *
+     * @param value      The initial value of this notify option.
+     * @param longOption The long option associated with this notify option.
+     */
+
+    public NotifyOption( String value, String longOption ) {
+	this( value, longOption, '\0' );
+    }
+
+    /**
+     * Constructs a character option initialized with the value and
+     * short option passed.
+     *
+     * @param value       The initial value of this NotifyOption option.
+     * @param shortOption The short option associated with this option.
+     */
+
+    public NotifyOption( String value, char shortOption ) {
+	this( value, null, shortOption );
+    }
+
+    /**
+     * Constructs an NotifyOption option initialized with the value, short
+     * and long option passed.
+     *
+     * @param shortOption The short option associated with this option.
+     * @param longOption  The long option associated with this option.
+     * @param value       The initial value of this NotifyOption option.
+     */
+
+    public NotifyOption( String value, String longOption, char shortOption ) {
+	super( longOption, shortOption );
+	this.value = value;
+	listeners = new java.util.ArrayList();
+    }
+
+    /**
+     * Return the value as an object.
+     *
+     * @return This value as an option.
+     */
+
+    public Object getObject() {
+	return value;
+    }
+
+    /**
+     * Modify this option based on a string representation.
+     *
+     * @param     value String representation of the object.
+     * @exception OptionModificationException Thrown if an error occurs
+     *                                  during modification of an option.
+     */
+
+    public void modify( String value ) throws OptionModificationException {
+	this.value = value;
+	java.util.Iterator iterator = listeners.iterator();
+	OptionEvent event = new OptionEvent( command, value, this );
+	while ( iterator.hasNext() ) {
+	    OptionListener listener = (OptionListener)iterator.next();
+	    listener.optionInvoked( event );
+	}
+    }
+
+    /**
+     * Modify this option based on a string representation.
+     *
+     * @param     value String representation of the object.
+     * @exception OptionModificationException Thrown if an error occurs
+     *                                  during modification of an option.
+     */
+
+    public void setValue( String value ) throws OptionModificationException {
+	modify( value );
+    }
+
+    /**
+     * Return this option as a string.
+     *
+     * @return This option as a string.
+     */
+
+    public String getValue() {
+	return value;
+    }
+
+    /**
+     * Return this option as a string.
+     *
+     * @return This option as a string.
+     */
+
+    public String getStringValue() {
+	return value;
+    }
+
+    /**
+     * Returns the type name of this option. For an NotifyOption, "NOTIFY"
+     * is returned.
+     *
+     * @return The type name of this option.
+     */
+
+    public String getTypeName() {
+	return "NOTIFY";
+    }
+
+    /**
+     * Adds an OptionListener to the notification list.
+     *
+     * @param listener The OptionListener to add.
+     */
+
+    public void addOptionListener( OptionListener listener ) {
+	listeners.add( listener );
+    }
+
+    /**
+     * Removes an OptionListener from the notification list.
+     *
+     * @param listener The OptionListener to remove.
+     */
+
+    public void removeOptionListener( OptionListener listener ) {
+	listeners.remove( listener );
+    }
+
+    /**
+     * Sets the command sent when an option is invoked.
+     *
+     * @param command  The command to send.
+     */
+
+    public void setOptionCommand( String command ) {
+	this.command = command;
+    }
+
+    /**
+     * Returns a string representation of this object.
+     *
+     * @return A string representation of this object.
+     */
+
+    public String toString() {
+	return value;
+    }
+} /** NotifyOption */
diff --git a/src/java/gnu/dtools/ritopt/Option.java b/src/java/gnu/dtools/ritopt/Option.java
new file mode 100644
index 0000000..9d9c43a
--- /dev/null
+++ b/src/java/gnu/dtools/ritopt/Option.java
@@ -0,0 +1,913 @@
+package gnu.dtools.ritopt;
+
+/**
+ * Option.java
+ *
+ * Version
+ *    $Id: Option.java,v 1.2 2005/08/14 20:42:46 mortenalver Exp $
+ */
+
+import java.util.*;
+
+/**
+ * This is the principal base class for all Option classes. It contains
+ * constructors for short and long option initialization, utility members
+ * for help reporting and file writing, and deprecation facilities.<p>
+ *
+ * Options that provide array support should inherit from the ArrayOption
+ * class, and follow the guidelines defined both in the Option and
+ * ArrayOption class descriptions.<p>
+ *
+ * Non-abstract subclasses should implement the modify method. When an option
+ * is invoked, the value of the option is passed to the modify method.<p>
+ *
+ * Subclasses should provide several constructors so that registration is
+ * simple and uniform. Recommended constructors include a default constructor,
+ * an interface for initialization of short and long options,
+ * and one that allows both short and long option fields to be
+ * initialized. If the subclass implementation provides constructors which
+ * initialize its members then the member parameters must be before
+ * the short and long option initialization parameters.<p>
+ *
+ * Event driven option processing is provided in the NotifyOption class. In
+ * order to use a NotifyOption, the recipient object must implement the
+ * OptionListener class. Although it is not required, subclass implementations
+ * of NotifyOption should implement the OptionNotifier interface.<p>
+ *
+ * By default, the Option class considers the width of an output device
+ * to be eighty characters. It initializes the width of the help fields
+ * based on this figure. If a field exceeds its field width, it is
+ * truncated. The width constraints can be changed by invoking the appropriate
+ * static mutators.<p>
+ *
+ * Similar to the help reporting facilities, the same constraints are placed
+ * on the listing of options provided by the built-in menu interface. These
+ * constraints can be modified by executing the appropriate static mutators.
+ * <p>
+ *
+ * The Option class provides a facility for writing options files.
+ * For option file writing, there are only two field width constraints; the
+ * assignment and the comment.
+ * <pre>
+ * Assignment:                           Comment:
+ * --longOrShortOption=optionValue       ;description goes here [d]
+ * </pre>
+ * As shown above, an assignment includes the long or short option text,
+ * an equal sign, and the option's value. The comment includes the
+ * description, and "[d]" if the option is deprecated.<p>
+ *
+ * If the assignment exceeds its field width, the comment is placed before
+ * the assignment on a separate line. The comment is truncated if it
+ * exceeds eighty characters when it is placed before the assignment.
+ * However, if the assignment does not exceeds its field width and the comment
+ * does, the comment is truncated, and continued on the next line at the
+ * columnar position defined by the assignment's field width. Field widths
+ * may be modified by invoking the appropriate static mutator.<p>
+ *
+ * This class also provides a facility for deprecating options. An option is
+ * deprecated to discourage its use without removing the functionality it
+ * provides. An option is deprecated by invoking the deprecate method.
+ * <hr>
+ *
+ * <pre>
+ * Copyright (C) Damian Ryan Eads, 2001. All Rights Reserved.
+ *
+ * ritopt 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.
+
+ * ritopt is distributed in the hope that 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 ritopt; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * </pre>
+ *
+ * @author Damian Eads
+ */
+
+public abstract class Option implements OptionModifiable {
+
+    /**
+     * The default width of the option field when the help usage is displayed.
+     */
+
+    public static final int DEFAULT_HELP_OPTION_SIZE = 22;
+
+    /**
+     * The default width of the type name field when the help usage is
+     * display.
+     */
+
+    public static final int DEFAULT_HELP_TYPENAME_SIZE = 10;
+
+    /**
+     * The default width of the description when the help usage is displayed.
+     */
+
+    public static final int DEFAULT_HELP_DESCRIPTION_SIZE = 48;
+
+    /**
+     * The default width of the deprecated field when the help usage is
+     * displayed.
+     */
+
+    public static final int DEFAULT_HELP_DEPRECATED_SIZE = 3;
+
+    /**
+     * The default width of the option field when the menu usage is displayed.
+     */
+
+    public static final int DEFAULT_MENU_OPTION_SIZE = 15;
+
+    /**
+     * The default width of the type name field when the menu usage is
+     * displayed.
+     */
+
+    public static final int DEFAULT_MENU_TYPENAME_SIZE = 10;
+
+    /**
+     * The default width of the description field when the menu usage is
+     * displayed.
+     */
+
+    public static final int DEFAULT_MENU_DESCRIPTION_SIZE = 48;
+
+    /**
+     * The default width of the deprecated field when the menu usage is
+     * displayed.
+     */
+
+    public static final int DEFAULT_MENU_DEPRECATED_SIZE = 3;
+
+    /**
+     * The default width of the option assignment in an option file.
+     */
+
+    public static final int DEFAULT_FILE_COMPLETE_OPTION_SIZE = 60;
+
+    /**
+     * The default width of the comment in an option file. If the option
+     * and the comment exceeds the width of the device, the comment is
+     * truncated to the next line at the same columnar position of the
+     * previous comment line. If the option assignment line is longer than
+     * the width, the comment line is put before the option assignment it
+     * refers.
+     */
+
+    public static final int DEFAULT_FILE_COMMENT_SIZE = 16;
+
+    /**
+     * The String holding the value of the long option. If there is no
+     * long option, this value is set to null.
+     */
+
+    private String longOption;
+
+    /**
+     * The character holding the value of the short option. If there is no
+     * short option,t his value is set to '\0'.
+     */
+
+    private char shortOption;
+
+    /**
+     * The String holding the description of this option.
+     */
+
+    private String description;
+
+    /**
+     * A flag identifying whether this option is deprecated.
+     */
+
+    private boolean deprecated;
+
+    /**
+     * The field width for the option specification that is reporter for
+     * help.
+     */
+
+    private static int helpOptionSpecificationSize = DEFAULT_HELP_OPTION_SIZE;
+
+    /**
+     * The field width for the type name that is reported for help.
+     */
+
+    private static int helpTypenameSize = DEFAULT_HELP_TYPENAME_SIZE;
+
+    /**
+     * The field width for the description that is reported during help.
+     */
+
+    private static int helpDescriptionSize = DEFAULT_HELP_DESCRIPTION_SIZE;
+
+    /**
+     * The field width for the deprecated flag that is reported during
+     * help.
+     */
+
+    private static int helpDeprecatedSize = DEFAULT_HELP_DEPRECATED_SIZE;
+
+    /**
+     * The field width for the option specification that is reported when
+     * the options are listed in the built-in menu.
+     */
+
+    private static int menuOptionSpecificationSize = DEFAULT_MENU_OPTION_SIZE;
+
+    /**
+     * The field width for the type name that is reported when the options
+     * are listed in the built-in menu.
+     */
+
+    private static int menuTypenameSize = DEFAULT_MENU_TYPENAME_SIZE;
+
+    /**
+     * The field width for the description that is reported when the options
+     * are listed in the built-in menu.
+     */
+
+    private static int menuDescriptionSize = DEFAULT_MENU_DESCRIPTION_SIZE;
+
+    /**
+     * The field width for the deprecated flag that is reported when the
+     * options are listed in the build-in menu.
+     */
+
+    private static int menuDeprecatedSize = DEFAULT_MENU_DEPRECATED_SIZE;
+
+    /**
+     * The field width for the assignment portion of an option that is 
+     * written to a file.
+     */
+
+    private static int fileCompleteOptionSize =
+                                            DEFAULT_FILE_COMPLETE_OPTION_SIZE;
+
+    /**
+     * The field width for the comment portion of an option that is written
+     * to a file.
+     */
+
+    private static int fileCommentSize = DEFAULT_FILE_COMMENT_SIZE;
+
+    /**
+     * A field indicating whether an option has been invoked.
+     */
+
+    protected boolean invoked;
+
+    /**
+     * Returns this option's value as an Object.
+     *
+     * @return An object representation of this option.
+     */
+
+    public abstract Object getObject();
+
+    /**
+     * Returns the option's value as a String. This String should conform
+     * to the formatting requirements prescribed by a modify method.
+     *
+     * @return The option's value as a String conforming to formatting
+     *         requirements.
+     */
+
+    public abstract String getStringValue();
+
+    /**
+     * Constructs an option with no initial short or long option value,
+     * and is by default uninvoked and undeprecated, and has a description
+     * initialized to the empty string.
+     */
+
+    public Option() {
+	super();
+	description = "";
+    }
+
+    /**
+     * Constructs an option by copying the option passed.
+     *
+     * @param option  The option to copy for this object's construction.
+     */
+
+    public Option( Option option ) {
+	longOption = option.getLongOption();
+	shortOption = option.getShortOption();
+	description = option.getDescription();
+	deprecated = option.isDeprecated();
+    }
+
+    /**
+     * Constructs an option by initializing its long option with the
+     * value passed. The short option is equal to the null character,
+     * and the description is equal to the empty string.
+     *
+     * @param longOption The value of the long option
+     */
+
+    public Option( String longOption ) {
+	this.longOption = longOption;
+	this.shortOption = '\0';
+	description = "";
+    }
+
+    /**
+     * Constructs an option by initializing its short option with the
+     * value passed. The long option is equal to null, and the description
+     * is equal to the empty string.
+     *
+     * @param shortOption The value of the short option.
+     */
+
+    public Option( char shortOption ) {
+	this.shortOption = shortOption;
+	this.longOption = null;
+	description = "";
+    }
+
+    /**
+     * Constructs an option by initializing its short and long options
+     * with the values passed. The description is set to the empty string.
+     *
+     * @param longOption The value of the long option.
+     * @param shortOption The value of the short option.
+     */
+
+    public Option( String longOption, char shortOption ) {
+	this.longOption = longOption;
+	this.shortOption = shortOption;
+	description = "";
+    }
+
+    /**
+     * Sets the long option.
+     *
+     * @param longOption The value to set the long option.
+     */
+
+    public void setKey( String longOption ) {
+	this.longOption = longOption;
+    }
+
+    /**
+     * Sets the short option.
+     *
+     * @param shortOption The value to set the short option.
+     */
+
+    public void setKey( char shortOption ) {
+	this.shortOption = shortOption;
+    }
+
+    /**
+     * Sets the short option.
+     *
+     * @param shortOption The value to set the short option.
+     */
+
+    public void setShortOption( char shortOption ) {
+	setKey( shortOption );
+    }
+
+    /**
+     * Sets the long option.
+     *
+     * @param longOption The value to set the long option.
+     */
+
+    public void setLongOption( String longOption ) {
+	setKey( longOption );
+    }
+
+    /**
+     * Sets the description of this option.
+     *
+     * @param description The description of this option.
+     */
+
+    public void setDescription( String description ) {
+	this.description = description;
+    }
+
+    /**
+     * Sets the deprecated flag to the value passed.
+     *
+     * @param deprecated A flag indicating whether the option is deprecated.
+     */
+
+    public void setDeprecated( boolean deprecated ) {
+	this.deprecated = deprecated;
+    }
+
+    /**
+     * Sets the field width for the option specification displayed
+     * in the help report.
+     *
+     * @param newSize The size to set the field width.
+     */
+
+    public static void setHelpOptionSpecificationSize( int newSize ) {
+	helpOptionSpecificationSize = newSize;
+    }
+
+    /**
+     * Sets the field width for the type name displayed in the help report.
+     *
+     * @param newSize The size to set the field width.
+     */
+
+    public static void setHelpTypenameSize( int newSize ) {
+	helpTypenameSize = newSize;
+    }
+
+    /**
+     * Sets the field width for the description displayed in the help report.
+     *
+     * @param newSize The size to set the field width.
+     */
+
+    public static void setHelpDescriptionSize( int newSize ) {
+	helpDescriptionSize = newSize;
+    }
+
+    /**
+     * Sets the field width for the deprecated flag displayed in the
+     * help report.
+     *
+     * @param newSize The size to set the field width.
+     */
+
+    public static void setHelpDeprecatedSize( int newSize ) {
+	helpDeprecatedSize = newSize;
+    }
+
+    /**
+     * Sets the field width for the option specification displayed
+     * in the menu listing of options.
+     *
+     * @param newSize The size to set the field width.
+     */
+
+    public static void setMenuOptionSpecificationSize( int newSize ) {
+	menuOptionSpecificationSize = newSize;
+    }
+
+    /**
+     * Sets the field width for the type name displayed in the menu
+     * listing of options.
+     *
+     * @param newSize The size to set the field width.
+     */
+
+    public static void setMenuTypenameSize( int newSize ) {
+	menuTypenameSize = newSize;
+    }
+
+    /**
+     * Sets the field width for the option description displayed
+     * in the menu listing of options.
+     *
+     * @param newSize The size to set the field width.
+     */
+
+    public static void setMenuDescriptionSize( int newSize ) {
+	menuDescriptionSize = newSize;
+    }
+
+    /**
+     * Sets the field width for the deprecated flag displayed
+     * in the menu listing of options.
+     *
+     * @param newSize The size to set the field width.
+     */
+
+    public static void setMenuDeprecatedSize( int newSize ) {
+	menuDeprecatedSize = newSize;
+    }
+
+    /**
+     * Sets the assignment field width used when options files are written.
+     *
+     * @param newSize The size to set the field width.
+     */
+
+    public static void setFileCompleteOptionSize( int newSize ) {
+	fileCompleteOptionSize = newSize;
+    }
+
+    /**
+     * Sets the assignment field width used when options files are written.
+     *
+     * @param newSize The size to set the field width.
+     */
+
+    public static void setFileCommentSize( int newSize ) {
+	fileCommentSize = newSize;
+    }
+
+    /**
+     * Sets whether this option has been invoked.
+     *
+     * @param A boolean indicating whether this option has been invoked.
+     */
+
+    public void setInvoked( boolean b ) {
+	invoked = b;
+    }
+
+    /**
+     * Deprecates this option.
+     */
+
+    public void deprecate() {
+	setDeprecated( true );
+    }
+
+    /**
+     * Return the name of this option. This method returns the same value as
+     * the getLongOption accessor.
+     *
+     * @return The name of this otpion.
+     */
+
+    public String getName() {
+	return longOption;
+    }
+
+    /**
+     * Return the short option key. There is no short option when this
+     * character is the null character.
+     *
+     * @return The short option key of this option.
+     */
+
+    public char getShortOption() {
+	return shortOption;
+    }
+
+    /**
+     * Return the long option key. There is no long option when this value
+     * is null.
+     *
+     * @return The long option key of this option.
+     */
+
+    public String getLongOption() {
+	return longOption;
+    }
+
+
+    /**
+     * Return a line used for help reporting.
+     *
+     * @return A line used for help reporting.
+     */
+
+    public String getHelp() {
+	return getHelpOptionSpecification() + " " + getHelpTypeName() + " "
+	    + getHelpDescription() + " " + getHelpDeprecated();
+    }
+
+    /**
+     * Return the option specification field used during help reporting.
+     *
+     * @return The option specification field.
+     */
+
+    public String getHelpOptionSpecification() {
+	return Utility.expandString(
+	    ( ( ( shortOption != '\0' ) ? ( "-" + getShortOption() ) : "  " )
+	    + ( ( longOption != null && shortOption != '\0' ) ? ", " : "  " )
+	    + ( ( longOption != null ) ? "--" + getLongOption(): "" ) ),
+			     helpOptionSpecificationSize );
+    }
+
+    /**
+     * Return the type name field used during help reporting.
+     *
+     * @return The type name field.
+     */
+
+    public String getHelpTypeName() {
+	return Utility.expandString( "<" + getTypeName() + ">",
+				     helpTypenameSize );
+    }
+
+    /**
+     * Return the description field used during help reporting.
+     *
+     * @return The description field.
+     */
+
+    public String getHelpDescription() {
+	return Utility.expandString( getDescription(),
+			     helpDescriptionSize );
+    }
+
+    /**
+     * Return the deprecated field used during help reporting.
+     *
+     * @return The deprecated field.
+     */
+
+    public String getHelpDeprecated() {
+	return Utility.expandString( isDeprecated() ? "[d]" : "",
+			     helpDeprecatedSize );
+    }
+
+    /**
+     * Return the header displayed at the top of the help report.
+     *
+     * @return The header displayed at the top of the help report.
+     */
+
+    public static String getHelpHeader() {
+	return Utility.expandString( "Option Name",
+				     helpOptionSpecificationSize ) + " "
+	    + Utility.expandString( "Type", helpTypenameSize ) + " "
+	    + Utility.expandString( "Description", helpDescriptionSize );
+    }
+
+    /**
+     * The description explaining the meaning of this option.
+     *
+     * @return This options description.
+     */
+
+    public String getDescription() {
+	return description;
+    }
+
+    /**
+     * The hash key of this option. This is used by classes that implement
+     * the option registrar class. This method should <b>not</b> be overrided.
+     *
+     * @return The hash key of this option.
+     */
+
+    public String getHashKey() {
+	return Option.getHashKey( longOption, shortOption );
+    }
+
+    /**
+     * The hash key of an option if there is no short option. This method
+     * should <b>not</b> be overrided.
+     *
+     * @param longOption The long option.
+     *
+     * @return The hash key of this option based on the long option.
+     */
+
+    public static String getHashKey( String longOption ) {
+	return "," + ( ( longOption != null ) ? longOption : "" );
+    }
+
+    /**
+     * The hash key of an option if there is no long option. This method
+     * should <b>not</b> be overrided.
+     *
+     * @param shortOption The short option.
+     *
+     * @return The hash key of this option based on the short option.
+     */
+
+    public static String getHashKey( char shortOption ) {
+	return "" + ( shortOption != '\0' ) + ",";
+    }
+
+    /**
+     * The hash key of an option if there both short and long options are
+     * defined.
+     *
+     * @param shortOption The short option.
+     * @param longOption  The long option.
+     *
+     * @return The hash key of this option based on both the short and long
+     *         options.
+     */
+
+    public static String getHashKey( String longOption, char shortOption ) {
+	return ( ( shortOption == '\0' ) ? "" : "" + shortOption ) +
+	    ( ( longOption == null ) ? "," : "," + longOption );
+    }
+
+    /**
+     * Returns whether this option is deprecated.
+     *
+     * @return A boolean indicating whether this option is deprecated.
+     */
+
+    public boolean isDeprecated() {
+	return deprecated;
+    }
+
+    /**
+     * Returns whether this option has been invoked.
+     *
+     * @return A boolean indicating whether this option has been invoked.
+     */
+
+    public boolean isInvoked() {
+	return invoked;
+    }
+
+    /**
+     * Returns (a) line(s) representing this option. This line is usually
+     * later written to an options file.
+     *
+     * @return Line(s) representing this option.
+     */
+
+    public String getOptionFileLine() {
+	boolean descriptionPrinted = false;
+	String retval = "";
+	String optionText = "";
+	String strval = getStringValue();
+	if ( longOption != null ) {
+	    optionText += "--" + longOption;
+	}
+	else if ( shortOption != '\0' ) {
+	    optionText += "-" + shortOption;
+	}
+	if ( optionText.length() > 0
+	     && Utility.trim( strval ).length() >= 0 ) {
+	    optionText += "=" + strval;
+	}
+	if ( optionText.length() <= fileCompleteOptionSize ) {
+	    retval += Utility.expandString( optionText,
+					    fileCompleteOptionSize );
+	}
+	else {
+	    retval += "; " + description + "\n";
+	    retval += optionText;
+	    descriptionPrinted = true;
+	}
+	if ( !descriptionPrinted ) { 
+	    StringBuffer descsplit = new StringBuffer( description );
+	    boolean tmp = false;
+	    while ( descsplit.length() > 0 ) {
+		String st = "";
+		int size = 0;
+		if ( tmp ) {
+		    st += Utility.getSpaces( fileCompleteOptionSize );
+		}
+		size = ( descsplit.length() >= fileCommentSize )
+		    ? fileCommentSize : descsplit.length();
+		st += "; " + descsplit.substring( 0, size );
+		descsplit.delete( 0, size );
+		retval += st + "\n";
+		tmp = true;
+	    }
+	    descriptionPrinted = true;
+	}
+	return retval;
+    }
+
+    /**
+     * Returns the field width for the option specification displayed in the
+     * help report.
+     *
+     * @return The field width.
+     */
+
+    public static int getHelpOptionSpecificationSize() {
+	return helpOptionSpecificationSize;
+    }
+
+    /**
+     * Returns the field width for the type name displayed in the help report.
+     *
+     * @return The field width.
+     */
+
+    public static int getHelpTypenameSize() {
+	return helpTypenameSize;
+    }
+
+    /**
+     * Returns the field width for the description displayed in the help
+     * report.
+     *
+     * @return The field width.
+     */
+
+    public static int getHelpDescriptionSize() {
+	return helpDescriptionSize;
+    }
+
+    /**
+     * Returns the field width for the deprecated flag displayed in the
+     * help report.
+     *
+     * @return The field width.
+     */
+
+    public static int getHelpDeprecatedSize() {
+	return helpDeprecatedSize;
+    }
+
+    /**
+     * Returns the field width for the option specification displayed in the
+     * menu listing of options.
+     *
+     * @return The field width.
+     */
+
+    public static int getMenuOptionSpecificationSize() {
+	return menuOptionSpecificationSize;
+    }
+
+    /**
+     * Returns the field width for the type name displayed in the
+     * menu listing of options.
+     *
+     * @return The field width.
+     */
+
+    public static int getMenuTypenameSize() {
+	return menuTypenameSize;
+    }
+
+    /**
+     * Returns the field width for the description displayed in the
+     * menu listing of options.
+     *
+     * @return The field width.
+     */
+
+    public static int getMenuDescriptionSize() {
+	return menuDescriptionSize;
+    }
+
+    /**
+     * Returns the field width for the deprecated flag displayed in the
+     * menu listing of options.
+     *
+     * @return The field width.
+     */
+
+    public static int getMenuDeprecatedSize() {
+	return menuDeprecatedSize;
+    }
+
+    /**
+     * Returns the field width for assignment portion of a option file line.
+     *
+     * @return The field width.
+     */
+
+    public static int getFileCompleteOptionSize() {
+	return fileCompleteOptionSize;
+    }
+
+    /**
+     * Returns the field width for assignment portion of a option file line.
+     *
+     * @return The field width.
+     */
+
+    public static int getFileCommentSize() {
+	return fileCommentSize;
+    }
+
+    /**
+     * Returns the type name of this option.
+     *
+     * @return The type name of this option.
+     */
+
+    public abstract String getTypeName();
+
+    /**
+     * Prepares the option for modification.
+     */
+
+    public void action() {
+	if ( deprecated ) {
+	    System.err.print( "Warning: " );
+	    if ( longOption != null ) {
+		System.err.print( "--" + longOption );
+	    }
+	    if ( shortOption != '\0' && longOption != null ) {
+		System.err.print( " or " );
+	    }
+	    if ( shortOption != '\0' ) {
+		System.err.println( "-" + shortOption + " is deprecated." );
+	    }
+	}
+    }
+
+} /** Option */
+
+
+
+
+
diff --git a/src/java/gnu/dtools/ritopt/OptionArrayable.java b/src/java/gnu/dtools/ritopt/OptionArrayable.java
new file mode 100644
index 0000000..17b311d
--- /dev/null
+++ b/src/java/gnu/dtools/ritopt/OptionArrayable.java
@@ -0,0 +1,65 @@
+package gnu.dtools.ritopt;
+
+/**
+ * If an option supports array registration and processing then it
+ * should implement this interface.<p>
+ *
+ * For example, let's say we are implementing an integer array option class.
+ *
+ * <pre>
+ * public class MyIntArray extends ArrayOption implements OptionArrayable,
+ *                                                        OptionModifiable {
+ *    int values[];
+ *
+ *    // rest of implementation goes here.
+ *
+ *    public void modify(java.lang.String[] value) {
+ *       try {
+ *          int newValues[] = new int[ value.length ];
+ *          for int( n = 0; n < value.length; n++ ) {
+ *             newValues[ n ] = Integer.parseInt( value[ n ] );
+ *          }
+ *          values[ n ] = newValues;
+ *       }
+ *       catch ( NumberFormatException e ) {
+ *          throw new OptionModificationException( "Not a number." );
+ *       }
+ *    }
+ * }
+ * </pre>
+ *
+ * <hr>
+ *
+ * <pre>
+ * Copyright (C) Damian Ryan Eads, 2001. All Rights Reserved.
+ *
+ * ritopt 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.
+
+ * ritopt is distributed in the hope that 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 ritopt; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * </pre>
+ *
+ * @author Damian Eads
+ */
+
+public interface OptionArrayable extends OptionModifiable {
+
+   /**
+     * Modify an option based on several string representations.
+     *
+     * @param     value String representation of the object.
+     * @exception OptionModificationException Thrown if an error occurs
+     *                                  during modification of an option.
+     */
+
+    void modify( String value[] ) throws OptionModificationException;
+}
diff --git a/src/java/gnu/dtools/ritopt/OptionEvent.java b/src/java/gnu/dtools/ritopt/OptionEvent.java
new file mode 100644
index 0000000..2d35002
--- /dev/null
+++ b/src/java/gnu/dtools/ritopt/OptionEvent.java
@@ -0,0 +1,195 @@
+package gnu.dtools.ritopt;
+/**
+ * OptionEvent.java
+ *
+ * Version:
+ *    $Id: OptionEvent.java,v 1.2 2005/11/08 04:53:27 mortenalver Exp $
+ */
+
+/**
+ * An event indicating that an option has been invoked.
+ * When an OptionListener is notified by a NotifyOption, it passes
+ * an OptionEvent object to all registered listeners. This includes
+ * the target NotifyOption, a command (NotifyOption passes the long
+ * option by default), and the option value.<p>
+ *
+ * <hr>
+ *
+ * <pre>
+ * Copyright (C) Damian Ryan Eads, 2001. All Rights Reserved.
+ *
+ * ritopt 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.
+
+ * ritopt is distributed in the hope that 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 ritopt; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * </pre>
+ *
+ * @author Damian Eads
+ */
+
+public class OptionEvent {
+
+    /**
+     * The command string associated with this option processing event.
+     */
+
+    private String command;
+
+    /**
+     * The value of the option processing event.
+     */
+
+    private String value;
+
+    /**
+     * The target Option in which the option processing event occurred.
+     */
+
+    private Option target;
+
+    /**
+     * Constructs an option event with the command set to "Default", the
+     * value set to the empty string, and the target set to null.
+     */
+
+    public OptionEvent() {
+	this( "Default", "", null );
+    }
+
+    /**
+     * Constructs an option event with the command set to the value passed,
+     * the value set to the empty string, and the target set to null.
+     *
+     * @param command The value to set the command string.
+     */
+
+    public OptionEvent( String command ) {
+	this( command, "", null );
+    }
+
+    /**
+     * Constructs an option event with the command and value set to the
+     * values passed, and the target set to null.
+     *
+     * @param command The value to set the command string.
+     * @param value   The value to set the option value.
+     */
+
+    public OptionEvent( String command, String value ) {
+	this( command, value, null );
+    }
+
+    /**
+     * Constructs an option event with the command set to the long or short
+     * option (whichever exists), the value set to the current value of
+     * the option, and the target option set to the option passed. If
+     * neither the short or long option exist, a value of "Default" is
+     * assigned.
+     *
+     * @param option The option to initialize this OptionEvent.
+     */
+
+    public OptionEvent( Option option ) {
+	this.target = option;
+	this.value = option.getStringValue();
+	String longOption = option.getLongOption();
+	char shortOption = option.getShortOption();
+						      
+        if ( longOption != null ) {
+	    command = longOption;
+	}
+	else if ( shortOption != '\0' ) {
+	    command = new Character( shortOption ).toString();
+	}
+	else {
+	    command = "Default";
+	}
+    }
+
+    /**
+     * Constructs an option event with the command, value, and target
+     * set to the values passed.
+     *
+     * @param command The value to set the command string.
+     * @param value   The value to set the option value.
+     * @param target  The target option in which the option processing
+     *                event occurred.
+     */
+
+    public OptionEvent( String command, String value, Option target ) {
+	this.command = command;
+	this.value = value;
+	this.target = target;
+    }
+
+    /**
+     * Returns the command string associated with the option.
+     *
+     * @return The command string associated with the option.
+     */
+
+    public String getCommand() {
+	return command;
+    }
+
+    /**
+     * Returns the value associated with the target option.
+     *
+     * @return The value associated with the target option.
+     */
+
+    public String getValue() {
+	return value;
+    }
+
+    /**
+     * Returns the target option of the option processing event.
+     *
+     * @return The target option.
+     */
+
+    public Option getTarget() {
+	return target;
+    }
+
+    /**
+     * Sets the command string to the value passed.
+     *
+     * @param command The value to set the command string.
+     */
+
+    public void setCommand( String command ) {
+	this.command = command;
+    }
+
+    /**
+     * Sets the value of this option event. This value generally should be
+     * equal to the value of the target option.
+     *
+     * @param value   The value of the option event.
+     */
+
+    public void setValue( String value ) {
+	this.value = value;
+    }
+
+    /**
+     * Sets the target option of the option processing event.
+     *
+     * @param target   The target option.
+     */
+
+    public void setTarget( Option target ) {
+	this.target = target;
+    }
+
+}
diff --git a/src/java/gnu/dtools/ritopt/OptionException.java b/src/java/gnu/dtools/ritopt/OptionException.java
new file mode 100644
index 0000000..bbc82d6
--- /dev/null
+++ b/src/java/gnu/dtools/ritopt/OptionException.java
@@ -0,0 +1,48 @@
+package gnu.dtools.ritopt;
+
+/**
+ * OptionException.java
+ *
+ * Version:
+ *    $Id: OptionException.java,v 1.1 2004/05/20 20:45:47 mortenalver Exp $
+ */
+
+/**
+ * An OptionException is thrown when an error occurs during option processing,
+ * modification, or registration. This class is the base class for all
+ * run-time based option processing exceptions. A class must throw an instance
+ * of one of the derived classes as this implementation is abstract.
+ *
+ * <pre>
+ * Copyright (C) Damian Ryan Eads, 2001. All Rights Reserved.
+ *
+ * ritopt 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.
+
+ * ritopt is distributed in the hope that 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 ritopt; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * </pre>
+ *
+ * @author Damian Eads
+ */
+
+public abstract class OptionException extends RuntimeException {
+
+    /**
+     * Constructs an OptionException.
+     *
+     * @param msg The exception message.
+     */
+
+    OptionException( String msg ) {
+	super( msg );
+    }
+}
diff --git a/src/java/gnu/dtools/ritopt/OptionListener.java b/src/java/gnu/dtools/ritopt/OptionListener.java
new file mode 100644
index 0000000..022b56c
--- /dev/null
+++ b/src/java/gnu/dtools/ritopt/OptionListener.java
@@ -0,0 +1,54 @@
+package gnu.dtools.ritopt;
+
+/**
+ * OptionListener.java
+ *
+ * Version:
+ *   $Id: OptionListener.java,v 1.1 2004/05/20 20:45:47 mortenalver Exp $
+ */
+
+/**
+ * This interface is used to receive notification of option processing
+ * events. Implementors are registered by being passed to an OptionNotifier's
+ * addOptionListener method.
+ *
+ * Option processing events occur when an option is invoked at the command
+ * line, menu, or is present in an options file.
+ *
+ * <hr>
+ *
+ * <pre>
+ * Copyright (C) Damian Ryan Eads, 2001. All Rights Reserved.
+ *
+ * ritopt 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.
+
+ * ritopt is distributed in the hope that 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 ritopt; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * </pre>
+ *
+ * @author Damian Eads
+ */
+
+public interface OptionListener {
+
+    /**
+     * Invoked when an option processing event occurs. Option processing
+     * events occur when an option is invoked at the command line, menu,
+     * or is present in an options file.
+     *
+     * @param e   An object containing information about the option processing
+     *            and invocation event.
+     */
+
+    public void optionInvoked( OptionEvent e );
+
+} /** OptionListener **/
diff --git a/src/java/gnu/dtools/ritopt/OptionMenu.java b/src/java/gnu/dtools/ritopt/OptionMenu.java
new file mode 100644
index 0000000..1ad8242
--- /dev/null
+++ b/src/java/gnu/dtools/ritopt/OptionMenu.java
@@ -0,0 +1,271 @@
+package gnu.dtools.ritopt;
+
+/**
+ * OptionMenu.java
+ *
+ * Version:
+ *    $Id: OptionMenu.java,v 1.1 2004/05/20 20:45:47 mortenalver Exp $
+ */
+
+import java.io.*;
+
+/**
+ * This class facilitates the built-in menu feature for ritopt. When the
+ * --menu long option is invoked, an instance of this class is notified,
+ * and the menu system starts.
+ *
+ * Here is an example run of the built-in menu.
+ * <pre>
+ * -> ?
+ *         - Options Delimiter
+ *         ? Help
+ *         = Run program and return to menu
+ *         ! Shell to Operating System
+ *         $ Exit menu
+ *         + Additional options
+ *         @<filename> Get options from file [default.opt]
+ *         @@ Get options from file [default.opt]
+ *         %<filename> Put options in file
+ *         %% Put options in file [default.opt]
+ *         . Quit
+ * -> =ls
+ * -> =uname
+ * CYGWIN_ME-4.90
+ * Exit status: 0
+ * Press enter to continue...
+ *
+ * -> =ls
+ * CVS
+ * Makefile
+ * Makefile.am
+ * Makefile.in
+ * edu
+ * gnu
+ * ritopt.jar
+ * Exit status: 0
+ * Press enter to continue..
+ *
+ * -> --help
+ * java FavoriteFood @optionfile [module] OPTIONS ... [module] OPTIONS
+ *
+ * Use --menu to invoke the interactive built-in menu.
+ *
+ * Option Name     Type       Description
+ *
+ * -h, --help      <NOTIFY>   Displays help for each option.
+ * -m, --menu      <NOTIFY>   Displays the built-in interactive menu.
+ *     --fatfree   <BOOLEAN>  No description given
+ * -v, --version   <NOTIFY>   Displays version information.
+ *     --name      <STRING>   No description given
+ * -g, --grub      <STRING>   Favorite Food
+ * -f, --food      <STRING>   Favorite Food
+ * -c, --food-coun <STRING>   No description given
+ *
+ * -> --grub=tacos
+ * Warning: --grub or -g is deprecated.
+ * -> --grubb
+ * Error: Option --grubb does not exist in module 'General'.
+ * -> .
+ *
+ * </pre>
+ * <hr>
+ *
+ * <pre>
+ * Copyright (C) Damian Ryan Eads, 2001. All Rights Reserved.
+ *
+ * ritopt 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.
+
+ * ritopt is distributed in the hope that 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 ritopt; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * </pre>
+ *
+ * @author Damian Eads
+ */
+
+public class OptionMenu implements OptionListener {
+
+    /**
+     * Commands starting with this substring are option invocations.
+     */
+
+    public static final String OPTION_COMMAND_CHAR = "-";
+
+    /**
+     * This command without any arguments displays the command summary.
+     * Otherwise, specific help information is provided based on the
+     * argument.
+     */
+
+    public static final String HELP_COMMAND_CHAR = "?";
+
+    /**
+     * This command must have an argument. When invoked, it executes
+     * the argument at the command shell.
+     */
+
+    public static final String RUN_COMMAND_CHAR = "=";
+
+    /**
+     * This command spawns a shell.
+     */
+
+    public static final String SHELL_COMMAND_CHAR = "!";
+
+    /**
+     * This command exits the built-in menu system.
+     */
+
+    public static final String EXIT_MENU_COMMAND_CHAR = "$";
+
+    /**
+     * This command lists registered option modules.
+     */
+
+    public static final String LIST_MODULES_COMMAND_CHAR = "+";
+
+    /**
+     * This command without any arguments loads the default option file.
+     * Otherwise, the file as the argument is loaded.
+     */
+
+    public static final String FILE_READ_COMMAND_CHAR = "@";
+
+    /**
+     * This command without any arguments writes to the default option file.
+     * Otherwise, the file as the argument is written.
+     */
+
+    public static final String FILE_WRITE_COMMAND_CHAR = "%";
+
+    /**
+     * Loads an option module. Invoking this command without any arguments,
+     * the default option module is loaded.
+     */
+
+    public static final String FILE_MODULE_COMMAND_CHAR = ":";
+
+    /**
+     * The menu prompt used for the built-in menu system.
+     */
+
+    public static final String MENU_PROMPT = "-> ";
+
+    /**
+     * The options registrar associated with this option menu.
+     */
+
+    private Options options;
+
+    /**
+     * A reader which is connected to standard input.
+     */
+
+    private BufferedReader reader;
+
+    /**
+     * Constructs a new built-in menu attaching it to the options registrar
+     * passed.
+     *
+     * @param options The option registrar associated with this built-in
+     *                menu.
+     */
+
+    public OptionMenu( Options options ) {
+	this.options = options;
+	reader = new BufferedReader( new InputStreamReader( System.in ) );
+    }
+
+    /**
+     * Starts the built-in menu system.
+     */
+
+    public void startMenu() {
+	String command = "";
+	while ( !command.equals( "$" ) ) {
+	    System.out.print( MENU_PROMPT );
+	    try {
+		command = reader.readLine();
+	    }
+	    catch ( IOException e ) {
+		return;
+	    }
+	    boolean commandEntered = command != null && command.length() > 0;
+	    if ( command.equals( "?" ) ) {
+		System.err.println( "\t- Options Delimiter" );
+		System.err.println( "\t? Help" );
+		System.err.println( "\t= Run program and return to menu" );
+		System.err.println( "\t! Shell to Operating System" );
+		System.err.println( "\t$ Exit menu" );
+		System.err.println( "\t+ Additional options" );
+		System.err.println( "\t@<filename> Get options from file ["
+				    + options.getDefaultOptionFilename()
+				    + "]" );
+		System.err.println( "\t@@ Get options from file ["
+				    + options.getDefaultOptionFilename()
+				    + "]" );
+                System.err.println( "\t%<filename> Put options in file" );
+		System.err.println( "\t%% Put options in file ["
+				    + options.getDefaultOptionFilename()
+				    + "]" );
+                System.err.println( "\t. Quit" );
+	    }
+	    else if ( commandEntered &&
+		      ( command.substring( 0, 1 ).equals(
+					    FILE_READ_COMMAND_CHAR )
+		      || command.substring( 0, 1 ).equals(
+					    FILE_WRITE_COMMAND_CHAR )
+		      || command.substring( 0, 1 ).equals(
+                                            OPTION_COMMAND_CHAR )
+		      || command.substring( 0, 1 ).equals(
+                                            FILE_MODULE_COMMAND_CHAR ) ) ) {
+		options.process( command );
+	    }
+	    else if ( commandEntered &&
+		      command.substring( 0, 1 ).equals( SHELL_COMMAND_CHAR ) ) {
+
+	    }
+	    else if ( commandEntered &&
+		      command.substring( 0, 1 ).equals( RUN_COMMAND_CHAR ) ) {
+		try {
+		    SimpleProcess p
+			= new SimpleProcess( Runtime.getRuntime().exec( command.substring( 1 ) ) );
+		    System.err.println( "Exit status: " + p.waitFor() );
+		}
+		catch ( Exception e ) {
+		    System.err.println( "ritopt: An Error Occurred During Process Execution" );
+		    e.printStackTrace();
+		}
+		finally {
+		    System.out.println( "Press enter to continue..." );
+		    try {
+			reader.readLine();
+		    } catch ( IOException e ) { }
+		}
+	    }
+	    else {
+		System.err.println( "(Type ? for Help)" );
+	    }
+	}
+    }
+
+    /**
+     * This method is notified when the --menu option is specified.
+     *
+     * @param event    The event associated.
+     */
+
+    public void optionInvoked( OptionEvent event ) {
+	if ( event.getCommand().equals( "menu" ) ) {
+	    startMenu();
+	}
+    }
+} /** OptionMenu **/
diff --git a/src/java/gnu/dtools/ritopt/OptionModifiable.java b/src/java/gnu/dtools/ritopt/OptionModifiable.java
new file mode 100644
index 0000000..bd09e49
--- /dev/null
+++ b/src/java/gnu/dtools/ritopt/OptionModifiable.java
@@ -0,0 +1,48 @@
+package gnu.dtools.ritopt;
+
+/**
+ * OptionModifiable.java
+ *
+ * Version:
+ *    $Id: OptionModifiable.java,v 1.1 2004/05/20 20:45:47 mortenalver Exp $
+ */
+
+/**
+ * Implementors of this interface are capable of being registered and
+ * processed. When an option is specified, its modify method is invoked.
+ *
+ * <hr>
+ *
+ * <pre>
+ * Copyright (C) Damian Ryan Eads, 2001. All Rights Reserved.
+ *
+ * ritopt 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.
+
+ * ritopt is distributed in the hope that 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 ritopt; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * </pre>
+ *
+ * @author Damian Eads
+ */
+
+public interface OptionModifiable {
+
+   /**
+    * Modify an option based on a string representation.
+    *
+    * @param     value String representation of the object.
+    * @exception OptionModificationException Thrown if an error occurs
+    *                                  during modification of an option.
+    */
+
+    void modify( String value ) throws OptionModificationException;
+} /** OptionModifiable **/
diff --git a/src/java/gnu/dtools/ritopt/OptionModificationException.java b/src/java/gnu/dtools/ritopt/OptionModificationException.java
new file mode 100644
index 0000000..8c63248
--- /dev/null
+++ b/src/java/gnu/dtools/ritopt/OptionModificationException.java
@@ -0,0 +1,49 @@
+package gnu.dtools.ritopt;
+
+/**
+ * OptionModificationException.java
+ *
+ * Version:
+ *    $Id: OptionModificationException.java,v 1.1 2004/05/20 20:45:47 mortenalver Exp $
+ */
+
+/**
+ * Instances of this class are thrown if there is an error during modification
+ * of an option's value.
+ *
+ * <hr>
+ *
+ * <pre>
+ * Copyright (C) Damian Ryan Eads, 2001. All Rights Reserved.
+ *
+ * ritopt 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.
+
+ * ritopt is distributed in the hope that 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 ritopt; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * </pre>
+ *
+ * @author Damian Eads
+ */
+
+public class OptionModificationException extends OptionException {
+
+    /**
+     * Construct an OptionModificationException.
+     *
+     * @param msg The exception message.
+     */
+
+    OptionModificationException( String msg ) {
+	super( msg );
+    }
+
+}
diff --git a/src/java/gnu/dtools/ritopt/OptionModule.java b/src/java/gnu/dtools/ritopt/OptionModule.java
new file mode 100644
index 0000000..56e7c00
--- /dev/null
+++ b/src/java/gnu/dtools/ritopt/OptionModule.java
@@ -0,0 +1,450 @@
+package gnu.dtools.ritopt;
+
+/**
+ * OptionModule.java
+ *
+ * Version:
+ *    $Id: OptionModule.java,v 1.1 2004/05/20 20:45:47 mortenalver Exp $
+ */
+
+import java.util.*;
+import java.io.*;
+
+/**
+ * This class is used as a repository for options. The Options class maintains
+ * an OptionModule repository for general options. The user may create option
+ * modules so that their options can overlap and be categorized. Option
+ * modules are invoked by specifying the option name delimited with square
+ * brackets.<p>
+ *
+ * For example, suppose we are writing a program called ServerManager
+ * that manages both an ftp and http server. One option that both a ftp
+ * and http kernel might have in common is the number of seconds before
+ * a request times out. Option modules are used to process two different
+ * values with the same option name. The shell command below demonstrates
+ * how two different modules are invoked.<p>
+ * <pre>
+ *  java ServerManager :http: --timeout=15 :ftp: --timeout=25
+ * </pre>
+ *
+ * Refer to the tutorial for more information on how to use option modules.
+ *
+ * <hr>
+ *
+ * <pre>
+ * Copyright (C) Damian Ryan Eads, 2001. All Rights Reserved.
+ *
+ * ritopt 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.
+
+ * ritopt is distributed in the hope that 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 ritopt; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * </pre>
+ *
+ * @author Damian Eads
+ */
+
+public class OptionModule implements OptionRegistrar {
+
+    /**
+     * A repository of options registered with this module.
+     */
+
+    private java.util.HashMap options;
+
+    /**
+     * The name of this module.
+     */
+
+    private String name;
+
+    /**
+     * Returns whether this module is deprecated.
+     */
+
+    private boolean deprecated;
+
+    /**
+     * The default short option.
+     */
+
+    public static final char DEFAULT_SHORT_OPTION = '\0';
+
+    /**
+     * The default long option.
+     */
+
+    public static final String DEFAULT_LONG_OPTION = null;
+
+    /**
+     * The default description.
+     */
+
+    public static final String DEFAULT_DESCRIPTION = "No description given";
+
+    /**
+     * The default deprecation status.
+     */
+
+    public static final boolean DEFAULT_DEPRECATED = false;
+
+    /**
+     * The default module name.
+     */
+
+    public static final String DEFAULT_MODULE_NAME = "Special";
+
+    /**
+     * Constructs an OptionModule with the default name.
+     */
+
+    public OptionModule() {
+	this( DEFAULT_MODULE_NAME );
+    }
+
+    /**
+     * Constructs an OptionModule with the name passed.
+     *
+     * @param name  The name of the module.
+     */
+
+    public OptionModule( String name ) {
+	options = new java.util.HashMap();
+	this.name = name;
+	deprecated = false;
+    }
+
+    /**
+     * Register an option into the repository as a long option.
+     *
+     * @param longOption  The long option name.
+     * @param option      The option to register.
+     */
+
+    public void register( String longOption, Option option ) {
+	register( longOption, DEFAULT_SHORT_OPTION, option );
+    }
+
+    /**
+     * Register an option into the repository as a short option.
+     *
+     * @param shortOption The short option name.
+     * @param option      The option to register.
+     */
+
+    public void register( char shortOption, Option option ) {
+	register( DEFAULT_LONG_OPTION, shortOption, option );
+
+    }
+
+    /**
+     * Register an option into the repository both as a short and long option.
+     *
+     * @param longOption  The long option name.
+     * @param shortOption The short option name.
+     * @param option      The option to register.
+     */
+
+    public void register( String longOption, char shortOption,
+			  Option option ) {
+	register( longOption, shortOption, DEFAULT_DESCRIPTION, option );
+    }
+
+    /**
+     * Register an option into the repository both as a short and long option.
+     * Initialize its description with the description passed.
+     *
+     * @param longOption  The long option name.
+     * @param shortOption The short option name.
+     * @param description The description of the option.
+     * @param option      The option to register.
+     */
+
+    public void register( String longOption, char shortOption,
+			  String description, Option option ) {
+	register( longOption, shortOption, description, option,
+	      DEFAULT_DEPRECATED );
+    }
+
+    /**
+     * Register an option into the repository both as a short and long option.
+     * Initialize its description with the description passed.
+     *
+     * @param longOption  The long option name.
+     * @param shortOption The short option name.
+     * @param description The description of the option.
+     * @param option      The option to register.
+     * @param deprecated  A boolean indicating whether an option should
+     *                    be deprecated.
+     */
+
+    public void register( String longOption, char shortOption,
+			  String description, Option option,
+			  boolean deprecated ) {
+	if ( optionExists( option ) ) {
+	    throw new OptionRegistrationException( "Option Already Registered",
+						   option );
+	}
+	option.setLongOption( longOption );
+	option.setShortOption( shortOption );
+	option.setDeprecated( deprecated );
+	option.setDescription( description );
+	options.put( option.getHashKey(), option );
+    }
+
+    /**
+     * Returns whether the option exists in this module.
+     *
+     * @param option   The option to check for existance.
+     *
+     * @return A boolean value indicating whether the option passed exists.
+     */
+
+    public boolean optionExists( Option option ) {
+	return optionExists( option.getShortOption() ) ||
+	       optionExists( option.getLongOption() );
+    }
+
+    /**
+     * Returns whether the option referred by a short option exists in this
+     * module.
+     *
+     * @param shortOption   The option to check for existance.
+     *
+     * @return A boolean value indicating whether the option passed exists.
+     */
+
+    public boolean optionExists( char shortOption ) {
+	Collection col = options.values();
+	Iterator it = col.iterator();
+	while ( it.hasNext() ) {
+	    Option next = (Option)it.next();
+	    char c = next.getShortOption();
+	    if ( c != 0 && c == shortOption ) return true;
+	}
+	return false;
+    }
+
+    /**
+     * Returns whether the option referred by a long option exists in this
+     * module.
+     *
+     * @param longOption   The option to check for existance.
+     *
+     * @return A boolean value indicating whether the option passed exists.
+     */
+
+    public boolean optionExists( String longOption ) {
+	Collection col = options.values();
+	Iterator it = col.iterator();
+	while ( it.hasNext() ) {
+	    Option next = (Option)it.next();
+	    String s = next.getLongOption();
+	    if ( s != null && s.equals( longOption ) ) return true;
+	}
+	return false;
+    }
+
+    /**
+     * Return an iterator over the option repository contained in this module.
+     *
+     * @return An iterator over the repository.
+     */
+
+    public Iterator getOptionIterator() {
+	return options.values().iterator();
+    }
+
+    /**
+     * Returns the option referred by the long option passed.
+     *
+     * @param shortOption The option to retrieve.
+     *
+     * @return An option referred to by this module. null is returned
+     *         if it does not exist.
+     */
+
+    public Option getOption( char shortOption ) {
+	Option retval = null;
+	Collection col = options.values();
+	Iterator it = col.iterator();
+	while ( it.hasNext() ) {
+	    Option next = (Option)it.next();
+	    char c = next.getShortOption();
+	    if ( c != '\0' && c == shortOption ) retval = next;
+	}
+	return retval;
+    }
+
+    /**
+     * Returns the option referred by the long option passed.
+     *
+     * @param longOption The option to retrieve.
+     *
+     * @return An option referred to by this module. null is returned
+     *         if it does not exist.
+     */
+
+    public Option getOption( String longOption ) {
+	Option retval = null;
+	Collection col = options.values();
+	Iterator it = col.iterator();
+	while ( it.hasNext() ) {
+	    Option next = (Option)it.next();
+	    String s = next.getLongOption();
+	    if ( s != null && s.equals( longOption ) ) retval = next;
+	}
+	return retval;
+    }
+
+    /**
+     * Returns the help information as a String.
+     *
+     * @return The help information as a String.
+     */
+
+    public String getHelp() {
+	String retval = "";
+	Collection col = options.values();
+	Iterator it = col.iterator();
+	while ( it.hasNext() ) {
+	    Option next = (Option)it.next();
+	    retval += next.getHelp() + "\n";
+	}
+	return retval;
+    }
+
+    /**
+     * Writes the help information to a print stream.
+     *
+     * @param ps  The print stream to write to.
+     */
+
+    public void writeFileToPrintStream( PrintStream ps ) {
+	Collection col = options.values();
+	Iterator it = col.iterator();
+	ps.println( ":" + name + ":" );
+	while ( it.hasNext() ) {
+	    Option next = (Option)it.next();
+	    ps.println( next.getOptionFileLine() );
+	}
+    }
+
+    /**
+     * Returns whether this module is deprecated.
+     *
+     * @return A boolean value indicating whether this module is deprecated.
+     */
+
+    public boolean isDeprecated() {
+	return deprecated;
+    }
+
+    /**
+     * Sets whether this module is deprecated.
+     *
+     * @param deprecated The new status.
+     */
+
+    public void setDeprecated( boolean deprecated ) {
+	this.deprecated = deprecated;
+    }
+
+    /**
+     * Called by the OptionsProcessor when an option in the target module
+     * is invoked.
+     *
+     * @param shortOption The option to invoke.
+     * @param text        The text to pass to the modifier.
+     */
+
+    public void action( char shortOption, char text ) {
+	action( shortOption, "" + text );
+    }
+
+    /**
+     * Called by the OptionsProcessor when an option in the target module
+     * is invoked.
+     *
+     * @param longOption The option to invoke.
+     * @param text       The text to pass to the modifier.
+     */
+
+    public void action( String longOption, char text ) {
+	action( longOption, "" + text );
+    }
+
+    /**
+     * Called by the OptionsProcessor when an option in the target module
+     * is invoked.
+     *
+     * @param shortOption The option to invoke.
+     * @param text        The text to pass to the modifier.
+     */
+
+    public void action( char shortOption, String text ) {
+	Option op = getOption( shortOption );
+	if ( op == null )
+	    throw new OptionProcessingException( "Option -" + shortOption +
+						 " does not"
+						 + " exist in module '"
+						 + name + "'." );
+	op.setInvoked( true );
+	op.action();
+	op.modify( text );
+    }
+
+    /**
+     * Called by the OptionsProcessor when an option in the target module
+     * is invoked.
+     *
+     * @param longOption The option to invoke.
+     * @param text       The text to pass to the modifier.
+     */
+
+
+    public void action( String longOption, String text ) {
+	Option op = getOption( longOption );
+	if ( op == null )
+	    throw new OptionProcessingException( "Option --" + longOption +
+						 " does not"
+						 + " exist in module '"
+						 + name + "'." );
+	op.setInvoked( true );
+	op.action();
+	op.modify( text );
+    }
+
+    /**
+     * Set the name of this module.
+     *
+     * @param name   The new name.
+     */
+
+    public void setName( String name ) {
+	this.name = name;
+    }
+
+    /**
+     * Returns the name of this module.
+     *
+     * @return The name of this module.
+     */
+
+    public String getName() {
+	return name;
+    }
+
+} /** OptionModule **/
+
+
+
+
diff --git a/src/java/gnu/dtools/ritopt/OptionModuleRegistrar.java b/src/java/gnu/dtools/ritopt/OptionModuleRegistrar.java
new file mode 100644
index 0000000..f77b0c1
--- /dev/null
+++ b/src/java/gnu/dtools/ritopt/OptionModuleRegistrar.java
@@ -0,0 +1,62 @@
+package gnu.dtools.ritopt;
+
+/**
+ * OptionModuleRegistrar.java
+ *
+ * Version:
+ *   $Id: OptionModuleRegistrar.java,v 1.1 2004/05/20 20:45:47 mortenalver Exp $
+ */
+
+/**
+ * Implementors are capable of registering option modules and storing them in a
+ * repository. A parent object may pass its child a reference to an
+ * OptionModuleRegistrar to preserve abstraction and constrain access to
+ * registration. This may be preferred so that children may only
+ * register their OptionModules without performing any administrating the
+ * repository.<p>
+ *
+ * The Options class implements this interface. It is not necessary to refer
+ * to instances as an OptionModuleRegistrar.<p>
+ *
+ * <hr>
+ *
+ * <pre>
+ * Copyright (C) Damian Ryan Eads, 2001. All Rights Reserved.
+ *
+ * ritopt 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.
+
+ * ritopt is distributed in the hope that 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 ritopt; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * </pre>
+ *
+ * @author Damian Eads
+ */
+
+public interface OptionModuleRegistrar {
+
+    /**
+     * Register an option module based on its name.
+     *
+     * @param module The option module to register.
+     */
+
+    public void register( OptionModule module );
+
+    /**
+     * Register an option module and associate it with the name passed.
+     *
+     * @param name   The name associated with the option module.
+     * @param module The option module to register.
+     */
+
+    public void register( String name, OptionModule module );
+}
diff --git a/src/java/gnu/dtools/ritopt/OptionNotifier.java b/src/java/gnu/dtools/ritopt/OptionNotifier.java
new file mode 100644
index 0000000..27e241c
--- /dev/null
+++ b/src/java/gnu/dtools/ritopt/OptionNotifier.java
@@ -0,0 +1,57 @@
+package gnu.dtools.ritopt;
+
+/**
+ * If an object is able notify and maintain a repository of listeners, it
+ * should implement this interface even though it is not required. This
+ * interface expects listener registration and event configuration behavior.
+ *
+ * <hr>
+ *
+ * <pre>
+ * Copyright (C) Damian Ryan Eads, 2001. All Rights Reserved.
+ *
+ * ritopt 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.
+
+ * ritopt is distributed in the hope that 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 ritopt; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * </pre>
+ *
+ * @author Damian Eads
+ */
+
+public interface OptionNotifier {
+
+    /**
+     * Adds an OptionListener to the notification list.
+     *
+     * @param listener The OptionListener to add.
+     */
+
+    public void addOptionListener( OptionListener listener );
+
+    /**
+     * Removes an OptionListener from the notification list.
+     *
+     * @param listener The OptionListener to remove.
+     */
+
+    public void removeOptionListener( OptionListener listener );
+
+    /**
+     * Sets the command sent when an option is invoked.
+     *
+     * @param command  The command to send.
+     */
+
+    public void setOptionCommand( String command );
+
+}
diff --git a/src/java/gnu/dtools/ritopt/OptionProcessingException.java b/src/java/gnu/dtools/ritopt/OptionProcessingException.java
new file mode 100644
index 0000000..771606c
--- /dev/null
+++ b/src/java/gnu/dtools/ritopt/OptionProcessingException.java
@@ -0,0 +1,49 @@
+package gnu.dtools.ritopt;
+
+/**
+ * OptionProcessingException.java
+ *
+ * Version:
+ *    $Id: OptionProcessingException.java,v 1.1 2004/05/20 20:45:47 mortenalver Exp $
+ */
+
+/**
+ * Instances of this exception are thrown when an error occurs when processing
+ * the command line.
+ *
+ * <hr>
+ *
+ * <pre>
+ * Copyright (C) Damian Ryan Eads, 2001. All Rights Reserved.
+ *
+ * ritopt 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.
+
+ * ritopt is distributed in the hope that 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 ritopt; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * </pre>
+ *
+ * @author Damian Eads
+ */
+
+public class OptionProcessingException extends OptionException {
+
+    /**
+     * Construct an OptionProcessingException.
+     *
+     * @param msg The exception message.
+     */
+
+
+    OptionProcessingException( String msg ) {
+	super( msg );
+    }
+}
diff --git a/src/java/gnu/dtools/ritopt/OptionRegistrar.java b/src/java/gnu/dtools/ritopt/OptionRegistrar.java
new file mode 100644
index 0000000..f9be341
--- /dev/null
+++ b/src/java/gnu/dtools/ritopt/OptionRegistrar.java
@@ -0,0 +1,98 @@
+package gnu.dtools.ritopt;
+
+/**
+ * Implementors are capable of registering options and storing them in a
+ * repository. A parent object may pass its child a reference to an
+ * OptionRegistrar to preserve abstraction and restrict access to
+ * registration. This may be preferred so that children may only
+ * register their options without performing any administrating the
+ * repository.
+ * <p>
+ *
+ * The Options and OptionModule classes implement this interface. It is not
+ * necessary to refer to instances as an OptionRegistrar.<p>
+ *
+ * <hr>
+ *
+ * <pre>
+ * Copyright (C) Damian Ryan Eads, 2001. All Rights Reserved.
+ *
+ * ritopt 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.
+
+ * ritopt is distributed in the hope that 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 ritopt; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * </pre>
+ *
+ * @author Damian Eads
+ */
+
+public interface OptionRegistrar {
+
+    /**
+     * Register an option into the repository as a long option.
+     *
+     * @param longName   The long option name.
+     * @param option     The option to register.
+     */
+
+    public void register( String longName, Option option );
+
+    /**
+     * Register an option into the repository as a short option.
+     *
+     * @param shortName  The short option name.
+     * @param option     The option to register.
+     */
+
+    public void register( char shortName, Option option );
+
+
+    /**
+     * Register an option into the repository both as a short and long option.
+     *
+     * @param longOption  The long option name.
+     * @param shortOption The short option name.
+     * @param option      The option to register.
+     */
+
+    public void register( String longOption, char shortOption,
+			  Option option );
+
+    /**
+     * Register an option into the repository both as a short and long option.
+     * Initialize its description with the description passed.
+     *
+     * @param longOption  The long option name.
+     * @param shortOption The short option name.
+     * @param description The description of the option.
+     * @param option      The option to register.
+     */
+
+    public void register( String longOption, char shortOption,
+			  String description, Option option );
+
+    /**
+     * Register an option into the repository both as a short and long option.
+     * Initialize its description with the description passed.
+     *
+     * @param longOption  The long option name.
+     * @param shortOption The short option name.
+     * @param description The description of the option.
+     * @param option      The option to register.
+     * @param deprecated  A boolean indicating whether an option should
+     *                    be deprecated.
+     */
+
+    public void register( String longOption, char shortOption,
+			  String description, Option option,
+			  boolean deprecated );
+}
diff --git a/src/java/gnu/dtools/ritopt/OptionRegistrationException.java b/src/java/gnu/dtools/ritopt/OptionRegistrationException.java
new file mode 100644
index 0000000..9105293
--- /dev/null
+++ b/src/java/gnu/dtools/ritopt/OptionRegistrationException.java
@@ -0,0 +1,78 @@
+package gnu.dtools.ritopt;
+
+/**
+ * OptionRegistrationException.java
+ *
+ * Version:
+ *   $Id: OptionRegistrationException.java,v 1.1 2004/05/20 20:45:47 mortenalver Exp $
+ */
+
+/**
+ * This exception indicates that an error has occurred during registration
+ * of an option, registrar, or module.
+ *
+ * <pre>
+ * Copyright (C) Damian Ryan Eads, 2001. All Rights Reserved.
+ *
+ * ritopt 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.
+
+ * ritopt is distributed in the hope that 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 ritopt; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * </pre>
+ *
+ * @author Damian Eads
+ */
+
+public class OptionRegistrationException extends OptionException {
+
+    /**
+     * The target option associated with the registration failure.
+     */
+
+    private Option target;
+
+    /**
+     * Construct an OptionRegistrationException.
+     *
+     * @param msg The exception message.
+     */
+
+
+    public OptionRegistrationException( String msg ) {
+	super( msg );
+    }
+
+    /**
+     * Construct an OptionRegisrationException and initialize its members
+     * with the message and target passed.
+     *
+     * @param msg     An exception message.
+     * @param target  The target option that caused the registration failure.
+     */
+
+    public OptionRegistrationException( String msg, Option target ) {
+	super( msg );
+	this.target = target;
+    }
+
+    /**
+     * Returns the target option associated with the registration failure.
+     *
+     * @return The target option.
+     */
+
+    public Option getTarget() {
+	return target;
+    }
+
+
+}
diff --git a/src/java/gnu/dtools/ritopt/Options.java b/src/java/gnu/dtools/ritopt/Options.java
new file mode 100644
index 0000000..bcc5b69
--- /dev/null
+++ b/src/java/gnu/dtools/ritopt/Options.java
@@ -0,0 +1,872 @@
+package gnu.dtools.ritopt;
+
+/**
+ * Options.java
+ *
+ * Version:
+ *    $Id: Options.java,v 1.5 2005/07/30 14:48:59 mortenalver Exp $
+
+ */
+
+import java.util.*;
+import java.io.*;
+import net.sf.jabref.*;
+
+/**
+ * This class functions as a repository for options and their modules. It
+ * facilitates registration of options and modules, as well as processing of
+ * arguments.<p>
+ *
+ * Information such as help, usage, and versions are displayed
+ * when the respective --help and --version options are specified.
+ * The --menu option will invoke the built-in menu.<p>
+ *
+ * In the example below, the program processes three simple options.
+ *
+ * <pre>
+ * public class AboutMe {
+ *
+ *    private static StringOption name = new StringOption( "Ryan" );
+ *    private static IntOption age = new IntOption( 19 );
+ *    private static DoubleOption bankBalance = new DoubleOption( 15.15 );
+ *
+ *    public static void main( String args[] ) {
+ *       Options repo = new Options( "java AboutMe" );
+ *       repo.register( "name", 'n', name, "The person's name." );
+ *       repo.register( "age", 'a', age, "The person's age." );
+ *       repo.register( "balance", 'b', "The person's bank balance.",
+ *                       bankBalance );
+ *       repo.process( args );
+g *       System.err.println( "" + name + ", age " + age + " has a " +
+ *                           " bank balance of " + bankBalance + "." );
+ *    }
+ * }
+ * </pre>
+ *
+ * <hr>
+ *
+ * <pre>
+ * Copyright (C) Damian Ryan Eads, 2001. All Rights Reserved.
+ *
+ * ritopt 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.
+ *
+ * ritopt is distributed in the hope that 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 ritopt; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * </pre>
+ *
+ * @author Damian Eads
+ */
+
+public class Options implements OptionRegistrar, OptionModuleRegistrar,
+                                OptionListener {
+
+    /**
+     * The default verbosity.
+     */
+
+    public static final int DEFAULT_VERBOSITY = 3;
+
+    /**
+     * This boolean defines whether options are deprecated by default.
+     */
+
+    public static final boolean DEFAULT_DEPRECATED = false;
+
+    /**
+     * The default reason for deprecation.
+     */
+
+    public static final String DEFAULT_REASON = "No reason given.";
+
+    /**
+     * The default general module name.
+     */
+
+    public static final String DEFAULT_GENERAL_MODULE_NAME = "General";
+
+    /**
+     * This boolean defines whether usage should be displayed.
+     */
+
+    public static final boolean DEFAULT_DISPLAY_USAGE = false; // Mod. Morten A.
+
+    /**
+     * This boolean defines whether the menu should be used.
+     */
+
+    public static final boolean DEFAULT_USE_MENU = false; // Mod. Morten A.
+
+    /**
+     * The default program name that is display in the usage.
+     */
+
+    public static final String DEFAULT_PROGRAM_NAME = "java program";
+
+    /**
+     * The default option file.
+     */
+
+    public static final String DEFAULT_OPTION_FILENAME = "default.opt";
+
+    /**
+     * The current verbosity.
+     */
+
+    private int verbosity;
+
+    /**
+     * The program to display in the usage.
+     */
+
+    private String usageProgram;
+
+    /**
+     * The version to display in the usage.
+     */
+
+    private String version;
+
+    /**
+     * The default option filename if an option file is not specified.
+     */
+
+    private String defaultOptionFilename;
+
+    /**
+     * This flag defines whether to display usage when help is displayed.
+     */
+
+    private boolean displayUsage;
+
+    /**
+     * This boolean defines whether the menu should be used.
+     */
+
+    private boolean useMenu;
+
+    /**
+     * When this flag is true, debugging information is displayed.
+     */
+
+    private boolean debugFlag;
+
+    /**
+     * The current module being processed.
+     */
+
+    private OptionModule currentModule;
+
+    /**
+     * The general option module.
+     */
+
+    private OptionModule generalModule;
+
+    /**
+     * A map of option modules.
+     */
+
+    private java.util.HashMap modules;
+
+    /**
+     * The help method is invoked when this option is invoked.
+     */
+
+    private NotifyOption helpOption;
+
+    /**
+     * The built-in menu system is invoked when this option is invoked.
+     */
+
+    private NotifyOption menuOption;
+
+    /**
+     * Version information is displayed when this option is specified.
+     */
+
+    private NotifyOption versionOption;
+
+    /**
+     * An instance of the built-in menu.
+     */
+
+    private OptionMenu menu;
+
+    /**
+     * Create an option repository.
+     */
+
+    public Options() {
+        this( DEFAULT_PROGRAM_NAME );
+    }
+
+    /**
+     * Create an option repository and associated it with a program name.
+     *
+     * @param programName A program name like "java Balloons".
+     */
+
+    public Options( String programName ) {
+        verbosity = DEFAULT_VERBOSITY;
+        displayUsage = DEFAULT_DISPLAY_USAGE;
+        useMenu = DEFAULT_USE_MENU;
+        defaultOptionFilename = DEFAULT_OPTION_FILENAME;
+        usageProgram = programName;
+        modules = new HashMap();
+        menu = new OptionMenu( this );
+        helpOption = new NotifyOption( this, "help", "" );
+        versionOption = new NotifyOption( this, "version", "" );
+        version = "Version 1.0";
+        menuOption = new NotifyOption( menu, "menu", "" );
+        generalModule = new OptionModule( DEFAULT_GENERAL_MODULE_NAME );
+        currentModule = generalModule;
+
+        // Mod. Morten A. ------------------------------------------------
+        register( "version", 'v',
+                  "Displays version information.", versionOption );
+        /*register( "help", 'h', "Displays help for each option.", helpOption );
+        register( "menu", 'm', "Displays the built-in interactive menu.",
+                  menuOption );*/
+        // End mod. Morten A. ------------------------------------------------
+    }
+
+    /**
+     * Returns the help information as a string.
+     *
+     * @return The help information.
+     */
+
+    public String getHelp() {
+        String retval = (displayUsage ? getUsage() + "\n\n" : "" ) +
+            // Mod. Morten A.
+            //"Use --menu to invoke the interactive built-in menu.\n\n" +
+            Option.getHelpHeader() + "\n\n" + generalModule.getHelp();
+        Iterator it = modules.values().iterator();
+        while ( it.hasNext() ) {
+            OptionModule module = (OptionModule)it.next();
+            retval += "\n\nOption Listing for " + module.getName() + "\n";
+            retval += module.getHelp() + "\n";
+        }
+        return retval;
+    }
+
+    /**
+     * Returns usage information of this program.
+     *
+     * @return The usage information.
+     */
+
+    public String getUsage() {
+        return getUsageProgram()
+            + " @optionfile :module: OPTIONS ... :module: OPTIONS";
+    }
+
+    /**
+     * Returns the program name displayed in the usage.
+     *
+     * @param The program name.
+     */
+
+    public String getUsageProgram() {
+        return usageProgram;
+    }
+
+    /**
+     * Returns the version of the program.
+     *
+     * @param The version.
+     */
+
+    public String getVersion() {
+        return version;
+    }
+
+    /**
+     * Returns the option filename to load or write to if one is not
+     * specified.
+     *
+     * @return The default option filename.
+     */
+
+    public String getDefaultOptionFilename() {
+        return defaultOptionFilename;
+    }
+
+    /**
+     * Returns whether debugging information should be displayed.
+     *
+     * @return A boolean indicating whether to display help information.
+     */
+
+    public boolean getDebugFlag() {
+        return debugFlag;
+    }
+
+    /**
+     * Returns whether the help information should display usage.
+     *
+     * @return A boolean indicating whether help should display usage.
+     */
+
+    public boolean shouldDisplayUsage() {
+        return displayUsage;
+    }
+
+    /**
+     * Returns whether the built-in menu system can be invoked.
+     *
+     * @return A boolean indicating whether the build-in menu system
+     *         can be invoked.
+     */
+
+    public boolean shouldUseMenu() {
+        return useMenu;
+    }
+
+    /**
+     * Sets whether usage can be displayed.
+     *
+     * @param b     A boolean value indicating that usage can be displayed.
+     */
+
+    public void setDisplayUsage( boolean b ) {
+        displayUsage = b;
+    }
+
+    /**
+     * Sets whether the built-in menu system can be used.
+     *
+     * @param b      A boolean value indicating whether the built-in menu
+     *               system can be used.
+     */
+
+    public void setUseMenu( boolean b ) {
+        useMenu = b;
+    }
+
+    /**
+     * Sets the program to display when the usage is displayed.
+     *
+     * @param program The program displayed during usage.
+     */
+
+    public void setUsageProgram( String program ) {
+        usageProgram = program;
+    }
+
+    /**
+     * Sets the version of the program.
+     *
+     * @param version The version.
+     */
+
+    public void setVersion( String version ) {
+        this.version = version;
+    }
+
+    /**
+     * Sets the option file to use when an option file is not specified.
+     *
+     * @param fn      The filename of the default option file.
+     */
+
+    public void setDefaultOptionFilename( String fn ) {
+        defaultOptionFilename = fn;
+    }
+
+    /**
+     * Sets the debugging flag.
+     *
+     * @param flag    The value to set the debugging flag.
+
+    public void setDebugFlag( boolean flag ) {
+        debugFlag = flag;
+    }
+
+    /**
+     * Displays the program's help which includes a description of each
+     * option. The usage is display if the usage flag is set to true.
+     */
+
+    public void displayHelp() {
+        System.err.println( getHelp() );
+    }
+
+    /**
+     * Displays the version of the program.
+     */
+
+    public void displayVersion() {
+        System.err.println( getVersion() +" (build " +Globals.BUILD +")");
+    }
+
+    /**
+     * Register an option into the repository as a long option.
+     *
+     * @param longOption  The long option name.
+     * @param option      The option to register.
+     */
+
+    public void register( String longOption, Option option ) {
+        generalModule.register( longOption, option );
+    }
+
+    /**
+     * Register an option into the repository as a short option.
+     *
+     * @param shortOption The short option name.
+     * @param option      The option to register.
+     */
+
+    public void register( char shortOption, Option option ) {
+        generalModule.register( shortOption, option );
+    }
+
+    /**
+     * Register an option into the repository both as a short and long option.
+     *
+     * @param longOption  The long option name.
+     * @param shortOption The short option name.
+     * @param option      The option to register.
+     */
+
+    public void register( String longOption, char shortOption,
+                          Option option ) {
+        generalModule.register( longOption, shortOption, option );
+    }
+
+    /**
+     * Register an option into the repository both as a short and long option.
+     * Initialize its description with the description passed.
+     *
+     * @param longOption  The long option name.
+     * @param shortOption The short option name.
+     * @param description The description of the option.
+     * @param option      The option to register.
+     */
+
+    public void register( String longOption, char shortOption,
+                          String description, Option option ) {
+        generalModule.register( longOption, shortOption, description, option );
+    }
+
+    /**
+     * Register an option into the repository both as a short and long option.
+     * Initialize its description with the description passed.
+     *
+     * @param longOption  The long option name.
+     * @param shortOption The short option name.
+     * @param description The description of the option.
+     * @param option      The option to register.
+     * @param deprecated  A boolean indicating whether an option should
+     *                    be deprecated.
+     */
+
+    public void register( String longOption, char shortOption,
+                          String description, Option option,
+                          boolean deprecated ) {
+        generalModule.register( longOption, shortOption, description, option,
+                                deprecated );
+    }
+
+    /**
+     * Register an option module based on its name.
+     *
+     * @param module The option module to register.
+     */
+
+    public void register( OptionModule module ) {
+        register( module.getName(), module );
+    }
+
+    /**
+     * Register an option module and associate it with the name passed.
+     *
+     * @param name   The name associated with the option module.
+     * @param module The option module to register.
+     */
+
+    public void register( String name, OptionModule module ) {
+        modules.put( name.toLowerCase(), module );
+    }
+
+    /**
+     * Process a string of values representing the invoked options. After
+     * all the options are processed, any leftover arguments are returned.
+     *
+     * @param args The arguments to process.
+     *
+     * @return The leftover arguments.
+     */
+
+    public String[] process( String args[] )
+    {
+        String []retval = new String[0];
+        try {
+            retval = processOptions( args );
+        }
+        catch ( OptionException e ) {
+            System.err.println( "Error: " + e.getMessage() );
+        }
+        /**
+        catch ( Exception e ) {
+            System.err.println( "Error: Unexpected Error in ritopt Processing." +
+                                "Check syntax." );
+                                }**/
+        return retval;
+    }
+
+    /**
+     * Retrieves an option module based on the name passed.
+     *
+     * @param name The name referring to the option module.
+     *
+     * @return The option module. Null is returned if the module does not
+     *         exist.
+     */
+
+    public OptionModule getModule( String name ) {
+        return (OptionModule)modules.get( name.toLowerCase() );
+    }
+
+    /**
+     * Returns a boolean indicating whether an option module exists.
+     *
+     * @param name The name referring to the option module.
+     *
+     * @return A boolean value indicating whether the module exists.
+     */
+
+    public boolean moduleExists( String name ) {
+        return getModule( name ) != null;
+    }
+
+    /**
+     * Receives NotifyOption events. If the event command equals "help"
+     * or "version", the appropriate display methods are invoked.
+     *
+     * @param event         The event object containing information about the
+     *                      invocation.
+     */
+
+    public void optionInvoked( OptionEvent event ) {
+        if ( event.getCommand().equals( "help" ) ) {
+            displayHelp();
+        }
+        else if ( event.getCommand().equals( "version" ) ) {
+            displayVersion();
+        }
+    }
+
+    /**
+     * Process a string representing the invoked options. This string
+     * gets split according to how they would be split when passed to
+     * a main method. The split array of options gets passed to a
+     * private method for processing. After all the options are processed,
+     * any leftover arguments are returned.
+     *
+     * @param str The arguments to process.
+     *
+     * @return The leftover arguments.
+     */
+
+    public String[] process( String str ) {
+        return process( split( str ) );
+    }
+
+    /**
+     * Splits a string representing command line arguments into several
+     * strings.
+     *
+     * @param split   The string to split.
+     *
+     * @return  The splitted string.
+     */
+
+    public String[] split( String str ) {
+        StringBuffer buf = new StringBuffer( str.length() );
+        java.util.List l = new java.util.ArrayList();
+        int scnt = Utility.count( str, '"' );
+        boolean q = false;
+        if ( ((double)scnt) / 2.0 != (double)(scnt / 2) ) {
+            throw new OptionProcessingException( "Expecting an end quote." );
+        }
+        for ( int n = 0; n < str.length(); n++ ) {
+            if ( str.charAt( n ) == '"' ) {
+                q = !q;
+            }
+            else if ( str.charAt( n ) == ' ' && !q ) {
+                l.add( buf.toString() );
+                buf = new StringBuffer( str.length() );
+            }
+            else {
+                buf.append( str.charAt( n ) );
+            }
+        }
+        if ( buf.length() != 0 ) {
+            l.add( buf.toString() );
+        }
+        Iterator it = l.iterator();
+        String retval[] = new String[ l.size() ];
+        int n = 0;
+        while ( it.hasNext() ) {
+            retval[ n++ ] = (String)it.next();
+        }
+        return retval;
+    }
+
+    /**
+     * Writes all options and their modules out to an options file.
+     *
+     * @param filename  The options filename to write.
+     */
+
+    public void writeOptionFile( String filename ) {
+        BufferedOutputStream writer = null;
+        String line = null;
+        Iterator it = null;
+        currentModule = generalModule;
+        try {
+            writer =
+                new BufferedOutputStream( new FileOutputStream( filename ) );
+            PrintStream ps = new PrintStream( writer );
+            generalModule.writeFileToPrintStream( ps );
+            it = modules.values().iterator();
+            while ( it.hasNext() ) {
+                OptionModule module = (OptionModule)it.next();
+                module.writeFileToPrintStream( ps );
+            }
+        }
+        catch ( IOException e ) {
+            throw new OptionProcessingException( e.getMessage() );
+        }
+        finally {
+            try {
+                if ( writer != null )
+                    writer.close();
+            }
+            catch( IOException e ) {
+                throw new OptionProcessingException( e.getMessage() );
+            }
+        }
+    }
+
+    /**
+     * Loads all options and their modules from an options file.
+     *
+     * @param filename  The options filename to write.
+     */
+
+    public void loadOptionFile( String filename ) {
+        BufferedReader reader = null;
+        String line = null;
+        currentModule = generalModule;
+        try {
+            reader = new BufferedReader( new FileReader( filename ) );
+            while ( ( line = reader.readLine() ) != null ) {
+                line = Utility.stripComments( line, '\"', ';' );
+                process( line );
+            }
+        }
+        catch ( IOException e ) {
+            throw new OptionProcessingException( e.getMessage() );
+        }
+        finally {
+            try {
+                if ( reader != null )
+                    reader.close();
+            }
+            catch( IOException e ) {
+                throw new OptionProcessingException( e.getMessage() );
+            }
+        }
+    }
+
+    /**
+     * Processes an array of strings representing command line arguments.
+     *
+     * @param  The arguments to process.
+     *
+     * @return The leftover arguments.
+     */
+
+    private String[] processOptions( String args[] ) {
+        String retval[] = null;
+        String moduleName = "general";
+        String optionFile = "";
+        char shortOption = '\0';
+        String longOption = "";
+        for ( int n = 0; n < args.length && retval == null; n++ ) {
+            boolean moduleInvoked = false;
+            boolean shortOptionInvoked = false;
+            boolean longOptionInvoked = false;
+            boolean readOptionFileInvoked = false;
+            boolean writeOptionFileInvoked = false;
+            if ( args[ n ].length() >= 1 ) {
+                char fc = args[ n ].charAt( 0 );
+                moduleInvoked = fc == ':';
+                readOptionFileInvoked = fc == '@';
+                writeOptionFileInvoked = fc == '%';
+            }
+            if ( args[ n ].length() >= 2 ) {
+                String s = args[ n ].substring( 0, 2 );
+                shortOptionInvoked = ( !s.equals( "--" ) &&
+                           s.charAt( 0 ) == '-' );
+                longOptionInvoked = ( s.equals( "--" ) );
+            }
+            if ( debugFlag ) {
+                System.err.println( "Short Option: " + shortOptionInvoked );
+                System.err.println( "Long Option: " + longOptionInvoked );
+                System.err.println( "Module: " + moduleInvoked );
+                System.err.println( "Load Option File: " +
+                                    readOptionFileInvoked );
+                System.err.println( "Write Option File: "
+                                    + writeOptionFileInvoked );
+            }
+            if ( moduleInvoked ) {
+                if (  args[ n ].charAt( args[ n ].length() - 1 ) != ':' ) {
+                    System.err.println( args[ n ] );
+                    throw new
+                        OptionProcessingException(
+                                                  "Module arguments must start"
+                                                  + " with : and end with :."
+                                                  );
+                }
+                else {
+                    moduleName = args[n].substring( 1,
+                                                    args[n].length() - 1
+                                                    ).toLowerCase();
+                    if ( moduleName.length() == 0
+                         || moduleName.equals( "general" ) ) {
+                        moduleName = "general";
+                        currentModule = generalModule;
+                    }
+                    else {
+                        currentModule = getModule( moduleName );
+                    }
+                    if ( currentModule == null )
+                        throw new OptionProcessingException( "Module '" +
+                                                             moduleName +
+                                                         "' does not exist." );
+                    if ( debugFlag ) {
+                        System.err.println( "Module: " + moduleName );
+                    }
+                }
+                moduleInvoked = false;
+            }
+            else if ( readOptionFileInvoked ) {
+                optionFile = Utility.trim( args[ n ].substring( 1 ) );
+                if ( optionFile.equals( "@" )
+                     || optionFile.length() == 0 )
+                    optionFile = defaultOptionFilename;
+                if ( debugFlag ) {
+                    System.err.println( "Option file: '" + optionFile + "'." );
+                }
+                loadOptionFile( optionFile );
+            }
+            else if ( shortOptionInvoked ) {
+                shortOption = args[ n ].charAt( 1 );
+                if ( !Utility.isAlphaNumeric( shortOption ) ) {
+                    throw new OptionProcessingException(
+                      "A short option must be alphanumeric. -" + shortOption
+                      + " is not acceptable." );
+                }
+                if ( debugFlag ) {
+                    System.err.println( "Short option text: " + shortOption );
+                }
+                char delim = ( args[ n ].length() >= 3 ) ?
+                    args[ n ].charAt( 2 ) : '\0';
+                if ( delim == '+' || delim == '-' ) {
+                    currentModule.action( shortOption, delim );
+                }
+                else if ( delim == '=' ) {
+                    currentModule.action( shortOption,
+                                          args[ n ].substring( 3 ) );
+                }
+                else if ( delim == '\0' ) {
+                    String dtext = "+";
+                    char dpeek = '\0';
+                    if ( n < args.length - 1 ) {
+                        dpeek = args[ n + 1 ].charAt( 0 );
+                        if ( !Utility.contains( args[ n + 1 ].charAt( 0 ),
+                                                "-[@" ) ) {
+                            dtext = args[ n + 1 ];
+                            n++;
+                        }
+                    }
+                    currentModule.action( shortOption, dtext );
+                }
+                else if ( Utility.isAlphaNumeric( delim ) ) {
+                    for ( int j = 1; j < args[ n ].length(); j++ ) {
+                        if ( Utility.isAlphaNumeric( args[ n ].charAt( j ) ) ) {
+                            currentModule.action( shortOption, "+" );
+                        }
+                        else {
+                            throw new OptionProcessingException(
+                              "A short option must be alphanumeric. -"
+                              + shortOption + " is not acceptable." );
+                        }
+                    }
+                }
+            }
+            else if ( longOptionInvoked ) {
+                char lastchar = args[ n ].charAt( args[ n ].length() - 1 );
+                int eqindex = args[ n ].indexOf( "=" );
+                if ( eqindex != -1 ) {
+                    longOption = args[ n ].substring( 2, eqindex );
+                    String value = args[ n ].substring( eqindex + 1 );
+                    currentModule.action( longOption, value );
+                }
+                else if ( Utility.contains( lastchar, "+-" ) ) {
+                    longOption = args[ n ].substring( 2,
+                                                      args[ n ].length() - 1 );
+                    currentModule.action( longOption, lastchar );
+                }
+                else {
+                    longOption = args[ n ].substring( 2 );
+                    String dtext = "+";
+                    char dpeek = '\0';
+                    if ( n < args.length - 1 && args[ n + 1 ].length() > 0 ) {
+                        dpeek = args[ n + 1 ].charAt( 0 );
+                        if ( !Utility.contains( args[ n + 1 ].charAt( 0 ),
+                                                "-[@" ) ) {
+                            dtext = args[ n + 1 ];
+                            n++;
+                        }
+                    }
+                    currentModule.action( longOption, dtext );
+                }
+                if ( debugFlag ) {
+                    System.err.println( "long option: " + longOption );
+                }
+            }
+            else if ( writeOptionFileInvoked ) {
+                optionFile = Utility.trim( args[ n ].substring( 1 ) );
+                if ( optionFile.equals( "%" )
+                     || optionFile.length() == 0 )
+                    optionFile = defaultOptionFilename;
+                if ( debugFlag ) {
+                    System.err.println( "Option file: '" + optionFile + "'." );
+                }
+                writeOptionFile( optionFile );
+            }
+            else {
+                retval = new String[ args.length - n ];
+                for ( int j = n; j < args.length; j++ ) {
+                    retval[ j - n ] = args[ j ];
+                }
+            }
+        }
+        if ( retval == null ) retval = new String[ 0 ];
+        return retval;
+    }
+}
diff --git a/src/java/gnu/dtools/ritopt/ShortOption.java b/src/java/gnu/dtools/ritopt/ShortOption.java
new file mode 100644
index 0000000..9445eda
--- /dev/null
+++ b/src/java/gnu/dtools/ritopt/ShortOption.java
@@ -0,0 +1,202 @@
+package gnu.dtools.ritopt;
+
+/**
+ * ShortOption.java
+ *
+ * Version:
+ *    $Id: ShortOption.java,v 1.1 2004/05/20 20:45:47 mortenalver Exp $
+ */
+
+/**
+ * This class is used for options with short values.
+ *
+ * <hr>
+ * <pre>
+ * Copyright (C) Damian Ryan Eads, 2001. All Rights Reserved.
+ *
+ * ritopt 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.
+
+ * ritopt is distributed in the hope that 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 ritopt; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * </pre>
+ *
+ * @author Damian Eads
+ */
+
+public class ShortOption extends Option {
+
+    /**
+     * The value of this short option.
+     */
+
+    private short value;
+
+    /**
+     * Constructs a short option that is initially set to zero.
+     */
+
+    public ShortOption() {
+	this( (short)0 );
+    }
+
+    /**
+     * Constructs a short option by copying the short option passed.
+     *
+     * @param op     The character option to copy.
+     */
+
+    public ShortOption( ShortOption op ) {
+	super( op );
+	op.value = op.getValue();
+    }
+
+    /**
+     * Constructs a short option initialized with the value passed.
+     *
+     * @param value    The initial value of this short option.
+     */
+
+    public ShortOption( short value ) {
+	this( value, null );
+    }
+
+    /**
+     * Constructs a short option initialized with the value and
+     * long option passed.
+     *
+     * @param value      The initial value of this short option.
+     * @param longOption The long option associated with short option.
+     */
+
+    public ShortOption( short value, String longOption ) {
+	this( value, longOption, '\0' );
+    }
+
+    /**
+     * Constructs a character option initialized with the value and
+     * short option passed.
+     *
+     * @param value       The initial value of this short option.
+     * @param shortOption The short option associated with this option.
+     */
+
+    public ShortOption( short value, char shortOption ) {
+	this( value, null, shortOption );
+    }
+
+    /**
+     * Constructs a short option initialized with the value, short
+     * and long option passed.
+     *
+     * @param shortOption The short option associated with this option.
+     * @param longOption  The long option associated with this option.
+     * @param value       The initial value of this short option.
+     */
+
+    public ShortOption( short value, String longOption, char shortOption ) {
+	super( longOption, shortOption );
+	this.value = value;
+    }
+
+    /**
+     * Return the value as an object.
+     *
+     * @return This value as an option.
+     */
+
+    public Object getObject() {
+	return new Short( value );
+    }
+
+    /**
+     * Modify this option based on a string representation.
+     *
+     * @param     value String representation of the object.
+     * @exception OptionModificationException Thrown if an error occurs
+     *                                  during modification of an option.
+     */
+
+    public void modify( String value ) throws OptionModificationException {
+	try {
+	    this.value = Short.parseShort( value );
+	}
+	catch ( NumberFormatException e ) {
+	    throw new OptionModificationException( "Error. A short must be"
+						   + " specified, not '"
+						   + value + "'." );
+	}
+    }
+
+    /**
+     * Modify this option based on a string representation.
+     *
+     * @param     value String representation of the object.
+     * @exception OptionModificationException Thrown if an error occurs
+     *                                  during modification of an option.
+     */
+
+    public void setValue( String value ) throws OptionModificationException {
+	modify( value );
+    }
+
+    /**
+     * Modify this option using a short value.
+     *
+     * @param     value A short value.
+     */
+
+    public void setValue( short value ) {
+	this.value = value;
+    }
+
+    /**
+     * Return this option as a short.
+     *
+     * @return This option as a short.
+     */
+
+    public short getValue() {
+	return value;
+    }
+
+    /**
+     * Return this option as a string.
+     *
+     * @return This option as a string.
+     */
+
+    public String getStringValue() {
+	return Short.toString( value );
+    }
+
+    /**
+     * Returns the type name of this option. For a ShortOption, "SHORT"
+     * is returned.
+     *
+     * @return The type name of this option.
+     */
+
+    public String getTypeName() {
+	return "SHORT";
+    }
+
+    /**
+     * Returns a string representation of this object.
+     *
+     * @return A string representation of this object.
+     */
+
+    public String toString() {
+	return getStringValue();
+    }
+
+} /** ShortOption */
diff --git a/src/java/gnu/dtools/ritopt/SimpleProcess.java b/src/java/gnu/dtools/ritopt/SimpleProcess.java
new file mode 100644
index 0000000..674d6f6
--- /dev/null
+++ b/src/java/gnu/dtools/ritopt/SimpleProcess.java
@@ -0,0 +1,217 @@
+package gnu.dtools.ritopt;
+
+/**
+ * SimpleProcess.java
+ *
+ * Version:
+ *   $Id: SimpleProcess.java,v 1.1 2004/05/20 20:45:47 mortenalver Exp $
+ */
+
+import java.io.*;
+
+/**
+ * A SimpleProcess is used to execute a shell process, and redirect an
+ * input stream to the processes' standard input, as well as redirect
+ * the processes' standard output/error to an output stream. The processes
+ * is multithreaded to prevent deadlock.<p>
+ *
+ * The example below demonstrates the use of this class.
+ * <pre>
+ *  class ExecuteProcess {
+ *       public static void main( String args[] ) {
+ *           if ( args.length > 0 ) {
+ *               String processName = args[ 0 ];
+ *               try {
+ *                   SimpleProcess process
+ *                      = new SimpleProcess( Runtime.getRuntime.exec(
+ *                                                            processName ) );
+ *                                          );
+ *                   int exitStatus = process.waitFor();
+ *                   System.out.println( "The process ran successfully" 
+ *                                       + " with an exit status of "
+ *                                       + exitStatus + "." );
+ *               }
+ *               catch ( Exception e ) {
+ *                   System.out.println( "The process was not successful. "
+ *                                       + " Reason: " + e.getMessage() );
+ *               }
+ *           }
+ *           else {
+ *               System.err.println( "Please specify a command" );
+ *           }
+ *       }
+ *  }
+ * </pre>
+ *
+ * <hr>
+ *
+ * <pre>
+ * Copyright (C) Damian Ryan Eads, 2001. All Rights Reserved.
+ *
+ * ritopt 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.
+
+ * ritopt is distributed in the hope that 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 ritopt; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * </pre>
+ *
+ * @author Damian Eads
+ */
+
+public class SimpleProcess extends Process {
+
+    /**
+     * The target process.
+     */
+
+    private Process process;
+
+    /**
+     * The input stream that the processes' standard input will use.
+     */
+
+    private InputStream processInput;
+
+    /**
+     * The print stream to redirect to.
+     */
+
+    private PrintStream yourOutput;
+
+    /**
+     * The print stream to redirect to.
+     */
+
+    private PrintStream yourError;
+
+    /**
+     * The StreamPrinters.
+     */
+
+    private StreamPrinter in, out, error;
+
+    /**
+     * Constructs a SimpleProcess, redirecting System.in to the its standard
+     * input, System.out to its standard output, and System.err to its standard
+     * error.
+     */
+
+    public SimpleProcess( Process process ) throws IOException {
+	this( process, System.in, System.out, System.err );
+    }
+
+    /**
+     * Constructs a SimpleProcess, initializing it with the streams passed.
+     *
+     * @param process       The target process.
+     * @param processInput  The stream that is redirected to the
+     *                      processes' standard input.
+     * @param processOutput The stream to redirect the processes's
+     *                      standard output.
+     * @param processError  The stream to redirect the processes's
+     *                      standard input.
+     */
+
+    public SimpleProcess( Process process, InputStream processInput,
+			  PrintStream yourOutput, PrintStream yourError )
+                         throws IOException {
+	super();
+	this.process = process;
+	this.processInput = processInput;
+	this.yourOutput = yourOutput;
+	this.yourError = yourError;
+    }
+
+    /**
+     * Returns the standard input of this process.
+     *
+     * @return The standard input of this process.
+     */
+
+    public OutputStream getOutputStream() {
+	return process.getOutputStream();
+    }
+
+    /**
+     * Returns the standard output of this process.
+     *
+     * @return The standard output of this process.
+     */
+
+    public InputStream getInputStream() {
+	return process.getInputStream();
+    }
+
+    /**
+     * Returns the standard error of this process.
+     *
+     * @return The standard error of this process.
+     */
+
+    public InputStream getErrorStream() {
+	return process.getErrorStream();
+    }
+
+    /**
+     * Begin redirecting the streams passed. This method should be invoked
+     * immediately after execution of a simple process to prevent thread
+     * deadlock.
+     *
+     * @return The exit status of the target process.
+     */
+
+    public int waitFor() throws InterruptedException {
+	int retval = waitForImpl();
+	if ( in != null ) {
+	    in.stop();
+	}
+	return retval;
+    }
+
+    /**
+     * Contains the implementation of wait for.
+     *
+     * @return The exit status of the target process.
+     */
+
+    private int waitForImpl() throws InterruptedException {
+	process = process;
+	in = new StreamPrinter( processInput,
+				new PrintStream( process.getOutputStream() ) );
+	in.setFlush( true );
+	out = new StreamPrinter( process.getInputStream(), yourOutput );
+	error = new StreamPrinter( process.getErrorStream(), yourError );
+	in.start();
+	out.start();
+	error.start();
+	out.join();
+	error.join();
+	return process.waitFor();
+    }
+
+    /**
+     * Returns the target processes' exit value.
+     *
+     * @return This processes' exit value.
+     */
+
+    public int exitValue() {
+	return process.exitValue();
+    }
+
+    /**
+     * Destroys the target process.
+     */
+
+    public void destroy() throws IllegalThreadStateException {
+	process.destroy();
+    }
+} /** SimpleProcess **/
diff --git a/src/java/gnu/dtools/ritopt/Stoppable.java b/src/java/gnu/dtools/ritopt/Stoppable.java
new file mode 100644
index 0000000..89ba9ea
--- /dev/null
+++ b/src/java/gnu/dtools/ritopt/Stoppable.java
@@ -0,0 +1,46 @@
+package gnu.dtools.ritopt;
+
+/**
+ * Implementors are capable of being stopped. This interface is used
+ * by the StreamPrinters in the SimpleProcess class so that it if an
+ * error has occurred.
+ *
+ * <hr>
+ *
+ * <pre>
+ * Copyright (C) Damian Ryan Eads, 2001. All Rights Reserved.
+ *
+ * ritopt 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.
+
+ * ritopt is distributed in the hope that 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 ritopt; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * </pre>
+ *
+ * @author Damian Eads
+ */
+
+public interface Stoppable {
+
+    /**
+     * Stop the implemetor from performing some sort of processing.
+     */
+
+    public void stop();
+
+    /**
+     * Returns whether the implementor has stopped.
+     *
+     * @return A boolean value.
+     */
+
+    public boolean isStopped();
+}
diff --git a/src/java/gnu/dtools/ritopt/StreamPrinter.java b/src/java/gnu/dtools/ritopt/StreamPrinter.java
new file mode 100644
index 0000000..d54fcb9
--- /dev/null
+++ b/src/java/gnu/dtools/ritopt/StreamPrinter.java
@@ -0,0 +1,191 @@
+package gnu.dtools.ritopt;
+
+/**
+ * StreamPrinter.java
+ *
+ * Version:
+ *   $Id: StreamPrinter.java,v 1.1 2004/05/20 20:45:47 mortenalver Exp $
+ */
+
+import java.io.*;
+
+/**
+ * Reads data from an input stream and outputs to a print stream. This class
+ * is used by the OptionMenu class to read from both standard output and
+ * standard error simultaneously when a shell command is executed. Since the
+ * StreamPrinter processes streams on a separate thread, deadlock is
+ * prevented.<p>
+ *
+ * <hr>
+ *
+ * <pre>
+ * Copyright (C) Damian Ryan Eads, 2001. All Rights Reserved.
+ *
+ * ritopt 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.
+
+ * ritopt is distributed in the hope that 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 ritopt; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * </pre>
+ *
+ * @author Damian Eads
+ */
+
+public class StreamPrinter implements Runnable, Stoppable {
+
+    /**
+     * The input stream to read from.
+     */
+
+    private InputStream stream;
+
+    /**
+     * The print stream to redirect to.
+     */
+
+    private PrintStream out;
+
+    /**
+     * The object to stop.
+     */
+
+    private Stoppable stop;
+
+    /**
+     * Whether this StreamPrinter has stopped processing.
+     */
+
+    private boolean stopped;
+
+    /**
+     * Whether the buffer should be flushed.
+     */
+
+    private boolean flush;
+
+    /**
+     * The thread associated with this StreamPrinter.
+     */
+
+    private Thread thread;
+
+    /**
+     * Constructs a new StreamPrinter.
+     *
+     * @param s The stream to read from.
+     * @param p The stream to output to.
+     */
+
+    public StreamPrinter( InputStream s, PrintStream p ) {
+	stream = s;
+	out = p;
+	thread = new Thread( this );
+    }
+
+    /**
+     * Starts the thread associated with this StreamPrinter.
+     */
+
+    public void start() throws InterruptedException {
+	thread.start();
+    }
+
+    /**
+     * Sets the object to stop when this object is finished.
+     *
+     * @param tostop The object to stop.
+     */
+
+    public void setStop( Stoppable tostop ) {
+	synchronized( this ) {
+	    stop = tostop;
+	}
+    }
+
+    /**
+     * Returns whether this StreamPrinter has stopped processing.
+     *
+     * @returns A boolean value.
+     */
+
+    public boolean isStopped() {
+	return stopped;
+    }
+
+    /**
+     * Sets whether the output stream should be flushed after each output
+     * step.
+     *
+     * @param b A boolean value.
+     */
+
+    public void setFlush( boolean flush ) {
+	synchronized ( this ) {
+	    this.flush = flush;
+	}
+    }
+
+    /**
+     * Stops this StreamPrinter's processing. 
+     */
+
+    public void stop() {
+	synchronized( this ) {
+	    stopped = true;
+	}
+	if ( stop != null ) {
+	    synchronized( stop ) {
+		if ( !stop.isStopped() ) {
+		    stop.stop();
+		}
+	    }
+	}
+    }
+
+    /**
+     * Joins this StreamPrinter's thread with the other threads.
+     */
+
+    public void join() throws InterruptedException {
+	thread.join();
+    }
+
+    /**
+     * Start the StreamPrinter thread. This is done automatically during
+     * construction.
+     */
+
+    // This implementation is lousy; buffering is needed.
+    public void run() {
+	int buf;
+	try {
+	    boolean me;
+	    while ( !stopped && ( buf = stream.read() ) != -1 ) {
+		synchronized( this ) {
+		    me = flush;
+		}
+		synchronized( out ) {
+		    out.print( (char)buf );
+		    if ( me ) out.flush();
+		}
+	    }
+	}
+	catch ( IOException e ) {
+	    out.println( "I/O error" );
+	}
+	finally {
+	    synchronized( out ) {
+		out.flush();
+	    }
+	    stop();
+	}
+    }
+}
diff --git a/src/java/gnu/dtools/ritopt/StringOption.java b/src/java/gnu/dtools/ritopt/StringOption.java
new file mode 100644
index 0000000..12d3454
--- /dev/null
+++ b/src/java/gnu/dtools/ritopt/StringOption.java
@@ -0,0 +1,184 @@
+package gnu.dtools.ritopt;
+
+/**
+ * StringOption.java
+ *
+ * Version:
+ *    $Id: StringOption.java,v 1.2 2005/11/08 04:53:27 mortenalver Exp $
+ */
+
+/**
+ * This class is used for options with String values. 
+ *
+ * <pre>
+ * Copyright (C) Damian Ryan Eads, 2001. All Rights Reserved.
+ *
+ * ritopt 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.
+
+ * ritopt is distributed in the hope that 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 ritopt; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * </pre>
+ *
+ * @author Damian Eads
+ */
+
+public class StringOption extends Option {
+
+    /**
+     * The value of this string option.
+     */
+
+    private String value = "";
+
+    /**
+     * Constructs a string option that is initially set to zero.
+     */
+
+    public StringOption() {
+	this( "" );
+    }
+
+    /**
+     * Constructs a string option by copying the string option passed.
+     *
+     * @param op     The character option to copy.
+     */
+
+    public StringOption( StringOption op ) {
+	super( op );
+	op.value = op.getValue();
+    }
+
+    /**
+     * Constructs a string option initialized with the value passed.
+     *
+     * @param value    The initial value of this string option.
+     */
+
+    public StringOption( String value ) {
+	this( value, null );
+    }
+
+    /**
+     * Constructs a string option initialized with the value and
+     * long option passed.
+     *
+     * @param value      The initial value of this string option.
+     * @param longOption The long option associated with string option.
+     */
+
+    public StringOption( String value, String longOption ) {
+	this( value, longOption, '\0' );
+    }
+
+    /**
+     * Constructs a character option initialized with the value and
+     * short option passed.
+     *
+     * @param value       The initial value of this string option.
+     * @param shortOption The short option associated with this option.
+     */
+
+    public StringOption( String value, char shortOption ) {
+	this( value, null, shortOption );
+    }
+
+    /**
+     * Constructs a string option initialized with the value, short
+     * and long option passed.
+     *
+     * @param shortOption The short option associated with this option.
+     * @param longOption  The long option associated with this option.
+     * @param value       The initial value of this string option.
+     */
+
+    public StringOption( String value, String longOption, char shortOption ) {
+	super( longOption, shortOption );
+	this.value = value;
+    }
+
+    /**
+     * Return the value as an object.
+     *
+     * @return This value as an option.
+     */
+
+    public Object getObject() {
+	return value;
+    }
+
+    /**
+     * Modify this option based on a string representation.
+     *
+     * @param     value String representation of the object.
+     * @exception OptionModificationException Thrown if an error occurs
+     *                                  during modification of an option.
+     */
+
+    public void modify( String value ) throws OptionModificationException {
+	this.value = value;
+    }
+
+    /**
+     * Modify this option based on a string representation.
+     *
+     * @param     value String representation of the object.
+     * @exception OptionModificationException Thrown if an error occurs
+     *                                  during modification of an option.
+     */
+
+    public void setValue( String value ) throws OptionModificationException {
+	modify( value );
+    }
+
+    /**
+     * Modify this option using a string value.
+     *
+     * @param     value A string value.
+     */
+
+    public String getValue() {
+	return value;
+    }
+
+    /**
+     * Return this option as a string.
+     *
+     * @return This option as a string.
+     */
+
+    public String getStringValue() {
+	return value;
+    }
+
+    /**
+     * Returns the type name of this option. For an StringOption, "STRING"
+     * is returned.
+     *
+     * @return The type name of this option.
+     */
+
+    public String getTypeName() {
+	return "STRING";
+    }
+
+    /**
+     * Returns a string representation of this object.
+     *
+     * @return A string representation of this object.
+     */
+
+    public String toString() {
+	return value;
+    }
+
+}
diff --git a/src/java/gnu/dtools/ritopt/Utility.java b/src/java/gnu/dtools/ritopt/Utility.java
new file mode 100644
index 0000000..2a81779
--- /dev/null
+++ b/src/java/gnu/dtools/ritopt/Utility.java
@@ -0,0 +1,339 @@
+package gnu.dtools.ritopt;
+
+/**
+ * Utility.java
+ *
+ * Version:
+ *    $Id: Utility.java,v 1.2 2005/11/08 04:53:27 mortenalver Exp $
+ */
+
+/**
+ * This class provides static utility members for some basic string operations.
+ *
+ * <hr>
+ *
+ * <pre>
+ * Copyright (C) Damian Ryan Eads, 2001. All Rights Reserved.
+ *
+ * ritopt 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.
+
+ * ritopt is distributed in the hope that 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 ritopt; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * </pre>
+ *
+ * @author Damian Eads
+ */
+
+public class Utility {
+
+    /**
+     * Returns true if any of the characters in the list appear in the
+     * check string passed.
+     *
+     * @param check The string to check.
+     * @param list  The list of valid characters.
+     *
+     * @return true if the criteria of this method is satisfied.
+     */
+
+    public static boolean contains( String check, String list ) {
+	for ( int n = 0; n < list.length(); n++ ) {
+	    if ( check.indexOf( list.substring( n, n + 1 ) ) != -1 )
+		return true;
+	}
+	return false;
+    }
+
+    /**
+     * Returns the number of occurances the character specification
+     * appears in the check string passed.
+     *
+     * @param check The string to check.
+     * @param spec  The character specification.
+     *
+     * @return the number of occurances of the character specification.
+     */
+
+    public static int count( String check, char spec ) {
+        int sum = 0;
+	for ( int n = 0; n < check.length(); n++ ) {
+	    if ( check.charAt( 0 ) == spec ) sum++;
+	}
+	return sum;
+    }
+
+    /**
+     * Returns true if any of the characters in the list are equal to
+     * the check character.
+     *
+     * @param check The character to check.
+     * @param list  The list of valid characters.
+     *
+     * @return true if any of the characters in the list equal the check
+     *              character. 
+     */
+
+    public static boolean contains( char check, String list ) {
+	return contains( "" + check, list );
+    }
+
+    /**
+     * Returns true if the string only contains letters in the phonetic
+     * alphabet.
+     *
+     * @param check The string to check.
+     *
+     * @return If this method's criteria is matched.
+     */
+
+    public static boolean isAlpha( String check ) {
+	boolean retval = false;
+	for ( int n = 0; n < check.length(); n++ ) {
+	    retval = isAlphaLower( check.charAt( n ) ) ||
+		isAlphaUpper( check.charAt( n ) );
+	}
+	return retval;
+    }
+
+    /**
+     * Returns true if the string only contains lower case letters in the
+     * phonetic alphabet.
+     *
+     * @param check The string to check.
+     *
+     * @return If this method's criteria is matched.
+     */
+
+    public static boolean isAlphaLower( String check ) {
+	boolean retval = false;
+	for ( int n = 0; n < check.length(); n++ ) {
+	    retval = isAlphaLower( check.charAt( n ) );
+	}
+	return retval;
+    }
+
+    /**
+     * Returns true if the string only contains upper case letters in the
+     * phonetic alphabet.
+     *
+     * @param check The string to check.
+     *
+     * @return If this method's criteria is matched.
+     */
+
+    public static boolean isAlphaUpper( String check ) {
+	boolean retval = false;
+	for ( int n = 0; n < check.length(); n++ ) {
+	    retval = isAlphaUpper( check.charAt( n ) );
+	}
+	return retval;
+    }
+
+    /**
+     * Returns true if the character is a letter in the phonetic alphabetic.
+     *
+     * @param check The character to check.
+     *
+     * @return true if this method's criteria is matched.
+     */
+
+    public static boolean isAlpha( char check ) {
+	return isAlphaLower( check ) || isAlphaUpper( check );
+    }
+
+    /**
+     * Returns true if the character is a lower case letter in the
+     * phonetic alphabetic.
+     *
+     * @param check The character to check.
+     *
+     * @return true if this method's criteria is matched.
+     */
+
+    public static boolean isAlphaLower( char check ) {
+	return check >= 'a' && check <= 'z';
+    }
+
+    /**
+     * Returns true if the character is a upper case letter in the
+     * phonetic alphabetic.
+     *
+     * @param check The character to check.
+     *
+     * @return true if this method's criteria is matched.
+     */
+
+    public static boolean isAlphaUpper( char check ) {
+	return check >= 'A' && check <= 'Z';
+    }
+
+    /**
+     * Returns true if the character is a letter in the phonetic alphabetic
+     * or is a decimal number.
+     *
+     * @param check The character to check.
+     *
+     * @return true if this method's criteria is matched.
+     */
+
+    public static boolean isAlphaNumeric( char check ) {
+	return isAlpha( check ) || isNumeric( check );
+    }
+
+    /**
+     * Returns true if the character is a decimal number.
+     *
+     * @param check The character to check.
+     *
+     * @return true if this method's criteria is matched.
+     */
+
+    public static boolean isNumeric( char check ) {
+	return check >= '0' && check <= '9'; 
+    }
+
+    /**
+     * Returns a string with no more and no less than <em>n</em> characters
+     * where n is the length. If the string passed is less than this length,
+     * an appropriate number of spaces is concatenated. If the string is
+     * longer than the length passed, a substring of the length passed
+     * is returned.
+     *
+     * @param s       The string to expand.
+     * @param length  The required length.
+     *
+     * @return The expanded string.
+     */
+
+    public static String expandString( String s, int length ) {
+	if ( s.length() > length ) s = s.substring( 0, length );
+	return s + getSpaces( length - s.length() );
+    }
+
+    /**
+     * Returns a string containing the number of spaces passed as an
+     * argument.
+     *
+     * @param count The number of spaces in the string returned.
+     *
+     * @return a string containing the number of spaces passed.
+     */
+
+    public static String getSpaces( int count ) {
+	return repeat( ' ', count );
+    }
+
+    /**
+     * Returns a string with a character repeated based on a count passed.
+     *
+     * @param c     The character to repeat.
+     * @param count The number of times to repeat the character.
+     */
+
+    public static String repeat( char c, int count ) {
+	StringBuffer retval = new StringBuffer( count );
+	for ( int n = 0; n < count; n++ ) {
+	    retval.append( c );
+	}
+	return retval.toString();
+    }
+
+    /**
+     * Trim spaces off the left side of this string.
+     *
+     * @param s The string to trim.
+     *
+     * @return  The trimmed string.
+     */
+
+    public static String ltrim( String s ) {
+	StringBuffer buf = new StringBuffer( s );
+	for ( int n = 0; n < buf.length() && buf.charAt( n ) == ' '; ) {
+	    buf.delete( 0, 1 );
+	}
+	return buf.toString();
+    }
+
+    /**
+     * Trim spaces off the right side of this string.
+     *
+     * @param s The string to trim.
+     *
+     * @return  The trimmed string.
+     */
+
+    public static String rtrim( String s ) {
+	StringBuffer buf = new StringBuffer( s );
+	for ( int k = buf.length() - 1; k >= 0 && buf.charAt( k ) == ' ';
+	      k = buf.length() - 1 ) {
+	    buf.delete( buf.length() - 1, buf.length() );
+	}
+	return buf.toString();
+    }
+
+    /**
+     * Trim spaces off both sides of this string.
+     *
+     * @param s The string to trim.
+     *
+     * @return  The trimmed string.
+     */
+
+    public static String trim( String s ) {
+	return ltrim( rtrim( s ) );
+    }
+
+    /**
+     * Takes a line (presumably from a file) and removes a comment if
+     * one exists. If the comment character is enclosed within a literal
+     * string defined by the delimiter passed, then the character is
+     * ignored.
+     *
+     * @param s         The string to strip comments off.
+     * @param delim     The string delimiter.
+     * @param comment   The comment character.
+     *
+     * @return A string stripped of comments.
+     */
+
+    public static String stripComments( String s, char delim, char comment ) {
+	String retval = s;
+	boolean q = false;
+	for ( int n = 0; n < s.length(); n++ ) {
+	    if ( s.charAt( n ) == delim ) {
+		q = !q;
+	    }
+	    else if ( !q && s.charAt( n ) == comment ) {
+		retval = s.substring( 0, n );
+	    }
+	}
+	return retval;
+    }
+
+    /**
+     * Returns a string with the passed string repeated based on the 
+     * integer count passed.
+     *
+     * @param s     The string to repeat.
+     * @param count The number of times to repeat the string.
+     *
+     * @return      The repeated string.
+     */
+
+    public static String repeat( String s, int count ) {
+	StringBuffer retval = new StringBuffer( s.length() * count );
+	for ( int n = 0; n < count; n++ ) {
+	    retval.append( s );
+	}
+	return retval.toString();
+    }
+}
diff --git a/src/java/jalopy.format.convention.xml b/src/java/jalopy.format.convention.xml
new file mode 100755
index 0000000..d0802e9
--- /dev/null
+++ b/src/java/jalopy.format.convention.xml
@@ -0,0 +1,406 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<jalopy>
+    <general>
+        <compliance>
+            <version>1</version>
+        </compliance>
+        <style>
+            <description>Jalopy convention definitions for the JabRef project</description>
+            <name>JabRef convention</name>
+        </style>
+    </general>
+    <inspector>
+        <enable>false</enable>
+        <naming>
+            <classes>
+                <abstract>[A-Z][a-zA-Z0-9]+</abstract>
+                <general>[A-Z][a-zA-Z0-9]+</general>
+            </classes>
+            <fields>
+                <default>[a-z][\w]+</default>
+                <defaultStatic>[a-z][\w]+</defaultStatic>
+                <defaultStaticFinal>[a-zA-Z][\w]+</defaultStaticFinal>
+                <private>[a-z][\w]+</private>
+                <privateStatic>[a-z][\w]+</privateStatic>
+                <privateStaticFinal>[a-zA-Z][\w]+</privateStaticFinal>
+                <protected>[a-z][\w]+</protected>
+                <protectedStatic>[a-z][\w]+</protectedStatic>
+                <protectedStaticFinal>[a-zA-Z][\w]+</protectedStaticFinal>
+                <public>[a-z][\w]+</public>
+                <publicStatic>[a-z][\w]+</publicStatic>
+                <publicStaticFinal>[a-zA-Z][\w]+</publicStaticFinal>
+            </fields>
+            <interfaces>[A-Z][a-zA-Z0-9]+</interfaces>
+            <labels>\w+</labels>
+            <methods>
+                <default>[a-z][\w]+</default>
+                <defaultStatic>[a-z][\w]+</defaultStatic>
+                <defaultStaticFinal>[a-z][\w]+</defaultStaticFinal>
+                <private>[a-z][\w]+</private>
+                <privateStatic>[a-z][\w]+</privateStatic>
+                <privateStaticFinal>[a-z][\w]+</privateStaticFinal>
+                <protected>[a-z][\w]+</protected>
+                <protectedStatic>[a-z][\w]+</protectedStatic>
+                <protectedStaticFinal>[a-z][\w]+</protectedStaticFinal>
+                <public>[a-z][\w]+</public>
+                <publicStatic>[a-z][\w]+</publicStatic>
+                <publicStaticFinal>[a-z][\w]+</publicStaticFinal>
+            </methods>
+            <packages>[a-z]+(?:\.[a-z]+)*</packages>
+            <parameters>
+                <default>[a-z][\w]+</default>
+                <final>[a-z][\w]+</final>
+            </parameters>
+            <variables>[a-z][\w]*</variables>
+        </naming>
+        <tips>
+            <adhereToNamingConvention>false</adhereToNamingConvention>
+            <alwaysOverrideEquals>false</alwaysOverrideEquals>
+            <alwaysOverrideHashCode>false</alwaysOverrideHashCode>
+            <avoidThreadGroups>false</avoidThreadGroups>
+            <declareCollectionComment>false</declareCollectionComment>
+            <dontIgnoreExceptions>false</dontIgnoreExceptions>
+            <dontSubstituteObjectEquals>false</dontSubstituteObjectEquals>
+            <neverDeclareException>false</neverDeclareException>
+            <neverDeclareThrowable>false</neverDeclareThrowable>
+            <neverInvokeWaitOutsideLoop>false</neverInvokeWaitOutsideLoop>
+            <neverReturnZeroArrays>false</neverReturnZeroArrays>
+            <neverUseEmptyFinally>false</neverUseEmptyFinally>
+            <obeyContractEquals>false</obeyContractEquals>
+            <overrideToString>false</overrideToString>
+            <referToObjectsByInterface>false</referToObjectsByInterface>
+            <replaceStructureWithClass>false</replaceStructureWithClass>
+            <stringLiterallI18n>false</stringLiterallI18n>
+            <useInterfaceOnlyForTypes>false</useInterfaceOnlyForTypes>
+            <wrongCollectionComment>false</wrongCollectionComment>
+        </tips>
+    </inspector>
+    <internal>
+        <version>6</version>
+    </internal>
+    <messages>
+        <priority>
+            <general>30000</general>
+            <parser>30000</parser>
+            <parserJavadoc>30000</parserJavadoc>
+            <printer>30000</printer>
+            <printerJavadoc>30000</printerJavadoc>
+            <transform>30000</transform>
+        </priority>
+        <showErrorStackTrace>true</showErrorStackTrace>
+    </messages>
+    <misc>
+        <threadCount>1</threadCount>
+    </misc>
+    <printer>
+        <alignment>
+            <methodCallChain>true</methodCallChain>
+            <parameterMethodDeclaration>false</parameterMethodDeclaration>
+            <ternaryOperator>true</ternaryOperator>
+            <variableAssignment>false</variableAssignment>
+            <variableIdentifier>false</variableIdentifier>
+        </alignment>
+        <backup>
+            <directory>bak</directory>
+            <level>0</level>
+        </backup>
+        <blanklines>
+            <after>
+                <block>1</block>
+                <braceLeft>0</braceLeft>
+                <class>1</class>
+                <declaration>0</declaration>
+                <footer>1</footer>
+                <header>0</header>
+                <interface>1</interface>
+                <lastImport>2</lastImport>
+                <method>1</method>
+                <package>1</package>
+            </after>
+            <before>
+                <block>1</block>
+                <braceRight>0</braceRight>
+                <caseBlock>1</caseBlock>
+                <comment>
+                    <javadoc>1</javadoc>
+                    <multiline>1</multiline>
+                    <singleline>1</singleline>
+                </comment>
+                <controlStatement>1</controlStatement>
+                <declaration>1</declaration>
+                <footer>0</footer>
+                <header>0</header>
+            </before>
+            <keepUpTo>1</keepUpTo>
+        </blanklines>
+        <braces>
+            <empty>
+                <cuddle>false</cuddle>
+                <insertStatement>false</insertStatement>
+            </empty>
+            <insert>
+                <dowhile>true</dowhile>
+                <for>true</for>
+                <ifelse>true</ifelse>
+                <while>true</while>
+            </insert>
+            <remove>
+                <block>true</block>
+                <dowhile>false</dowhile>
+                <for>false</for>
+                <ifelse>false</ifelse>
+                <while>false</while>
+            </remove>
+            <treatDifferent>
+                <methodClass>false</methodClass>
+                <methodClassIfWrapped>false</methodClassIfWrapped>
+            </treatDifferent>
+        </braces>
+        <chunks>
+            <blanklines>true</blanklines>
+            <comments>true</comments>
+        </chunks>
+        <comments>
+            <format>
+                <multiline>false</multiline>
+            </format>
+            <javadoc>
+                <check>
+                    <innerclass>false</innerclass>
+                    <tags>false</tags>
+                    <throwsTags>false</throwsTags>
+                </check>
+                <fieldsShort>true</fieldsShort>
+                <generate>
+                    <class>1</class>
+                    <constructor>0</constructor>
+                    <field>0</field>
+                    <method>0</method>
+                </generate>
+                <parseComments>false</parseComments>
+                <tags>
+                    <in-line />
+                    <standard />
+                </tags>
+                <templates>
+                    <method>
+                        <bottom> */</bottom>
+                        <exception> * @throws $exceptionType$ DOCUMENT ME!</exception>
+                        <param> * @param $paramType$ DOCUMENT ME!</param>
+                        <return> * @return DOCUMENT ME!</return>
+                        <top>/**| * DOCUMENT ME!</top>
+                    </method>
+                </templates>
+            </javadoc>
+            <remove>
+                <javadoc>false</javadoc>
+                <multiline>false</multiline>
+                <singleline>false</singleline>
+            </remove>
+            <separator>
+                <fillCharacter>/</fillCharacter>
+                <insert>true</insert>
+                <insertRecursive>false</insertRecursive>
+                <text>
+                    <class>Inner Classes</class>
+                    <constructor>Constructors</constructor>
+                    <field>Instance fields</field>
+                    <initializer>Instance initializers</initializer>
+                    <interface>Inner Interfaces</interface>
+                    <method>Methods</method>
+                    <static>Static fields/initializers</static>
+                </text>
+            </separator>
+        </comments>
+        <environment />
+        <footer>
+            <keys />
+            <smartMode>5</smartMode>
+            <text>///////////////////////////////////////////////////////////////////////////////
+//  END OF FILE.
+///////////////////////////////////////////////////////////////////////////////</text>
+            <use>true</use>
+        </footer>
+
+        <!-- header should not used, because there are some LGPL sources and other authors -->
+        <header>
+            <keys>JOELib header</keys>
+            <smartMode>5</smartMode>
+			<text>///////////////////////////////////////////////////////////////////////////////
+//  Filename: $RCSfile: jalopy.format.convention.xml,v $
+//  Language: Java
+//  Compiler: JDK 1.4
+//  Version:  $Revision: 1.1 $
+//            $Date: 2004/01/28 22:41:11 $
+//            $Author: wegner $
+//
+//  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.
+///////////////////////////////////////////////////////////////////////////////</text>
+            <use>false</use>
+        </header>
+        <history>
+            <policy>disabled</policy>
+        </history>
+        <imports>
+            <grouping>
+                <defaultDepth>3</defaultDepth>
+                <packages>*:0|gnu:2|java:2|javax:2|org:2|com:2|net:2</packages>
+            </grouping>
+            <policy>disabled</policy>
+            <sort>true</sort>
+        </imports>
+
+        <indentation>
+            <caseFromSwitch>false</caseFromSwitch>
+            <continuation>
+                <block>true</block>
+                <operator>false</operator>
+            </continuation>
+            <firstColumnComments>true</firstColumnComments>
+            <label>false</label>
+            <policy>
+                <deep>false</deep>
+            </policy>
+            <sizes>
+                <braceCuddled>1</braceCuddled>
+                <braceLeft>0</braceLeft>
+                <braceRight>0</braceRight>
+                <braceRightAfter>1</braceRightAfter>
+                <continuation>4</continuation>
+                <deep>55</deep>
+                <extends>-1</extends>
+                <general>4</general>
+                <implements>-1</implements>
+                <leading>0</leading>
+                <tabs>8</tabs>
+                <throws>-1</throws>
+                <trailingComment>1</trailingComment>
+            </sizes>
+            <tabs>
+                <enable>false</enable>
+                <onlyLeading>false</onlyLeading>
+            </tabs>
+        </indentation>
+        <misc>
+            <arrayBracketsAfterIdent>false</arrayBracketsAfterIdent>
+            <forceFormatting>false</forceFormatting>
+            <insertExpressionParentheses>true</insertExpressionParentheses>
+            <insertLoggingConditional>true</insertLoggingConditional>
+            <insertTrailingNewline>true</insertTrailingNewline>
+            <insertUID>false</insertUID>
+        </misc>
+        <sorting>
+            <declaration>
+                <class>true</class>
+                <constructor>true</constructor>
+                <enable>true</enable>
+                <interface>true</interface>
+                <method>true</method>
+                <order>static|field|initializer|constructor|method|interface|class</order>
+                <variable>true</variable>
+            </declaration>
+            <modifier>
+                <enable>false</enable>
+                <order>public|protected|private|abstract|static|final|synchronized|transient|volatile|native|strictfp</order>
+            </modifier>
+        </sorting>
+
+        <whitespace>
+            <after>
+                <comma>true</comma>
+                <semicolon>true</semicolon>
+                <typeCast>true</typeCast>
+            </after>
+            <before>
+                <braces>false</braces>
+                <brackets>false</brackets>
+                <bracketsTypes>false</bracketsTypes>
+                <caseColon>false</caseColon>
+                <operator>
+                    <not>false</not>
+                </operator>
+                <parentheses>
+                    <methodCall>false</methodCall>
+                    <methodDeclaration>false</methodDeclaration>
+                    <statement>true</statement>
+                </parentheses>
+            </before>
+            <padding>
+                <braces>false</braces>
+                <brackets>false</brackets>
+                <operator>
+                    <assignment>true</assignment>
+                    <bitwise>true</bitwise>
+                    <logical>true</logical>
+                    <mathematical>true</mathematical>
+                    <relational>true</relational>
+                    <shift>true</shift>
+                </operator>
+                <parenthesis>false</parenthesis>
+                <typeCast>false</typeCast>
+            </padding>
+        </whitespace>
+        <wrapping>
+            <always>
+                <after>
+                    <arrayElement>0</arrayElement>
+                    <braceRight>true</braceRight>
+                    <extendsTypes>false</extendsTypes>
+                    <implementsTypes>false</implementsTypes>
+                    <label>true</label>
+                    <methodCallChained>false</methodCallChained>
+                    <ternaryOperator>
+                        <first>false</first>
+                        <second>false</second>
+                    </ternaryOperator>
+                    <throwsTypes>false</throwsTypes>
+                </after>
+                <before>
+                    <braceLeft>true</braceLeft>
+                    <extends>false</extends>
+                    <implements>false</implements>
+                    <throws>false</throws>
+                </before>
+                <parameter>
+                    <methodCall>false</methodCall>
+                    <methodCallNested>false</methodCallNested>
+                    <methodDeclaration>false</methodDeclaration>
+                </parameter>
+            </always>
+            <general>
+                <beforeOperator>false</beforeOperator>
+                <enable>true</enable>
+                <lineLength>80</lineLength>
+            </general>
+            <ondemand>
+                <after>
+                    <assignment>false</assignment>
+                    <leftParenthesis>false</leftParenthesis>
+                    <parameter>false</parameter>
+                    <types>
+                        <extends>false</extends>
+                        <implements>false</implements>
+                        <throws>false</throws>
+                    </types>
+                </after>
+                <before>
+                    <rightParenthesis>false</rightParenthesis>
+                </before>
+                <groupingParentheses>false</groupingParentheses>
+            </ondemand>
+        </wrapping>
+    </printer>
+</jalopy>
+
+<!--+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+   END OF FILE
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-->
diff --git a/src/java/net/sf/ext/BrowserLauncher.java b/src/java/net/sf/ext/BrowserLauncher.java
new file mode 100644
index 0000000..650bb15
--- /dev/null
+++ b/src/java/net/sf/ext/BrowserLauncher.java
@@ -0,0 +1,596 @@
+package net.sf.ext;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+/**
+ * BrowserLauncher is a class that provides one static method, openURL, which opens the default
+ * web browser for the current user of the system to the given URL.  It may support other
+ * protocols depending on the system -- mailto, ftp, etc. -- but that has not been rigorously
+ * tested and is not guaranteed to work.
+ * <p>
+ * Yes, this is platform-specific code, and yes, it may rely on classes on certain platforms
+ * that are not part of the standard JDK.  What we're trying to do, though, is to take something
+ * that's frequently desirable but inherently platform-specific -- opening a default browser --
+ * and allow programmers (you, for example) to do so without worrying about dropping into native
+ * code or doing anything else similarly evil.
+ * <p>
+ * Anyway, this code is completely in Java and will run on all JDK 1.1-compliant systems without
+ * modification or a need for additional libraries.  All classes that are required on certain
+ * platforms to allow this to run are dynamically loaded at runtime via reflection and, if not
+ * found, will not cause this to do anything other than returning an error when opening the
+ * browser.
+ * <p>
+ * There are certain system requirements for this class, as it's running through Runtime.exec(),
+ * which is Java's way of making a native system call.  Currently, this requires that a Macintosh
+ * have a Finder which supports the GURL event, which is true for Mac OS 8.0 and 8.1 systems that
+ * have the Internet Scripting AppleScript dictionary installed in the Scripting Additions folder
+ * in the Extensions folder (which is installed by default as far as I know under Mac OS 8.0 and
+ * 8.1), and for all Mac OS 8.5 and later systems.  On Windows, it only runs under Win32 systems
+ * (Windows 95, 98, and NT 4.0, as well as later versions of all).  On other systems, this drops
+ * back from the inherently platform-sensitive concept of a default browser and simply attempts
+ * to launch Netscape via a shell command.
+ * <p>
+ * This code is Copyright 1999-2001 by Eric Albert (ejalbert at cs.stanford.edu) and may be
+ * redistributed or modified in any form without restrictions as long as the portion of this
+ * comment from this paragraph through the end of the comment is not removed.  The author
+ * requests that he be notified of any application, applet, or other binary that makes use of
+ * this code, but that's more out of curiosity than anything and is not required.  This software
+ * includes no warranty.  The author is not repsonsible for any loss of data or functionality
+ * or any adverse or unexpected effects of using this software.
+ * <p>
+ * Credits:
+ * <br>Steven Spencer, JavaWorld magazine (<a href="http://www.javaworld.com/javaworld/javatips/jw-javatip66.html">Java Tip 66</a>)
+ * <br>Thanks also to Ron B. Yeh, Eric Shapiro, Ben Engber, Paul Teitlebaum, Andrea Cantatore,
+ * Larry Barowski, Trevor Bedzek, Frank Miedrich, and Ron Rabakukk
+ *
+ * @author Eric Albert (<a href="mailto:ejalbert at cs.stanford.edu">ejalbert at cs.stanford.edu</a>)
+ * @version 1.4b1 (Released June 20, 2001)
+ */
+public class BrowserLauncher {
+
+    /**
+     * The Java virtual machine that we are running on.  Actually, in most cases we only care
+     * about the operating system, but some operating systems require us to switch on the VM. */
+    private static int jvm;
+
+    /** The browser for the system */
+    private static Object browser;
+
+    /**
+     * Caches whether any classes, methods, and fields that are not part of the JDK and need to
+     * be dynamically loaded at runtime loaded successfully.
+     * <p>
+     * Note that if this is <code>false</code>, <code>openURL()</code> will always return an
+     * IOException.
+     */
+    private static boolean loadedWithoutErrors;
+
+    /** The com.apple.mrj.MRJFileUtils class */
+    private static Class mrjFileUtilsClass;
+
+    /** The com.apple.mrj.MRJOSType class */
+    private static Class mrjOSTypeClass;
+
+    /** The com.apple.MacOS.AEDesc class */
+    private static Class aeDescClass;
+    
+    /** The <init>(int) method of com.apple.MacOS.AETarget */
+    private static Constructor aeTargetConstructor;
+    
+    /** The <init>(int, int, int) method of com.apple.MacOS.AppleEvent */
+    private static Constructor appleEventConstructor;
+    
+    /** The <init>(String) method of com.apple.MacOS.AEDesc */
+    private static Constructor aeDescConstructor;
+    
+    /** The findFolder method of com.apple.mrj.MRJFileUtils */
+    private static Method findFolder;
+
+    /** The getFileCreator method of com.apple.mrj.MRJFileUtils */
+    private static Method getFileCreator;
+    
+    /** The getFileType method of com.apple.mrj.MRJFileUtils */
+    private static Method getFileType;
+    
+    /** The openURL method of com.apple.mrj.MRJFileUtils */
+    private static Method openURL;
+    
+    /** The makeOSType method of com.apple.MacOS.OSUtils */
+    private static Method makeOSType;
+    
+    /** The putParameter method of com.apple.MacOS.AppleEvent */
+    private static Method putParameter;
+    
+    /** The sendNoReply method of com.apple.MacOS.AppleEvent */
+    private static Method sendNoReply;
+    
+    /** Actually an MRJOSType pointing to the System Folder on a Macintosh */
+    private static Object kSystemFolderType;
+
+    /** The keyDirectObject AppleEvent parameter type */
+    private static Integer keyDirectObject;
+
+    /** The kAutoGenerateReturnID AppleEvent code */
+    private static Integer kAutoGenerateReturnID;
+    
+    /** The kAnyTransactionID AppleEvent code */
+    private static Integer kAnyTransactionID;
+
+    /** The linkage object required for JDirect 3 on Mac OS X. */
+    private static Object linkage;
+    
+    /** The framework to reference on Mac OS X */
+    private static final String JDirect_MacOSX = "/System/Library/Frameworks/Carbon.framework/Frameworks/HIToolbox.framework/HIToolbox";
+
+    /** JVM constant for MRJ 2.0 */
+    private static final int MRJ_2_0 = 0;
+    
+    /** JVM constant for MRJ 2.1 or later */
+    private static final int MRJ_2_1 = 1;
+
+    /** JVM constant for Java on Mac OS X 10.0 (MRJ 3.0) */
+    private static final int MRJ_3_0 = 3;
+    
+    /** JVM constant for MRJ 3.1 */
+    private static final int MRJ_3_1 = 4;
+
+    /** JVM constant for any Windows NT JVM */
+    private static final int WINDOWS_NT = 5;
+    
+    /** JVM constant for any Windows 9x JVM */
+    private static final int WINDOWS_9x = 6;
+
+    /** JVM constant for any Linux JVM */
+    private static final int LINUX = 7;
+
+    /** JVM constant for any other platform */
+    private static final int OTHER = -1;
+
+    /**
+     * The file type of the Finder on a Macintosh.  Hardcoding "Finder" would keep non-U.S. English
+     * systems from working properly.
+     */
+    private static final String FINDER_TYPE = "FNDR";
+
+    /**
+     * The creator code of the Finder on a Macintosh, which is needed to send AppleEvents to the
+     * application.
+     */
+    private static final String FINDER_CREATOR = "MACS";
+
+    /** The name for the AppleEvent type corresponding to a GetURL event. */
+    private static final String GURL_EVENT = "GURL";
+
+    /**
+     * The first parameter that needs to be passed into Runtime.exec() to open the default web
+     * browser on Windows.
+     */
+    private static final String FIRST_WINDOWS_PARAMETER = "/c";
+    
+    /** The second parameter for Runtime.exec() on Windows. */
+    private static final String SECOND_WINDOWS_PARAMETER = "start";
+    
+    /**
+     * The third parameter for Runtime.exec() on Windows.  This is a "title"
+     * parameter that the command line expects.  Setting this parameter allows
+     * URLs containing spaces to work.
+     */
+    private static final String THIRD_WINDOWS_PARAMETER = "\"\"";
+    
+    /**
+     * The shell parameters for Netscape that opens a given URL in an already-open copy of Netscape
+     * on many command-line systems.
+     */
+    private static final String NETSCAPE_REMOTE_PARAMETER = "-remote";
+    private static final String NETSCAPE_OPEN_PARAMETER_START = "'openURL(";
+    private static final String NETSCAPE_OPEN_PARAMETER_END = ")'";
+    
+    /**
+     * The message from any exception thrown throughout the initialization process.
+     */
+    private static String errorMessage;
+
+    /**
+     * An initialization block that determines the operating system and loads the necessary
+     * runtime data.
+     */
+    static {
+        loadedWithoutErrors = true;
+        String osName = System.getProperty("os.name");
+        if (osName.startsWith("Mac OS")) {
+            String mrjVersion = System.getProperty("mrj.version");
+            String majorMRJVersion = mrjVersion.substring(0, 3);
+            try {
+                double version = Double.valueOf(majorMRJVersion).doubleValue();
+                if (version == 2) {
+                    jvm = MRJ_2_0;
+                } else if (version >= 2.1 && version < 3) {
+                    // Assume that all 2.x versions of MRJ work the same.  MRJ 2.1 actually
+                    // works via Runtime.exec() and 2.2 supports that but has an openURL() method
+                    // as well that we currently ignore.
+                    jvm = MRJ_2_1;
+                } else if (version == 3.0) {
+                    jvm = MRJ_3_0;
+                } else if (version >= 3.1) {
+                    // Assume that all 3.1 and later versions of MRJ work the same.
+                    jvm = MRJ_3_1;
+                } else {
+                    loadedWithoutErrors = false;
+                    errorMessage = "Unsupported MRJ version: " + version;
+                }
+            } catch (NumberFormatException nfe) {
+                loadedWithoutErrors = false;
+                errorMessage = "Invalid MRJ version: " + mrjVersion;
+            }
+        } else if (osName.startsWith("Windows")) {
+            if (osName.indexOf("9") != -1) {
+                jvm = WINDOWS_9x;
+            } else {
+                jvm = WINDOWS_NT;
+            }
+        } else if (osName.startsWith("Linux")) {
+          jvm = LINUX;
+        }else {
+            jvm = OTHER;
+        }
+        
+        if (loadedWithoutErrors) {  // if we haven't hit any errors yet
+            loadedWithoutErrors = loadClasses();
+        }
+    }
+
+    /**
+     * This class should be never be instantiated; this just ensures so.
+     */
+    private BrowserLauncher() { }
+    
+    /**
+     * Called by a static initializer to load any classes, fields, and methods required at runtime
+     * to locate the user's web browser.
+     * @return <code>true</code> if all intialization succeeded
+     *          <code>false</code> if any portion of the initialization failed
+     */
+    private static boolean loadClasses() {
+        switch (jvm) {
+            case MRJ_2_0:
+                try {
+                    Class aeTargetClass = Class.forName("com.apple.MacOS.AETarget");
+                    Class osUtilsClass = Class.forName("com.apple.MacOS.OSUtils");
+                    Class appleEventClass = Class.forName("com.apple.MacOS.AppleEvent");
+                    Class aeClass = Class.forName("com.apple.MacOS.ae");
+                    aeDescClass = Class.forName("com.apple.MacOS.AEDesc");
+
+                    aeTargetConstructor = aeTargetClass.getDeclaredConstructor(new Class [] { int.class });
+                    appleEventConstructor = appleEventClass.getDeclaredConstructor(new Class[] { int.class, int.class, aeTargetClass, int.class, int.class });
+                    aeDescConstructor = aeDescClass.getDeclaredConstructor(new Class[] { String.class });
+
+                    makeOSType = osUtilsClass.getDeclaredMethod("makeOSType", new Class [] { String.class });
+                    putParameter = appleEventClass.getDeclaredMethod("putParameter", new Class[] { int.class, aeDescClass });
+                    sendNoReply = appleEventClass.getDeclaredMethod("sendNoReply", new Class[] { });
+
+                    Field keyDirectObjectField = aeClass.getDeclaredField("keyDirectObject");
+                    keyDirectObject = (Integer) keyDirectObjectField.get(null);
+                    Field autoGenerateReturnIDField = appleEventClass.getDeclaredField("kAutoGenerateReturnID");
+                    kAutoGenerateReturnID = (Integer) autoGenerateReturnIDField.get(null);
+                    Field anyTransactionIDField = appleEventClass.getDeclaredField("kAnyTransactionID");
+                    kAnyTransactionID = (Integer) anyTransactionIDField.get(null);
+                } catch (ClassNotFoundException cnfe) {
+                    errorMessage = cnfe.getMessage();
+                    return false;
+                } catch (NoSuchMethodException nsme) {
+                    errorMessage = nsme.getMessage();
+                    return false;
+                } catch (NoSuchFieldException nsfe) {
+                    errorMessage = nsfe.getMessage();
+                    return false;
+                } catch (IllegalAccessException iae) {
+                    errorMessage = iae.getMessage();
+                    return false;
+                }
+                break;
+            case MRJ_2_1:
+                try {
+                    mrjFileUtilsClass = Class.forName("com.apple.mrj.MRJFileUtils");
+                    mrjOSTypeClass = Class.forName("com.apple.mrj.MRJOSType");
+                    Field systemFolderField = mrjFileUtilsClass.getDeclaredField("kSystemFolderType");
+                    kSystemFolderType = systemFolderField.get(null);
+                    findFolder = mrjFileUtilsClass.getDeclaredMethod("findFolder", new Class[] { mrjOSTypeClass });
+                    getFileCreator = mrjFileUtilsClass.getDeclaredMethod("getFileCreator", new Class[] { File.class });
+                    getFileType = mrjFileUtilsClass.getDeclaredMethod("getFileType", new Class[] { File.class });
+                } catch (ClassNotFoundException cnfe) {
+                    errorMessage = cnfe.getMessage();
+                    return false;
+                } catch (NoSuchFieldException nsfe) {
+                    errorMessage = nsfe.getMessage();
+                    return false;
+                } catch (NoSuchMethodException nsme) {
+                    errorMessage = nsme.getMessage();
+                    return false;
+                } catch (SecurityException se) {
+                    errorMessage = se.getMessage();
+                    return false;
+                } catch (IllegalAccessException iae) {
+                    errorMessage = iae.getMessage();
+                    return false;
+                }
+                break;
+            case MRJ_3_0:
+                try {
+                    Class linker = Class.forName("com.apple.mrj.jdirect.Linker");
+                    Constructor constructor = linker.getConstructor(new Class[]{ Class.class });
+                    linkage = constructor.newInstance(new Object[] { BrowserLauncher.class });
+                } catch (ClassNotFoundException cnfe) {
+                    errorMessage = cnfe.getMessage();
+                    return false;
+                } catch (NoSuchMethodException nsme) {
+                    errorMessage = nsme.getMessage();
+                    return false;
+                } catch (InvocationTargetException ite) {
+                    errorMessage = ite.getMessage();
+                    return false;
+                } catch (InstantiationException ie) {
+                    errorMessage = ie.getMessage();
+                    return false;
+                } catch (IllegalAccessException iae) {
+                    errorMessage = iae.getMessage();
+                    return false;
+                }
+                break;
+            case MRJ_3_1:
+                try {
+                    mrjFileUtilsClass = Class.forName("com.apple.mrj.MRJFileUtils");
+                    openURL = mrjFileUtilsClass.getDeclaredMethod("openURL", new Class[] { String.class });
+                } catch (ClassNotFoundException cnfe) {
+                    errorMessage = cnfe.getMessage();
+                    return false;
+                } catch (NoSuchMethodException nsme) {
+                    errorMessage = nsme.getMessage();
+                    return false;
+                }
+                break;
+            default:
+                break;
+        }
+        return true;
+    }
+
+    /**
+     * Attempts to locate the default web browser on the local system.  Caches results so it
+     * only locates the browser once for each use of this class per JVM instance.
+     * @return The browser for the system.  Note that this may not be what you would consider
+     *          to be a standard web browser; instead, it's the application that gets called to
+     *          open the default web browser.  In some cases, this will be a non-String object
+     *          that provides the means of calling the default browser.
+     */
+    private static Object locateBrowser() {
+        if (browser != null) {
+            return browser;
+        }
+        switch (jvm) {
+            case MRJ_2_0:
+                try {
+                    Integer finderCreatorCode = (Integer) makeOSType.invoke(null, new Object[] { FINDER_CREATOR });
+                    Object aeTarget = aeTargetConstructor.newInstance(new Object[] { finderCreatorCode });
+                    Integer gurlType = (Integer) makeOSType.invoke(null, new Object[] { GURL_EVENT });
+                    Object appleEvent = appleEventConstructor.newInstance(new Object[] { gurlType, gurlType, aeTarget, kAutoGenerateReturnID, kAnyTransactionID });
+                    // Don't set browser = appleEvent because then the next time we call
+                    // locateBrowser(), we'll get the same AppleEvent, to which we'll already have
+                    // added the relevant parameter. Instead, regenerate the AppleEvent every time.
+                    // There's probably a way to do this better; if any has any ideas, please let
+                    // me know.
+                    return appleEvent;
+                } catch (IllegalAccessException iae) {
+                    browser = null;
+                    errorMessage = iae.getMessage();
+                    return browser;
+                } catch (InstantiationException ie) {
+                    browser = null;
+                    errorMessage = ie.getMessage();
+                    return browser;
+                } catch (InvocationTargetException ite) {
+                    browser = null;
+                    errorMessage = ite.getMessage();
+                    return browser;
+                }
+            case MRJ_2_1:
+                File systemFolder;
+                try {
+                    systemFolder = (File) findFolder.invoke(null, new Object[] { kSystemFolderType });
+                } catch (IllegalArgumentException iare) {
+                    browser = null;
+                    errorMessage = iare.getMessage();
+                    return browser;
+                } catch (IllegalAccessException iae) {
+                    browser = null;
+                    errorMessage = iae.getMessage();
+                    return browser;
+                } catch (InvocationTargetException ite) {
+                    browser = null;
+                    errorMessage = ite.getTargetException().getClass() + ": " + ite.getTargetException().getMessage();
+                    return browser;
+                }
+                String[] systemFolderFiles = systemFolder.list();
+                // Avoid a FilenameFilter because that can't be stopped mid-list
+                for(int i = 0; i < systemFolderFiles.length; i++) {
+                    try {
+                        File file = new File(systemFolder, systemFolderFiles[i]);
+                        if (!file.isFile()) {
+                            continue;
+                        }
+                        // We're looking for a file with a creator code of 'MACS' and
+                        // a type of 'FNDR'.  Only requiring the type results in non-Finder
+                        // applications being picked up on certain Mac OS 9 systems,
+                        // especially German ones, and sending a GURL event to those
+                        // applications results in a logout under Multiple Users.
+                        Object fileType = getFileType.invoke(null, new Object[] { file });
+                        if (FINDER_TYPE.equals(fileType.toString())) {
+                            Object fileCreator = getFileCreator.invoke(null, new Object[] { file });
+                            if (FINDER_CREATOR.equals(fileCreator.toString())) {
+                                browser = file.toString();  // Actually the Finder, but that's OK
+                                return browser;
+                            }
+                        }
+                    } catch (IllegalArgumentException iare) {
+                        browser = browser;
+                        errorMessage = iare.getMessage();
+                        return null;
+                    } catch (IllegalAccessException iae) {
+                        browser = null;
+                        errorMessage = iae.getMessage();
+                        return browser;
+                    } catch (InvocationTargetException ite) {
+                        browser = null;
+                        errorMessage = ite.getTargetException().getClass() + ": " + ite.getTargetException().getMessage();
+                        return browser;
+                    }
+                }
+                browser = null;
+                break;
+            case MRJ_3_0:
+            case MRJ_3_1:
+                browser = "";   // Return something non-null
+                break;
+            case WINDOWS_NT:
+                browser = "cmd.exe";
+                break;
+            case WINDOWS_9x:
+                browser = "command.com";
+                break;
+            case LINUX:
+		if ((new File("/usr/bin/mozilla")).exists())
+		    browser = "mozilla";
+		else if ((new File("/usr/bin/firefox")).exists())
+		    browser = "firefox";
+		else
+		    browser = "mozilla";
+                break;
+            case OTHER:
+            default:
+                browser = "netscape";
+                break;
+        }
+        return browser;
+    }
+
+    /**
+     * Attempts to open the default web browser to the given URL.
+     * @param url The URL to open
+     * @throws IOException If the web browser could not be located or does not run
+     */
+    public static void openURL(String url) throws IOException {
+        if (!loadedWithoutErrors) {
+            throw new IOException("Exception in finding browser: " + errorMessage);
+        }
+        Object browser = locateBrowser();
+        if (browser == null) {
+            throw new IOException("Unable to locate browser: " + errorMessage);
+        }
+        
+        switch (jvm) {
+            case MRJ_2_0:
+                Object aeDesc = null;
+                try {
+                    aeDesc = aeDescConstructor.newInstance(new Object[] { url });
+                    putParameter.invoke(browser, new Object[] { keyDirectObject, aeDesc });
+                    sendNoReply.invoke(browser, new Object[] { });
+                } catch (InvocationTargetException ite) {
+                    throw new IOException("InvocationTargetException while creating AEDesc: " + ite.getMessage());
+                } catch (IllegalAccessException iae) {
+                    throw new IOException("IllegalAccessException while building AppleEvent: " + iae.getMessage());
+                } catch (InstantiationException ie) {
+                    throw new IOException("InstantiationException while creating AEDesc: " + ie.getMessage());
+                } finally {
+                    aeDesc = null;  // Encourage it to get disposed if it was created
+                    browser = null; // Ditto
+                }
+                break;
+            case MRJ_2_1:
+                Runtime.getRuntime().exec(new String[] { (String) browser, url } );
+                break;
+            case MRJ_3_0:
+                int[] instance = new int[1];
+                int result = ICStart(instance, 0);
+                if (result == 0) {
+                    int[] selectionStart = new int[] { 0 };
+                    byte[] urlBytes = url.getBytes();
+                    int[] selectionEnd = new int[] { urlBytes.length };
+                    result = ICLaunchURL(instance[0], new byte[] { 0 }, urlBytes,
+                                            urlBytes.length, selectionStart,
+                                            selectionEnd);
+                    if (result == 0) {
+                        // Ignore the return value; the URL was launched successfully
+                        // regardless of what happens here.
+                        ICStop(instance);
+                    } else {
+                        throw new IOException("Unable to launch URL: " + result);
+                    }
+                } else {
+                    throw new IOException("Unable to create an Internet Config instance: " + result);
+                }
+                break;
+            case MRJ_3_1:
+                try {
+                    openURL.invoke(null, new Object[] { url });
+                } catch (InvocationTargetException ite) {
+                    throw new IOException("InvocationTargetException while calling openURL: " + ite.getMessage());
+                } catch (IllegalAccessException iae) {
+                    throw new IOException("IllegalAccessException while calling openURL: " + iae.getMessage());
+                }
+                break;
+            case WINDOWS_NT:
+            case WINDOWS_9x:
+                // Add quotes around the URL to allow ampersands and other special
+                // characters to work.
+                Process process = Runtime.getRuntime().exec(new String[] { (String) browser,
+                                                                FIRST_WINDOWS_PARAMETER,
+                                                                SECOND_WINDOWS_PARAMETER,
+                                                                THIRD_WINDOWS_PARAMETER,
+                                                                '"' + url + '"' });
+                // This avoids a memory leak on some versions of Java on Windows.
+                // That's hinted at in <http://developer.java.sun.com/developer/qow/archive/68/>.
+                try {
+                    process.waitFor();
+                    process.exitValue();
+                } catch (InterruptedException ie) {
+                    throw new IOException("InterruptedException while launching browser: " + ie.getMessage());
+                }
+                break;
+            case OTHER:
+                // Assume that we're on Unix and that Netscape is installed
+                
+                // First, attempt to open the URL in a currently running session of Netscape
+                process = Runtime.getRuntime().exec(new String[] { (String) browser,
+                                                    NETSCAPE_REMOTE_PARAMETER,
+                                                    NETSCAPE_OPEN_PARAMETER_START +
+                                                    url +
+                                                    NETSCAPE_OPEN_PARAMETER_END });
+                try {
+                    int exitCode = process.waitFor();
+                    if (exitCode != 0) {    // if Netscape was not open
+                        Runtime.getRuntime().exec(new String[] { (String) browser, url });
+                    }
+                } catch (InterruptedException ie) {
+                    throw new IOException("InterruptedException while launching browser: " + ie.getMessage());
+                }
+                break;
+            default:
+                // This should never occur, but if it does, we'll try the simplest thing possible
+                Runtime.getRuntime().exec(new String[] { (String) browser, url });
+                break;
+        }
+    }
+
+    /**
+     * Methods required for Mac OS X.  The presence of native methods does not cause
+     * any problems on other platforms.
+     */
+    private native static int ICStart(int[] instance, int signature);
+    private native static int ICStop(int[] instance);
+    private native static int ICLaunchURL(int instance, byte[] hint, byte[] data, int len,
+                                            int[] selectionStart, int[] selectionEnd);
+}
diff --git a/src/java/net/sf/jabref/AbstractWorker.java b/src/java/net/sf/jabref/AbstractWorker.java
new file mode 100644
index 0000000..38a51be
--- /dev/null
+++ b/src/java/net/sf/jabref/AbstractWorker.java
@@ -0,0 +1,51 @@
+package net.sf.jabref;
+
+import spin.Spin;
+
+/**
+ * Convenience class for creating an object used for performing a time-
+ * consuming action off the Swing thread, and optionally performing GUI
+ * work afterwards. This class is supported by runCommand() in BasePanel,
+ * which, if the action called is an AbstractWorker, will run its run()
+ * method through the Worker interface, and then its update() method through
+ * the CallBack interface. This procedure ensures that run() cannot freeze
+ * the GUI, and that update() can safely update GUI components.
+ */
+public abstract class AbstractWorker implements Worker, CallBack {
+
+    private Worker worker;
+    private CallBack callBack;
+
+    public AbstractWorker() {
+	worker = (Worker)Spin.off(this);
+	callBack = (CallBack)Spin.over(this);
+
+    }
+
+    public void init() throws Throwable {
+
+    }
+
+    /**
+     * This method returns a wrapped Worker instance of this AbstractWorker.
+     * whose methods will automatically be run off the EDT (Swing) thread.
+     */
+    public Worker getWorker() {
+	return worker;
+    }
+
+    /**
+     * This method returns a wrapped CallBack instance of this AbstractWorker
+     * whose methods will automatically be run on the EDT (Swing) thread.
+     */
+    public CallBack getCallBack() {
+	return callBack;
+    }
+
+    /**
+     * Empty implementation of the update() method. Override this method
+     * if a callback is needed.
+     */
+    public void update() {
+    }
+}
diff --git a/src/java/net/sf/jabref/AdvancedTab.java b/src/java/net/sf/jabref/AdvancedTab.java
new file mode 100644
index 0000000..b58afa0
--- /dev/null
+++ b/src/java/net/sf/jabref/AdvancedTab.java
@@ -0,0 +1,158 @@
+package net.sf.jabref;
+
+import javax.swing.*;
+import javax.swing.event.ChangeListener;
+import javax.swing.event.ChangeEvent;
+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.remote.RemoteListener;
+
+public class AdvancedTab extends JPanel implements PrefsTab {
+
+    JabRefPreferences _prefs;
+    JabRefFrame _frame;
+    HelpDialog helpDiag;
+    HelpAction remoteHelp;
+    JPanel pan = new JPanel(),
+        lnf = new JPanel();
+    JLabel lab;
+    JCheckBox useDefault, useRemoteServer;
+    JTextField className, remoteServerPort;
+    JButton def1 = new JButton(Globals.lang("Default")),
+        def2 = new JButton(Globals.lang("Default"));
+    JPanel p1 = new JPanel(),
+        p2 = new JPanel();
+    String oldLnf = "";
+    boolean oldUseDef;
+    int oldPort = -1;
+
+    public AdvancedTab(JabRefPreferences prefs, HelpDialog diag) {
+        _prefs = prefs;
+
+
+    remoteHelp = new HelpAction(diag, GUIGlobals.remoteHelp, "Help",
+                GUIGlobals.helpSmallIconFile);
+    useDefault = new JCheckBox(Globals.lang("Use other look and feel"));
+    useRemoteServer = new JCheckBox(Globals.lang("Listen for remote operation on port")+":");
+    remoteServerPort = new JTextField();
+    className = new JTextField(50);
+    final JTextField clName = className;
+    useDefault.addChangeListener(new ChangeListener() {
+        public void stateChanged(ChangeEvent e) {
+            clName.setEnabled(((JCheckBox)e.getSource()).isSelected());
+        }
+        });
+
+    FormLayout layout = new FormLayout
+        ("1dlu, 8dlu, left:pref, 4dlu, fill:3dlu",//, 4dlu, fill:pref",// 4dlu, left:pref, 4dlu",
+         "");
+    DefaultFormBuilder builder = new DefaultFormBuilder(layout);
+    JPanel pan = new JPanel();
+    builder.appendSeparator(Globals.lang("Look and feel"));
+    JLabel lab = new JLabel(Globals.lang("Default look and feel")+": "
+             +(Globals.ON_WIN ? GUIGlobals.windowsDefaultLookAndFeel :
+               GUIGlobals.linuxDefaultLookAndFeel));
+    builder.nextLine();
+    builder.append(pan);
+    builder.append(lab);
+    builder.nextLine();
+    builder.append(pan);
+    builder.append(useDefault);
+    builder.nextLine();
+    builder.append(pan);
+    JPanel pan2 = new JPanel();
+    lab = new JLabel(Globals.lang("Class name")+":");
+    pan2.add(lab);
+    pan2.add(className);
+    builder.append(pan2);
+    builder.nextLine();
+    builder.append(pan);
+    lab = new JLabel(Globals.lang("Note that you must specify the fully qualified class name for the look and feel,"));
+    builder.append(lab);
+    builder.nextLine();
+    builder.append(pan);
+    lab = new JLabel(Globals.lang("and the class must be available in your classpath next time you start JabRef."));
+    builder.append(lab);
+    builder.nextLine();
+    builder.appendSeparator(Globals.lang("Remote operation"));
+    builder.nextLine();
+    builder.append(new JPanel());
+    JPanel p = new JPanel();
+    p.add(useRemoteServer);
+    p.add(remoteServerPort);
+    p.add(remoteHelp.getIconButton());
+    builder.append(p);
+
+    pan = builder.getPanel();
+    pan.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+    setLayout(new BorderLayout());
+    add(pan, BorderLayout.CENTER);
+
+    }
+
+    public void setValues() {
+    oldUseDef = _prefs.getBoolean("useDefaultLookAndFeel");
+    oldLnf = _prefs.get("lookAndFeel");
+    useDefault.setSelected(!oldUseDef);
+    className.setText(oldLnf);
+    className.setEnabled(!oldUseDef);
+    useRemoteServer.setSelected(_prefs.getBoolean("useRemoteServer"));
+    oldPort = _prefs.getInt("remoteServerPort");
+    remoteServerPort.setText(String.valueOf(oldPort));
+    }
+
+    public void storeSettings() {
+        _prefs.putBoolean("useDefaultLookAndFeel", !useDefault.isSelected());
+        _prefs.put("lookAndFeel", className.getText());
+        try {
+            int port = Integer.parseInt(remoteServerPort.getText());
+            if (port != oldPort) {
+                _prefs.putInt("remoteServerPort", port);
+                /*JOptionPane.showMessageDialog(null, Globals.lang("You have changed the menu and label font size. "
+                        + "You must restart JabRef for this to come into effect."), Globals.lang("Changed font settings"),
+                        JOptionPane.WARNING_MESSAGE);*/
+            }
+
+        } catch (NumberFormatException ex) {
+            ex.printStackTrace();
+        }
+        _prefs.putBoolean("useRemoteServer", useRemoteServer.isSelected());
+        if (useRemoteServer.isSelected() && (JabRef.remoteListener == null)) {
+            // Start the listener now.
+
+            JabRef.remoteListener = RemoteListener.openRemoteListener(JabRef.ths);
+            if (JabRef.remoteListener != null) {
+                JabRef.remoteListener.start();
+            }
+        } else if (!useRemoteServer.isSelected() && (JabRef.remoteListener != null)) {
+            JabRef.remoteListener.disable();
+            JabRef.remoteListener = null;
+        }
+
+        if ((useDefault.isSelected() == oldUseDef) ||
+            !oldLnf.equals(className.getText())) {
+            JOptionPane.showMessageDialog(null, Globals.lang("You have changed the look and feel setting. "
+                                                             +"You must restart JabRef for this to come into effect."), Globals.lang("Changed look and feel settings"),
+                                          JOptionPane.WARNING_MESSAGE);
+        }
+    }
+
+    public boolean readyToClose() {
+	   
+        try {
+            int size = Integer.parseInt(remoteServerPort.getText());
+            return true; // Ok, the number was legal.
+        } catch (NumberFormatException ex) {
+            JOptionPane.showMessageDialog
+                    (null, Globals.lang("You must enter an integer value in the text field for") + " '" +
+                    Globals.lang("Remote server port") + "'", Globals.lang("Remote server port"),
+                            JOptionPane.ERROR_MESSAGE);
+            return false;
+        }
+
+    }
+
+}
diff --git a/src/java/net/sf/jabref/AppearancePrefsTab.java b/src/java/net/sf/jabref/AppearancePrefsTab.java
new file mode 100644
index 0000000..2b4d4eb
--- /dev/null
+++ b/src/java/net/sf/jabref/AppearancePrefsTab.java
@@ -0,0 +1,157 @@
+package net.sf.jabref;
+
+import java.util.Vector;
+import javax.swing.*;
+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;
+
+class AppearancePrefsTab extends JPanel implements PrefsTab {
+
+    JabRefPreferences _prefs;
+    private JCheckBox colorCodes, antialias;
+    private GridBagLayout gbl = new GridBagLayout();
+    private JButton fontButton = new JButton(Globals.lang("Set table font"));
+    private ColorSetupPanel colorPanel = new ColorSetupPanel();
+    private Font font = GUIGlobals.CURRENTFONT;
+    private int oldMenuFontSize;
+    private JTextField fontSize;
+
+    /**
+     * Customization of appearance parameters.
+     *
+     * @param prefs a <code>JabRefPreferences</code> value
+     */
+    public AppearancePrefsTab(JabRefPreferences prefs) {
+        _prefs = prefs;
+         setLayout(new BorderLayout());
+
+        // Font sizes:
+        fontSize = new JTextField();
+
+
+        colorCodes = new JCheckBox(Globals.lang
+                   ("Color codes for required and optional fields"));
+        antialias = new JCheckBox(Globals.lang
+                  ("Use antialiasing font"));
+
+        FormLayout layout = new FormLayout
+                ("1dlu, 8dlu, left:pref, 4dlu, fill:pref, 4dlu, fill:60dlu, 4dlu, fill:pref",
+                        "");
+        DefaultFormBuilder builder = new DefaultFormBuilder(layout);
+        builder.setLeadingColumnOffset(2);
+        JLabel lab;
+        builder.appendSeparator(Globals.lang("General"));
+        JPanel p1 = new JPanel();
+        lab = new JLabel(Globals.lang("Menu and label font size") + ":");
+        p1.add(lab);
+        p1.add(fontSize);
+        builder.append(p1);
+        builder.nextLine();
+        builder.append(antialias);
+        builder.nextLine();
+        builder.appendSeparator(Globals.lang("Table appearance"));
+        builder.append(colorCodes);
+        builder.nextLine();
+        builder.append(fontButton);
+        builder.nextLine();
+        builder.append(colorPanel);
+
+
+
+    JPanel upper = new JPanel(),
+        sort = new JPanel(),
+        namesp = new JPanel(),
+            iconCol = new JPanel();
+    upper.setLayout(gbl);
+    sort.setLayout(gbl);
+        namesp.setLayout(gbl);
+        iconCol.setLayout(gbl);
+
+
+
+    fontButton.addActionListener(new ActionListener() {
+        public void actionPerformed(ActionEvent e) {
+            // JDialog dl = new EntryCustomizationDialog(ths);
+            Font f=new FontSelectorDialog
+                (null, GUIGlobals.CURRENTFONT).getSelectedFont();
+            if(f==null)
+                return;
+            else
+                font = f;
+        }
+        });
+    /*menuFontButton.addActionListener(new ActionListener() {
+         public void actionPerformed(ActionEvent e) {
+             Font f=new FontSelectorDialog
+                 (null, menuFont).getSelectedFont();
+             if(f==null)
+                 return;
+             else
+                 menuFont = f;
+         }
+         });*/
+
+    JPanel pan = builder.getPanel();
+    pan.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+    add(pan, BorderLayout.CENTER);
+    }
+
+    public void setValues() {
+        colorCodes.setSelected(_prefs.getBoolean("tableColorCodesOn"));
+        antialias.setSelected(_prefs.getBoolean("antialias"));
+        fontSize.setText("" + _prefs.getInt("menuFontSize"));
+        oldMenuFontSize = _prefs.getInt("menuFontSize");
+
+        colorPanel.setValues();
+    }
+
+    /**
+     * Store changes to table preferences. This method is called when
+     * the user clicks Ok.
+     *
+     */
+    public void storeSettings() {
+
+        _prefs.putBoolean("tableColorCodesOn", colorCodes.isSelected());
+        _prefs.putBoolean("antialias", antialias.isSelected());
+        _prefs.put("fontFamily", font.getFamily());
+        _prefs.putInt("fontStyle", font.getStyle());
+        _prefs.putInt("fontSize", font.getSize());
+        GUIGlobals.CURRENTFONT = font;
+        colorPanel.storeSettings();
+        try {
+            int size = Integer.parseInt(fontSize.getText());
+            if (size != oldMenuFontSize) {
+                _prefs.putInt("menuFontSize", size);
+                JOptionPane.showMessageDialog(null, Globals.lang("You have changed the menu and label font size. "
+                        + "You must restart JabRef for this to come into effect."), Globals.lang("Changed font settings"),
+                        JOptionPane.WARNING_MESSAGE);
+            }
+
+        } catch (NumberFormatException ex) {
+            ex.printStackTrace();
+        }
+    }
+
+    public boolean readyToClose() {
+        try {
+            // Test if font size is a number:
+            int size = Integer.parseInt(fontSize.getText());
+
+        } catch (NumberFormatException ex) {
+            JOptionPane.showMessageDialog
+                    (null, Globals.lang("You must enter an integer value in the text field for") + " '" +
+                            Globals.lang("Menu and label font size") + "'", Globals.lang("Changed font settings"),
+                            JOptionPane.ERROR_MESSAGE);
+            return false;
+        }
+        return true;
+
+    }
+
+}
diff --git a/src/java/net/sf/jabref/AuthorList.java b/src/java/net/sf/jabref/AuthorList.java
new file mode 100644
index 0000000..4f5bb54
--- /dev/null
+++ b/src/java/net/sf/jabref/AuthorList.java
@@ -0,0 +1,820 @@
+package net.sf.jabref;
+
+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.
+ * <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:
+ * <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);
+ * <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."
+ * </ol>
+ */
+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;
+            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
diff --git a/src/java/net/sf/jabref/BaseAction.java b/src/java/net/sf/jabref/BaseAction.java
new file mode 100644
index 0000000..30b111a
--- /dev/null
+++ b/src/java/net/sf/jabref/BaseAction.java
@@ -0,0 +1,10 @@
+package net.sf.jabref;
+
+/**
+ * BaseAction is used to define actions that are called from the
+ * base frame through runCommand(). runCommand() finds the
+ * appropriate BaseAction object, and runs its action() method.
+ */
+public abstract class BaseAction {//implements Runnable {
+    public abstract void action() throws Throwable;
+}
diff --git a/src/java/net/sf/jabref/BasePanel.java b/src/java/net/sf/jabref/BasePanel.java
new file mode 100644
index 0000000..36cab5b
--- /dev/null
+++ b/src/java/net/sf/jabref/BasePanel.java
@@ -0,0 +1,2562 @@
+/*
+Copyright (C) 2003 Morten O. Alver and 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;
+
+import java.awt.*;
+import java.awt.datatransfer.*;
+import java.awt.event.*;
+import java.io.*;
+import java.util.*;
+import java.util.List;
+import javax.swing.*;
+import javax.swing.tree.TreePath;
+import javax.swing.undo.*;
+import net.sf.jabref.collab.*;
+import net.sf.jabref.export.*;
+import net.sf.jabref.external.PushToLyx;
+import net.sf.jabref.external.AutoSetExternalFileForEntries;
+import net.sf.jabref.external.PushToEmacs;
+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.journals.AbbreviateAction;
+import net.sf.jabref.journals.UnabbreviateAction;
+import net.sf.jabref.gui.*;
+import net.sf.jabref.search.NoSearchMatcher;
+import net.sf.jabref.search.SearchMatcher;
+import com.jgoodies.uif_lite.component.UIFSplitPane;
+import ca.odell.glazedlists.FilterList;
+import ca.odell.glazedlists.matchers.Matcher;
+import ca.odell.glazedlists.event.ListEventListener;
+import ca.odell.glazedlists.event.ListEvent;
+
+public class BasePanel extends JPanel implements ClipboardOwner, FileUpdateListener {
+
+    public final static int SHOWING_NOTHING=0, SHOWING_PREVIEW=1, SHOWING_EDITOR=2, WILL_SHOW_EDITOR=3;
+    private int mode=0;
+    private EntryEditor currentEditor = null;
+    private PreviewPanel currentPreview = null;
+
+  boolean tmp = true;
+
+    private MainTableSelectionListener selectionListener = null;
+    private ListEventListener groupsHighlightListener;
+    UIFSplitPane contentPane = new UIFSplitPane();
+
+    JSplitPane splitPane;
+    //BibtexEntry testE = new BibtexEntry("tt");
+    //boolean previewActive = true;
+
+    JabRefFrame frame;
+    BibtexDatabase database;
+    // The database shown in this panel.
+    File file = null,
+        fileToOpen = null; // The filename of the database.
+    String fileMonitorHandle = null;
+    boolean saving = false, updatedExternally = false;
+    private String encoding;
+
+    GridBagLayout gbl = new GridBagLayout();
+    GridBagConstraints con = new GridBagConstraints();
+
+    //Hashtable autoCompleters = new Hashtable();
+    // Hashtable that holds as keys the names of the fields where
+    // autocomplete is active, and references to the autocompleter objects.
+
+    // The undo manager.
+    public CountingUndoManager undoManager = new CountingUndoManager(this);
+    UndoAction undoAction = new UndoAction();
+    RedoAction redoAction = new RedoAction();
+
+    //ExampleFileFilter fileFilter;
+    // File filter for .bib files.
+
+    boolean baseChanged = false, nonUndoableChange = false;
+    // Used to track whether the base has changed since last save.
+
+    //EntryTableModel tableModel = null;
+    //public EntryTable entryTable = null;
+    public MainTable mainTable = null;
+    public FilterList searchFilterList = null, groupFilterList = null;
+
+    public RightClickMenu rcm;
+
+    BibtexEntry showing = null;
+    // To indicate which entry is currently shown.
+    public HashMap entryEditors = new HashMap();
+    // To contain instantiated entry editors. This is to save time
+    // in switching between entries.
+
+    //HashMap entryTypeForms = new HashMap();
+    // Hashmap to keep track of which entries currently have open
+    // EntryTypeForm dialogs.
+
+    PreambleEditor preambleEditor = null;
+    // Keeps track of the preamble dialog if it is open.
+
+    StringDialog stringDialog = null;
+    // Keeps track of the string dialog if it is open.
+
+    /**
+     * The group selector component for this database. Instantiated by the
+     * SidePaneManager if necessary, or from this class if merging groups from a
+     * different database.
+     */
+    //GroupSelector groupSelector;
+
+    public boolean sortingBySearchResults = false,
+        coloringBySearchResults = false,
+    hidingNonHits = false,
+        sortingByGroup = false,
+        sortingByCiteSeerResults = false,
+        coloringByGroup = false;
+        //previewEnabled = Globals.prefs.getBoolean("previewEnabled");
+    int lastSearchHits = -1; // The number of hits in the latest search.
+    // Potential use in hiding non-hits completely.
+
+    // MetaData parses, keeps and writes meta data.
+    MetaData metaData;
+    HashMap fieldExtras = new HashMap();
+    //## keep track of all keys for duplicate key warning and unique key generation
+    //private HashMap allKeys  = new HashMap();	// use a map instead of a set since i need to know how many of each key is inthere
+
+    private boolean suppressOutput = false;
+
+    private HashMap actions = new HashMap();
+    private SidePaneManager sidePaneManager;
+
+    /**
+     * Create a new BasePanel with an empty database.
+     * @param frame The application window.
+     */
+    public BasePanel(JabRefFrame frame) {
+      this.sidePaneManager = Globals.sidePaneManager;
+      database = new BibtexDatabase();
+      metaData = new MetaData();
+      this.frame = frame;
+      setupActions();
+      setupMainPanel();
+        encoding = Globals.prefs.get("defaultEncoding");
+        //System.out.println("Default: "+encoding);
+    }
+
+    public BasePanel(JabRefFrame frame, BibtexDatabase db, File file,
+                     HashMap meta, String encoding) {
+
+        this.encoding = encoding;
+       // System.out.println(encoding);
+     //super(JSplitPane.HORIZONTAL_SPLIT, true);
+      this.sidePaneManager = Globals.sidePaneManager;
+      this.frame = frame;
+      database = db;
+      if (meta != null)
+        parseMetaData(meta);
+      else
+        metaData = new MetaData();
+      setupActions();
+      setupMainPanel();
+      /*if (Globals.prefs.getBoolean("autoComplete")) {
+            db.setCompleters(autoCompleters);
+            }*/
+
+      this.file = file;
+
+      // Register so we get notifications about outside changes to the file.
+      if (file != null)
+        try {
+          fileMonitorHandle = Globals.fileUpdateMonitor.addUpdateListener(this,
+              file);
+        } catch (IOException ex) {
+        }
+    }
+
+    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 String getEncoding() { return encoding; }
+    public void setEncoding(String encoding) {
+    this.encoding = encoding;
+    }
+
+    public void output(String s) {
+    //Util.pr("\""+s+"\""+(SwingUtilities.isEventDispatchThread()));
+        if (!suppressOutput)
+            frame.output(s);
+    }
+
+    private void setupActions() {
+
+        actions.put("undo", undoAction);
+        actions.put("redo", redoAction);
+
+        // The action for opening an entry editor.
+        actions.put("edit", new BaseAction() {
+            public void action() {
+                selectionListener.editSignalled();
+            }
+                /*
+                  if (isShowingEditor()) {
+                      new FocusRequester(splitPane.getBottomComponent());
+                      return;
+                  }
+
+                  frame.block();
+                //(new Thread() {
+                //public void run() {
+                int clickedOn = -1;
+                // We demand that one and only one row is selected.
+                if (entryTable.getSelectedRowCount() == 1) {
+                  clickedOn = entryTable.getSelectedRow();
+                }
+                if (clickedOn >= 0) {
+                  String id = tableModel.getIdForRow(clickedOn);
+                  BibtexEntry be = database.getEntryById(id);
+                  showEntry(be);
+
+                  if (splitPane.getBottomComponent() != null) {
+                      new FocusRequester(splitPane.getBottomComponent());
+                  }
+
+                }
+        frame.unblock();
+              }
+                */
+            });
+
+        // The action for saving a database.
+        actions.put("save", new AbstractWorker() {
+            private boolean success = false;
+            public void init() throws Throwable {
+                success = false;
+                if (file == null)
+                    runCommand("saveAs");
+                else {
+
+                    if (updatedExternally || Globals.fileUpdateMonitor.hasBeenModified(fileMonitorHandle)) {
+                        String[] opts = new String[]{Globals.lang("Review changes"), Globals.lang("Save"),
+                                Globals.lang("Cancel")};
+                        int answer = JOptionPane.showOptionDialog(frame, Globals.lang("File has been updated externally. "
+                                + "What do you want to do?"), Globals.lang("File updated externally"),
+                                JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE,
+                                null, opts, opts[0]);
+                        /*  int choice = JOptionPane.showConfirmDialog(frame, Globals.lang("File has been updated externally. "
++"Are you sure you want to save?"), Globals.lang("File updated externally"),
+                       JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE);*/
+
+                        if (answer == JOptionPane.CANCEL_OPTION)
+                            return;
+                        else if (answer == JOptionPane.YES_OPTION) {
+                            ChangeScanner scanner = new ChangeScanner(frame, BasePanel.this); //, panel.database(), panel.metaData());
+                            //try {
+                            scanner.changeScan(file());
+                            setUpdatedExternally(false);
+                            SwingUtilities.invokeLater(new Runnable() {
+                                public void run() {
+                                    sidePaneManager.hideAway("fileUpdate");
+                                }
+                            });
+
+                            //} catch (IOException ex) {
+                            //    ex.printStackTrace();
+                            //}
+
+                            return;
+                        }
+                    }
+
+                    frame.output(Globals.lang("Saving database") + "...");
+                    saving = true;
+                }
+            }
+
+            public void update() {
+                if (success) {
+                    frame.setTabTitle(BasePanel.this, file.getName());
+                    frame.output(Globals.lang("Saved database")+" '"
+                             +file.getPath()+"'.");
+                } else {
+                    frame.output(Globals.lang("Save failed"));
+                }
+            }
+
+            public void run() {
+                try {
+                    success = saveDatabase(file, false, encoding);
+
+                    //Util.pr("Testing resolve string... BasePanel line 237");
+                    //Util.pr("Resolve aq: "+database.resolveString("aq"));
+                    //Util.pr("Resolve text: "+database.resolveForStrings("A text which refers to the string #aq# and #billball#, hurra."));
+
+                    try {
+                        Globals.fileUpdateMonitor.updateTimeStamp(fileMonitorHandle);
+                    } catch (IllegalArgumentException ex) {
+                        // This means the file has not yet been registered, which is the case
+                        // when doing a "Save as". Maybe we should change the monitor so no
+                        // exception is cast.
+                    }
+                    saving = false;
+                    if (success) {
+                        undoManager.markUnchanged();
+                        // (Only) after a successful save the following
+                        // statement marks that the base is unchanged
+                        // since last save:
+                        nonUndoableChange = false;
+                        baseChanged = false;
+                        updatedExternally = false;
+                    }
+                } catch (SaveException ex2) {
+                    ex2.printStackTrace();
+                }
+            }
+        });
+
+        actions.put("saveAs", new BaseAction () {
+                public void action() throws Throwable {
+
+                  String chosenFile = Globals.getNewFile(frame, Globals.prefs, new File(Globals.prefs.get("workingDirectory")), ".bib",
+                                                         JFileChooser.SAVE_DIALOG, false);
+
+                  if (chosenFile != null) {
+                    file = new File(chosenFile);
+                    if (!file.exists() ||
+                        (JOptionPane.showConfirmDialog
+                         (frame, "'"+file.getName()+"' "+Globals.lang("exists. Overwrite file?"),
+                          Globals.lang("Save database"), JOptionPane.OK_CANCEL_OPTION)
+                         == JOptionPane.OK_OPTION)) {
+
+                      runCommand("save");
+
+                      // Register so we get notifications about outside changes to the file.
+                      try {
+                        fileMonitorHandle = Globals.fileUpdateMonitor.addUpdateListener(BasePanel.this,file);
+                      } catch (IOException ex) {
+                        ex.printStackTrace();
+                      }
+
+                      Globals.prefs.put("workingDirectory", file.getParent());
+                      frame.getFileHistory().newFile(file.getPath());
+                    }
+                    else
+                      file = null;
+                    }
+                }
+            });
+
+        actions.put("saveSelectedAs", new BaseAction () {
+                public void action() throws Throwable {
+
+                  String chosenFile = Globals.getNewFile(frame, Globals.prefs, new File(Globals.prefs.get("workingDirectory")), ".bib",
+                                                         JFileChooser.SAVE_DIALOG, false);
+                  if (chosenFile != null) {
+                    File expFile = new File(chosenFile);
+                    if (!expFile.exists() ||
+                        (JOptionPane.showConfirmDialog
+                         (frame, "'"+expFile.getName()+"' "+
+                          Globals.lang("exists. Overwrite file?"),
+                          Globals.lang("Save database"), JOptionPane.OK_CANCEL_OPTION)
+                         == JOptionPane.OK_OPTION)) {
+                      saveDatabase(expFile, true, Globals.prefs.get("defaultEncoding"));
+                      //runCommand("save");
+                      frame.getFileHistory().newFile(expFile.getPath());
+                      frame.output(Globals.lang("Saved selected to")+" '"
+                                   +expFile.getPath()+"'.");
+                        }
+                    }
+                }
+            });
+
+        // The action for copying selected entries.
+        actions.put("copy", new BaseAction() {
+                public void action() {
+                    BibtexEntry[] bes = mainTable.getSelectedEntries();
+
+                    if ((bes != null) && (bes.length > 0)) {
+                        TransferableBibtexEntry trbe
+                            = new TransferableBibtexEntry(bes);
+                        // ! look at ClipBoardManager
+                        Toolkit.getDefaultToolkit().getSystemClipboard()
+                            .setContents(trbe, BasePanel.this);
+                        output(Globals.lang("Copied")+" "+(bes.length>1 ? bes.length+" "
+                                                           +Globals.lang("entries")
+                                                           : "1 "+Globals.lang("entry")+"."));
+                    } else {
+                        // The user maybe selected a single cell.
+                        int[] rows = mainTable.getSelectedRows(),
+                            cols = mainTable.getSelectedColumns();
+                        if ((cols.length == 1) && (rows.length == 1)) {
+                            // Copy single value.
+                            Object o = mainTable.getValueAt(rows[0], cols[0]);
+                            if (o != null) {
+                                StringSelection ss = new StringSelection(o.toString());
+                                Toolkit.getDefaultToolkit().getSystemClipboard()
+                                    .setContents(ss, BasePanel.this);
+
+                                output(Globals.lang("Copied cell contents")+".");
+                            }
+                        }
+                    }
+                }
+            });
+
+        actions.put("cut", new BaseAction() {
+                public void action() throws Throwable {
+                    runCommand("copy");
+                    BibtexEntry[] bes = mainTable.getSelectedEntries();
+                    //int row0 = mainTable.getSelectedRow();
+                    if ((bes != null) && (bes.length > 0)) {
+                        // Create a CompoundEdit to make the action undoable.
+                        NamedCompound ce = new NamedCompound
+                        (Globals.lang(bes.length > 1 ? "cut entries" : "cut entry"));
+                        // Loop through the array of entries, and delete them.
+                        for (int i=0; i<bes.length; i++) {
+                            database.removeEntry(bes[i].getId());
+                            ensureNotShowing(bes[i]);
+                            ce.addEdit(new UndoableRemoveEntry
+                                       (database, bes[i], BasePanel.this));
+                        }
+                        //entryTable.clearSelection();
+                        frame.output(Globals.lang("Cut_pr")+" "+
+                                     (bes.length>1 ? bes.length
+                                      +" "+ Globals.lang("entries")
+                                      : Globals.lang("entry"))+".");
+                        ce.end();
+                        undoManager.addEdit(ce);
+                        markBaseChanged();
+
+                        // Reselect the entry in the first prev. selected position:
+                        /*if (row0 >= entryTable.getRowCount())
+                            row0 = entryTable.getRowCount()-1;
+                        if (row0 >= 0)
+                            entryTable.addRowSelectionInterval(row0, row0);*/
+                    }
+                }
+            });
+
+        actions.put("delete", new BaseAction() {
+                public void action() {
+                  boolean cancelled = false;
+                  BibtexEntry[] bes = mainTable.getSelectedEntries();
+                  int row0 = mainTable.getSelectedRow();
+                  if ((bes != null) && (bes.length > 0)) {
+
+                      boolean goOn = showDeleteConfirmationDialog(bes.length);
+                      if (!goOn) {
+                          return;
+                      }
+                      else {
+                          // Create a CompoundEdit to make the action undoable.
+                          NamedCompound ce = new NamedCompound
+                              (Globals.lang(bes.length > 1 ? "delete entries" : "delete entry"));
+                          // Loop through the array of entries, and delete them.
+                          for (int i = 0; i < bes.length; i++) {
+                              database.removeEntry(bes[i].getId());
+                              ensureNotShowing(bes[i]);
+                              ce.addEdit(new UndoableRemoveEntry(database, bes[i], BasePanel.this));
+                          }
+                          markBaseChanged();
+                          frame.output(Globals.lang("Deleted") + " " +
+                                       (bes.length > 1 ? bes.length
+                                        + " " + Globals.lang("entries")
+                                        : Globals.lang("entry")) + ".");
+                          ce.end();
+                          undoManager.addEdit(ce);
+                          //entryTable.clearSelection();
+                      }
+
+
+                          // Reselect the entry in the first prev. selected position:
+                          /*if (row0 >= entryTable.getRowCount())
+                              row0 = entryTable.getRowCount()-1;
+                          if (row0 >= 0) {
+                             final int toSel = row0;
+                            //
+                              SwingUtilities.invokeLater(new Runnable() {
+                                public void run() {
+                                    entryTable.addRowSelectionInterval(toSel, toSel);
+                                    //entryTable.ensureVisible(toSel);
+                                }
+                              });
+                            */
+                          }
+
+                      }
+
+            });
+
+        // The action for pasting entries or cell contents.
+        // Edited by Seb Wills <saw27 at mrao.cam.ac.uk> on 14-Apr-04:
+        //  - more robust detection of available content flavors (doesn't only look at first one offered)
+        //  - support for parsing string-flavor clipboard contents which are bibtex entries.
+        //    This allows you to (a) paste entire bibtex entries from a text editor, web browser, etc
+        //                       (b) copy and paste entries between multiple instances of JabRef (since
+        //         only the text representation seems to get as far as the X clipboard, at least on my system)
+        actions.put("paste", new BaseAction() {
+                public void action() {
+                    // Get clipboard contents, and see if TransferableBibtexEntry is among the content flavors offered
+                    Transferable content = Toolkit.getDefaultToolkit()
+                        .getSystemClipboard().getContents(null);
+                    if (content != null) {
+                        BibtexEntry[] bes = null;
+                        if (content.isDataFlavorSupported(TransferableBibtexEntry.entryFlavor)) {
+                            // We have determined that the clipboard data is a set of entries.
+                            try {
+                                bes = (BibtexEntry[])(content.getTransferData(TransferableBibtexEntry.entryFlavor));
+
+                            } catch (UnsupportedFlavorException ex) {
+                                ex.printStackTrace();
+                            } catch (IOException ex) {
+                                ex.printStackTrace();
+                            }
+                        } else if (content.isDataFlavorSupported(DataFlavor.stringFlavor)) {
+                            // We have determined that no TransferableBibtexEntry is available, but
+                            // there is a string, which we will handle according to context:
+                            int[] rows = mainTable.getSelectedRows();
+                                //cols = entryTable.getSelectedColumns();
+                            //Util.pr(rows.length+" x "+cols.length);
+                            /*if ((cols != null) && (cols.length == 1) && (cols[0] != 0)
+                                && (rows != null) && (rows.length == 1)) {
+                                // A single cell is highlighted, so paste the string straight into it without parsing
+                                try {
+                                    tableModel.setValueAt((String)(content.getTransferData(DataFlavor.stringFlavor)), rows[0], cols[0]);
+                                    refreshTable();
+                                    markBaseChanged();
+                                    output("Pasted cell contents");
+                                } catch (UnsupportedFlavorException ex) {
+                                    ex.printStackTrace();
+                                } catch (IOException ex) {
+                                    ex.printStackTrace();
+                                } catch (IllegalArgumentException ex) {
+                                    output("Can't paste.");
+                                }
+                            } else {*/
+                              // no single cell is selected, so try parsing the clipboard contents as bibtex entries instead
+                              try {
+                                  BibtexParser bp = new BibtexParser
+                                      (new java.io.StringReader( (String) (content.getTransferData(
+                                      DataFlavor.stringFlavor))));
+                                  BibtexDatabase db = bp.parse().getDatabase();
+                                  Util.pr("Parsed " + db.getEntryCount() + " entries from clipboard text");
+                                  if(db.getEntryCount()>0) {
+                                      Set keySet = db.getKeySet();
+                                      if (keySet != null) {
+                                          // Copy references to the entries into a BibtexEntry array.
+                                          // Could import directly from db, but going via bes allows re-use
+                                          // of the same pasting code as used for TransferableBibtexEntries
+                                          bes = new BibtexEntry[db.getEntryCount()];
+                                          Iterator it = keySet.iterator();
+                                          for (int i=0; it.hasNext();i++) {
+                                              bes[i]=db.getEntryById((String) (it.next()));
+                                          }
+                                      }
+                                  } /*else {
+                                    String cont = (String)(content.getTransferData(DataFlavor.stringFlavor));
+                                    Util.pr("----------------\n"+cont+"\n---------------------");
+                                    TextAnalyzer ta = new TextAnalyzer(cont);
+                                      output(Globals.lang("Unable to parse clipboard text as Bibtex entries."));
+                                      }*/
+                              } catch (UnsupportedFlavorException ex) {
+                                  ex.printStackTrace();
+                              } catch (Throwable ex) {
+                                  ex.printStackTrace();
+                              }
+
+                        }
+
+                        // finally we paste in the entries (if any), which either came from TransferableBibtexEntries
+                        // or were parsed from a string
+                        if ((bes != null) && (bes.length > 0)) {
+                          NamedCompound ce = new NamedCompound
+                              (Globals.lang(bes.length > 1 ? "paste entries" : "paste entry"));
+                          for (int i=0; i<bes.length; i++) {
+                            try {
+                              BibtexEntry be = (BibtexEntry)(bes[i].clone());
+                              // We have to clone the
+                              // entries, since the pasted
+                              // entries must exist
+                              // independently of the copied
+                              // ones.
+                              be.setId(Util.createNeutralId());
+                              database.insertEntry(be);
+                              ce.addEdit(new UndoableInsertEntry
+                                         (database, be, BasePanel.this));
+                            } catch (KeyCollisionException ex) {
+                              Util.pr("KeyCollisionException... this shouldn't happen.");
+                            }
+                          }
+                          ce.end();
+                          undoManager.addEdit(ce);
+                          //entryTable.clearSelection();
+                          //entryTable.revalidate();
+                          output(Globals.lang("Pasted")+" "+
+                                 (bes.length>1 ? bes.length+" "+
+                                  Globals.lang("entries") : "1 "+Globals.lang("entry"))
+                                 +".");
+                          markBaseChanged();
+                        }
+                      }
+
+                    }
+
+});
+
+        actions.put("selectAll", new BaseAction() {
+                public void action() {
+                    mainTable.selectAll();
+                }
+            });
+
+        // The action for opening the preamble editor
+        actions.put("editPreamble", new BaseAction() {
+                public void action() {
+                    if (preambleEditor == null) {
+                        PreambleEditor form = new PreambleEditor
+                            (frame, BasePanel.this, database, Globals.prefs);
+                        Util.placeDialog(form, frame);
+                        form.setVisible(true);
+                        preambleEditor = form;
+                    } else {
+                        preambleEditor.setVisible(true);
+                    }
+
+                }
+            });
+
+        // The action for opening the string editor
+        actions.put("editStrings", new BaseAction() {
+                public void action() {
+                    if (stringDialog == null) {
+                        StringDialog form = new StringDialog
+                            (frame, BasePanel.this, database, Globals.prefs);
+                        Util.placeDialog(form, frame);
+                        form.setVisible(true);
+                        stringDialog = form;
+                    } else {
+                        stringDialog.setVisible(true);
+                    }
+
+                }
+            });
+
+        // The action for toggling the groups interface
+        actions.put("toggleGroups", new BaseAction() {
+            public void action() {
+              sidePaneManager.togglePanel("groups");
+              frame.groupToggle.setSelected(sidePaneManager.isPanelVisible("groups"));
+            }
+        });
+
+    // The action for pushing citations to an open Lyx/Kile instance:
+        actions.put("pushToLyX", new PushToLyx(BasePanel.this));
+
+            actions.put("pushToWinEdt",new BaseAction(){
+              public void action(){
+                    final List entries = mainTable.getSelected();
+                    final int numSelected = entries.size();
+                    // Globals.logger("Pushing " +numSelected+(numSelected>1? " entries" : "entry") + " to WinEdt");
+
+                    if( numSelected > 0){
+                      Thread pushThread = new Thread() {
+                        public void run() {
+                          String winEdt = Globals.prefs.get("winEdtPath");
+                          //winEdt = "osascript";
+                          try {
+                            StringBuffer toSend = new StringBuffer("\"[InsText('\\")
+                              .append(Globals.prefs.get("citeCommand")).append("{");
+                            String citeKey = "";//, message = "";
+                            boolean first = true;
+                            for (Iterator i=entries.iterator(); i.hasNext();) {
+                                BibtexEntry bes = (BibtexEntry)i.next();
+                              citeKey = (String) bes.getField(GUIGlobals.KEY_FIELD);
+                              // if the key is empty we give a warning and ignore this entry
+                              if (citeKey == null || citeKey.equals(""))
+                                continue;
+                              if (first) {
+                                toSend.append(citeKey);
+                                first = false;
+                              }
+                              else {
+                                  toSend.append(",").append(citeKey);
+                                //message += ", ";
+                              }
+                              //message += (1 + rows[i]);
+
+                            }
+                            if (first)
+                              output(Globals.lang("Please define BibTeX key first"));
+                            else {
+                              toSend.append("}');]\"");
+                              //System.out.println(toSend.toString());
+                              Runtime.getRuntime().exec(winEdt + " " + toSend.toString());
+                              Globals.lang("Pushed citations to WinEdt");
+                                /*output(
+                                  Globals.lang("Pushed the citations for the following rows to")+"WinEdt: " +
+                                  message);*/
+                            }
+                          }
+
+                          catch (IOException excep) {
+                            output(Globals.lang("Error")+": "+Globals.lang("Could not call executable")+" '"
+                                   +winEdt+"'.");
+                            excep.printStackTrace();
+                          }
+                        }
+                      };
+
+                      pushThread.start();
+                    }
+                  }
+            });
+
+        actions.put("pushToEmacs", new PushToEmacs(BasePanel.this));
+
+        // The action for auto-generating keys.
+        actions.put("makeKey", new AbstractWorker() {
+        //int[] rows;
+        List entries;
+        int numSelected;
+        boolean cancelled = false;
+
+        // Run first, in EDT:
+        public void init() {
+
+                    entries = new ArrayList(Arrays.asList(getSelectedEntries()));
+                    //rows = entryTable.getSelectedRows() ;
+                    numSelected = entries.size();
+
+                    if (entries.size() == 0) { // None selected. Inform the user to select entries first.
+                        JOptionPane.showMessageDialog(frame, Globals.lang("First select the entries you want keys to be generated for."),
+                                                      Globals.lang("Autogenerate BibTeX key"), JOptionPane.INFORMATION_MESSAGE);
+                        return ;
+                    }
+            frame.block();
+            output(Globals.lang("Generating BibTeX key for")+" "+
+                           numSelected+" "+(numSelected>1 ? Globals.lang("entries")
+                                            : Globals.lang("entry"))+"...");
+        }
+
+        // Run second, on a different thread:
+                public void run() {
+                    BibtexEntry bes = null ;
+                    NamedCompound ce = new NamedCompound(Globals.lang("autogenerate keys"));
+                    //BibtexEntry be;
+                    Object oldValue;
+                    boolean hasShownWarning = false;
+                    // First check if any entries have keys set already. If so, possibly remove
+                    // them from consideration, or warn about overwriting keys.
+                    loop: for (Iterator i=entries.iterator(); i.hasNext();) {
+                        bes = (BibtexEntry)i.next();
+                        if (bes.getField(GUIGlobals.KEY_FIELD) != null) {
+                            if (Globals.prefs.getBoolean("avoidOverwritingKey"))
+                                // Rmove the entry, because its key is already set:
+                                i.remove();
+                            else if (Globals.prefs.getBoolean("warnBeforeOverwritingKey")) {
+                                // Ask if the user wants to cancel the operation:
+                                CheckBoxMessage cbm = new CheckBoxMessage(Globals.lang("One or more keys will be overwritten. Continue?"),
+                                        Globals.lang("Disable this confirmation dialog"), false);
+                                int answer = JOptionPane.showConfirmDialog(frame, cbm, Globals.lang("Overwrite keys"),
+                                        JOptionPane.YES_NO_OPTION);
+                                if (cbm.isSelected())
+                                    Globals.prefs.putBoolean("warnBeforeOverwritingKey", false);
+                                if (answer == JOptionPane.NO_OPTION) {
+                                    // Ok, break off the operation.
+                                    cancelled = true;
+                                    return;
+                                }
+                                // No need to check more entries, because the user has already confirmed
+                                // that it's ok to overwrite keys:
+                                break loop;
+                            }
+                        }
+                    }
+
+                    HashMap oldvals = new HashMap();
+                    // Iterate again, removing already set keys. This is skipped if overwriting
+                    // is disabled, since all entries with keys set will have been removed.
+                    if (!Globals.prefs.getBoolean("avoidOverwritingKey")) for (Iterator i=entries.iterator(); i.hasNext();) {
+                        bes = (BibtexEntry)i.next();
+                        // Store the old value:
+                        oldvals.put(bes, bes.getField(GUIGlobals.KEY_FIELD));
+                        database.setCiteKeyForEntry(bes.getId(), null);
+                    }
+
+                    // Finally, set the new keys:
+                    for (Iterator i=entries.iterator(); i.hasNext();) {
+                        bes = (BibtexEntry)i.next();
+                        bes = LabelPatternUtil.makeLabel(Globals.prefs.getKeyPattern(), database, bes);
+                        ce.addEdit(new UndoableKeyChange
+                                   (database, bes.getId(), (String)oldvals.get(bes),
+                                    (String)bes.getField(GUIGlobals.KEY_FIELD)));
+                    }
+                    ce.end();
+                    undoManager.addEdit(ce);
+        }
+
+        // Run third, on EDT:
+        public void update() {
+            if (cancelled) {
+                frame.unblock();
+                return;
+            }
+            markBaseChanged() ;
+            numSelected = entries.size();
+            output(Globals.lang("Generated BibTeX key for")+" "+
+               numSelected+" "+(numSelected!=1 ? Globals.lang("entries")
+                                    : Globals.lang("entry")));
+            frame.unblock();
+        }
+    });
+
+        actions.put("search", new BaseAction() {
+                public void action() {
+                    //sidePaneManager.togglePanel("search");
+                    sidePaneManager.ensureVisible("search");
+                    //boolean on = sidePaneManager.isPanelVisible("search");
+                    frame.searchToggle.setSelected(true);
+                    if (true)
+                      frame.searchManager.startSearch();
+                }
+            });
+
+        actions.put("toggleSearch", new BaseAction() {
+                public void action() {
+                    //sidePaneManager.togglePanel("search");
+                    sidePaneManager.togglePanel("search");
+                    boolean on = sidePaneManager.isPanelVisible("search");
+                    frame.searchToggle.setSelected(on);
+                    if (on)
+                      frame.searchManager.startSearch();
+                }
+            });
+
+        actions.put("incSearch", new BaseAction() {
+                public void action() {
+                    sidePaneManager.ensureVisible("search");
+                    frame.searchToggle.setSelected(true);
+                    frame.searchManager.startIncrementalSearch();
+                }
+            });
+
+        // The action for copying the selected entry's key.
+        actions.put("copyKey", new BaseAction() {
+                public void action() {
+                    BibtexEntry[] bes = mainTable.getSelectedEntries();
+                    if ((bes != null) && (bes.length > 0)) {
+                        storeCurrentEdit();
+                        //String[] keys = new String[bes.length];
+                        Vector keys = new Vector();
+                        // Collect all non-null keys.
+                        for (int i=0; i<bes.length; i++)
+                            if (bes[i].getField(Globals.KEY_FIELD) != null)
+                                keys.add(bes[i].getField(Globals.KEY_FIELD));
+                        if (keys.size() == 0) {
+                            output("None of the selected entries have BibTeX keys.");
+                            return;
+                        }
+                        StringBuffer sb = new StringBuffer((String)keys.elementAt(0));
+                        for (int i=1; i<keys.size(); i++) {
+                            sb.append(',');
+                            sb.append((String)keys.elementAt(i));
+                        }
+
+                        StringSelection ss = new StringSelection(sb.toString());
+                        Toolkit.getDefaultToolkit().getSystemClipboard()
+                            .setContents(ss, BasePanel.this);
+
+                        if (keys.size() == bes.length)
+                            // All entries had keys.
+                            output(Globals.lang((bes.length > 1) ? "Copied keys"
+                                                : "Copied key")+".");
+                        else
+                            output(Globals.lang("Warning")+": "+(bes.length-keys.size())
+                                   +" "+Globals.lang("out of")+" "+bes.length+" "+
+                                   Globals.lang("entries have undefined BibTeX key")+".");
+                    }
+                }
+            });
+
+        // The action for copying a cite for the selected entry.
+        actions.put("copyCiteKey", new BaseAction() {
+                public void action() {
+                    BibtexEntry[] bes = mainTable.getSelectedEntries();
+                    if ((bes != null) && (bes.length > 0)) {
+                        storeCurrentEdit();
+                        //String[] keys = new String[bes.length];
+                        Vector keys = new Vector();
+                        // Collect all non-null keys.
+                        for (int i=0; i<bes.length; i++)
+                            if (bes[i].getField(Globals.KEY_FIELD) != null)
+                                keys.add(bes[i].getField(Globals.KEY_FIELD));
+                        if (keys.size() == 0) {
+                            output("None of the selected entries have BibTeX keys.");
+                            return;
+                        }
+                        StringBuffer sb = new StringBuffer((String)keys.elementAt(0));
+                        for (int i=1; i<keys.size(); i++) {
+                            sb.append(',');
+                            sb.append((String)keys.elementAt(i));
+                        }
+
+                        StringSelection ss = new StringSelection
+                            ("\\cite{"+sb.toString()+"}");
+                        Toolkit.getDefaultToolkit().getSystemClipboard()
+                            .setContents(ss, BasePanel.this);
+
+                        if (keys.size() == bes.length)
+                            // All entries had keys.
+                            output(Globals.lang((bes.length > 1) ? "Copied keys"
+                                                : "Copied key")+".");
+                        else
+                            output(Globals.lang("Warning")+": "+(bes.length-keys.size())
+                                   +" "+Globals.lang("out of")+" "+bes.length+" "+
+                                   Globals.lang("entries have undefined BibTeX key")+".");
+                    }
+                }
+            });
+
+          actions.put("mergeDatabase", new BaseAction() {
+            public void action() {
+
+                final MergeDialog md = new MergeDialog(frame, Globals.lang("Append database"), true);
+                Util.placeDialog(md, BasePanel.this);
+                md.setVisible(true);
+                if (md.okPressed) {
+                  String chosenFile = Globals.getNewFile(frame, Globals.prefs, new File(Globals.prefs.get("workingDirectory")),
+                                                         null, JFileChooser.OPEN_DIALOG, false);
+                  /*JFileChooser chooser = (Globals.prefs.get("workingDirectory") == null) ?
+                      new JabRefFileChooser((File)null) :
+                      new JabRefFileChooser(new File(Globals.prefs.get("workingDirectory")));
+                  chooser.addChoosableFileFilter( new OpenFileFilter() );//nb nov2
+                  int returnVal = chooser.showOpenDialog(BasePanel.this);*/
+                  if(chosenFile == null)
+                    return;
+                  fileToOpen = new File(chosenFile);
+
+                    // Run the actual open in a thread to prevent the program
+                    // locking until the file is loaded.
+                    (new Thread() {
+                        public void run() {
+                            openIt(md.importEntries(), md.importStrings(),
+                                    md.importGroups(), md.importSelectorWords());
+                        }
+                    }).start();
+                    frame.getFileHistory().newFile(fileToOpen.getPath());
+                }
+
+              }
+
+              void openIt(boolean importEntries, boolean importStrings,
+                          boolean importGroups, boolean importSelectorWords) {
+                if ((fileToOpen != null) && (fileToOpen.exists())) {
+                  try {
+                    Globals.prefs.put("workingDirectory", fileToOpen.getPath());
+                    // Should this be done _after_ we know it was successfully opened?
+                    String encoding = Globals.prefs.get("defaultEncoding");
+                    ParserResult pr = OpenDatabaseAction.loadDatabase(fileToOpen, encoding);
+                    mergeFromBibtex(pr, importEntries, importStrings, importGroups, importSelectorWords);
+                    output(Globals.lang("Imported from database")+" '"+fileToOpen.getPath()+"'");
+                    fileToOpen = null;
+                  } catch (Throwable ex) {
+                    ex.printStackTrace();
+                    JOptionPane.showMessageDialog
+                        (BasePanel.this, ex.getMessage(),
+                         "Open database", JOptionPane.ERROR_MESSAGE);
+                  }
+                }
+              }
+            });
+
+         actions.put("openFile", new BaseAction() {
+           public void action() {
+             (new Thread() {
+               public void run() {
+                 BibtexEntry[] bes = mainTable.getSelectedEntries();
+                 String field = "ps";
+                 if ( (bes != null) && (bes.length == 1)) {
+                   Object link = bes[0].getField("ps");
+                   if (bes[0].getField("pdf") != null) {
+                     link = bes[0].getField("pdf");
+                     field = "pdf";
+                   }
+                   String filepath = null;
+                   if (link != null) {
+                     filepath = link.toString();
+                   }
+                   else {
+
+                     // see if we can fall back to a filename based on the bibtex key
+                     String basefile;
+                     Object key = bes[0].getField(Globals.KEY_FIELD);
+                     if (key != null) {
+                       basefile = key.toString();
+                        final String[] types = new String[] {"pdf", "ps"};
+                        final String sep = System.getProperty("file.separator");
+                        for (int i = 0; i < types.length; i++) {
+                            String dir = Globals.prefs.get(types[i]+"Directory");
+                            if (dir.endsWith(sep)) {
+                                dir = dir.substring(0, dir.length()-sep.length());
+                            }
+                            String found = Util.findPdf(basefile, types[i], dir, new OpenFileFilter("."+types[i]));
+                            if (found != null) {
+                                filepath = dir+sep+found;
+                                break;
+                            }
+                        }
+                     }
+                   }
+
+
+                   if (filepath != null) {
+                     //output(Globals.lang("Calling external viewer..."));
+                     try {
+                       Util.openExternalViewer(filepath, field, Globals.prefs);
+                       output(Globals.lang("External viewer called") + ".");
+                     }
+                     catch (IOException ex) {
+                       output(Globals.lang("Error") + ": " + ex.getMessage());
+                     }
+                   }
+                   else
+                     output(Globals.lang(
+                         "No pdf or ps defined, and no file matching Bibtex key found") +
+                            ".");
+                 }
+                 else
+                   output(Globals.lang("No entries or multiple entries selected."));
+               }
+             }).start();
+           }
+         });
+
+
+              actions.put("openUrl", new BaseAction() {
+                      public void action() {
+                          BibtexEntry[] bes = mainTable.getSelectedEntries();
+                          String field = "doi";
+                          if ((bes != null) && (bes.length == 1)) {
+                              Object link = bes[0].getField("doi");
+                              if (bes[0].getField("url") != null) {
+                                link = bes[0].getField("url");
+                                field = "url";
+                              }
+                              if (link != null) {
+                                //output(Globals.lang("Calling external viewer..."));
+                                try {
+                                  Util.openExternalViewer(link.toString(), field, Globals.prefs);
+                                  output(Globals.lang("External viewer called")+".");
+                                } catch (IOException ex) {
+                                    output(Globals.lang("Error") + ": " + ex.getMessage());
+                                }
+                              }
+                              else
+                                  output(Globals.lang("No url defined")+".");
+                          } else
+                            output(Globals.lang("No entries or multiple entries selected."));
+                      }
+              });
+
+          actions.put("replaceAll", new BaseAction() {
+                    public void action() {
+                      ReplaceStringDialog rsd = new ReplaceStringDialog(frame);
+                      rsd.setVisible(true);
+                      if (!rsd.okPressed())
+                          return;
+                      int counter = 0;
+                      NamedCompound ce = new NamedCompound(Globals.lang("Replace string"));
+                      if (!rsd.selOnly()) {
+                          for (Iterator i=database.getKeySet().iterator();
+                               i.hasNext();)
+                              counter += rsd.replace(database.getEntryById((String)i.next()), ce);
+                      } else {
+                          BibtexEntry[] bes = mainTable.getSelectedEntries();
+                          for (int i=0; i<bes.length; i++)
+                              counter += rsd.replace(bes[i], ce);
+                      }
+
+                      output(Globals.lang("Replaced")+" "+counter+" "+
+                             Globals.lang(counter==1?"occurence":"occurences")+".");
+                      if (counter > 0) {
+                          ce.end();
+                          undoManager.addEdit(ce);
+                          markBaseChanged();
+                      }
+                  }
+              });
+
+              actions.put("dupliCheck", new BaseAction() {
+                public void action() {
+                  DuplicateSearch ds = new DuplicateSearch(BasePanel.this);
+                  ds.start();
+                }
+              });
+
+              actions.put("strictDupliCheck", new BaseAction() {
+                public void action() {
+                  StrictDuplicateSearch ds = new StrictDuplicateSearch(BasePanel.this);
+                  ds.start();
+                }
+              });
+
+              actions.put("plainTextImport", new BaseAction() {
+                public void action()
+                {
+                  // get Type of new entry
+                  EntryTypeDialog etd = new EntryTypeDialog(frame);
+                  Util.placeDialog(etd, BasePanel.this);
+                  etd.setVisible(true);
+                  BibtexEntryType tp = etd.getChoice();
+                  if (tp == null)
+                    return;
+
+                  String id = Util.createNeutralId();
+                  BibtexEntry bibEntry = new BibtexEntry(id, tp) ;
+                  TextInputDialog tidialog = new TextInputDialog(frame, BasePanel.this,
+                                                                 "import", true,
+                                                                 bibEntry) ;
+                  Util.placeDialog(tidialog, BasePanel.this);
+                  tidialog.setVisible(true);
+
+                  if (tidialog.okPressed())
+                  {
+                      Util.setAutomaticFields(Arrays.asList(new BibtexEntry[] {bibEntry}));
+                    insertEntry(bibEntry) ;
+                  }
+                }
+              });
+
+              // The action starts the "import from plain text" dialog
+              /*actions.put("importPlainText", new BaseAction() {
+                      public void action()
+                      {
+                        BibtexEntry bibEntry = null ;
+                        // try to get the first marked entry
+                        BibtexEntry[] bes = entryTable.getSelectedEntries();
+                        if ((bes != null) && (bes.length > 0))
+                          bibEntry = bes[0] ;
+
+                        if (bibEntry != null)
+                        {
+                          // Create an UndoableInsertEntry object.
+                          undoManager.addEdit(new UndoableInsertEntry(database, bibEntry, BasePanel.this));
+
+                          TextInputDialog tidialog = new TextInputDialog(frame, BasePanel.this, 
+                                                                         "import", true,
+                                                                         bibEntry) ;
+                          Util.placeDialog(tidialog, BasePanel.this);
+                          tidialog.setVisible(true);
+
+                          if (tidialog.okPressed())
+                          {
+                            output(Globals.lang("changed ")+" '"
+                                   +bibEntry.getType().getName().toLowerCase()+"' "
+                                   +Globals.lang("entry")+".");
+                            refreshTable();
+                            int row = tableModel.getNumberFromName(bibEntry.getId());
+
+                            entryTable.clearSelection();
+                            entryTable.scrollTo(row);
+                            markBaseChanged(); // The database just changed.
+                            if (Globals.prefs.getBoolean("autoOpenForm"))
+                            {
+                                  showEntry(bibEntry);
+                            }
+                          }
+                        }
+                      }
+                  });
+                */
+              actions.put("markEntries", new AbstractWorker() {
+                  private int besLength = -1;
+                public void run() {
+
+                  NamedCompound ce = new NamedCompound(Globals.lang("Mark entries"));
+                  BibtexEntry[] bes = mainTable.getSelectedEntries();
+                  besLength = bes.length;
+          if (bes == null)
+              return;
+                  for (int i=0; i<bes.length; i++) {
+                      Util.markEntry(bes[i], ce);
+                  }
+                  ce.end();
+                  undoManager.addEdit(ce);
+                }
+
+                public void update() {
+                  markBaseChanged();
+                  output(Globals.lang("Marked selected")+" "+Globals.lang(besLength>0?"entry":"entries"));
+
+                }
+              });
+
+              actions.put("unmarkEntries", new BaseAction() {
+                public void action() {
+                    try {
+                  NamedCompound ce = new NamedCompound(Globals.lang("Unmark entries"));
+                  BibtexEntry[] bes = mainTable.getSelectedEntries();
+          if (bes == null)
+              return;
+                  for (int i=0; i<bes.length; i++) {
+                      Util.unmarkEntry(bes[i], database, ce);
+                  }
+                  ce.end();
+                  undoManager.addEdit(ce);
+                  markBaseChanged();
+                  output(Globals.lang("Unmarked selected")+" "+Globals.lang(bes.length>0?"entry":"entries"));
+                    } catch (Throwable ex) { ex.printStackTrace(); }
+                }
+              });
+
+              actions.put("unmarkAll", new BaseAction() {
+                public void action() {
+                  NamedCompound ce = new NamedCompound(Globals.lang("Unmark all"));
+                  Set keySet = database.getKeySet();
+                  for (Iterator i = keySet.iterator(); i.hasNext(); ) {
+                    BibtexEntry be = database.getEntryById( (String) i.next());
+                    Util.unmarkEntry(be, database, ce);
+
+                  }
+                  ce.end();
+                  undoManager.addEdit(ce);
+                  markBaseChanged();
+                }
+              });
+
+              actions.put("togglePreview", new BaseAction() {
+                      public void action() {
+                          boolean enabled = !Globals.prefs.getBoolean("previewEnabled");
+                          Globals.prefs.putBoolean("previewEnabled", enabled);
+                          frame.setPreviewActive(enabled);
+                          frame.previewToggle.setSelected(enabled);
+                      }
+                  });
+
+              actions.put("toggleHighlightGroupsMatchingAny", new BaseAction() {
+                public void action() {
+                    boolean enabled = !Globals.prefs.getBoolean("highlightGroupsMatchingAny");
+                    Globals.prefs.putBoolean("highlightGroupsMatchingAny", enabled);
+                    frame.highlightAny.setSelected(enabled);
+                    if (enabled) {
+                        frame.highlightAll.setSelected(false);
+                        Globals.prefs.putBoolean("highlightGroupsMatchingAll", false);
+                    }
+                    // ping the listener so it updates:
+                    groupsHighlightListener.listChanged(null);
+                }
+              });
+
+              actions.put("toggleHighlightGroupsMatchingAll", new BaseAction() {
+                  public void action() {
+                      boolean enabled = !Globals.prefs.getBoolean("highlightGroupsMatchingAll");
+                      Globals.prefs.putBoolean("highlightGroupsMatchingAll", enabled);
+                      frame.highlightAll.setSelected(enabled);
+                      if (enabled) {
+                          frame.highlightAny.setSelected(false);
+                          Globals.prefs.putBoolean("highlightGroupsMatchingAny", false);
+                      }
+                      // ping the listener so it updates:
+                      groupsHighlightListener.listChanged(null);
+                  }
+                });
+
+              actions.put("switchPreview", new BaseAction() {
+                      public void action() {
+                          selectionListener.switchPreview();
+                      }
+                  });
+
+              actions.put("manageSelectors", new BaseAction() {
+                      public void action() {
+                          ContentSelectorDialog2 csd = new ContentSelectorDialog2
+                              (frame, frame, BasePanel.this, false, metaData, null);
+                          Util.placeDialog(csd, frame);
+                          csd.setVisible(true);
+                      }
+                  });
+
+
+              actions.put("exportToClipboard", new AbstractWorker() {
+              String message = null;
+              public void run() {
+              if (mainTable.getSelected().size() == 0) {
+                  message = Globals.lang("No entries selected")+".";
+                  getCallBack().update();
+                  return;
+              }
+
+              // Make a list of possible formats:
+              Map formats = new HashMap();
+              formats.put("BibTeXML", "bibtexml");
+              formats.put("DocBook", "docbook");
+              formats.put("HTML", "html");
+                          formats.put("RTF (Harvard)", "harvard/harvard");
+              formats.put("Simple HTML", "simplehtml");
+              for (int i = 0; i < Globals.prefs.customExports.size(); i++) {
+                  Object o = (Globals.prefs.customExports.getElementAt(i))[0];
+                  formats.put(o, o);
+              }
+                          Object[] array = formats.keySet().toArray();
+                          Arrays.sort(array);
+              JList list = new JList(array);
+              list.setBorder(BorderFactory.createEtchedBorder());
+              list.setSelectionInterval(0,0);
+              list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+              int answer =
+                  JOptionPane.showOptionDialog(frame, list, Globals.lang("Select format"),
+                               JOptionPane.YES_NO_OPTION,
+                               JOptionPane.QUESTION_MESSAGE, null,
+                               new String[] {Globals.lang("Ok"), Globals.lang("Cancel")},
+                               Globals.lang("Ok"));
+
+              if (answer == JOptionPane.NO_OPTION)
+                  return;
+
+              String lfName = (String)(formats.get(list.getSelectedValue()));
+              final boolean custom = (list.getSelectedIndex() >= Globals.STANDARD_EXPORT_COUNT);
+              String dir = null;
+              if (custom) {
+                  int index = list.getSelectedIndex()-Globals.STANDARD_EXPORT_COUNT;
+                  dir = (String)(Globals.prefs.customExports.getElementAt(index)[1]);
+                  File f = new File(dir);
+                  lfName = f.getName();
+                  lfName = lfName.substring(0, lfName.indexOf("."));
+                  // Remove file name - we want the directory only.
+                  dir = f.getParent()+System.getProperty("file.separator");
+              }
+              final String format = lfName,
+                  directory = dir;
+
+              try {
+                  BibtexEntry[] bes = mainTable.getSelectedEntries();
+                  StringWriter sw = new StringWriter();
+                  FileActions.exportEntries(database, bes, format, custom, directory, sw);
+                  ClipboardOwner owner = new ClipboardOwner() {
+                    public void lostOwnership(Clipboard clipboard, Transferable content) {}
+                  };
+                  //StringSelection ss = new StringSelection(sw.toString());
+                  RtfSelection rs = new RtfSelection(sw.toString());
+                     Toolkit.getDefaultToolkit().getSystemClipboard()
+                        .setContents(rs, owner);
+                  message = Globals.lang("Entries exported to clipboard")+": "+bes.length;
+              } catch (Exception ex) {
+                  ex.printStackTrace();
+              }
+              }
+
+              public void update() {
+              output(message);
+              }
+
+          });
+
+
+
+        actions.put("abbreviateIso", new AbbreviateAction(this, true));
+        actions.put("abbreviateMedline", new AbbreviateAction(this, false));
+        actions.put("unabbreviate", new UnabbreviateAction(this));
+        actions.put("autoSetPdf", new AutoSetExternalFileForEntries(this, "pdf"));
+        actions.put("autoSetPs", new AutoSetExternalFileForEntries(this, "ps"));
+
+    }
+
+    /**
+     * This method is called from JabRefFrame is a database specific
+     * action is requested by the user. Runs the command if it is
+     * defined, or prints an error message to the standard error
+     * stream.
+     *
+     * @param _command The name of the command to run.
+    */
+    public void runCommand(String _command) {
+      final String command = _command;
+      //(new Thread() {
+      //  public void run() {
+          if (actions.get(command) == null)
+            Util.pr("No action defined for'" + command + "'");
+            else {
+        Object o = actions.get(command);
+        try {
+            if (o instanceof BaseAction)
+            ((BaseAction)o).action();
+            else {
+            // This part uses Spin's features:
+            Worker wrk = ((AbstractWorker)o).getWorker();
+            // The Worker returned by getWorker() has been wrapped
+            // by Spin.off(), which makes its methods be run in
+            // a different thread from the EDT.
+            CallBack clb = ((AbstractWorker)o).getCallBack();
+
+            ((AbstractWorker)o).init(); // This method runs in this same thread, the EDT.
+            // Useful for initial GUI actions, like printing a message.
+
+            // The CallBack returned by getCallBack() has been wrapped
+            // by Spin.over(), which makes its methods be run on
+            // the EDT.
+            wrk.run(); // Runs the potentially time-consuming action
+            // without freezing the GUI. The magic is that THIS line
+            // of execution will not continue until run() is finished.
+            clb.update(); // Runs the update() method on the EDT.
+            }
+        } catch (Throwable ex) {
+            // If the action has blocked the JabRefFrame before crashing, we need to unblock it.
+            // The call to unblock will simply hide the glasspane, so there is no harm in calling
+            // it even if the frame hasn't been blocked.
+            frame.unblock();
+            ex.printStackTrace();
+        }
+        }
+      //  }
+      //}).start();
+    }
+
+    private boolean saveDatabase(File file, boolean selectedOnly, String encoding) throws SaveException {
+        SaveSession session;
+        frame.block();
+        try {
+            if (!selectedOnly)
+                session = FileActions.saveDatabase(database, metaData, file,
+                                           Globals.prefs, false, false, encoding);
+            else
+                session = FileActions.savePartOfDatabase(database, metaData, file,
+                                               Globals.prefs, mainTable.getSelectedEntries(), encoding);
+
+        } catch (SaveException ex) {
+            if (ex.specificEntry()) {
+                // Error occured during processing of
+                // be. Highlight it:
+                int row = mainTable.findEntry(ex.getEntry()),
+                    topShow = Math.max(0, row-3);
+                mainTable.setRowSelectionInterval(row, row);
+                mainTable.scrollTo(topShow);
+                showEntry(ex.getEntry());
+            }
+            else ex.printStackTrace();
+
+            JOptionPane.showMessageDialog
+                (frame, Globals.lang("Could not save file")
+                 +".\n"+ex.getMessage(),
+                 Globals.lang("Save database"),
+                 JOptionPane.ERROR_MESSAGE);
+            throw new SaveException("rt");
+
+        } finally {
+            frame.unblock();
+        }
+
+        boolean commit = true;
+        if (!session.getWriter().couldEncodeAll()) {
+              String warning = Globals.lang("The chosen encoding '%0' could not encode the following characters: ",
+                      session.getEncoding())+session.getWriter().getProblemCharacters()
+                      +"\nDo you want to continue?";
+            //int answer = JOptionPane.showConfirmDialog(frame, warning, Globals.lang("Save database"),
+            //        JOptionPane.YES_NO_OPTION);
+            String message = Globals.lang("The chosen encoding '%0' could not encode the following characters: ",
+                      session.getEncoding())+session.getWriter().getProblemCharacters()
+                      +"\nWhat do you want to do?";
+            String tryDiff = Globals.lang("Try different encoding");
+            int answer = JOptionPane.showOptionDialog(frame, message, Globals.lang("Save database"),
+                    JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE, null,
+                    new String[] {Globals.lang("Save"), tryDiff, Globals.lang("Cancel")}, tryDiff);
+
+            if (answer == JOptionPane.NO_OPTION) {
+                // The user wants to use another encoding.
+                Object choice = JOptionPane.showInputDialog(frame, Globals.lang("Select encoding"), Globals.lang("Save database"),
+                        JOptionPane.QUESTION_MESSAGE, null, Globals.ENCODINGS, encoding);
+                if (choice != null) {
+                    String newEncoding = (String)choice;
+                    return saveDatabase(file, selectedOnly, newEncoding);
+                } else
+                    commit = false;
+            } else if (answer == JOptionPane.CANCEL_OPTION)
+                    commit = false;
+
+
+          }
+
+        try {
+            if (commit) {
+                session.commit();
+                this.encoding = encoding; // Make sure to remember which encoding we used.
+            }
+            else
+                session.cancel();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+
+        return commit;
+    }
+
+
+    /**
+     * This method is called from JabRefFrame when the user wants to
+     * create a new entry. If the argument is null, the user is
+     * prompted for an entry type.
+     *
+     * @param type The type of the entry to create.
+     */
+    public void newEntry(BibtexEntryType type) {
+        if (type == null) {
+            // Find out what type is wanted.
+            EntryTypeDialog etd = new EntryTypeDialog(frame);
+            // We want to center the dialog, to make it look nicer.
+            Util.placeDialog(etd, frame);
+            etd.setVisible(true);
+            type = etd.getChoice();
+        }
+        if (type != null) { // Only if the dialog was not cancelled.
+            String id = Util.createNeutralId();
+            final BibtexEntry be = new BibtexEntry(id, type);
+            try {
+                database.insertEntry(be);
+
+                // Set owner/timestamp if options are enabled:
+                ArrayList list = new ArrayList();
+                list.add(be);
+                Util.setAutomaticFields(list);
+
+                // Create an UndoableInsertEntry object.
+                undoManager.addEdit(new UndoableInsertEntry(database, be, BasePanel.this));
+                output(Globals.lang("Added new")+" '"+type.getName().toLowerCase()+"' "
+                       +Globals.lang("entry")+".");
+                final int row = mainTable.findEntry(be);
+
+                // We are going to select the new entry. Before that, make sure that we are in
+                // show-entry mode. If we aren't already in that mode, enter the WILL_SHOW_EDITOR
+                // mode which makes sure the selection will trigger display of the entry editor
+                // and adjustment of the splitter.
+                if (mode != SHOWING_EDITOR) {
+                    mode = WILL_SHOW_EDITOR;
+                }
+
+                highlightEntry(be);  // Selects the entry. The selection listener will open the editor.
+                
+                markBaseChanged(); // The database just changed.
+                new FocusRequester(getEntryEditor(be));
+            } catch (KeyCollisionException ex) {
+                Util.pr(ex.getMessage());
+            }
+        }
+    }
+
+        public void mergeFromBibtex(ParserResult pr,
+                                    boolean importEntries, boolean importStrings,
+                                    boolean importGroups, boolean importSelectorWords)
+                throws KeyCollisionException {
+
+            BibtexDatabase fromDatabase = pr.getDatabase();
+            ArrayList appendedEntries = new ArrayList();
+            ArrayList originalEntries = new ArrayList();
+            BibtexEntry originalEntry;
+            NamedCompound ce = new NamedCompound(Globals.lang("Append database"));
+            MetaData meta = new MetaData(pr.getMetaData(), pr.getDatabase());
+
+            if (importEntries) { // Add entries
+                Iterator i = fromDatabase.getKeySet().iterator();
+                while (i.hasNext()) {
+                    originalEntry = fromDatabase.getEntryById((String) i.next());
+                    BibtexEntry be = (BibtexEntry) (originalEntry.clone());
+                    be.setId(Util.createNeutralId());
+                    database.insertEntry(be);
+                    appendedEntries.add(be);
+                    originalEntries.add(originalEntry);
+                    ce.addEdit(new UndoableInsertEntry(database, be, this));
+                }
+            }
+
+            if (importStrings) {
+                BibtexString bs;
+                int pos = 0;
+                Iterator i = fromDatabase.getStringKeySet().iterator();
+                for (; i.hasNext();) {
+                    bs = (BibtexString) (fromDatabase.getString(i.next()).clone());
+                    if (!database.hasStringLabel(bs.getName())) {
+                        //pos = toDatabase.getStringCount();
+                        database.addString(bs);
+                        ce.addEdit(new UndoableInsertString(this, database, bs));
+                    }
+                }
+            }
+
+            if (importGroups) {
+                GroupTreeNode newGroups = meta.getGroups();
+                if (newGroups != null) {
+
+                    // ensure that there is always only one AllEntriesGroup
+                    if (newGroups.getGroup() instanceof AllEntriesGroup) {
+                        // create a dummy group
+                        ExplicitGroup group = new ExplicitGroup("Imported",
+                                AbstractGroup.INDEPENDENT); // JZTODO lyrics
+                        newGroups.setGroup(group);
+                        for (int i = 0; i < appendedEntries.size(); ++i)
+                            group.addEntry((BibtexEntry) appendedEntries.get(i));
+                    }
+
+                    // groupsSelector is always created, even when no groups
+                    // have been defined. therefore, no check for null is
+                    // required here
+                    frame.groupSelector.addGroups(newGroups, ce);
+                    // for explicit groups, the entries copied to the mother fromDatabase have to
+                    // be "reassigned", i.e. the old reference is removed and the reference
+                    // to the new fromDatabase is added.
+                    GroupTreeNode node;
+                    ExplicitGroup group;
+                    BibtexEntry entry;
+                    for (Enumeration e = newGroups.preorderEnumeration(); e.hasMoreElements();) {
+                        node = (GroupTreeNode) e.nextElement();
+                        if (!(node.getGroup() instanceof ExplicitGroup))
+                            continue;
+                        group = (ExplicitGroup) node.getGroup();
+                        for (int i = 0; i < originalEntries.size(); ++i) {
+                            entry = (BibtexEntry) originalEntries.get(i);
+                            if (group.contains(entry)) {
+                                group.removeEntry(entry);
+                                group.addEntry((BibtexEntry) appendedEntries.get(i));
+                            }
+                        }
+                    }
+                    frame.groupSelector.revalidateGroups();
+                }
+            }
+
+            if (importSelectorWords) {
+                Iterator i = meta.iterator();
+                while (i.hasNext()) {
+                    String s = (String) i.next();
+                    if (s.startsWith(Globals.SELECTOR_META_PREFIX)) {
+                        metaData().putData(s, meta.getData(s));
+                    }
+                }
+            }
+
+            ce.end();
+            undoManager.addEdit(ce);
+            markBaseChanged();
+        }
+
+
+    /**
+     * This method is called from JabRefFrame when the user wants to
+     * create a new entry.
+     * @param bibEntry The new entry.
+     */
+    public void insertEntry(BibtexEntry bibEntry)
+    {
+      if (bibEntry != null)
+      {
+        try
+        {
+          database.insertEntry(bibEntry) ;
+          if (Globals.prefs.getBoolean("useOwner"))
+            // Set owner field to default value
+            bibEntry.setField(Globals.OWNER, Globals.prefs.get("defaultOwner") );
+            // Create an UndoableInsertEntry object.
+            undoManager.addEdit(new UndoableInsertEntry(database, bibEntry, BasePanel.this));
+            output(Globals.lang("Added new")+" '"
+                   +bibEntry.getType().getName().toLowerCase()+"' "
+                   +Globals.lang("entry")+".");
+            int row = mainTable.findEntry(bibEntry);
+
+            mainTable.clearSelection();
+            mainTable.scrollTo(row);
+            markBaseChanged(); // The database just changed.
+            if (Globals.prefs.getBoolean("autoOpenForm"))
+            {
+                  showEntry(bibEntry);
+            }
+        } catch (KeyCollisionException ex) { Util.pr(ex.getMessage()); }
+      }
+    }
+
+    public void createMainTable() {
+        //Comparator comp = new FieldComparator("author");
+
+        GlazedEntrySorter eventList = new GlazedEntrySorter(database.getEntryMap(), null);
+        // Must initialize sort columns somehow:
+
+        database.addDatabaseChangeListener(eventList);
+        groupFilterList = new FilterList(eventList.getTheList(), NoSearchMatcher.INSTANCE);
+        searchFilterList = new FilterList(groupFilterList, NoSearchMatcher.INSTANCE);
+        //final SortedList sortedList = new SortedList(searchFilterList, null);
+        MainTableFormat tableFormat = new MainTableFormat(this);
+        tableFormat.updateTableFormat();
+        //EventTableModel tableModel = new EventTableModel(sortedList, tableFormat);
+        mainTable = new MainTable(/*tableModel, */tableFormat, searchFilterList);
+        selectionListener = new MainTableSelectionListener(this, mainTable);
+        mainTable.updateFont();
+        mainTable.addSelectionListener(selectionListener);
+        mainTable.addMouseListener(selectionListener);
+
+        // Add the listener that will take care of highlighting groups as the selection changes:
+        groupsHighlightListener = new ListEventListener() {
+            public void listChanged(ListEvent listEvent) {
+                if (Globals.prefs.getBoolean("highlightGroupsMatchingAny"))
+                    getGroupSelector().showMatchingGroups(
+                            mainTable.getSelectedEntries(), false);
+                else if (Globals.prefs.getBoolean("highlightGroupsMatchingAll"))
+                    getGroupSelector().showMatchingGroups(
+                            mainTable.getSelectedEntries(), true);
+                else // no highlight
+                    getGroupSelector().showMatchingGroups(null, true);
+            }
+        };
+        mainTable.addSelectionListener(groupsHighlightListener);
+
+        mainTable.getActionMap().put("cut", new AbstractAction() {
+                public void actionPerformed(ActionEvent e) {
+                    try { runCommand("cut");
+                    } catch (Throwable ex) {
+                        ex.printStackTrace();
+                    }
+                }
+            });
+        mainTable.getActionMap().put("copy", new AbstractAction() {
+                public void actionPerformed(ActionEvent e) {
+                    try { runCommand("copy");
+                    } catch (Throwable ex) {
+                        ex.printStackTrace();
+                    }
+                }
+            });
+        mainTable.getActionMap().put("paste", new AbstractAction() {
+                public void actionPerformed(ActionEvent e) {
+                    try { runCommand("paste");
+                    } catch (Throwable ex) {
+                        ex.printStackTrace();
+                    }
+                }
+            });
+
+        mainTable.addKeyListener(new KeyAdapter() {
+
+                public void keyPressed(KeyEvent e) {
+                    final int keyCode = e.getKeyCode();
+                    final TreePath path = frame.groupSelector.getSelectionPath();
+                    final GroupTreeNode node = path == null ? null : (GroupTreeNode) path.getLastPathComponent();
+
+                    if (e.isControlDown()) {
+                        switch (keyCode) {
+                        // The up/down/left/rightkeystrokes are displayed in the
+                        // GroupSelector's popup menu, so if they are to be changed,
+                        // edit GroupSelector.java accordingly!
+                        case KeyEvent.VK_UP:
+                            e.consume();
+                            if (node != null)
+                                frame.groupSelector.moveNodeUp(node, true);
+                            break;
+                        case KeyEvent.VK_DOWN:
+                            e.consume();
+                            if (node != null)
+                                frame.groupSelector.moveNodeDown(node, true);
+                            break;
+                        case KeyEvent.VK_LEFT:
+                            e.consume();
+                            if (node != null)
+                                frame.groupSelector.moveNodeLeft(node, true);
+                            break;
+                        case KeyEvent.VK_RIGHT:
+                            e.consume();
+                            if (node != null)
+                                frame.groupSelector.moveNodeRight(node, true);
+                            break;
+                        case KeyEvent.VK_PAGE_DOWN:
+                            frame.nextTab.actionPerformed(null);
+                            e.consume();
+                            break;
+                        case KeyEvent.VK_PAGE_UP:
+                            frame.prevTab.actionPerformed(null);
+                            e.consume();
+                            break;
+                        }
+                    } else if (keyCode == KeyEvent.VK_ENTER){
+                        e.consume();
+                        try { runCommand("edit");
+                        } catch (Throwable ex) {
+                            ex.printStackTrace();
+                        }
+                    }
+                }
+        });
+    }
+
+    public void setupMainPanel() {
+        //System.out.println("setupMainPanel");
+        //splitPane = new com.jgoodies.uif_lite.component.UIFSplitPane(JSplitPane.VERTICAL_SPLIT);
+        splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
+        splitPane.setDividerSize(GUIGlobals.SPLIT_PANE_DIVIDER_SIZE);
+        // We replace the default FocusTraversalPolicy with a subclass
+        // that only allows FieldEditor components to gain keyboard focus,
+        // if there is an entry editor open.
+        /*splitPane.setFocusTraversalPolicy(new LayoutFocusTraversalPolicy() {
+                protected boolean accept(Component c) {
+                    Util.pr("jaa");
+                    if (showing == null)
+                        return super.accept(c);
+                    else
+                        return (super.accept(c) &&
+                                (c instanceof FieldEditor));
+                }
+                });*/
+
+        createMainTable();
+
+        splitPane.setTopComponent(mainTable.getPane());
+
+        //setupTable();
+        // If an entry is currently being shown, make sure it stays shown,
+        // otherwise set the bottom component to null.
+        if (mode == SHOWING_PREVIEW) {
+            mode = SHOWING_NOTHING;
+            int row = mainTable.findEntry(currentPreview.entry);
+            if (row >= 0)
+                mainTable.setRowSelectionInterval(row, row);
+
+        }
+        else if (mode == SHOWING_EDITOR) {
+            mode = SHOWING_NOTHING;
+            /*int row = mainTable.findEntry(currentEditor.entry);
+            if (row >= 0)
+                mainTable.setRowSelectionInterval(row, row);
+            */
+            //showEntryEditor(currentEditor);
+        } else
+            splitPane.setBottomComponent(null);
+
+
+        setLayout(new BorderLayout());
+        removeAll();
+        add(splitPane, BorderLayout.CENTER);
+        //add(contentPane, BorderLayout.CENTER);
+
+        //add(sidePaneManager.getPanel(), BorderLayout.WEST);
+        //add(splitPane, BorderLayout.CENTER);
+
+    //setLayout(gbl);
+    //con.fill = GridBagConstraints.BOTH;
+    //con.weighty = 1;
+    //con.weightx = 0;
+    //gbl.setConstraints(sidePaneManager.getPanel(), con);
+    //con.weightx = 1;
+    //gbl.setConstraints(splitPane, con);
+        //mainPanel.setDividerLocation(GUIGlobals.SPLIT_PANE_DIVIDER_LOCATION);
+        //setDividerSize(GUIGlobals.SPLIT_PANE_DIVIDER_SIZE);
+        //setResizeWeight(0);
+        splitPane.revalidate();
+        revalidate();
+        repaint();
+    }
+
+
+    /**
+     * This method is called after a database has been parsed. The
+     * hashmap contains the contents of all comments in the .bib file
+     * that started with the meta flag (GUIGlobals.META_FLAG).
+     * In this method, the meta data are input to their respective
+     * handlers.
+     *
+     * @param meta Metadata to input.
+     */
+    public void parseMetaData(HashMap meta) {
+        metaData = new MetaData(meta,database());
+
+    }
+
+    /*
+    public void refreshTable() {
+        //System.out.println("hiding="+hidingNonHits+"\tlastHits="+lastSearchHits);
+        // This method is called by EntryTypeForm when a field value is
+        // stored. The table is scheduled for repaint.
+        entryTable.assureNotEditing();
+        //entryTable.invalidate();
+        BibtexEntry[] bes = entryTable.getSelectedEntries();
+    if (hidingNonHits)
+        tableModel.update(lastSearchHits);
+    else
+        tableModel.update();
+    //tableModel.remap();
+        if ((bes != null) && (bes.length > 0))
+            selectEntries(bes, 0);
+
+    //long toc = System.currentTimeMillis();
+    //	Util.pr("Refresh took: "+(toc-tic)+" ms");
+    } */
+
+    public void updatePreamble() {
+        if (preambleEditor != null)
+            preambleEditor.updatePreamble();
+    }
+
+    public void assureStringDialogNotEditing() {
+        if (stringDialog != null)
+            stringDialog.assureNotEditing();
+    }
+
+    public void updateStringDialog() {
+        if (stringDialog != null)
+            stringDialog.refreshTable();
+    }
+
+    public void updateEntryPreviewToRow(BibtexEntry e) {
+
+    }
+
+    public void adjustSplitter() {
+        int mode = getMode();
+        if (mode == SHOWING_PREVIEW) {
+            splitPane.setDividerLocation(splitPane.getHeight()-GUIGlobals.PREVIEW_PANEL_HEIGHT);
+        } else {
+            splitPane.setDividerLocation(GUIGlobals.VERTICAL_DIVIDER_LOCATION);
+
+        }
+    }
+
+
+
+    /**
+     * Stores the source view in the entry editor, if one is open, has the source view
+     * selected and the source has been edited.
+     * @return boolean false if there is a validation error in the source panel, true otherwise.
+     */
+    public boolean entryEditorAllowsChange() {
+      Component c = splitPane.getBottomComponent();
+      if ((c != null) && (c instanceof EntryEditor)) {
+        return ((EntryEditor)c).lastSourceAccepted();
+      }
+      else
+        return true;
+    }
+
+    public void moveFocusToEntryEditor() {
+      Component c = splitPane.getBottomComponent();
+      if ((c != null) && (c instanceof EntryEditor)) {
+        new FocusRequester(c);
+      }
+    }
+
+    /**
+     * Ensure that no preview is shown. Called when preview is turned off. Must chech if
+     * a preview is in fact visible before doing anything rash.
+     */
+    public void hidePreview() {
+        Globals.prefs.putBoolean("previewEnabled", false);
+
+      Component c = splitPane.getBottomComponent();
+      if ((c != null) && !(c instanceof EntryEditor))
+        splitPane.setBottomComponent(null);
+    }
+
+    public boolean isShowingEditor() {
+      return ((splitPane.getBottomComponent() != null)
+              && (splitPane.getBottomComponent() instanceof EntryEditor));
+    }
+
+    public void showEntry(final BibtexEntry be) {
+        if (showing == be) {
+            if (splitPane.getBottomComponent() == null) {
+                // This is the special occasion when showing is set to an
+                // entry, but no entry editor is in fact shown. This happens
+                // after Preferences dialog is closed, and it means that we
+                // must make sure the same entry is shown again. We do this by
+                // setting showing to null, and recursively calling this method.
+                showing = null;
+                showEntry(be);
+            } else {
+              // The correct entry is already being shown. Make sure the editor
+              // is updated.
+              ((EntryEditor)splitPane.getBottomComponent()).updateAllFields();
+
+            }
+            return;
+
+        }
+
+        EntryEditor form;
+        int divLoc = -1;
+        String visName = null;
+        if (showing != null) {
+            visName = ((EntryEditor)splitPane.getBottomComponent()).
+                getVisiblePanelName();
+        }
+        if (showing != null)
+            divLoc = splitPane.getDividerLocation();
+
+        if (entryEditors.containsKey(be.getType().getName())) {
+            // We already have an editor for this entry type.
+            form = (EntryEditor)entryEditors.get
+                ((be.getType().getName()));
+            form.switchTo(be);
+            if (visName != null)
+                form.setVisiblePanel(visName);
+            splitPane.setBottomComponent(form);
+            //highlightEntry(be);
+        } else {
+            // We must instantiate a new editor for this type.
+            form = new EntryEditor(frame, BasePanel.this, be);
+            if (visName != null)
+                form.setVisiblePanel(visName);
+            splitPane.setBottomComponent(form);
+
+            //highlightEntry(be);
+            entryEditors.put(be.getType().getName(), form);
+
+        }
+        if (divLoc > 0) {
+          splitPane.setDividerLocation(divLoc);
+        }
+        else
+            splitPane.setDividerLocation
+                (GUIGlobals.VERTICAL_DIVIDER_LOCATION);
+        //new FocusRequester(form);
+        //form.requestFocus();
+
+        showing = be;
+        setEntryEditorEnabled(true); // Make sure it is enabled.
+    }
+
+    /**
+     * Get an entry editor ready to edit the given entry. If an appropriate editor is already
+     * cached, it will be updated and returned.
+     * @param entry The entry to be edited.
+     * @return A suitable entry editor.
+     */
+    public EntryEditor getEntryEditor(BibtexEntry entry) {
+        EntryEditor form;
+        if (entryEditors.containsKey(entry.getType().getName())) {
+            EntryEditor visibleNow = currentEditor;
+            // We already have an editor for this entry type.
+            form = (EntryEditor)entryEditors.get
+                ((entry.getType().getName()));
+
+            form.switchTo(entry);
+            //if (visName != null)
+            //    form.setVisiblePanel(visName);
+        } else {
+            // We must instantiate a new editor for this type.
+            form = new EntryEditor(frame, BasePanel.this, entry);
+            //if (visName != null)
+            //    form.setVisiblePanel(visName);
+
+            entryEditors.put(entry.getType().getName(), form);
+        }
+        return form;
+    }
+
+    public EntryEditor getCurrentEditor() {
+        return currentEditor;
+    }
+
+    /**
+     * Sets the given entry editor as the bottom component in the split pane. If an entry editor already
+     * was shown, makes sure that the divider doesn't move.
+     * Updates the mode to SHOWING_EDITOR.
+     * @param editor The entry editor to add.
+     */
+    public void showEntryEditor(EntryEditor editor) {
+        int oldSplitterLocation = -1;
+        if (mode == SHOWING_EDITOR)
+            oldSplitterLocation = splitPane.getDividerLocation();
+        boolean adjustSplitter = (mode == WILL_SHOW_EDITOR);
+        mode = SHOWING_EDITOR;
+        currentEditor = editor;
+        splitPane.setBottomComponent(editor);
+        if (oldSplitterLocation > 0)
+            splitPane.setDividerLocation(oldSplitterLocation);
+        if (adjustSplitter) {
+            adjustSplitter();
+            //new FocusRequester(editor);
+        }
+    }
+
+    /**
+     * Sets the given preview panel as the bottom component in the split panel.
+     * Updates the mode to SHOWING_PREVIEW.
+     * @param preview The preview to show.
+     */
+    public void showPreview(PreviewPanel preview) {
+        mode = SHOWING_PREVIEW;
+        currentPreview = preview;
+        splitPane.setBottomComponent(preview.getPane());
+    }
+
+    /**
+     * Removes the bottom component.
+     */
+    public void hideBottomComponent() {
+        mode = SHOWING_NOTHING;
+        splitPane.setBottomComponent(null);
+    }
+
+    /**
+     * This method selects the given entry, and scrolls it into view in the table.
+     * If an entryEditor is shown, it is given focus afterwards.
+     */
+    public void highlightEntry(final BibtexEntry be) {
+        //SwingUtilities.invokeLater(new Thread() {
+        //     public void run() {
+                 final int row = mainTable.findEntry(be);
+                 if (row >= 0) {
+                    mainTable.setRowSelectionInterval(row, row);
+                    //entryTable.setActiveRow(row);
+                    mainTable.ensureVisible(row);
+                 }
+        //     }
+        //});
+    }
+
+
+    /**
+     * This method is called from an EntryEditor when it should be closed. We relay
+     * to the selection listener, which takes care of the rest.
+     * @param editor The entry editor to close.
+     */
+    public void entryEditorClosing(EntryEditor editor) {
+        selectionListener.entryEditorClosing(editor);
+    }
+
+    /**
+     * This method selects the given enties.
+     * If an entryEditor is shown, it is given focus afterwards.
+     */
+    /*public void selectEntries(final BibtexEntry[] bes, final int toScrollTo) {
+
+        SwingUtilities.invokeLater(new Thread() {
+             public void run() {
+                 int rowToScrollTo = 0;
+                 entryTable.revalidate();
+                 entryTable.clearSelection();
+                 loop: for (int i=0; i<bes.length; i++) {
+                    if (bes[i] == null)
+                        continue loop;
+                    int row = tableModel.getNumberFromName(bes[i].getId());
+                    if (i==toScrollTo)
+                    rowToScrollTo = row;
+                    if (row >= 0)
+                        entryTable.addRowSelectionIntervalQuietly(row, row);
+                 }
+                 entryTable.ensureVisible(rowToScrollTo);
+                 Component comp = splitPane.getBottomComponent();
+                 //if (comp instanceof EntryEditor)
+                 //    comp.requestFocus();
+             }
+        });
+    } */
+
+    /**
+     * Closes the entry editor if it is showing the given entry.
+     *
+     * @param be a <code>BibtexEntry</code> value
+     */
+    public void ensureNotShowing(BibtexEntry be) {
+        if ((mode == SHOWING_EDITOR) && (currentEditor.getEntry() == be)) {
+            selectionListener.entryEditorClosing(currentEditor);
+        }
+    }
+
+    public void updateEntryEditorIfShowing() {
+        if (mode == SHOWING_EDITOR) {
+            if (currentEditor.getType() != currentEditor.getEntry().getType()) {
+                // The entry has changed type, so we must get a new editor.
+                showing = null;
+                EntryEditor newEditor = getEntryEditor(currentEditor.getEntry());
+                showEntryEditor(newEditor);
+            } else {
+                currentEditor.updateAllFields();
+                currentEditor.updateSource();
+            }
+        }
+    }
+
+    /**
+     * If an entry editor is showing, make sure its currently focused field
+     * stores its changes, if any.
+     */
+    public void storeCurrentEdit() {
+        if (isShowingEditor()) {
+            EntryEditor editor = (EntryEditor)splitPane.getBottomComponent();
+            editor.storeCurrentEdit();
+        }
+
+    }
+
+    /**
+     * This method iterates through all existing entry editors in this
+     * BasePanel, telling each to update all its instances of
+     * FieldContentSelector. This is done to ensure that the list of words
+     * in each selector is up-to-date after the user has made changes in
+     * the Manage dialog.
+     */
+    public void updateAllContentSelectors() {
+        for (Iterator i=entryEditors.keySet().iterator(); i.hasNext();) {
+            EntryEditor ed = (EntryEditor)entryEditors.get(i.next());
+            ed.updateAllContentSelectors();
+        }
+    }
+
+    public void rebuildAllEntryEditors() {
+        for (Iterator i=entryEditors.keySet().iterator(); i.hasNext();) {
+            EntryEditor ed = (EntryEditor)entryEditors.get(i.next());
+            ed.rebuildPanels();
+        }
+
+    }
+
+    public void markBaseChanged() {
+        baseChanged = true;
+
+        // Put an asterix behind the file name to indicate the
+        // database has changed.
+        String oldTitle = frame.getTabTitle(this);
+        if (!oldTitle.endsWith("*"))
+            frame.setTabTitle(this, oldTitle+"*");
+
+        // If the status line states that the base has been saved, we
+        // remove this message, since it is no longer relevant. If a
+        // different message is shown, we leave it.
+        if (frame.statusLine.getText().startsWith("Saved database"))
+            frame.output(" ");
+    }
+
+    public void markNonUndoableBaseChanged() {
+        nonUndoableChange = true;
+        markBaseChanged();
+    }
+
+    public synchronized void markChangedOrUnChanged() {
+        if (undoManager.hasChanged()) {
+            if (!baseChanged)
+                markBaseChanged();
+        }
+        else if (baseChanged && !nonUndoableChange) {
+            baseChanged = false;
+            if (file != null)
+                frame.setTabTitle(BasePanel.this, file.getName());
+            else
+                frame.setTabTitle(BasePanel.this, Globals.lang("untitled"));
+        }
+    }
+
+    /**
+     * Selects a single entry, and scrolls the table to center it.
+     *
+     * @param pos Current position of entry to select.
+     *
+     */
+    public void selectSingleEntry(int pos) {
+        mainTable.clearSelection();
+        mainTable.addRowSelectionInterval(pos, pos);
+        mainTable.scrollToCenter(pos, 0);
+    }
+
+    /* *
+     * Selects all entries with a non-zero value in the field
+     * @param field <code>String</code> field name.
+     */
+/*    public void selectResults(String field) {
+      LinkedList intervals = new LinkedList();
+      int prevStart = -1, prevToSel = 0;
+      // First we build a list of intervals to select, without touching the table.
+      for (int i = 0; i < entryTable.getRowCount(); i++) {
+        String value = (String) (database.getEntryById
+                                 (tableModel.getIdForRow(i)))
+            .getField(field);
+        if ( (value != null) && !value.equals("0")) {
+          if (prevStart < 0)
+            prevStart = i;
+          prevToSel = i;
+        }
+        else if (prevStart >= 0) {
+          intervals.add(new int[] {prevStart, prevToSel});
+          prevStart = -1;
+        }
+      }
+      // Then select those intervals, if any.
+      if (intervals.size() > 0) {
+        entryTable.setSelectionListenerEnabled(false);
+        entryTable.clearSelection();
+        for (Iterator i=intervals.iterator(); i.hasNext();) {
+          int[] interval = (int[])i.next();
+          entryTable.addRowSelectionInterval(interval[0], interval[1]);
+        }
+        entryTable.setSelectionListenerEnabled(true);
+      }
+  */
+
+    public void setSearchMatcher(SearchMatcher matcher) {
+        searchFilterList.setMatcher(matcher);
+    }
+
+    public void setGroupMatcher(Matcher matcher) {
+        groupFilterList.setMatcher(matcher);
+    }
+
+    public void stopShowingSearchResults() {
+        searchFilterList.setMatcher(NoSearchMatcher.INSTANCE);
+    }
+
+    public void stopShowingGroup() {
+        groupFilterList.setMatcher(NoSearchMatcher.INSTANCE);
+
+     }
+
+     public BibtexDatabase getDatabase(){
+        return database ;
+    }
+
+    public void preambleEditorClosing() {
+        preambleEditor = null;
+    }
+
+    public void stringsClosing() {
+        stringDialog = null;
+    }
+
+    public void changeType(BibtexEntry entry, BibtexEntryType type) {
+      changeType(new BibtexEntry[] {entry}, type);
+    }
+
+    public void changeType(BibtexEntryType type) {
+      BibtexEntry[] bes = mainTable.getSelectedEntries();
+      changeType(bes, type);
+    }
+
+    public void changeType(BibtexEntry[] bes, BibtexEntryType type) {
+
+        if ((bes == null) || (bes.length == 0)) {
+            output("First select the entries you wish to change type "+
+                   "for.");
+            return;
+        }
+        if (bes.length > 1) {
+            int choice = JOptionPane.showConfirmDialog
+                (this, "Multiple entries selected. Do you want to change"
+                 +"\nthe type of all these to '"+type.getName()+"'?",
+                 "Change type", JOptionPane.YES_NO_OPTION,
+                 JOptionPane.WARNING_MESSAGE);
+            if (choice == JOptionPane.NO_OPTION)
+                return;
+        }
+
+        NamedCompound ce = new NamedCompound(Globals.lang("change type"));
+        for (int i=0; i<bes.length; i++) {
+            ce.addEdit(new UndoableChangeType(bes[i],
+                                              bes[i].getType(),
+                                              type));
+            bes[i].setType(type);
+        }
+
+        output(Globals.lang("Changed type to")+" '"+type.getName()+"' "
+               +Globals.lang("for")+" "+bes.length
+               +" "+Globals.lang("entries")+".");
+        ce.end();
+        undoManager.addEdit(ce);
+        markBaseChanged();
+        updateEntryEditorIfShowing();
+    }
+
+    public boolean showDeleteConfirmationDialog(int numberOfEntries) {
+        if (Globals.prefs.getBoolean("confirmDelete")) {
+            String msg = Globals.lang("Really delete the selected")
+                + " " + Globals.lang("entry") + "?",
+                title = Globals.lang("Delete entry");
+            if (numberOfEntries > 1) {
+                msg = Globals.lang("Really delete the selected")
+                    + " " + numberOfEntries + " " + Globals.lang("entries") + "?";
+                title = Globals.lang("Delete multiple entries");
+            }
+
+            CheckBoxMessage cb = new CheckBoxMessage
+                (msg, Globals.lang("Disable this confirmation dialog"), false);
+
+            int answer = JOptionPane.showConfirmDialog(frame, cb, title,
+                                                       JOptionPane.YES_NO_OPTION,
+                                                       JOptionPane.QUESTION_MESSAGE);
+            if (cb.isSelected())
+                Globals.prefs.putBoolean("confirmDelete", false);
+            return (answer == JOptionPane.YES_OPTION);
+        } else return true;
+
+    }
+
+    /**
+     * Activates or deactivates the entry preview, depending on the argument.
+     * When deactivating, makes sure that any visible preview is hidden.
+     * @param enabled
+     */
+    public void setPreviewActive(boolean enabled) {
+        selectionListener.setPreviewActive(enabled);
+    }
+
+
+    class UndoAction extends BaseAction {
+        public void action() {
+            try {
+                String name = undoManager.getUndoPresentationName();
+                undoManager.undo();
+                markBaseChanged();
+                frame.output(name);
+            } catch (CannotUndoException ex) {
+                frame.output(Globals.lang("Nothing to undo")+".");
+            }
+            // After everything, enable/disable the undo/redo actions
+            // appropriately.
+            //updateUndoState();
+            //redoAction.updateRedoState();
+            markChangedOrUnChanged();
+        }
+    }
+
+    class RedoAction extends BaseAction {
+        public void action() {
+            try {
+                String name = undoManager.getRedoPresentationName();
+                undoManager.redo();
+                markBaseChanged();
+                frame.output(name);
+            } catch (CannotRedoException ex) {
+                frame.output(Globals.lang("Nothing to redo")+".");
+            }
+            // After everything, enable/disable the undo/redo actions
+            // appropriately.
+            //updateRedoState();
+            //undoAction.updateUndoState();
+            markChangedOrUnChanged();
+        }
+    }
+
+    // Method pertaining to the ClipboardOwner interface.
+    public void lostOwnership(Clipboard clipboard, Transferable contents) {}
+
+
+  public void setEntryEditorEnabled(boolean enabled) {
+    if ((showing != null) && (splitPane.getBottomComponent() instanceof EntryEditor)) {
+          EntryEditor ed = (EntryEditor)splitPane.getBottomComponent();
+          if (ed.isEnabled() != enabled)
+            ed.setEnabled(enabled);
+    }
+  }
+
+  public String fileMonitorHandle() { return fileMonitorHandle; }
+
+    public void fileUpdated() {
+      if (saving)
+        return; // We are just saving the file, so this message is most likely due
+      // to bad timing. If not, we'll handle it on the next polling.
+      //Util.pr("File '"+file.getPath()+"' has been modified.");
+      updatedExternally = true;
+
+      // Adding the sidepane component is Swing work, so we must do this in the Swing
+      // thread:
+      Thread t = new Thread() {
+        public void run() {
+            // Test: running scan automatically in background
+            ChangeScanner scanner = new ChangeScanner(frame, BasePanel.this);
+            scanner.changeScan(BasePanel.this.file());
+            try {
+                scanner.join();
+            } catch (InterruptedException e) {
+                e.printStackTrace();
+            }
+
+            if (scanner.changesFound()) {
+                FileUpdatePanel pan = new FileUpdatePanel(frame, BasePanel.this, sidePaneManager, file, scanner);
+          sidePaneManager.add("fileUpdate", pan);
+                setUpdatedExternally(false);
+                //scanner.displayResult();
+            } else {
+                setUpdatedExternally(false);
+                //System.out.println("No changes found.");
+        }
+
+        }
+      };
+      SwingUtilities.invokeLater(t);
+
+    }
+
+      public void fileRemoved() {
+        Util.pr("File '"+file.getPath()+"' has been deleted.");
+      }
+
+
+      public void cleanUp() {
+        if (fileMonitorHandle != null)
+          Globals.fileUpdateMonitor.removeUpdateListener(fileMonitorHandle);
+      }
+
+  public void setUpdatedExternally(boolean b) {
+    updatedExternally = b;
+  }
+
+    /**
+     * Get an array containing the currently selected entries.
+     *
+     * @return An array containing the selected entries.
+     */
+    public BibtexEntry[] getSelectedEntries() {
+        return mainTable.getSelectedEntries();
+    }
+
+    /**
+     * Get a String containing a comma-separated list of the bibtex keys
+     * of the selected entries.
+     *
+     * @return A comma-separated list of the keys of the selected entries.
+     */
+    public String getKeysForSelection() {
+        List entries = mainTable.getSelected();
+        StringBuffer result = new StringBuffer();
+        String citeKey = "";//, message = "";
+        boolean first = true;
+        for (Iterator i = entries.iterator(); i.hasNext();) {
+            BibtexEntry bes = (BibtexEntry) i.next();
+            citeKey = (String) bes.getField(GUIGlobals.KEY_FIELD);
+            // if the key is empty we give a warning and ignore this entry
+            if (citeKey == null || citeKey.equals(""))
+                continue;
+            if (first) {
+                result.append(citeKey);
+                first = false;
+            } else {
+                result.append(",").append(citeKey);
+            }
+        }
+        return result.toString();
+    }
+
+    public GroupSelector getGroupSelector() {
+        return frame.groupSelector;
+    }
+}
diff --git a/src/java/net/sf/jabref/BibtexDatabase.java b/src/java/net/sf/jabref/BibtexDatabase.java
new file mode 100644
index 0000000..6208906
--- /dev/null
+++ b/src/java/net/sf/jabref/BibtexDatabase.java
@@ -0,0 +1,530 @@
+/*
+Copyright (C) 2003 David Weitzman, 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
+
+Note:
+Modified for use in JabRef
+
+*/
+
+
+// created by : ?
+//
+// modified : r.nagel 23.08.2004
+//                - insert getEntryByKey() methode needed by AuxSubGenerator
+
+package net.sf.jabref;
+
+import java.beans.*;
+import java.util.*;
+
+import javax.swing.JOptionPane;
+
+import net.sf.jabref.groups.GroupSelector;
+
+public class BibtexDatabase
+{
+    Map _entries = new Hashtable();
+    String _preamble = null;
+    HashMap _strings = new HashMap();
+    Vector _strings_ = new Vector();
+    Hashtable _autoCompleters = null;
+    Set changeListeners = new HashSet();
+    private BibtexDatabase ths = this;
+
+    private HashMap allKeys  = new HashMap();	// use a map instead of a set since i need to know how many of each key is inthere
+
+    /* Entries are stored in a HashMap with the ID as key.
+     * What happens if someone changes a BibtexEntry's ID
+     * after it has been added to this BibtexDatabase?
+     * The key of that entry would be the old ID, not the new one.
+     * Use a PropertyChangeListener to identify an ID change
+     * and update the Map.
+     */
+    private final VetoableChangeListener listener =
+        new VetoableChangeListener()
+        {
+            public void vetoableChange(PropertyChangeEvent pce)
+                throws PropertyVetoException
+            {
+		if (pce.getPropertyName() == null)
+		    fireDatabaseChanged (new DatabaseChangeEvent(ths, DatabaseChangeEvent.CHANGING_ENTRY, (BibtexEntry)pce.getSource()));
+                else if ("id".equals(pce.getPropertyName()))
+                {
+                    // locate the entry under its old key
+                    Object oldEntry =
+                        _entries.remove((String) pce.getOldValue());
+
+                    if (oldEntry != pce.getSource())
+                    {
+                        // Something is very wrong!
+                        // The entry under the old key isn't
+                        // the one that sent this event.
+                        // Restore the old state.
+                        _entries.put(pce.getOldValue(), oldEntry);
+                        throw new PropertyVetoException("Wrong old ID", pce);
+                    }
+
+                    if (_entries.get(pce.getNewValue()) != null)
+                    {
+                        _entries.put(pce.getOldValue(), oldEntry);
+                        throw new PropertyVetoException
+                            ("New ID already in use, please choose another",
+                            pce);
+                    }
+
+                    // and re-file this entry
+                    _entries.put((String) pce.getNewValue(),
+                        (BibtexEntry) pce.getSource());
+                } else {
+		    fireDatabaseChanged (new DatabaseChangeEvent(ths, DatabaseChangeEvent.CHANGED_ENTRY, (BibtexEntry)pce.getSource()));
+		    //Util.pr(pce.getSource().toString()+"\n"+pce.getPropertyName()
+		    //    +"\n"+pce.getNewValue());
+		}
+            }
+        };
+
+    /**
+     * Returns the number of entries.
+     */
+    public synchronized int getEntryCount()
+    {
+        return _entries.size();
+    }
+
+    /**
+     * Returns a Set containing the keys to all entries.
+     * Use getKeySet().iterator() to iterate over all entries.
+     */
+    public synchronized Set getKeySet()
+    {
+        return _entries.keySet();
+    }
+
+    /**
+     * Returns an EntrySorter with the sorted entries from this base,
+     * sorted by the given Comparator.
+     */
+    public synchronized EntrySorter getSorter(java.util.Comparator comp) {
+	EntrySorter sorter = new EntrySorter(_entries, comp);
+	addDatabaseChangeListener(sorter);
+        return sorter;
+    }
+
+    /**
+     * Just temporary, for testing purposes....
+     * @return
+     */
+    public Map getEntryMap() { return _entries; }
+
+    /**
+     * Returns the entry with the given ID (-> entry_type + hashcode).
+     */
+    public synchronized BibtexEntry getEntryById(String id)
+    {
+        return (BibtexEntry) _entries.get(id);
+    }
+    
+    public synchronized Collection getEntries() {
+    	return _entries.values();
+    }
+
+    /**
+     * Returns the entry with the given bibtex key.
+     */
+    public synchronized BibtexEntry getEntryByKey(String key)
+    {
+      BibtexEntry back = null ;
+
+      int keyHash = key.hashCode() ; // key hash for better performance
+
+      Set keySet = _entries.keySet();
+      if (keySet != null)
+      {
+          Iterator it = keySet.iterator();
+          boolean loop = it.hasNext() ;
+          while(loop)
+          {
+            String entrieID = (String) it.next() ;
+            BibtexEntry entry = getEntryById(entrieID) ;
+            if ((entry != null) && (entry.getCiteKey() != null))
+            {
+              String citeKey = entry.getCiteKey() ;
+              if (citeKey != null)
+              {
+                if (keyHash == citeKey.hashCode() )
+                {
+                  loop = false ;
+                  back = entry ;
+                }
+                else loop = it.hasNext() ;
+              } else loop = it.hasNext() ;
+            }
+          }
+      }
+      return back ;
+    }
+    
+    public synchronized BibtexEntry[] getEntriesByKey(String key) {
+        Vector entries = new Vector();
+        BibtexEntry entry;
+        for (Iterator it = _entries.entrySet().iterator(); it.hasNext(); ) {
+            entry = (BibtexEntry)((Map.Entry)it.next()).getValue();
+            if (key.equals(entry.getCiteKey()))
+                entries.add(entry);
+        }
+        BibtexEntry[] entryArray = new BibtexEntry[entries.size()];
+        return (BibtexEntry[]) entries.toArray(entryArray);
+    }    
+
+    /**
+     * Inserts the entry, given that its ID is not already in use.
+     * use Util.createId(...) to make up a unique ID for an entry.
+     */
+    public synchronized boolean insertEntry(BibtexEntry entry)
+        throws KeyCollisionException
+    {
+        String id = entry.getId();
+        if (getEntryById(id) != null)
+        {
+          throw new KeyCollisionException(
+                "ID is already in use, please choose another");
+        }
+
+        entry.addPropertyChangeListener(listener);
+
+        // Possibly add a FieldChangeListener, which is there to add
+        // new words to the autocompleter's dictionary. In case the
+        // entry is non-empty (pasted), update completers.
+        /*if (_autoCompleters != null) {
+            entry.addPropertyChangeListener(new FieldChangeListener
+                                            (_autoCompleters, entry));
+            Util.updateCompletersForEntry(_autoCompleters,
+                                          entry);
+        }
+        */
+        _entries.put(id, entry);
+
+	fireDatabaseChanged(new DatabaseChangeEvent(this, DatabaseChangeEvent.ADDED_ENTRY, entry));
+
+        return checkForDuplicateKeyAndAdd(null, entry.getCiteKey(), false);
+    }
+
+    /**
+     * Removes the entry with the given string.
+     */
+    public synchronized BibtexEntry removeEntry(String id)
+    {
+        BibtexEntry oldValue = (BibtexEntry) _entries.remove(id);
+        removeKeyFromSet(oldValue.getCiteKey());
+
+        if (oldValue != null)
+        {
+            oldValue.removePropertyChangeListener(listener);
+        }
+
+	fireDatabaseChanged(new DatabaseChangeEvent(this, DatabaseChangeEvent.REMOVED_ENTRY, oldValue));
+
+        return oldValue;
+    }
+
+    public synchronized boolean setCiteKeyForEntry(String id, String key) {
+        if (!_entries.containsKey(id)) return false; // Entry doesn't exist!
+        BibtexEntry entry = getEntryById(id);
+        String oldKey = entry.getCiteKey();
+        if (key != null)
+          entry.setField(Globals.KEY_FIELD, key);
+        else
+          entry.clearField(Globals.KEY_FIELD);
+        return checkForDuplicateKeyAndAdd(oldKey, entry.getCiteKey(), false);
+    }
+
+    /**
+     * Sets the database's preamble.
+     */
+    public synchronized void setPreamble(String preamble)
+    {
+        _preamble = preamble;
+    }
+
+    /**
+     * Returns the database's preamble.
+     */
+    public synchronized String getPreamble()
+    {
+        return _preamble;
+    }
+
+    /**
+     * Inserts a Bibtex String at the given index.
+     */
+    public synchronized void addString(BibtexString string)
+        throws KeyCollisionException
+    {
+        for (java.util.Iterator i=_strings.keySet().iterator(); i.hasNext();) {
+            if (((BibtexString)_strings.get(i.next())).getName().equals(string.getName()))
+                throw new KeyCollisionException("A string with this label already exists,");
+        }
+	
+	if (_strings.containsKey(string.getId()))
+	    throw new KeyCollisionException("Duplicate BibtexString id.");
+	
+        _strings.put(string.getId(), string);
+    }
+
+    /**
+     * Removes the string at the given index.
+     */
+    public synchronized void removeString(String id) {
+        _strings.remove(id);
+    }
+
+    /**
+     * Returns a Set of keys to all BibtexString objects in the database.
+     * These are in no sorted order.
+     */
+    public Set getStringKeySet() {
+	return _strings.keySet();
+    }
+
+    /**
+     * Returns the string at the given index.
+     */
+    public synchronized BibtexString getString(Object o) {
+        return (BibtexString)(_strings.get(o));
+    }
+
+    /**
+     * Returns the number of strings.
+     */
+    public synchronized int getStringCount() {
+        return _strings.size();
+    }
+
+    /**
+     * Returns true if a string with the given label already exists.
+     */
+    public synchronized boolean hasStringLabel(String label) {
+        for (java.util.Iterator i=_strings.keySet().iterator(); i.hasNext();) {
+            if (((BibtexString)_strings.get(i.next())).getName().equals(label))
+                return true;
+        }
+        return false;
+    }
+
+   /**
+    * If the label represents a string contained in this database, returns
+    * that string's content. Resolves references to other strings, taking
+    * care not to follow a circular reference pattern.
+    * If the string is undefined, returns the label itself.
+    */
+    public String resolveString(String label) {
+	return resolveString(label, new HashSet());
+    }
+   
+    /**
+     * Resolves any references to strings contained in this database,
+     * if possible.
+     */
+    public String resolveForStrings(String content) {
+	return resolveContent(content, new HashSet());
+    }
+
+    private String resolveString(String label, HashSet usedIds) {
+
+        for (java.util.Iterator i=_strings.keySet().iterator(); i.hasNext();) {
+            BibtexString string = (BibtexString)_strings.get(i.next());
+
+	        //Util.pr(label+" : "+string.getName());
+            if (string.getName().toLowerCase().equals(label.toLowerCase())) {
+
+		// First check if this string label has been resolved
+		// earlier in this recursion. If so, we have a
+		// circular reference, and have to stop to avoid
+		// infinite recursion.
+		if (usedIds.contains(string.getId())) {
+		    Util.pr("Stopped due to circular reference in strings: "+label);
+		    return label;
+		}
+		// If not, log this string's ID now.
+		usedIds.add(string.getId());
+
+		// Ok, we found the string. Now we must make sure we
+		// resolve any references to other strings in this one.
+		String res = string.getContent();
+		res = resolveContent(res, usedIds);
+
+		// Finished with recursing this branch, so we remove our
+		// ID again:
+		usedIds.remove(string.getId());
+
+		return res;
+	    }
+        }
+        
+        // If we get to this point, the string has obviously not been defined locally.
+        // Check if one of the standard BibTeX month strings has been used:
+        Object o;
+        if ((o = Globals.MONTH_STRINGS.get(label.toLowerCase())) != null) {
+            return (String)o;
+        }
+        
+        return label;
+    }
+
+    private String resolveContent(String res, HashSet usedIds) {
+	//if (res.matches(".*#[-\\^\\:\\w]+#.*")) {
+    if (res.matches(".*#[^#]+#.*")) {
+	    StringBuffer newRes = new StringBuffer();
+	    int piv = 0, next = 0;
+	    while ((next=res.indexOf("#", piv)) >= 0) {
+		// We found the next string ref. Append the text
+		// up to it.
+		if (next > 0)
+		    newRes.append(res.substring(piv, next));
+		int stringEnd = res.indexOf("#", next+1);
+		if (stringEnd >= 0) {
+		    // We found the boundaries of the string ref,
+		    // now resolve that one.
+		    String refLabel = res.substring(next+1, stringEnd);
+		    newRes.append(resolveString(refLabel, usedIds));
+		}
+		piv = stringEnd+1;
+	    }
+	    if (piv < res.length()-1)
+		newRes.append(res.substring(piv));
+	    res = newRes.toString();
+	}
+	return res;
+    }
+
+    //##########################################
+    //  usage:
+    //  isDuplicate=checkForDuplicateKeyAndAdd( null, b.getKey() , issueDuplicateWarning);
+    //############################################
+        // if the newkey already exists and is not the same as oldkey it will give a warning
+    // else it will add the newkey to the to set and remove the oldkey
+    public boolean checkForDuplicateKeyAndAdd(String oldKey, String newKey, boolean issueWarning){
+                // Globals.logger(" checkForDuplicateKeyAndAdd [oldKey = " + oldKey + "] [newKey = " + newKey + "]");
+
+        boolean duplicate=false;
+        if(oldKey==null){// this is a new entry so don't bother removing oldKey
+            duplicate= addKeyToSet( newKey);
+        }else{
+            if(oldKey.equals(newKey)){// were OK because the user did not change keys
+                duplicate=false;
+            }else{// user changed the key
+
+                // removed the oldkey
+                // But what if more than two have the same key?
+                // this means that user can add another key and would not get a warning!
+                // consider this: i add a key xxx, then i add another key xxx . I get a warning. I delete the key xxx. JBM
+                // removes this key from the allKey. then I add another key xxx. I don't get a warning!
+                // i need a way to count the number of keys of each type
+                // hashmap=>int (increment each time)
+
+                removeKeyFromSet( oldKey);
+                duplicate = addKeyToSet( newKey );
+            }
+        }
+        if(duplicate==true && issueWarning==true){
+            JOptionPane.showMessageDialog(null,  Globals.lang("Warning there is a duplicate key")+":" + newKey ,
+                                          Globals.lang("Duplicate Key Warning"),
+                                          JOptionPane.WARNING_MESSAGE);//, options);
+
+        }
+        return duplicate;
+    }
+
+    /**
+     * Returns the number of occurences of the given key in this database.
+     */
+    public int getNumberOfKeyOccurences(String key) {
+        Object o = allKeys.get(key);
+        if (o == null)
+            return 0;
+        else
+            return ((Integer)o).intValue();
+            
+    }
+    
+    //========================================================
+    // keep track of all the keys to warn if there are duplicates
+    //========================================================
+    private boolean addKeyToSet(String key){
+                boolean exists=false;
+                if((key == null) || key.equals(""))
+                        return false;//don't put empty key
+                if(allKeys.containsKey(key)){
+                        // warning
+                        exists=true;
+                        allKeys.put( key, new Integer( ((Integer)allKeys.get(key)).intValue() + 1));// incrementInteger( allKeys.get(key)));
+                }else
+                        allKeys.put( key, new Integer(1));
+                return exists;
+    }
+    //========================================================
+    // reduce the number of keys by 1. if this number goes to zero then remove from the set
+    // note: there is a good reason why we should not use a hashset but use hashmap instead
+    //========================================================
+    private void removeKeyFromSet(String key){
+                if((key == null) || key.equals("")) return;
+                if(allKeys.containsKey(key)){
+                        Integer tI = (Integer)allKeys.get(key); // if(allKeys.get(key) instanceof Integer)
+                        if(tI.intValue()==1)
+                                allKeys.remove( key);
+                        else
+                                allKeys.put( key, new Integer( ((Integer)tI).intValue() - 1));//decrementInteger( tI ));
+                }
+    }
+
+
+    
+    public void fireDatabaseChanged(DatabaseChangeEvent e) {
+	for (Iterator i=changeListeners.iterator(); i.hasNext();) {
+	    ((DatabaseChangeListener)i.next()).databaseChanged(e);
+	}
+    }
+
+    public void addDatabaseChangeListener(DatabaseChangeListener l) {
+	changeListeners.add(l);
+    }
+
+    public void removeDatabaseChangeListener(DatabaseChangeListener l) {
+	changeListeners.remove(l);
+    }
+
+    /*
+    public void setCompleters(Hashtable autoCompleters) {
+        _autoCompleters = autoCompleters;
+
+        for (Iterator i=getKeySet().iterator(); i.hasNext();) {
+            BibtexEntry be = getEntryById((String)(i.next()));
+            be.addPropertyChangeListener(new FieldChangeListener
+                                         (autoCompleters, be));
+
+            Util.updateCompletersForEntry(autoCompleters, be);
+        }
+        }*/
+}
diff --git a/src/java/net/sf/jabref/BibtexEntry.java b/src/java/net/sf/jabref/BibtexEntry.java
new file mode 100644
index 0000000..ff8b194
--- /dev/null
+++ b/src/java/net/sf/jabref/BibtexEntry.java
@@ -0,0 +1,415 @@
+/*
+Copyright (C) 2003 David Weitzman, 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
+
+Note:
+Modified for use in JabRef.
+
+*/
+
+package net.sf.jabref;
+
+import net.sf.jabref.export.FieldFormatter;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyVetoException;
+import java.beans.VetoableChangeListener;
+import java.beans.VetoableChangeSupport;
+
+import java.util.*;
+import java.io.*;
+
+
+public class BibtexEntry
+{
+    private String _id;
+    private BibtexEntryType _type;
+    private Map _fields = new HashMap();
+    VetoableChangeSupport _changeSupport = new VetoableChangeSupport(this);
+
+    // Search and grouping status is stored in boolean fields for quick reference:
+    private boolean searchHit, groupHit;
+
+    public BibtexEntry(String id)
+    {
+        this(id, BibtexEntryType.OTHER);
+    }
+
+    public BibtexEntry(String id, BibtexEntryType type)
+    {
+        if (id == null)
+        {
+            throw new NullPointerException("Every BibtexEntry must have an ID");
+        }
+
+        _id = id;
+        setType(type);
+    }
+
+    /**
+     * Returns an array describing the optional fields for this entry.
+     */
+    public String[] getOptionalFields()
+    {
+        return _type.getOptionalFields();
+    }
+
+    /**
+     * Returns an array describing the required fields for this entry.
+     */
+    public String[] getRequiredFields()
+    {
+        return _type.getRequiredFields();
+    }
+
+    /**
+     * Returns an array describing general fields.
+     */
+    public String[] getGeneralFields() {
+        return _type.getGeneralFields();
+    }
+
+    /**
+     * Returns an array containing the names of all fields that are
+     * set for this particular entry.
+     */
+    public Object[] getAllFields() {
+        return _fields.keySet().toArray();
+    }
+
+    /**
+     * Returns a string describing the required fields for this entry.
+     */
+    public String describeRequiredFields()
+    {
+        return _type.describeRequiredFields();
+    }
+
+    /**
+     * Returns true if this entry contains the fields it needs to be
+     * complete.
+     */
+    public boolean hasAllRequiredFields()
+    {
+        return _type.hasAllRequiredFields(this);
+    }
+
+    /**
+     * Returns this entry's type.
+     */
+    public BibtexEntryType getType()
+    {
+        return _type;
+    }
+
+    /**
+     * Sets this entry's type.
+     */
+    public void setType(BibtexEntryType type)
+    {
+        if (type == null)
+        {
+            throw new NullPointerException(
+                "Every BibtexEntry must have a type.  Instead of null, use type OTHER");
+        }
+
+        _type = type;
+    }
+
+    /**
+     * Prompts the entry to call BibtexEntryType.getType(String) with
+     * its current type name as argument, and sets its type according
+     * to what is returned. This method is called when a user changes
+     * the type customization, to make sure all entries are set with
+     * current types.
+     * @return true if the entry could find a type, false if not (in
+     * this case the type will have been set to
+     * BibtexEntryType.TYPELESS).
+     */
+    public boolean updateType() {
+        BibtexEntryType newType = BibtexEntryType.getType(_type.getName());
+        if (newType != null) {
+            _type = newType;
+            return true;
+        }
+        _type = BibtexEntryType.TYPELESS;
+        return false;
+    }
+
+    /**
+     * Sets this entry's ID, provided the database containing it
+     * doesn't veto the change.
+     */
+    public void setId(String id) throws KeyCollisionException {
+
+        if (id == null) {
+            throw new
+                NullPointerException("Every BibtexEntry must have an ID");
+        }
+
+        try
+        {
+            firePropertyChangedEvent("id", _id, id);
+        }
+        catch (PropertyVetoException pv)
+        {
+            throw new KeyCollisionException("Couldn't change ID: " + pv);
+        }
+
+        _id = id;
+    }
+
+    /**
+     * Returns this entry's ID.
+     */
+    public String getId()
+    {
+        return _id;
+    }
+
+    /**
+     * Returns the contents of the given field, or null if it is not set.
+     */
+    public Object getField(String name) {
+        return _fields.get(name);
+    }
+
+    public String getCiteKey() {
+        return (_fields.containsKey(Globals.KEY_FIELD) ?
+                (String)_fields.get(Globals.KEY_FIELD) : null);
+    }
+
+    /**
+     * Sets the given field to the given value.
+     */
+    public void setField(HashMap fields){
+        _fields.putAll(fields); 
+    }
+
+    public void setField(String name, Object value) {
+
+        if ("id".equals(name)) {
+            throw new IllegalArgumentException("The field name '" + name +
+                                               "' is reserved");
+        }
+
+        // This mechanism is probably not really necessary.
+        //Object normalValue = FieldTypes.normalize(name, value);
+
+
+	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);
+            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);
+            throw new IllegalArgumentException("Change rejected: " + pve);
+        }
+
+    }
+
+    /**
+     * Removes the mapping for the field name.
+     */
+    public void clearField(String name) {
+
+      if ("id".equals(name)) {
+           throw new IllegalArgumentException("The field name '" + name +
+                                              "' is reserved");
+       }
+       Object oldValue = _fields.get(name);
+       _fields.remove(name);
+       try {
+           firePropertyChangedEvent(name, oldValue, "");
+       } catch (PropertyVetoException pve) {
+           throw new IllegalArgumentException("Change rejected: " + pve);
+       }
+
+
+    }
+
+    protected boolean allFieldsPresent(String[] fields) {
+        for (int i = 0; i < fields.length; i++) {
+            if (getField(fields[i]) == null) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    private void firePropertyChangedEvent(String fieldName, Object oldValue,
+        Object newValue) throws PropertyVetoException
+    {
+        _changeSupport.fireVetoableChange(new PropertyChangeEvent(this,
+                fieldName, oldValue, newValue));
+    }
+
+    /**
+     * Adds a VetoableChangeListener, which is notified of field
+     * changes. This is useful for an object that needs to update
+     * itself each time a field changes.
+     */
+    public void addPropertyChangeListener(VetoableChangeListener listener)
+    {
+        _changeSupport.addVetoableChangeListener(listener);
+    }
+
+    /**
+     * Removes a property listener.
+     */
+    public void removePropertyChangeListener(VetoableChangeListener listener)
+    {
+        _changeSupport.removeVetoableChangeListener(listener);
+    }
+
+    /**
+     * Write this entry to the given Writer, with the given FieldFormatter.
+     * @param write True if this is a write, false if it is a display. The write will
+     * not include non-writeable fields if it is a write, otherwise non-displayable fields
+     * will be ignored. Refer to GUIGlobals for isWriteableField(String) and
+     * isDisplayableField(String).
+     */
+    public void write(Writer out, FieldFormatter ff, boolean write) throws IOException {
+        // Write header with type and bibtex-key.
+        out.write("@"+_type.getName().toUpperCase()+"{");
+
+        String str = Util.shaveString((String)getField(GUIGlobals.KEY_FIELD));
+        out.write(((str == null) ? "" : str)+","+Globals.NEWLINE);
+        HashMap written = new HashMap();
+        written.put(GUIGlobals.KEY_FIELD, null);
+        // Write required fields first.
+        String[] s = getRequiredFields();
+        if (s != null) for (int i=0; i<s.length; i++) {
+            writeField(s[i], out, ff);
+            written.put(s[i], null);
+        }
+        // Then optional fields.
+        s = getOptionalFields();
+        if (s != null) for (int i=0; i<s.length; i++) {
+            if (!written.containsKey(s[i])) { // If field appears both in req. and opt. don't repeat.
+                writeField(s[i], out, ff);
+                written.put(s[i], null);
+            }
+        }
+        // Then write remaining fields in alphabetic order.
+        TreeSet remainingFields = new TreeSet();
+        for (Iterator i = _fields.keySet().iterator(); i.hasNext(); ) {
+            String key = (String)i.next();
+            boolean writeIt = (write ? GUIGlobals.isWriteableField(key) :
+                               GUIGlobals.isDisplayableField(key));
+            if (!written.containsKey(key) && writeIt)
+               	remainingFields.add(key);
+        }
+        for (Iterator i = remainingFields.iterator(); i.hasNext(); )
+            writeField((String)i.next(),out,ff);
+
+        // Finally, end the entry.
+        out.write("}"+Globals.NEWLINE);
+    }
+
+    private void writeField(String name, Writer out,
+                            FieldFormatter ff) throws IOException {
+        Object o = getField(name);
+        if (o != null) {
+            out.write("  "+name+" = ");
+
+            try {
+                out.write(ff.format(o.toString(), name));
+            } catch (Throwable ex) {
+                throw new IOException
+                    (Globals.lang("Error in field")+" '"+name+"': "+ex.getMessage());
+            }
+            //Util.writeField(name, o, out);
+            out.write(","+Globals.NEWLINE);
+        }
+    }
+
+    /**
+     * Returns a clone of this entry. Useful for copying.
+     */
+    public Object clone() {
+        BibtexEntry clone = new BibtexEntry(_id, _type);
+        clone._fields = (Map)((HashMap)_fields).clone();
+        return clone;
+    }
+
+   
+    public String toString() {
+	return getType().getName()+":"+getField(Globals.KEY_FIELD);
+    }
+
+    public boolean isSearchHit() {
+        return searchHit;
+    }
+
+    public void setSearchHit(boolean searchHit) {
+        this.searchHit = searchHit;
+    }
+
+    public boolean isGroupHit() {
+        return groupHit;
+    }
+
+    public void setGroupHit(boolean groupHit) {
+        this.groupHit = groupHit;
+    }
+
+    /**
+     * @param maxCharacters The maximum number of characters (additional
+     * characters are replaced with "..."). Set to 0 to disable truncation.
+     * @return A short textual description of the entry in the format:
+     * Author1, Author2: Title (Year)
+     */
+    public String getAuthorTitleYear(int maxCharacters) {
+        String[] s = new String[] {
+                (String) getField("author"),
+                (String) getField("title"),
+                (String) getField("year")};
+        for (int i = 0; i < s.length; ++i)
+            if (s[i] == null)
+                s[i] = "N/A";
+        String text = s[0] + ": \"" + s[1] + "\" (" + s[2] + ")";
+        if (maxCharacters <= 0 || text.length() <= maxCharacters)
+            return text;
+        return text.substring(0, maxCharacters + 1) + "...";
+    }
+}
diff --git a/src/java/net/sf/jabref/BibtexEntryType.java b/src/java/net/sf/jabref/BibtexEntryType.java
new file mode 100644
index 0000000..a9facc0
--- /dev/null
+++ b/src/java/net/sf/jabref/BibtexEntryType.java
@@ -0,0 +1,803 @@
+/*
+Copyright (C) 2003 David Weitzman, 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
+
+Note:
+Modified for use in JabRef.
+
+*/
+package net.sf.jabref;
+
+import java.io.*;
+import java.util.*;
+
+public abstract class BibtexEntryType implements Comparable
+{
+
+    public static final BibtexEntryType OTHER =
+        new BibtexEntryType()
+        {
+            public String getName()
+            {
+                return "Other";
+            }
+
+            public String[] getOptionalFields()
+            {
+                return new String[0];
+            }
+
+            public String[] getRequiredFields()
+            {
+                return new String[0];
+            }
+
+
+            public String describeRequiredFields()
+            {
+                return "";
+            }
+
+            public boolean hasAllRequiredFields(BibtexEntry entry)
+            {
+                return true;
+            }
+        };
+
+
+    public static final BibtexEntryType ARTICLE =
+        new BibtexEntryType()
+        {
+            public String getName()
+            {
+                return "Article";
+            }
+
+            public String[] getOptionalFields()
+            {
+                return new String[]
+                {
+                    "number", "month", "eid", "note"
+                };
+            }
+
+            public String[] getRequiredFields()
+            {
+                return new String[]
+                {
+                    "author", "title", "journal", "year", "volume", "pages"
+                };
+            }
+
+            public String describeRequiredFields()
+            {
+                return "AUTHOR, TITLE, JOURNAL and YEAR";
+            }
+
+            public boolean hasAllRequiredFields(BibtexEntry entry)
+            {
+                return entry.allFieldsPresent(new String[]
+                    {
+                        "author", "title", "journal", "year", "bibtexkey", "volume", "pages"
+                    });
+            }
+        };
+
+    public static final BibtexEntryType BOOKLET =
+        new BibtexEntryType()
+        {
+            public String getName()
+            {
+                return "Booklet";
+            }
+
+            public String[] getOptionalFields()
+            {
+                return new String[]
+                {
+                    "author", "howpublished", "lastchecked", "address", "month", "year", "note"
+                };
+            }
+
+            public String[] getRequiredFields()
+            {
+                return new String[]
+                {
+                    "title"
+                };
+            }
+
+            public String describeRequiredFields()
+            {
+                return "TITLE";
+            }
+
+            public boolean hasAllRequiredFields(BibtexEntry entry)
+            {
+                return entry.allFieldsPresent(new String[]
+                    {
+                        "title", "bibtexkey"
+                    });
+            }
+        };
+
+
+   public static final BibtexEntryType INBOOK =
+        new BibtexEntryType()
+        {
+            public String getName()
+            {
+                return "Inbook";
+            }
+
+            public String[] getOptionalFields()
+            {
+                return new String[]
+                {
+                    "volume", "number", "series", "type", "address", "edition",
+		    "month", "note"
+                };
+            }
+
+            public String[] getRequiredFields()
+            {
+                return new String[]
+                {
+                    "chapter", "pages", "title", "publisher", "year", "editor",
+		    "author"
+                };
+            }
+
+            public String describeRequiredFields()
+            {
+                return "TITLE, CHAPTER and/or PAGES, PUBLISHER, YEAR, and an "
+		    +"EDITOR and/or AUTHOR";
+            }
+
+            public boolean hasAllRequiredFields(BibtexEntry entry)
+            {
+                return entry.allFieldsPresent(new String[]
+                    {
+                        "title", "publisher", "year", "bibtexkey"
+                    }) &&
+		    (((entry.getField("author") != null) ||
+		      (entry.getField("editor") != null)) &&
+		     ((entry.getField("chapter") != null) ||
+		      (entry.getField("pages") != null)));
+            }
+        };
+
+    public static final BibtexEntryType BOOK =
+        new BibtexEntryType()
+        {
+            public String getName()
+            {
+                return "Book";
+            }
+
+            public String[] getOptionalFields()
+            {
+                return new String[]
+                {
+                    "volume", "number", "series", "address", "edition", "month",
+                    "note"
+                };
+            }
+
+            public String[] getRequiredFields()
+            {
+                return new String[]
+                {
+                    "title", "publisher", "year", "editor", "author"
+                };
+            }
+
+            public String describeRequiredFields()
+            {
+                return "TITLE, PUBLISHER, YEAR, and an EDITOR and/or AUTHOR";
+            }
+
+            public boolean hasAllRequiredFields(BibtexEntry entry)
+            {
+                return entry.allFieldsPresent(new String[]
+                    {
+                        "title", "publisher", "year", "bibtexkey"
+                    }) &&
+                ((entry.getField("author") != null) ||
+                (entry.getField("editor") != null));
+            }
+        };
+
+
+    public static final BibtexEntryType INCOLLECTION =
+        new BibtexEntryType()
+        {
+            public String getName()
+            {
+                return "Incollection";
+            }
+
+            public String[] getOptionalFields()
+            {
+                return new String[]
+                {
+                    "editor", "volume", "number", "series", "type", "chapter",
+		    "pages", "address", "edition", "month", "note"
+                };
+            }
+
+            public String[] getRequiredFields()
+            {
+                return new String[]
+                {
+                    "author", "title", "booktitle", "publisher", "year"
+                };
+            }
+
+            public String describeRequiredFields()
+            {
+                return "AUTHOR, TITLE, BOOKTITLE, PUBLISHER and YEAR";
+            }
+
+            public boolean hasAllRequiredFields(BibtexEntry entry)
+            {
+                return entry.allFieldsPresent(new String[]
+                    {
+			"author", "title", "booktitle", "publisher", "year",
+			"bibtexkey"
+
+                    });
+            }
+        };
+
+    public static final BibtexEntryType CONFERENCE =
+        new BibtexEntryType()
+        {
+            public String getName()
+            {
+                return "Conference";
+            }
+
+            public String[] getOptionalFields()
+            {
+                return new String[]
+                {
+                    "editor", "volume", "number", "series", "pages",
+		    "address", "month", "organization", "publisher", "note"
+                };
+            }
+
+            public String[] getRequiredFields()
+            {
+                return new String[]
+                {
+                    "author", "title", "booktitle", "year"
+                };
+            }
+
+            public String describeRequiredFields()
+            {
+                return "AUTHOR, TITLE, BOOKTITLE and YEAR";
+            }
+
+            public boolean hasAllRequiredFields(BibtexEntry entry)
+            {
+                return entry.allFieldsPresent(new String[]
+                    {
+			"author", "title", "booktitle", "year" , "bibtexkey"
+                    });
+            }
+        };
+
+    public static final BibtexEntryType INPROCEEDINGS =
+        new BibtexEntryType()
+        {
+            public String getName()
+            {
+                return "Inproceedings";
+            }
+
+            public String[] getOptionalFields()
+            {
+                return new String[]
+                {
+                    "editor", "volume", "number", "series", "pages",
+		    "address", "month", "organization", "publisher", "note"
+                };
+            }
+
+            public String[] getRequiredFields()
+            {
+                return new String[]
+                {
+                    "author", "title", "booktitle", "year"
+                };
+            }
+
+            public String describeRequiredFields()
+            {
+                return "AUTHOR, TITLE, BOOKTITLE and YEAR";
+            }
+
+            public boolean hasAllRequiredFields(BibtexEntry entry)
+            {
+                return entry.allFieldsPresent(new String[]
+                    {
+			"author", "title", "booktitle", "year" , "bibtexkey"
+                    });
+            }
+        };
+
+    public static final BibtexEntryType PROCEEDINGS =
+        new BibtexEntryType()
+        {
+            public String getName()
+            {
+                return "Proceedings";
+            }
+
+            public String[] getOptionalFields()
+            {
+                return new String[]
+                {
+                    "editor", "volume", "number", "series", "address",
+		    "publisher", "note", "month", "organization"
+                };
+            }
+
+            public String[] getRequiredFields()
+            {
+                return new String[]
+                {
+                    "title", "year"
+                };
+            }
+
+            public String describeRequiredFields()
+            {
+                return "TITLE and YEAR";
+            }
+
+            public boolean hasAllRequiredFields(BibtexEntry entry)
+            {
+                return entry.allFieldsPresent(new String[]
+                    {
+			"title", "year", "bibtexkey"
+                    });
+            }
+        };
+
+
+    public static final BibtexEntryType MANUAL =
+        new BibtexEntryType()
+        {
+            public String getName()
+            {
+                return "Manual";
+            }
+
+            public String[] getOptionalFields()
+            {
+                return new String[]
+                {
+                    "author", "organization", "address", "edition",
+		    "month", "year", "note"
+                };
+            }
+
+            public String[] getRequiredFields()
+            {
+                return new String[]
+                {
+                    "title"
+                };
+            }
+
+            public String describeRequiredFields()
+            {
+                return "TITLE";
+            }
+
+            public boolean hasAllRequiredFields(BibtexEntry entry)
+            {
+                return entry.allFieldsPresent(new String[]
+                    {
+                        "title", "bibtexkey"
+                    });
+            }
+        };
+
+    public static final BibtexEntryType TECHREPORT =
+        new BibtexEntryType()
+        {
+            public String getName()
+            {
+                return "Techreport";
+            }
+
+            public String[] getOptionalFields()
+            {
+                return new String[]
+                {
+                    "type", "number", "address", "month", "note"
+                };
+            }
+
+            public String[] getRequiredFields()
+            {
+                return new String[]
+                {
+                    "author", "title", "institution", "year"
+                };
+            }
+
+            public String describeRequiredFields()
+            {
+                return "AUTHOR, TITLE, INSTITUTION and YEAR";
+            }
+
+            public boolean hasAllRequiredFields(BibtexEntry entry)
+            {
+                return entry.allFieldsPresent(new String[]
+                    {
+			"author", "title", "institution", "year",
+			"bibtexkey"
+                    });
+            }
+        };
+
+
+    public static final BibtexEntryType MASTERSTHESIS =
+        new BibtexEntryType()
+        {
+            public String getName()
+            {
+                return "Mastersthesis";
+            }
+
+            public String[] getOptionalFields()
+            {
+                return new String[]
+                {
+                    "type", "address", "month", "note"
+                };
+            }
+
+            public String[] getRequiredFields()
+            {
+                return new String[]
+                {
+                    "author", "title", "school", "year"
+                };
+            }
+
+            public String describeRequiredFields()
+            {
+                return "AUTHOR, TITLE, SCHOOL and YEAR";
+            }
+
+            public boolean hasAllRequiredFields(BibtexEntry entry)
+            {
+                return entry.allFieldsPresent(new String[]
+                    {
+                        "author", "title", "school", "year", "bibtexkey"
+                    });
+            }
+        };
+
+
+    public static final BibtexEntryType PHDTHESIS =
+        new BibtexEntryType()
+        {
+            public String getName()
+            {
+                return "Phdthesis";
+            }
+
+            public String[] getOptionalFields()
+            {
+                return new String[]
+                {
+                    "type", "address", "month", "note"
+                };
+            }
+
+            public String[] getRequiredFields()
+            {
+                return new String[]
+                {
+                    "author", "title", "school", "year"
+                };
+            }
+
+            public String describeRequiredFields()
+            {
+                return "AUTHOR, TITLE, SCHOOL and YEAR";
+            }
+
+            public boolean hasAllRequiredFields(BibtexEntry entry)
+            {
+                return entry.allFieldsPresent(new String[]
+                    {
+                        "author", "title", "school", "year", "bibtexkey"
+                    });
+            }
+        };
+
+    public static final BibtexEntryType UNPUBLISHED =
+        new BibtexEntryType()
+        {
+            public String getName()
+            {
+                return "Unpublished";
+            }
+
+            public String[] getOptionalFields()
+            {
+                return new String[]
+                {
+                    "month", "year"
+                };
+            }
+
+            public String[] getRequiredFields()
+            {
+                return new String[]
+                {
+                    "author", "title", "note"
+                };
+            }
+
+            public String describeRequiredFields()
+            {
+                return "AUTHOR, TITLE and NOTE";
+            }
+
+            public boolean hasAllRequiredFields(BibtexEntry entry)
+            {
+                return entry.allFieldsPresent(new String[]
+                    {
+			"author", "title", "note", "bibtexkey"
+                    });
+            }
+        };
+
+
+    public static final BibtexEntryType MISC =
+        new BibtexEntryType()
+        {
+            public String getName()
+            {
+                return "Misc";
+            }
+
+            public String[] getOptionalFields()
+            {
+                return new String[]
+                {
+                    "author", "title", "howpublished", "month", "year", "note"
+                };
+            }
+
+            public String[] getRequiredFields()
+            {
+                return null;
+            }
+
+            public String describeRequiredFields()
+            {
+                return "None";
+            }
+
+            public boolean hasAllRequiredFields(BibtexEntry entry)
+            {
+		return entry.allFieldsPresent(new String[]
+                    {
+			"bibtexkey"
+                    });
+            }
+        };
+
+    /**
+     * This type is provided as an emergency choice if the user makes
+     * customization changes that remove the type of an entry.
+     */
+    public static final BibtexEntryType TYPELESS =
+        new BibtexEntryType()
+        {
+            public String getName()
+            {
+                return "Typeless";
+            }
+
+            public String[] getOptionalFields()
+            {
+                return null;
+            }
+
+            public String[] getRequiredFields()
+            {
+                return null;
+            }
+
+            public String describeRequiredFields()
+            {
+                return "None";
+            }
+
+            public boolean hasAllRequiredFields(BibtexEntry entry)
+            {
+		return false;
+           }
+        };
+
+
+    public abstract String getName();
+
+    public int compareTo(Object o) {
+	return getName().compareTo(((BibtexEntryType)o).getName());
+    }
+
+    public abstract String[] getOptionalFields();
+
+    public abstract String[] getRequiredFields();
+
+    public String[] getGeneralFields() {
+        return new String[]
+	    {"crossref", "keywords", "doi", "url",
+	     "citeseerurl", "pdf", "abstract", "comment"};
+    }
+
+    public abstract String describeRequiredFields();
+
+    public abstract boolean hasAllRequiredFields(BibtexEntry entry);
+
+
+    public String[] getUtilityFields(){
+        return new String[] {"search" } ;
+    }
+
+
+    public boolean isRequired(String field) {
+	String[] req = getRequiredFields();
+	if (req == null) return false;
+	for (int i=0; i<req.length; i++)
+	    if (req[i].equals(field)) return true;
+	return false;
+    }
+
+    public boolean isOptional(String field) {
+	String[] opt = getOptionalFields();
+	if (opt == null) return false;
+	for (int i=0; i<opt.length; i++)
+	    if (opt[i].equals(field)) return true;
+	return false;
+    }
+
+    public static TreeMap ALL_TYPES = new TreeMap();
+    public static TreeMap STANDARD_TYPES = new TreeMap();
+    static {
+	// Put the standard entry types into the type map.
+	ALL_TYPES.put("article", ARTICLE);
+	ALL_TYPES.put("inbook", INBOOK);
+	ALL_TYPES.put("book", BOOK);
+	ALL_TYPES.put("booklet", BOOKLET);
+	ALL_TYPES.put("incollection", INCOLLECTION);
+        ALL_TYPES.put("conference", CONFERENCE);
+	ALL_TYPES.put("inproceedings", INPROCEEDINGS);
+	ALL_TYPES.put("proceedings", PROCEEDINGS);
+	ALL_TYPES.put("manual", MANUAL);
+	ALL_TYPES.put("mastersthesis", MASTERSTHESIS);
+	ALL_TYPES.put("phdthesis", PHDTHESIS);
+	ALL_TYPES.put("techreport", TECHREPORT);
+	ALL_TYPES.put("unpublished", UNPUBLISHED);
+        ALL_TYPES.put("misc", MISC);
+        ALL_TYPES.put("other", OTHER);
+
+	// We need a record of the standard types, in case the user wants
+	// to remove a customized version. Therefore we clone the map.
+	STANDARD_TYPES = (TreeMap)ALL_TYPES.clone();
+    }
+
+    /**
+     * This method returns the BibtexEntryType for the name of a type,
+     * or null if it does not exist.
+     */
+    public static BibtexEntryType getType(String name) {
+	//Util.pr("'"+name+"'");
+	Object o = ALL_TYPES.get(name.toLowerCase());
+	if (o == null)
+	    return null;
+	else return (BibtexEntryType)o;
+    }
+
+    /**
+     * This method returns the standard BibtexEntryType for the
+     * name of a type, or null if it does not exist.
+     */
+    public static BibtexEntryType getStandardType(String name) {
+	//Util.pr("'"+name+"'");
+	Object o = STANDARD_TYPES.get(name.toLowerCase());
+	if (o == null)
+	    return null;
+	else return (BibtexEntryType)o;
+    }
+
+    /**
+     * Removes a customized entry type from the type map. If this type
+     * overrode a standard type, we reinstate the standard one.
+     *
+     * @param name The customized entry type to remove.
+     */
+    public static void removeType(String name) {
+	//BibtexEntryType type = getType(name);
+	String nm = name.toLowerCase();
+        //System.out.println(ALL_TYPES.size());
+	ALL_TYPES.remove(nm);
+        //System.out.println(ALL_TYPES.size());
+	if (STANDARD_TYPES.get(nm) != null) {
+	    // In this case the user has removed a customized version
+	    // of a standard type. We reinstate the standard type.
+	    ALL_TYPES.put(nm, STANDARD_TYPES.get(nm));
+	}
+
+    }
+
+    /**
+     * Load all custom entry types from preferences. This method is
+     * called from JabRef when the program starts.
+     */
+    public static void loadCustomEntryTypes(JabRefPreferences prefs) {
+	int number = 0;
+	CustomEntryType type;
+	while ((type = prefs.getCustomEntryType(number)) != null) {
+	    ALL_TYPES.put(type.getName().toLowerCase(), type);
+	    number++;
+	}
+    }
+
+    /**
+     * Iterate through all entry types, and store those that are
+     * custom defined to preferences. This method is called from
+     * JabRefFrame when the program closes.
+     */
+    public static void saveCustomEntryTypes(JabRefPreferences prefs) {
+	Iterator i=ALL_TYPES.keySet().iterator();
+	int number = 0;
+	//Vector customTypes = new Vector(10, 10);
+	while (i.hasNext()) {
+	    Object o=ALL_TYPES.get(i.next());
+	    if (o instanceof CustomEntryType) {
+		// Store this entry type.
+		prefs.storeCustomEntryType((CustomEntryType)o, number);
+		number++;
+	    }
+	}
+	// Then, if there are more 'old' custom types defined, remove these
+	// from preferences. This is necessary if the number of custom types
+	// has decreased.
+	prefs.purgeCustomEntryTypes(number);
+    }
+
+}
diff --git a/src/java/net/sf/jabref/BibtexString.java b/src/java/net/sf/jabref/BibtexString.java
new file mode 100644
index 0000000..0f0dfe6
--- /dev/null
+++ b/src/java/net/sf/jabref/BibtexString.java
@@ -0,0 +1,68 @@
+/*
+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.
+
+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;
+
+public class BibtexString {
+
+    String _name, _content, _id;
+
+    public BibtexString(String id, String name, String content) {
+	_id = id;
+	_name = name;
+	_content = content;
+    }
+
+    public String getId() {
+	return _id;
+    }
+
+    public void setId(String id) {
+	_id = id;
+    }
+
+    public String getName() {
+	return _name;
+    }
+
+    public void setName(String name) {
+	_name = name;
+    }
+
+    public String getContent() {
+	return ((_content == null) ? "" : _content);
+    }
+
+    public void setContent(String content) {
+	_content = content;
+    }
+
+    public Object clone() {
+      return new BibtexString(_id, _name, _content);
+    }
+
+}
diff --git a/src/java/net/sf/jabref/BibtexStringComparator.java b/src/java/net/sf/jabref/BibtexStringComparator.java
new file mode 100644
index 0000000..8147c44
--- /dev/null
+++ b/src/java/net/sf/jabref/BibtexStringComparator.java
@@ -0,0 +1,106 @@
+/*
+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.
+
+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.util.Comparator;
+import java.util.regex.Pattern;
+import java.util.regex.Matcher;
+
+public class BibtexStringComparator implements Comparator {
+
+    protected boolean considerRefs;
+    private static final String MARKER = "__MARKER__";
+    private static final String PADDED_MARKER = " "+MARKER+" ";
+
+    /**
+     * @param considerRefs Indicates whether the strings should be
+     *                     sorted according to internal references in addition to
+     *                     alphabetical sorting.
+     */
+    public BibtexStringComparator(boolean considerRefs) {
+        this.considerRefs = considerRefs;
+    }
+
+    public int compare(Object one, Object two) {
+        BibtexString s1 = (BibtexString) one;
+        BibtexString s2 = (BibtexString) two;
+
+        /*
+         If crossreferences are to be considered, the following block sorts by the number of string
+         references, so strings with less references precede those with more.
+        */
+        if (considerRefs) {
+            //Pattern refPat = Pattern.compile("#[A-Za-z]+#");
+            int ref1 = s1.getContent().replaceAll("#[A-Za-z]+#", PADDED_MARKER).split(MARKER).length,
+                ref2 = s2.getContent().replaceAll("#[A-Za-z]+#", PADDED_MARKER).split(MARKER).length;
+
+            if (ref1 != ref2)
+                return ref1-ref2;
+        }
+
+        int res = 0;
+
+        // First check their names:
+        String name1 = s1.getName().toLowerCase(),
+                name2 = s2.getName().toLowerCase();
+
+        res = name1.compareTo(name2);
+
+        if (res == 0)
+            return res;
+
+        // Then, if we are supposed to, see if the ordering needs
+        // to be changed because of one string referring to the other.x
+        if (considerRefs) {
+
+            // First order them:
+            BibtexString pre, post;
+            if (res < 0) {
+                pre = s1;
+                post = s2;
+            } else {
+                pre = s2;
+                post = s1;
+            }
+
+            // Then see if "pre" refers to "post", which is the only
+            // situation when we must change the ordering:
+            String namePost = post.getName().toLowerCase(),
+                    textPre = pre.getContent().toLowerCase();
+
+            // If that is the case, reverse the order found:
+            if (textPre.indexOf("#" + namePost + "#") >= 0)
+                res = -res;
+
+
+        }
+
+        return res;
+    }
+
+}
diff --git a/src/java/net/sf/jabref/CallBack.java b/src/java/net/sf/jabref/CallBack.java
new file mode 100644
index 0000000..66b4b30
--- /dev/null
+++ b/src/java/net/sf/jabref/CallBack.java
@@ -0,0 +1,8 @@
+package net.sf.jabref;
+
+
+public interface CallBack {
+
+    public void update();
+
+}
diff --git a/src/java/net/sf/jabref/CheckBoxMessage.java b/src/java/net/sf/jabref/CheckBoxMessage.java
new file mode 100644
index 0000000..23e33bd
--- /dev/null
+++ b/src/java/net/sf/jabref/CheckBoxMessage.java
@@ -0,0 +1,36 @@
+package net.sf.jabref;
+
+import javax.swing.JPanel;
+import javax.swing.JLabel;
+import javax.swing.JCheckBox;
+import java.awt.BorderLayout;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+
+
+public class CheckBoxMessage extends JPanel {
+  BorderLayout borderLayout1 = new BorderLayout();
+  GridBagLayout gbl = new GridBagLayout();
+  GridBagConstraints con = new GridBagConstraints();
+  JCheckBox cb;
+
+  public CheckBoxMessage(String message, String cbText, boolean defaultValue) {
+    cb = new JCheckBox(cbText, defaultValue);
+    setLayout(gbl);
+    con.gridwidth = GridBagConstraints.REMAINDER;
+
+    JLabel lab = new JLabel(message+"\n"), empt = new JLabel("");
+    cb.setHorizontalAlignment(JLabel.LEFT);
+    gbl.setConstraints(lab, con);
+    add(lab);
+    con.anchor = GridBagConstraints.WEST;
+    con.insets = new Insets(10, 0, 0, 0);
+    gbl.setConstraints(cb, con);
+    add(cb);
+  }
+
+  public boolean isSelected() {
+    return cb.isSelected();
+  }
+}
diff --git a/src/java/net/sf/jabref/ClipBoardManager.java b/src/java/net/sf/jabref/ClipBoardManager.java
new file mode 100644
index 0000000..70dbf91
--- /dev/null
+++ b/src/java/net/sf/jabref/ClipBoardManager.java
@@ -0,0 +1,78 @@
+/*
+  based on "Clipboard copy and paste" demo from http://www.javapractices.com/Topic82.cjp
+*/
+
+// created by : r.nagel 14.09.2004
+//
+// function : handle all clipboard action
+//
+// modified :
+
+
+package net.sf.jabref ;
+
+import java.awt.datatransfer.Clipboard ;
+import java.awt.datatransfer.ClipboardOwner ;
+import java.awt.datatransfer.Transferable ;
+import java.awt.datatransfer.StringSelection ;
+import java.awt.datatransfer.DataFlavor ;
+import java.awt.datatransfer.UnsupportedFlavorException ;
+import java.awt.Toolkit ;
+import java.io.* ;
+
+public class ClipBoardManager implements ClipboardOwner
+{
+  public static ClipBoardManager clipBoard = new ClipBoardManager() ;
+
+  /**
+   * Empty implementation of the ClipboardOwner interface.
+   */
+  public void lostOwnership( Clipboard aClipboard, Transferable aContents )
+  {
+    //do nothing
+  }
+
+  /**
+   * Place a String on the clipboard, and make this class the
+   * owner of the Clipboard's contents.
+   */
+  public void setClipboardContents( String aString )
+  {
+    StringSelection stringSelection = new StringSelection( aString ) ;
+    Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard() ;
+    clipboard.setContents( stringSelection, this ) ;
+  }
+
+  /**
+   * Get the String residing on the clipboard.
+   *
+   * @return any text found on the Clipboard; if none found, return an
+   * empty String.
+   */
+  public String getClipboardContents()
+  {
+    String result = "" ;
+    Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard() ;
+    //odd: the Object param of getContents is not currently used
+    Transferable contents = clipboard.getContents( null ) ;
+    boolean hasTransferableText = ( contents != null ) &&
+        contents.isDataFlavorSupported( DataFlavor.stringFlavor ) ;
+    if ( hasTransferableText )
+    {
+      try
+      {
+        result = ( String ) contents.getTransferData( DataFlavor.stringFlavor ) ;
+      }
+      catch ( UnsupportedFlavorException ex )
+      {
+        //highly unlikely since we are using a standard DataFlavor
+        System.out.println( ex ) ;
+      }
+      catch ( IOException ex )
+      {
+        System.out.println( ex ) ;
+      }
+    }
+    return result ;
+  }
+}
diff --git a/src/java/net/sf/jabref/ContentSelectorDialog.java b/src/java/net/sf/jabref/ContentSelectorDialog.java
new file mode 100644
index 0000000..733df9b
--- /dev/null
+++ b/src/java/net/sf/jabref/ContentSelectorDialog.java
@@ -0,0 +1,309 @@
+package net.sf.jabref;
+
+import java.awt.*;
+import javax.swing.*;
+import javax.swing.border.*;
+import java.awt.event.*;
+import java.util.Iterator;
+import java.util.Vector;
+import java.util.TreeSet;
+
+public class ContentSelectorDialog extends JDialog {
+    JPanel panel1 = new JPanel();
+    JPanel jPanel2 = new JPanel();
+    JButton Close = new JButton();
+    GridBagLayout gridBagLayout1 = new GridBagLayout();
+    JPanel jPanel1 = new JPanel();
+    JLabel lab = new JLabel();
+    JTextField fieldTf = new JTextField();
+    JButton add = new JButton();
+    JPanel jPanel3 = new JPanel();
+    JButton remove = new JButton();
+    JComboBox fieldSelector = new JComboBox();
+    GridBagLayout gridBagLayout2 = new GridBagLayout();
+    //HelpAction help;
+    JButton help;
+    JPanel jPanel4 = new JPanel();
+    GridBagLayout gridBagLayout3 = new GridBagLayout();
+    GridBagLayout gridBagLayout4 = new GridBagLayout();
+    TitledBorder titledBorder1;
+    TitledBorder titledBorder2;
+    JLabel jLabel1 = new JLabel();
+    JComboBox wordSelector = new JComboBox();
+    JTextField wordTf = new JTextField();
+    JPanel jPanel5 = new JPanel();
+    GridBagLayout gridBagLayout5 = new GridBagLayout();
+    JButton addWord = new JButton();
+    JPanel jPanel6 = new JPanel();
+    JButton removeWord = new JButton();
+    GridBagLayout gridBagLayout6 = new GridBagLayout();
+    JButton select = new JButton();
+
+    final String
+	WORD_EMPTY_TEXT = Globals.lang("<no field>"),
+	WORD_FIRSTLINE_TEXT = Globals.lang("<select word>"),
+	FIELD_FIRST_LINE = Globals.lang("<field name>");
+    MetaData metaData;
+    String currentField = null;
+    TreeSet fieldSet, wordSet;
+    JabRefFrame frame;
+
+    public ContentSelectorDialog(JabRefFrame frame, boolean modal, MetaData metaData) {
+	super(frame, Globals.lang("Setup selectors"), modal);
+	this.metaData = metaData;
+	this.frame = frame;
+	help = new JButton(Globals.lang("Help"));
+	help.addActionListener(new HelpAction(frame.helpDiag, GUIGlobals.contentSelectorHelp, "Help"));
+	//help = new HelpAction(frame.helpDiag, GUIGlobals.contentSelectorHelp, "Help");
+	try {
+	    jbInit();
+	    wordSelector.addItem(WORD_EMPTY_TEXT);
+	    pack();
+	}
+	catch(Exception ex) {
+	    ex.printStackTrace();
+	}
+    }
+
+    public ContentSelectorDialog(JabRefFrame frame, boolean modal, MetaData metaData,
+				 String fieldName) {
+	this(frame, modal, metaData);
+
+	try {
+	    fieldSelector.setSelectedItem(fieldName);
+	} catch (Exception ex) {
+	    ex.printStackTrace();
+	}
+
+	// The next two lines remove the part of the interface allowing
+	// the user to control which fields have a selector. I think this
+	// makes the dialog more intuitive. When the user opens this dialog
+	// from the Tools menu, the full interface will be available.
+	panel1.remove(jPanel1);
+	pack();
+    }
+
+    /**
+     * Set the contents of the field selector combobox.
+     *
+     */
+    private void setupFieldSelector() {
+	fieldSelector.removeAllItems();
+	fieldSelector.addItem(FIELD_FIRST_LINE);
+	for (Iterator i=metaData.iterator(); i.hasNext();) {
+	    String s = (String)i.next();
+	    if (s.startsWith(Globals.SELECTOR_META_PREFIX))
+		fieldSelector.addItem(s.substring(Globals.SELECTOR_META_PREFIX.length()));
+	}
+
+    }
+
+
+    private void updateWordPanel() {
+	if (currentField == null) {
+	    titledBorder2.setTitle("");
+	    jPanel3.repaint();
+	    return;
+	}
+	titledBorder2.setTitle(Globals.lang("Field")+": "+currentField);
+	jPanel3.repaint();
+	fillWordSelector();
+	wordTf.setText("");
+    }
+
+    private void fillWordSelector() {
+	wordSelector.removeAllItems();
+	wordSelector.addItem(WORD_FIRSTLINE_TEXT);
+	Vector items = metaData.getData(Globals.SELECTOR_META_PREFIX+currentField);
+	if ((items != null)) { // && (items.size() > 0)) {
+	    wordSet = new TreeSet(items);
+	    for (Iterator i=wordSet.iterator(); i.hasNext();)
+		wordSelector.addItem(i.next());
+	}
+    }
+
+    private void addWord() {
+	if (currentField == null)
+	    return;
+	String word = wordTf.getText().trim();
+
+	if (!wordSet.contains(word)) {
+	    Util.pr(Globals.SELECTOR_META_PREFIX+currentField);
+	    wordSet.add(word);
+	    // Create a new Vector for this word list, and update the MetaData.
+	    metaData.putData(Globals.SELECTOR_META_PREFIX+currentField,
+			     new Vector(wordSet));
+	    fillWordSelector();
+	    frame.basePanel().markNonUndoableBaseChanged();
+	    //wordTf.selectAll();
+	    wordTf.setText("");
+	    wordTf.requestFocus();
+	}
+    }
+
+    private void addField() {
+	currentField = fieldTf.getText().trim().toLowerCase();
+	if (metaData.getData(Globals.SELECTOR_META_PREFIX+currentField) == null) {
+	    metaData.putData(Globals.SELECTOR_META_PREFIX+currentField,
+			     new Vector());
+	    frame.basePanel().markNonUndoableBaseChanged();
+	    setupFieldSelector();
+	    updateWordPanel();
+	}
+    }
+
+    private void removeWord() {
+	String word = wordTf.getText().trim();
+	if (wordSet.contains(word)) {
+	    wordSet.remove(word);
+	    // Create a new Vector for this word list, and update the MetaData.
+	    metaData.putData(Globals.SELECTOR_META_PREFIX+currentField,
+			     new Vector(wordSet));
+	    fillWordSelector();
+	    frame.basePanel().markNonUndoableBaseChanged();
+	    //wordTf.selectAll();
+	    wordTf.setText("");
+	    wordTf.requestFocus();
+	}
+    }
+
+    void fieldSelector_actionPerformed(ActionEvent e) {
+	if (fieldSelector.getSelectedIndex() > 0) {
+	    //fieldTf.setText((String)fieldSelector.getSelectedItem());
+	    currentField = (String)fieldSelector.getSelectedItem();
+	    updateWordPanel();
+	}
+    }
+
+    private void jbInit() {
+	titledBorder1 = new TitledBorder(BorderFactory.createEtchedBorder(Color.white,new Color(142, 142, 142)),Globals.lang("Selector enabled fields"));
+	titledBorder2 = new TitledBorder(BorderFactory.createEtchedBorder(Color.white,new Color(142, 142, 142)),Globals.lang("Item list for field"));
+	//jPanel1.setBackground(GUIGlobals.lightGray);
+	//jPanel2.setBackground(GUIGlobals.lightGray);
+	//panel1.setBackground(GUIGlobals.lightGray);
+	panel1.setLayout(gridBagLayout1);
+	Close.setText(Globals.lang("Close"));
+	Close.addActionListener(new ContentSelectorDialog_Close_actionAdapter(this));
+	lab.setRequestFocusEnabled(true);
+	lab.setText(Globals.lang("Field name")+":");
+	fieldTf.setSelectionEnd(8);
+	add.setText(Globals.lang("Add"));
+	remove.setText(Globals.lang("Remove"));
+	jPanel1.setLayout(gridBagLayout2);
+	jPanel1.setBorder(titledBorder1);
+	jPanel3.setBorder(titledBorder2);
+	jPanel3.setLayout(gridBagLayout4);
+	jPanel4.setLayout(gridBagLayout3);
+	jLabel1.setText(Globals.lang("Word")+":");
+	jPanel5.setLayout(gridBagLayout5);
+	addWord.setText(Globals.lang("Add"));
+	removeWord.setText(Globals.lang("Remove"));
+	jPanel6.setLayout(gridBagLayout6);
+	select.setText(Globals.lang("Select"));
+	fieldSelector.addActionListener(new ContentSelectorDialog_fieldSelector_actionAdapter(this));
+	getContentPane().add(panel1);
+	this.getContentPane().add(jPanel2, BorderLayout.SOUTH);
+	//JToolBar tlb = new JToolBar();
+	//tlb.setLayout(new GridLayout(1,1));
+	//tlb.setPreferredSize(new Dimension(28, 28));
+	//tlb.setFloatable(false);
+	//tlb.add(help);
+	jPanel2.add(help, null);
+	jPanel2.add(Close, null);
+
+	panel1.add(jPanel1,   new GridBagConstraints(0, 0, 1, 1, 1.0, 0.0
+						     ,GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(5, 5, 5, 5), 0, 0));
+	jPanel1.add(lab,      new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0
+						     ,GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0));
+	jPanel1.add(fieldTf,        new GridBagConstraints(2, 0, 1, 1, 0.0, 0.0
+							       ,GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 1, 0));
+	panel1.add(jPanel3,    new GridBagConstraints(0, 1, 1, 1, 1.0, 1.0
+						      ,GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(5, 5, 5, 5), 0, 0));
+	jPanel3.add(jLabel1,             new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0
+								,GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0));
+	jPanel1.add(fieldSelector,       new GridBagConstraints(1, 0, 1, 1, 0.0, 0.0
+								,GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0));
+	jPanel1.add(jPanel4,    new GridBagConstraints(2, 1, 1, 1, 0.0, 0.0
+						       ,GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0));
+	jPanel4.add(add,     new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0
+						    ,GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(5, 5, 5, 5), 0, 0));
+	jPanel4.add(remove,  new GridBagConstraints(1, 0, 1, 1, 0.0, 0.0
+						    ,GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(5, 0, 5, 5), 0, 0));
+	jPanel3.add(wordSelector,             new GridBagConstraints(1, 0, 1, 1, 0.0, 0.0
+								     ,GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0));
+	jPanel3.add(wordTf,                  new GridBagConstraints(2, 0, 1, 1, 0.0, 0.0
+									 ,GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0));
+	jPanel3.add(jPanel5,       new GridBagConstraints(2, 2, 1, 1, 0.0, 0.0
+							  ,GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
+	jPanel3.add(jPanel6,    new GridBagConstraints(2, 1, 1, 1, 0.0, 0.0
+						       ,GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0));
+	jPanel6.add(addWord,   new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0
+						      ,GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0));
+	jPanel6.add(removeWord,  new GridBagConstraints(1, 0, 1, 1, 0.0, 0.0
+							,GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(5, 0, 5, 5), 0, 0));
+	jPanel1.add(select,  new GridBagConstraints(1, 1, 1, 1, 0.0, 0.0
+						    ,GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0));
+
+
+	add.addActionListener(new ActionListener() {
+		public void actionPerformed(ActionEvent e) {
+		    addField();
+		}
+	    });
+
+	wordTf.addActionListener(new ActionListener() {
+		public void actionPerformed(ActionEvent e) {
+		    addWord();
+		}
+	    });
+	addWord.addActionListener(new ActionListener() {
+		public void actionPerformed(ActionEvent e) {
+		    addWord();
+		}
+	    });
+	removeWord.addActionListener(new ActionListener() {
+		public void actionPerformed(ActionEvent e) {
+		    removeWord();
+		}
+	    });
+	wordSelector.addActionListener(new ActionListener() {
+		public void actionPerformed(ActionEvent e) {
+		    if (wordSelector.getSelectedIndex() > 0) {
+			wordTf.setText((String)wordSelector.getSelectedItem());
+			wordTf.requestFocus();
+		    }
+		}
+	    });
+
+
+
+	setupFieldSelector();
+    }
+
+    void Close_actionPerformed(ActionEvent e) {
+	dispose();
+    }
+
+}
+
+class ContentSelectorDialog_Close_actionAdapter implements java.awt.event.ActionListener {
+    ContentSelectorDialog adaptee;
+
+    ContentSelectorDialog_Close_actionAdapter(ContentSelectorDialog adaptee) {
+	this.adaptee = adaptee;
+    }
+    public void actionPerformed(ActionEvent e) {
+	adaptee.Close_actionPerformed(e);
+    }
+}
+
+class ContentSelectorDialog_fieldSelector_actionAdapter implements java.awt.event.ActionListener {
+    ContentSelectorDialog adaptee;
+
+    ContentSelectorDialog_fieldSelector_actionAdapter(ContentSelectorDialog adaptee) {
+	this.adaptee = adaptee;
+    }
+    public void actionPerformed(ActionEvent e) {
+	adaptee.fieldSelector_actionPerformed(e);
+    }
+}
diff --git a/src/java/net/sf/jabref/ContentSelectorDialog2.java b/src/java/net/sf/jabref/ContentSelectorDialog2.java
new file mode 100644
index 0000000..38d2c8f
--- /dev/null
+++ b/src/java/net/sf/jabref/ContentSelectorDialog2.java
@@ -0,0 +1,438 @@
+package net.sf.jabref;
+
+import java.awt.*;
+import javax.swing.*;
+import javax.swing.border.*;
+import javax.swing.event.*;
+import java.awt.event.*;
+import java.util.Iterator;
+import java.util.Vector;
+import java.util.HashMap;
+import java.util.TreeSet;
+import java.util.ArrayList;
+
+public class ContentSelectorDialog2 extends JDialog {
+
+    ActionListener wordEditFieldListener = null;
+    GridBagLayout gbl = new GridBagLayout();
+    GridBagConstraints con = new GridBagConstraints();
+    JPanel fieldPan = new JPanel(),
+	wordPan = new JPanel(),
+	buttonPan = new JPanel(),
+	fieldNamePan = new JPanel(),
+	wordEditPan = new JPanel();
+
+    final String
+	WORD_EMPTY_TEXT = Globals.lang("<no field>"),
+	WORD_FIRSTLINE_TEXT = Globals.lang("<select word>"),
+	FIELD_FIRST_LINE = Globals.lang("<field name>");
+    MetaData metaData;
+    String currentField = null;
+    TreeSet fieldSet, wordSet;
+    JabRefFrame frame;
+    BasePanel panel;
+    JButton help = new JButton(Globals.lang("Help")),
+	newField = new JButton(Globals.lang("New")),
+	removeField = new JButton(Globals.lang("Remove")),
+	newWord = new JButton(Globals.lang("New")),
+	removeWord = new JButton(Globals.lang("Remove")),
+	ok = new JButton(Globals.lang("Ok")),
+	cancel = new JButton(Globals.lang("Cancel")),
+	apply = new JButton(Globals.lang("Apply"));
+    DefaultListModel fieldListModel = new DefaultListModel(),
+	wordListModel = new DefaultListModel();
+    JList fieldList = new JList(fieldListModel),
+	wordList = new JList(wordListModel);
+    JTextField fieldNameField = new JTextField("", 20),
+	wordEditField = new JTextField("", 20);
+    JScrollPane fPane = new JScrollPane(fieldList),
+	wPane = new JScrollPane(wordList);
+
+    HashMap wordListModels = new HashMap();
+    ArrayList removedFields = new ArrayList();
+
+    public ContentSelectorDialog2(Frame owner, JabRefFrame frame, BasePanel panel, boolean modal, MetaData metaData,
+              String fieldName) {
+        super(owner, Globals.lang("Setup selectors"), modal);
+        this.metaData = metaData;
+        this.frame = frame;
+        this.panel = panel;
+        this.currentField = fieldName;
+        doInit();
+    }
+    
+    public ContentSelectorDialog2(Dialog owner, JabRefFrame frame, BasePanel panel, boolean modal, MetaData metaData,
+              String fieldName) {
+        super(owner, Globals.lang("Setup selectors"), modal);
+        this.metaData = metaData;
+        this.frame = frame;
+        this.panel = panel;
+        this.currentField = fieldName;
+        doInit();
+    }
+    
+    /** Called from constructors */
+    private void doInit() {
+        //help = new JButton(Globals.lang("Help"));
+        //help.addActionListener(new HelpAction(frame.helpDiag, GUIGlobals.contentSelectorHelp, "Help"));
+        //help = new HelpAction(frame.helpDiag, GUIGlobals.contentSelectorHelp, "Help");
+        initLayout();
+        //  wordSelector.addItem(WORD_EMPTY_TEXT);
+    
+        setupFieldSelector();
+        setupWordSelector();
+        setupActions();
+        int fieldInd = fieldListModel.indexOf(currentField);
+        if (fieldInd >= 0)
+            fieldList.setSelectedIndex(fieldInd);
+    
+        pack();
+    }
+
+
+    private void setupActions() {
+
+	wordList.addListSelectionListener(new ListSelectionListener() {
+		public void valueChanged(ListSelectionEvent e) {
+		    wordEditField.setText((String)wordList.getSelectedValue());
+		    wordEditField.selectAll();
+		    new FocusRequester(wordEditField);
+		}
+	    });
+
+	newWord.addActionListener(new ActionListener() {
+		public void actionPerformed(ActionEvent e) {
+		    newWordAction();
+		}
+	    });
+                
+        wordEditFieldListener = new ActionListener() {
+            public void actionPerformed(ActionEvent e) {
+                int index = wordList.getSelectedIndex();
+                String old = (String)wordList.getSelectedValue(),
+            	newVal = wordEditField.getText();
+                if (newVal.equals("") || newVal.equals(old))
+                    return; // Empty string or no change.
+                int newIndex = findPos(wordListModel, newVal);
+                if (index >= 0) {
+                    wordListModel.remove(index);
+                    wordListModel.add((newIndex <= index ? newIndex : newIndex-1),
+                      newVal);
+                } else
+                    wordListModel.add(newIndex, newVal);
+		    
+                wordEditField.selectAll();
+            }
+	};
+        wordEditField.addActionListener(wordEditFieldListener);
+        
+	removeWord.addActionListener(new ActionListener() {
+		public void actionPerformed(ActionEvent e) {
+		    int index = wordList.getSelectedIndex();
+		    if (index == -1)
+			return;
+		    wordListModel.remove(index);
+		    wordEditField.setText("");
+		    if (wordListModel.size() > 0)
+			wordList.setSelectedIndex(Math.min(index, wordListModel.size()-1));
+		}
+	    });
+
+
+	fieldList.addListSelectionListener(new ListSelectionListener() {
+		public void valueChanged(ListSelectionEvent e) {
+		    currentField = (String)fieldList.getSelectedValue();
+		    fieldNameField.setText("");
+		    setupWordSelector();
+		}
+	    });
+
+	newField.addActionListener(new ActionListener() {
+		public void actionPerformed(ActionEvent e) {
+		    fieldListModel.add(0, FIELD_FIRST_LINE);
+		    fieldList.setSelectedIndex(0);
+		    fPane.getVerticalScrollBar().setValue(0);
+		    fieldNameField.setEnabled(true);
+		    fieldNameField.setText(currentField);
+		    fieldNameField.selectAll();
+
+		    new FocusRequester(fieldNameField);
+		}
+	    });
+
+	fieldNameField.addActionListener(new ActionListener() {
+		public void actionPerformed(ActionEvent e) {
+		    fieldNameField.transferFocus();
+		}
+	    });
+
+	fieldNameField.addFocusListener(new FocusAdapter() {
+		public void focusLost(FocusEvent e) {
+		    String s = fieldNameField.getText();
+		    fieldNameField.setText("");
+		    fieldNameField.setEnabled(false);
+		    if (!FIELD_FIRST_LINE.equals(s) && !"".equals(s)) {
+			// Add new field.
+			int pos = findPos(fieldListModel, s);
+			fieldListModel.remove(0);
+			fieldListModel.add(Math.max(0, pos-1), s);
+			fieldList.setSelectedIndex(pos);
+			currentField = s;
+			setupWordSelector();
+			newWordAction();
+			//new FocusRequester(wordEditField);
+		    }
+		}
+	    });
+
+	removeField.addActionListener(new ActionListener() {
+		public void actionPerformed(ActionEvent e) {
+		    int index = fieldList.getSelectedIndex();
+		    if (index == -1)
+			return;
+		    String fieldName = (String)fieldListModel.get(index);
+		    removedFields.add(fieldName);
+		    fieldListModel.remove(index);
+		    wordListModels.remove(fieldName);
+		    fieldNameField.setText("");
+		    if (fieldListModel.size() > 0)
+			fieldList.setSelectedIndex(Math.min(index, wordListModel.size()-1));
+		}
+	    });
+
+	help.addActionListener(new ActionListener() {
+		public void actionPerformed(ActionEvent e) {
+		    frame.helpDiag.showPage(GUIGlobals.contentSelectorHelp);
+		}
+	    });
+
+	ok.addActionListener(new ActionListener() {
+		public void actionPerformed(ActionEvent e) {
+		    applyChanges();
+		    dispose();
+		}
+	    });
+
+	apply.addActionListener(new ActionListener() {
+		public void actionPerformed(ActionEvent e) {
+            // Store if an entry is currently being edited:
+            if (!wordEditField.getText().equals("")) {
+                wordEditFieldListener.actionPerformed(null);
+            }
+		    applyChanges();
+		}
+	    });
+
+	cancel.addActionListener(new ActionListener() {
+		public void actionPerformed(ActionEvent e) {
+		    dispose();
+		}
+	    });
+
+    }
+
+    private void newWordAction() {
+	if ((wordListModel.size() == 0) || 
+	    !wordListModel.get(0).equals(WORD_FIRSTLINE_TEXT))
+	    wordListModel.add(0, WORD_FIRSTLINE_TEXT);
+	wordList.setSelectedIndex(0);
+	wPane.getVerticalScrollBar().setValue(0);
+    }
+
+
+    private void applyChanges() {
+	boolean changedFieldSet = false; // Watch if we need to rebuild entry editors
+
+	// First remove the mappings for fields that have been deleted.
+	// If these were re-added, they will be added below, so it doesn't
+	// cause any harm to remove them here.
+	for (Iterator i=removedFields.iterator(); i.hasNext();) {
+	    String fieldName = (String)i.next();
+	    metaData.remove(Globals.SELECTOR_META_PREFIX+fieldName);
+	    changedFieldSet = true;
+	}
+
+	// Cycle through all fields that we have created listmodels for:
+	loop: for (Iterator i=wordListModels.keySet().iterator(); i.hasNext();) {
+	    // For each field name, store the values:
+	    String fieldName = (String)i.next();
+	    if ((fieldName == null) || FIELD_FIRST_LINE.equals(fieldName))
+		continue loop;
+	    DefaultListModel lm = (DefaultListModel)wordListModels.get(fieldName);
+	    int start = 0;
+	    // Avoid storing the <new word> marker if it is there:
+	    if (lm.size() > 0)
+		while ((start<lm.size()) && ((String)lm.get(start)).equals(WORD_FIRSTLINE_TEXT))
+		    start++;
+	    Vector data = metaData.getData(Globals.SELECTOR_META_PREFIX+fieldName);
+	    boolean newField = false;
+	    if (data == null) {
+		newField = true;
+		data = new Vector();
+		changedFieldSet = true;
+
+	    } else
+		data.clear();
+	    for (int wrd=start; wrd<lm.size(); wrd++) {
+		String word = (String)lm.get(wrd);
+		data.add(word);
+	    }
+	    if (newField)
+		metaData.putData(Globals.SELECTOR_META_PREFIX+fieldName, data);
+	}
+
+	// System.out.println("TODO: remove metadata for removed selector field.");
+	panel.markNonUndoableBaseChanged();
+
+	// Update all selectors in the current BasePanel.
+	if (!changedFieldSet)
+	    panel.updateAllContentSelectors();
+	else {
+	    panel.rebuildAllEntryEditors();
+	}
+    }
+
+    /**
+     * Set the contents of the field selector list.
+     *
+     */
+    private void setupFieldSelector() {
+	fieldListModel.clear();
+	//fieldListModel.addElement(FIELD_FIRST_LINE);
+	for (Iterator i=metaData.iterator(); i.hasNext();) {
+	    String s = (String)i.next();
+	    if (s.startsWith(Globals.SELECTOR_META_PREFIX))
+		fieldListModel.addElement(s.substring(Globals.SELECTOR_META_PREFIX.length()));
+	}
+
+    }
+
+
+    private void setupWordSelector() {
+
+	// Have we already created a listmodel for this field?
+	Object o = wordListModels.get(currentField);
+	if (o != null) {
+	    wordListModel = (DefaultListModel)o;
+	    wordList.setModel(wordListModel);
+	} else {
+	    wordListModel = new DefaultListModel();
+	    wordList.setModel(wordListModel);
+	    wordListModels.put(currentField, wordListModel);
+	    wordListModel.clear();
+	    //wordListModel.addElement(WORD_FIRSTLINE_TEXT);
+	    Vector items = metaData.getData(Globals.SELECTOR_META_PREFIX+currentField);
+	    if ((items != null)) { // && (items.size() > 0)) {
+		wordSet = new TreeSet(items);
+		for (Iterator i=wordSet.iterator(); i.hasNext();) {
+		    String s = (String)i.next();
+		    int index = findPos(wordListModel, s);
+		    wordListModel.add(index, s);
+		}
+	    }
+	}
+    }
+
+    private int findPos(DefaultListModel lm, String item) {
+	for (int i=0; i<lm.size(); i++) {
+	    String s = (String)lm.get(i);
+	    if (item.compareToIgnoreCase(s) < 0) { // item precedes s
+		return i;
+	    }
+	}
+	return wordListModel.size();
+    }
+
+    private void initLayout() {
+	fieldNameField.setEnabled(false);
+	fieldList.setVisibleRowCount(4);
+	wordList.setVisibleRowCount(10);
+	final String VAL = "Uren luren himmelturen, ja Besseggen.";
+	fieldList.setPrototypeCellValue(VAL);
+	wordList.setPrototypeCellValue(VAL);
+
+	fieldPan.setBorder(BorderFactory.createTitledBorder
+			       (BorderFactory.createEtchedBorder(),
+				Globals.lang("Field name")));
+	wordPan.setBorder(BorderFactory.createTitledBorder
+			       (BorderFactory.createEtchedBorder(),
+				Globals.lang("Keyword")));
+	fieldPan.setLayout(gbl);
+	wordPan.setLayout(gbl);
+	con.insets = new Insets(2, 2, 2, 2);
+	con.fill = GridBagConstraints.BOTH;
+	con.gridwidth = 2;
+	con.weightx = 1;
+	con.weighty = 1;
+	con.gridx = 0;
+	con.gridy = 0;
+	gbl.setConstraints(fPane, con);
+	fieldPan.add(fPane);
+	gbl.setConstraints(wPane, con);
+	wordPan.add(wPane);
+	con.gridwidth = 1;
+	con.gridx = 2;
+	//con.weightx = 0.7;
+	con.gridheight = 2;
+	gbl.setConstraints(fieldNamePan, con);
+	fieldPan.add(fieldNamePan);
+	gbl.setConstraints(wordEditPan, con);
+	wordPan.add(wordEditPan);
+	con.gridx = 0;
+	con.gridy = 1;
+	con.weightx = 0;
+	con.weighty = 0;
+	con.gridwidth = 1;
+	con.gridheight = 1;
+	con.fill = GridBagConstraints.NONE;
+	con.anchor = GridBagConstraints.WEST;
+	gbl.setConstraints(newField, con);
+	fieldPan.add(newField);
+	gbl.setConstraints(newWord, con);
+	wordPan.add(newWord);
+	con.gridx = 1;
+	//con.anchor = GridBagConstraints.EAST;
+	gbl.setConstraints(removeField, con);
+	fieldPan.add(removeField);
+	gbl.setConstraints(removeWord, con);
+	wordPan.add(removeWord);
+	con.anchor = GridBagConstraints.WEST;
+	con.gridx = 0;
+	con.gridy = 0;
+	gbl.setConstraints(fieldNameField, con);
+	fieldNamePan.add(fieldNameField);
+	gbl.setConstraints(wordEditField, con);
+	wordEditPan.add(wordEditField);
+
+	// Add buttons:
+	buttonPan.add(help);
+	buttonPan.add(Box.createHorizontalStrut(10));
+	buttonPan.add(ok);
+	buttonPan.add(apply);
+	buttonPan.add(cancel);
+
+	// Add panels to dialog:
+	con.fill = GridBagConstraints.BOTH;
+	getContentPane().setLayout(gbl);
+	con.weightx = 1;
+	con.weighty = 0.5;
+	con.gridwidth = 1;
+	con.gridheight = 1;
+	con.gridx = 0;
+	con.gridy = 0;
+	gbl.setConstraints(fieldPan, con);
+	getContentPane().add(fieldPan);
+	con.gridy = 1;
+	gbl.setConstraints(wordPan, con);
+	getContentPane().add(wordPan);
+	con.weighty = 0;
+	con.gridy = 2;
+	con.insets = new Insets(12, 2, 2, 2);
+	gbl.setConstraints(buttonPan, con);
+	getContentPane().add(buttonPan);
+
+
+    }
+
+
+}
diff --git a/src/java/net/sf/jabref/CrossRefEntryComparator.java b/src/java/net/sf/jabref/CrossRefEntryComparator.java
new file mode 100644
index 0000000..ca7e142
--- /dev/null
+++ b/src/java/net/sf/jabref/CrossRefEntryComparator.java
@@ -0,0 +1,57 @@
+/*
+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.
+
+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.util.Comparator;
+
+/**
+ * Compares Bibtex entries based on their 'crossref' fields. Entries including
+ * this field are deemed smaller than entries without this field. This serves
+ * the purpose of always placing referenced entries after referring entries in
+ * the .bib file. After this criterion comes comparisons of individual fields.
+ */
+public class CrossRefEntryComparator implements Comparator {
+
+    private String crossRefField = "crossref";
+
+    public int compare(Object o1, Object o2) throws ClassCastException {
+	if (!(o1 instanceof BibtexEntry) || !(o2 instanceof BibtexEntry))
+	   throw new ClassCastException("Trouble comparing objects. This shouldn't happen.");
+	BibtexEntry e1 = (BibtexEntry)o1,
+	    e2 = (BibtexEntry)o2;
+
+	Object f1 = e1.getField(crossRefField),
+	    f2 = e2.getField(crossRefField);
+
+	if ((f1 == null) && (f2 == null)) return 0; //secComparator.compare(e1, e2);
+	if ((f1 != null) && (f2 != null)) return 0; //secComparator.compare(e1, e2);
+	if (f1 != null) return -1;
+	else return 1;
+    }
+
+}
diff --git a/src/java/net/sf/jabref/CustomEntryType.java b/src/java/net/sf/jabref/CustomEntryType.java
new file mode 100644
index 0000000..5a866dc
--- /dev/null
+++ b/src/java/net/sf/jabref/CustomEntryType.java
@@ -0,0 +1,118 @@
+package net.sf.jabref;
+
+import java.io.*;
+
+/**
+ * This class is used to represent customized entry types.
+ *
+ */
+public class CustomEntryType extends BibtexEntryType {
+
+    private String name;
+    private String[] req, opt;
+
+    public CustomEntryType(String name_, String[] req_, String[] opt_) {
+	name = name_;
+	req = req_;
+	opt = opt_;
+    }
+
+    public CustomEntryType(String name_, String reqStr, String optStr) {
+	name = name_;
+	if (reqStr.length() == 0)
+	    req = new String[0];
+	else
+	    req = reqStr.split(";");
+	if (optStr.length() == 0)
+	    opt = new String[0];
+	else
+	    opt = optStr.split(";");	
+    }
+
+    public String getName() {
+	return name;
+    }
+
+    public String[] getOptionalFields() {
+	return opt;
+    }
+    public String[] getRequiredFields() {
+	return req;
+    }
+
+    //    public boolean isTemporary
+
+    public String describeRequiredFields() {
+	StringBuffer sb = new StringBuffer();
+	for (int i=0; i<req.length; i++) {
+	    sb.append(req[i]);
+	    sb.append(((i<=req.length-1)&&(req.length>1))?", ":"");
+	}
+	return sb.toString();
+    }
+
+    public String describeOptionalFields() {
+	StringBuffer sb = new StringBuffer();
+	for (int i=0; i<opt.length; i++) {
+	    sb.append(opt[i]);
+	    sb.append(((i<=opt.length-1)&&(opt.length>1))?", ":"");
+	}
+	return sb.toString();
+    }
+
+    public boolean hasAllRequiredFields(BibtexEntry entry) {
+	for (int i=0; i<req.length; i++)
+	    if (entry.getField(req[i]) == null) return false;
+	return true;
+    }
+
+    public void save(Writer out) throws IOException {
+	out.write("@comment{");
+	out.write(GUIGlobals.ENTRYTYPE_FLAG);
+	out.write(getName());
+	out.write(": req[");
+	StringBuffer sb = new StringBuffer();
+	for (int i=0; i<req.length; i++) {
+	    sb.append(req[i]);
+	    if (i<req.length-1)
+		sb.append(";");
+	}
+	out.write(sb.toString());
+	out.write("] opt[");
+	sb = new StringBuffer();
+	for (int i=0; i<opt.length; i++) {
+	    sb.append(opt[i]);
+	    if (i<opt.length-1)
+		sb.append(";");
+	}
+	out.write(sb.toString());
+	out.write("]}"+Globals.NEWLINE);
+    }
+
+    public static CustomEntryType parseEntryType(String comment) { 
+	try {
+	    //if ((comment.length() < 9+GUIGlobals.ENTRYTYPE_FLAG.length())
+	    //	|| comment
+	    //System.out.println(">"+comment+"<");
+	    String rest;
+	    rest = comment.substring(GUIGlobals.ENTRYTYPE_FLAG.length());
+	    int nPos = rest.indexOf(':');
+	    String name = rest.substring(0, nPos);
+	    rest = rest.substring(nPos+2);
+
+	    int rPos = rest.indexOf(']');
+	    if (rPos < 4)
+		throw new IndexOutOfBoundsException();
+	    String reqFields = rest.substring(4, rPos);
+	    //System.out.println(name+"\nr '"+reqFields+"'");
+	    int oPos = rest.indexOf(']', rPos+1);
+	    String optFields = rest.substring(rPos+6, oPos);
+	    //System.out.println("o '"+optFields+"'");
+	    return new CustomEntryType(name, reqFields, optFields);
+	} catch (IndexOutOfBoundsException ex) {
+	    Globals.logger("Ill-formed entrytype comment in BibTeX file.");
+	    return null;
+	}
+
+    }
+}
diff --git a/src/java/net/sf/jabref/DatabaseChangeEvent.java b/src/java/net/sf/jabref/DatabaseChangeEvent.java
new file mode 100644
index 0000000..e5c34bd
--- /dev/null
+++ b/src/java/net/sf/jabref/DatabaseChangeEvent.java
@@ -0,0 +1,36 @@
+package net.sf.jabref;
+
+
+public class DatabaseChangeEvent {
+
+    static class ChangeType {
+    }
+
+    public static ChangeType ADDED_ENTRY = new ChangeType(),
+	REMOVED_ENTRY = new ChangeType(),
+	CHANGED_ENTRY = new ChangeType(),
+	CHANGING_ENTRY = new ChangeType();
+
+    private BibtexEntry entry;
+    private ChangeType type;
+    private BibtexDatabase source;
+
+    public DatabaseChangeEvent(BibtexDatabase source, ChangeType type, 
+			       BibtexEntry entry) {
+	this.source = source;
+	this.type = type;
+	this.entry = entry;
+    }
+
+    public BibtexDatabase getSource() {
+	return source;
+    }
+
+    public BibtexEntry getEntry() {
+	return entry;
+    }
+
+    public ChangeType getType() {
+	return type;
+    }
+}
diff --git a/src/java/net/sf/jabref/DatabaseChangeListener.java b/src/java/net/sf/jabref/DatabaseChangeListener.java
new file mode 100644
index 0000000..e901328
--- /dev/null
+++ b/src/java/net/sf/jabref/DatabaseChangeListener.java
@@ -0,0 +1,8 @@
+package net.sf.jabref;
+
+
+public interface DatabaseChangeListener {
+    
+    public void databaseChanged(DatabaseChangeEvent e);
+
+}
diff --git a/src/java/net/sf/jabref/DatabaseSearch.java b/src/java/net/sf/jabref/DatabaseSearch.java
new file mode 100644
index 0000000..385a53c
--- /dev/null
+++ b/src/java/net/sf/jabref/DatabaseSearch.java
@@ -0,0 +1,107 @@
+/*
+ Copyright (C) 2003 Nathan Dunn, 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.util.*;
+import java.util.regex.PatternSyntaxException;
+
+import javax.swing.SwingUtilities;
+
+public class DatabaseSearch extends Thread {
+	BasePanel panel = null;
+	BibtexDatabase thisDatabase = null;
+	SearchRuleSet thisRuleSet = null;
+	Hashtable thisSearchOptions = null;
+	String searchValueField = null;
+	boolean reorder, select, grayOut;
+	ErrorMessageDisplay errorDisplay;
+	Set matches = new HashSet();
+	public DatabaseSearch(ErrorMessageDisplay errorDisplay,
+			Hashtable searchOptions, SearchRuleSet searchRules,
+			BasePanel panel, String searchValueField, boolean reorder,
+			boolean grayOut, boolean select) {
+		this.panel = panel;
+		this.errorDisplay = errorDisplay;
+		thisDatabase = panel.getDatabase();
+		thisSearchOptions = searchOptions;
+		thisRuleSet = searchRules;
+		this.searchValueField = searchValueField;
+		this.reorder = reorder;
+		this.select = select;
+		this.grayOut = grayOut;
+	}
+
+	public void run() {
+		int searchScore = 0;
+		matches.clear();
+		BibtexEntry bes = null;
+		int hits = 0;
+
+		for (Iterator i = thisDatabase.getKeySet().iterator(); i.hasNext();) {
+			// 1. search all required fields using searchString
+
+			bes = thisDatabase.getEntryById((String) i.next());
+			if (bes == null)
+				continue;
+			// (thisTableModel.getNameFromNumber(row));
+
+			// 2. add score per each hit
+			try {
+				searchScore = thisRuleSet.applyRule(thisSearchOptions, bes);
+			} catch (PatternSyntaxException ex) {
+				// There is something wrong with the regexp pattern.
+				errorDisplay.reportError("Malformed regular expression", ex);
+				return;
+			}
+			// When using float search, it messes up the sort order if we retain
+			// graded search scores, because the table is sorted by the score.
+			// To prevent this, we let the search score saturate at 1.
+			if (searchScore > 0)
+				searchScore = 1;
+
+			// 2.1 set score to search field
+			bes.setField(searchValueField, String.valueOf(searchScore));
+
+			if (searchScore > 0) {
+				hits++;
+				matches.add(bes);
+			}
+		}
+		final int outputHits = hits;
+		SwingUtilities.invokeLater(new Thread() {
+			public void run() {
+				panel.output(Globals
+                    .lang("Searched database. Global number of hits")
+                    + ": " + outputHits);
+			}
+		});
+	}
+	
+	public Iterator matches() {
+		return matches.iterator();
+	}
+}
diff --git a/src/java/net/sf/jabref/DisplayPanel.java b/src/java/net/sf/jabref/DisplayPanel.java
new file mode 100644
index 0000000..2192363
--- /dev/null
+++ b/src/java/net/sf/jabref/DisplayPanel.java
@@ -0,0 +1,29 @@
+package net.sf.jabref;
+
+import javax.swing.*;
+import java.awt.*;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: alver
+ * Date: 12.mar.2005
+ * Time: 14:58:21
+ * To change this template use File | Settings | File Templates.
+ */
+public class DisplayPanel {
+
+    private JPanel panel = new JPanel();
+    private BibtexEntry activeEntry = null;
+
+    public DisplayPanel() {
+        panel.setLayout(new BorderLayout());
+    }
+
+    public void setEntry(BibtexEntry entry) {
+        activeEntry = entry;
+    }
+
+    public JPanel getPanel() {
+        return panel;
+    }
+}
diff --git a/src/java/net/sf/jabref/DuplicateResolverDialog.java b/src/java/net/sf/jabref/DuplicateResolverDialog.java
new file mode 100644
index 0000000..b57ba0f
--- /dev/null
+++ b/src/java/net/sf/jabref/DuplicateResolverDialog.java
@@ -0,0 +1,216 @@
+package net.sf.jabref;
+
+import javax.swing.JDialog;
+import java.awt.HeadlessException;
+import java.awt.GridBagLayout;
+import java.awt.GridBagConstraints;
+import javax.swing.*;
+import java.awt.Insets;
+import java.awt.BorderLayout;
+import java.awt.event.ActionListener;
+import java.awt.event.ActionEvent;
+import java.io.*;
+import net.sf.jabref.export.*;
+import java.awt.*;
+
+
+// created by : ?
+//
+// modified : r.nagel 2.09.2004
+//            - insert close button
+
+public class DuplicateResolverDialog extends JDialog {
+
+    public static final int
+	NOT_CHOSEN = -1,
+	KEEP_BOTH = 0,
+	KEEP_UPPER = 1,
+	KEEP_LOWER = 2,
+	BREAK      = 5,  // close
+	DUPLICATE_SEARCH = 1,
+	IMPORT_CHECK = 2,
+    INSPECTION = 3;
+
+    final Dimension DIM = new Dimension(650, 600);
+    
+    PreviewPanel p1, p2;
+    JTextArea ta1, ta2;
+    JTabbedPane tabbed = new JTabbedPane();
+    GridBagLayout gbl = new GridBagLayout();
+    GridBagConstraints con = new GridBagConstraints();
+    JButton first, second, both,
+	cancel = new JButton(Globals.lang("Cancel"));
+    JPanel options = new JPanel(),
+	main = new JPanel(),
+	source = new JPanel();
+    int status = NOT_CHOSEN;
+    boolean block = true;
+    TitleLabel lab;
+    
+  public DuplicateResolverDialog(JabRefFrame frame, BibtexEntry one, BibtexEntry two, int type) {
+    super(frame, Globals.lang("Possible duplicate entries"), true);
+
+      switch (type) {
+          case DUPLICATE_SEARCH:
+              first = new JButton(Globals.lang("Keep upper"));
+              second = new JButton(Globals.lang("Keep lower"));
+              both = new JButton(Globals.lang("Keep both"));
+              break;
+          case INSPECTION:
+              first = new JButton(Globals.lang("Remove old entry"));
+              second = new JButton(Globals.lang("Remove entry from import"));
+              both = new JButton(Globals.lang("Keep both"));
+              break;
+          default:
+              first = new JButton(Globals.lang("Import and remove old entry"));
+	          second = new JButton(Globals.lang("Do not import entry"));
+	          both = new JButton(Globals.lang("Import and keep old entry"));
+      }
+
+    String layout = Globals.prefs.get("preview0");
+    p1 = new PreviewPanel(one, layout);
+    p2 = new PreviewPanel(two, layout);
+    ta1 = new JTextArea();
+    ta2 = new JTextArea();
+    ta1.setEditable(false);
+    ta2.setEditable(false);
+    
+    //ta1.setPreferredSize(dim); 
+    //ta2.setPreferredSize(dim);
+    
+    setSourceView(one, two);
+
+    //getContentPane().setLayout();
+    main.setLayout(gbl);
+    source.setLayout(gbl);
+    con.insets = new Insets(10,10,0,10);
+    con.fill = GridBagConstraints.BOTH;
+    con.gridwidth = GridBagConstraints.REMAINDER;
+    con.weightx = 1;
+    con.weighty = 0;
+    lab = new TitleLabel(Globals.lang((type==DUPLICATE_SEARCH)?"":
+				  "Entry in current database"));
+    gbl.setConstraints(lab, con);
+    main.add(lab);
+    con.weighty = 1;
+    con.insets = new Insets(5,10,10,10);
+    JScrollPane sp = new JScrollPane(p1);
+    gbl.setConstraints(sp, con);
+    main.add(sp);
+    con.weighty = 0;
+    con.insets = new Insets(10,10,0,10);
+    lab = new TitleLabel(Globals.lang((type==DUPLICATE_SEARCH)?"":
+				  "Entry in import"));
+    gbl.setConstraints(lab, con);
+    main.add(lab);
+    con.weighty = 1;
+    con.insets = new Insets(5,10,10,10);
+    sp = new JScrollPane(ta1);
+    gbl.setConstraints(sp, con);
+    source.add(sp);
+    sp = new JScrollPane(p2);
+    gbl.setConstraints(sp, con);
+    main.add(sp);
+    sp = new JScrollPane(ta2);
+    gbl.setConstraints(sp, con);
+    source.add(sp);
+    tabbed.add(Globals.lang("Short form"), main);
+    tabbed.add(Globals.lang("Complete record"), source);
+    options.add(first);
+    options.add(second);
+    options.add(both);
+    if (type != IMPORT_CHECK) {
+        options.add(Box.createHorizontalStrut(5));
+        options.add(cancel);
+    }
+
+    first.addActionListener(new ActionListener() {
+      public void actionPerformed(ActionEvent e) {
+        status = KEEP_UPPER;
+        block = false;
+        dispose();
+      }
+    });
+
+    second.addActionListener(new ActionListener() {
+      public void actionPerformed(ActionEvent e) {
+        status = KEEP_LOWER;
+        block = false;
+        dispose();
+      }
+    });
+
+    both.addActionListener(new ActionListener() {
+      public void actionPerformed(ActionEvent e) {
+        status = KEEP_BOTH;
+        block = false;
+        dispose();
+      }
+    });
+
+    cancel.addActionListener(new ActionListener() {
+      public void actionPerformed(ActionEvent e) {
+        status = BREAK;
+        block = false;
+        dispose();
+      }
+    });
+
+    getContentPane().add(tabbed, BorderLayout.CENTER);
+    getContentPane().add(options, BorderLayout.SOUTH);
+    pack();
+    
+    
+    if (getHeight() > DIM.height) {
+        setSize(new Dimension(getWidth(), DIM.height));
+    }
+    if (getWidth() > DIM.width) {
+        setSize(new Dimension(DIM.width, getHeight()));
+    }
+    
+    
+    both.requestFocus();
+    Util.placeDialog(this, frame);
+  }
+
+  private void setSourceView(BibtexEntry one, BibtexEntry two) {
+    try {
+      StringWriter sw = new StringWriter();
+      one.write(sw, new LatexFieldFormatter(), false);
+      ta1.setText(sw.getBuffer().toString());
+      sw = new StringWriter();
+      two.write(sw, new LatexFieldFormatter(), false);
+      ta2.setText(sw.getBuffer().toString());
+    }
+    catch (IOException ex) {
+    }
+  }
+
+
+
+  public void setEntries(BibtexEntry newOne, BibtexEntry newTwo) {
+    setSourceView(newOne, newTwo);
+    p1.setEntry(newOne);
+    p2.setEntry(newTwo);
+    status = NOT_CHOSEN;
+    p1.revalidate();
+    p1.repaint();
+    block = true;
+  }
+
+public boolean isBlocking() {
+  return block;
+}
+
+  public int getSelected() {
+    return status;
+  }
+
+  public static int resolveDuplicate(JabRefFrame frame, BibtexEntry one, BibtexEntry two) {
+    DuplicateResolverDialog drd = new DuplicateResolverDialog(frame, one, two,
+							      DUPLICATE_SEARCH);
+    drd.show();
+    return drd.getSelected();
+  }
+
+}
diff --git a/src/java/net/sf/jabref/DuplicateSearch.java b/src/java/net/sf/jabref/DuplicateSearch.java
new file mode 100644
index 0000000..01e2f27
--- /dev/null
+++ b/src/java/net/sf/jabref/DuplicateSearch.java
@@ -0,0 +1,194 @@
+/*
+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.
+
+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
+
+*/
+
+// created by : ?
+//
+// modified : r.nagel 2.09.2004
+//            - new SearcherThread.setFinish() method
+//            - replace thread.sleep in run() by wait() and notify() mechanism
+
+package net.sf.jabref;
+
+import net.sf.jabref.undo.NamedCompound;
+import net.sf.jabref.undo.UndoableRemoveEntry;
+import java.util.Vector;
+
+public class DuplicateSearch extends Thread {
+
+  BasePanel panel;
+  BibtexEntry[] bes;
+  final Vector duplicates = new Vector();
+
+  public DuplicateSearch(BasePanel bp) {
+    panel = bp;
+  }
+
+public void run() {
+  NamedCompound ce = null;
+  int duplicateCounter = 0;
+  panel.output(Globals.lang("Searching for duplicates..."));
+  Object[] keys = panel.database.getKeySet().toArray();
+  if ((keys == null) || (keys.length < 2))
+    return;
+  bes = new BibtexEntry[keys.length];
+  for (int i=0; i<keys.length; i++)
+    bes[i] = panel.database.getEntryById((String)keys[i]);
+
+  SearcherThread st = new SearcherThread();
+  st.setPriority(Thread.MIN_PRIORITY);
+  st.start();
+  int current = 0;
+  DuplicateResolverDialog drd = null;
+
+/*
+  loop: while (!st.finished() || (current < duplicates.size()))
+  {
+    if ( current >= duplicates.size() )
+    {
+      // No more duplicates to resolve, but search is still in progress. Sleep a little.
+       try
+       {
+         sleep(10);
+       } catch (InterruptedException ex) {}
+       continue loop;
+    }
+  }
+*/
+
+  while (!st.finished() || (current < duplicates.size()))
+  {
+    if (current >= duplicates.size() )
+    {
+      // wait until the search thread puts something into duplicates vector
+      // or finish its work
+      synchronized(duplicates)
+      {
+         try
+         {
+           duplicates.wait();
+         }
+         catch (Exception e) {}
+      }
+    } else  // duplicates found
+    {
+      BibtexEntry[] be = ( BibtexEntry[] ) duplicates.get( current ) ;
+      current++ ;
+      if ( ( panel.database.getEntryById( be[0].getId() ) != null ) &&
+           ( panel.database.getEntryById( be[1].getId() ) != null ) )
+      {
+
+        drd = new DuplicateResolverDialog( panel.frame, be[0], be[1],
+					   DuplicateResolverDialog.DUPLICATE_SEARCH) ;
+        drd.show() ;
+
+        duplicateCounter++ ;
+        int answer = drd.getSelected() ;
+        if ( answer == DuplicateResolverDialog.KEEP_UPPER )
+        {
+          if ( ce == null ) ce = new NamedCompound(Globals.lang("duplicate removal")) ;
+          panel.database.removeEntry( be[1].getId() ) ;
+          panel.markBaseChanged() ;
+          ce.addEdit( new UndoableRemoveEntry( panel.database, be[1], panel ) ) ;
+        }
+        else if ( answer == DuplicateResolverDialog.KEEP_LOWER )
+        {
+          if ( ce == null ) ce = new NamedCompound(Globals.lang("duplicate removal")) ;
+          panel.database.removeEntry( be[0].getId() ) ;
+          panel.markBaseChanged() ;
+          ce.addEdit( new UndoableRemoveEntry( panel.database, be[0], panel ) ) ;
+        }
+        else if ( answer == DuplicateResolverDialog.BREAK )
+        {
+          st.setFinished() ; // thread killing
+          current = Integer.MAX_VALUE ;
+          duplicateCounter-- ; // correct counter
+        }
+        drd.dispose();
+      }
+    }
+  }
+
+  if (drd != null)
+    drd.dispose();
+
+  panel.output(Globals.lang("Duplicate pairs found") + ": " + duplicates.size()
+               +" " +Globals.lang("pairs processed") +": " +duplicateCounter );
+
+  if (ce != null)
+  {
+    ce.end();
+    //Util.pr("ox");
+    panel.undoManager.addEdit(ce);
+    //markBaseChanged();
+    //refreshTable();
+  }
+}
+
+
+class SearcherThread extends Thread {
+
+  private boolean finished = false;
+
+  public void run() {
+    for (int i = 0; (i < bes.length - 1) && !finished ; i++) {
+      for (int j = i + 1; (j < bes.length) && !finished ; j++) {
+        boolean eq = Util.isDuplicate(bes[i], bes[j],
+                                      Globals.duplicateThreshold);
+
+        // If (suspected) duplicates, add them to the duplicates vector.
+        if (eq)
+        {
+          synchronized (duplicates)
+          {
+            duplicates.add( new BibtexEntry[] {bes[i], bes[j]} ) ;
+            duplicates.notifyAll(); // send wake up all
+          }
+        }
+      }
+    }
+    finished = true;
+
+    // if no duplicates found, the graphical thread will never wake up
+    synchronized(duplicates)
+    {
+      duplicates.notifyAll();
+    }
+  }
+
+  public boolean finished() {
+    return finished;
+  }
+
+  // Thread cancel option
+  // no synchronized used because no "realy" critical situations expected
+  public void setFinished()
+  {
+    finished = true ;
+  }
+}
+
+}
diff --git a/src/java/net/sf/jabref/EntryComparator.java b/src/java/net/sf/jabref/EntryComparator.java
new file mode 100644
index 0000000..b363528
--- /dev/null
+++ b/src/java/net/sf/jabref/EntryComparator.java
@@ -0,0 +1,144 @@
+/*
+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.
+
+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.util.Comparator;
+
+/**
+ * This implementation of Comparator takes care of most of the details of sorting BibTeX entries in JabRef.
+ * It is structured as a node in a linked list of comparators, where each node can contain a link to a
+ * new comparator that decides the ordering (by recursion) if this one can't find a difference. The next
+ * node, if any, is given at construction time, and an arbitrary number of nodes can be included.
+ * If the entries are equal by this comparator, and there is no next entry, the entries' unique IDs will
+ * decide the ordering. Consequently, this comparator can never return 0 unless the entries are the same
+ * object.
+ */
+public class EntryComparator implements Comparator {
+
+    String sortField;
+    boolean descending, binary=false;
+    Comparator next;
+
+    public EntryComparator(boolean binary, boolean desc, String field, Comparator next) {
+        this.binary = binary;
+        this.sortField = field;
+        this.descending = desc;
+        this.next = next;
+    }
+
+    public EntryComparator(boolean binary, boolean desc, String field) {
+        this.binary = binary;
+        this.sortField = field;
+        this.descending = desc;
+        this.next = null;
+    }
+
+
+    public int compare(Object o1, Object o2) throws ClassCastException {
+      //if (o1 == null) Util.pr("o1 == null");
+     //if (o2 == null) Util.pr("o2 == null");
+
+    /*  The explicit instanceof test is unnecessary, since the
+         explicit casts below will throw ClassCastException anyway
+         if there is trouble.
+
+     if (!(o1 instanceof BibtexEntry) || !(o2 instanceof BibtexEntry))
+       throw new ClassCastException("Trouble comparing objects: "+o1.toString()+"\n\n"+o2.toString());*/
+
+    BibtexEntry e1 = (BibtexEntry)o1,
+        e2 = (BibtexEntry)o2;
+
+    if (e1 == e2)
+        return 0;
+
+    //Util.pr("EntryComparator: "+e1+" : "+e2);
+    Object f1 = e1.getField(sortField),
+        f2 = e2.getField(sortField);
+
+    if (binary) {
+        // We just separate on set and unset fields:
+        if (f1 != null)
+            return (f2 == null) ? -1 :
+                    (next != null ? next.compare(o1, o2) : idCompare(e1, e2));
+        else
+            return (f2 == null) ? (next != null ? next.compare(o1, o2) : idCompare(e1, e2))
+                    : 1;
+    }
+
+    // If the field is author or editor, we rearrange names so they are
+    // sorted according to last name.
+    if (sortField.equals("author") || sortField.equals("editor")) {
+        if (f1 != null)
+        f1 = AuthorList.fixAuthorForAlphabetization((String)f1);
+                //ImportFormatReader.fixAuthor_lastNameFirst((String)f1);
+        if (f2 != null)
+        f2 = AuthorList.fixAuthorForAlphabetization((String)f2);
+                //ImportFormatReader.fixAuthor_lastNameFirst((String)f2);
+    } else if (sortField.equals(GUIGlobals.TYPE_HEADER)) {
+          // Sort by type.
+          f1 = e1.getType().getName();
+          f2 = e2.getType().getName();
+        }
+
+	if ((f1 == null) && (f2 == null)) return (next != null ? next.compare(o1, o2) : idCompare(e1, e2));
+	if ((f1 != null) && (f2 == null)) return -1;
+	if ((f1 == null) && (f2 != null)) return 1;
+
+	int result = 0;
+
+	//String ours = ((String)e1.getField(sortField)).toLowerCase(),
+	//    theirs = ((String)e2.getField(sortField)).toLowerCase();
+	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();
+		int comp = ours.compareTo(theirs);
+		result = -comp;
+	}
+	if (result != 0)
+	    return (descending ? result : -result); // Primary sort.
+	if (next != null)
+	    return next.compare(o1, o2); // Secondary sort if existent.
+	else {
+
+        return idCompare(e1, e2); // If still equal, we use the unique IDs.
+    }
+    }
+
+    private int idCompare(BibtexEntry b1, BibtexEntry b2) {
+    return ((String)(b1.getId())).compareTo((String)(b2.getId()));
+    }
+
+}
diff --git a/src/java/net/sf/jabref/EntryCustomizationDialog.java b/src/java/net/sf/jabref/EntryCustomizationDialog.java
new file mode 100644
index 0000000..98af0ec
--- /dev/null
+++ b/src/java/net/sf/jabref/EntryCustomizationDialog.java
@@ -0,0 +1,428 @@
+/*
+Copyright (C) 2002-2003 Nizar N. Batada nbatada at stanford.edu
+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.util.*;
+import java.io.*;
+import javax.swing.*;
+import java.awt.event.*;
+import java.awt.*;
+
+class EntryCustomizationDialog extends JDialog implements ItemListener
+{
+    BibtexEntryType type;
+
+    JScrollPane reqSP, optSP;
+    JButton ok, cancel, helpButton, delete, importTypes, exportTypes;
+    JPanel panel=new JPanel(),
+	fieldPanel = new JPanel(),
+	typePanel = new JPanel();
+    int width=10;
+    JLabel messageLabel=new JLabel("", SwingConstants.CENTER);
+
+    JTextField name = new JTextField("", width);
+    JTextArea req_ta=new JTextArea("",5,width),//10 row, 20 columns
+	opt_ta=new JTextArea("",5,width);//10 row, 20 columns
+    // need to get FIeld name from somewhere
+
+    JComboBox types_cb = new JComboBox();
+
+    HelpAction help;
+
+    GridBagLayout gbl = new GridBagLayout();
+    GridBagConstraints con = new GridBagConstraints();
+    JPanel buttonPanel = new JPanel();
+
+    JabRefFrame parent;
+    EntryCustomizationDialog ths = this;
+
+    public EntryCustomizationDialog(JabRefFrame parent)
+    {
+	//Type=Article, Book etc
+	// templateName will be used to put on the dialog frame
+	// create 10 default entries
+	// return an array
+	super(parent,Globals.lang("Customize entry types"), false);
+	this.parent = parent;
+	help = new HelpAction(parent.helpDiag, GUIGlobals.customEntriesHelp,
+			      "Help", GUIGlobals.helpSmallIconFile);
+	setTypeSelection();
+	//setSize(440,400);
+	initialize();
+	makeButtons();
+
+	reqSP = new JScrollPane(req_ta,
+				JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
+				JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
+	optSP = new JScrollPane(opt_ta,
+				JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
+				JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
+	//helpButton = new JButton(help);
+	//helpButton.setText(null);
+        JToolBar tlb = new JToolBar();
+        tlb.setFloatable(false);
+        tlb.add(help);
+	//panel.setBackground(GUIGlobals.lightGray);
+	//buttonPanel.setBackground(GUIGlobals.lightGray);
+	panel.setLayout(gbl);
+	typePanel.setLayout(gbl);
+	fieldPanel.setLayout(gbl);
+	//panel.setBorder(BorderFactory.createEtchedBorder());
+	fieldPanel.setBorder(BorderFactory.createEtchedBorder());
+	typePanel.setBorder(BorderFactory.createEtchedBorder());
+
+	JLabel lab = new JLabel(Globals.lang("Type")+": "),
+	    lab2 = new JLabel(Globals.lang("Name")+": ");
+	con.insets = new Insets(5, 5, 5, 5);
+	gbl.setConstraints(lab, con);
+	gbl.setConstraints(lab2, con);
+	gbl.setConstraints(types_cb, con);
+
+	con.weightx = 1;
+	con.fill = GridBagConstraints.HORIZONTAL;
+	gbl.setConstraints(name, con);
+	con.fill = GridBagConstraints.NONE;
+	con.gridwidth = GridBagConstraints.REMAINDER;
+	con.weightx = 0;
+	//gbl.setConstraints(helpButton, con);
+	gbl.setConstraints(tlb, con);
+	con.gridwidth = 1;
+	typePanel.add(lab);
+	typePanel.add(types_cb);
+	typePanel.add(lab2);
+	typePanel.add(name);
+	//typePanel.add(helpButton);
+	typePanel.add(tlb);
+	lab = new JLabel(Globals.lang("Required fields"));
+	con.fill = GridBagConstraints.BOTH;
+	con.weightx = 1;
+	gbl.setConstraints(lab, con);
+	con.weighty = 1;
+	gbl.setConstraints(reqSP, con);
+	fieldPanel.add(lab);
+	con.gridwidth = GridBagConstraints.REMAINDER;
+	lab = new JLabel(Globals.lang("Optional fields"));
+	con.weighty = 0;
+	gbl.setConstraints(lab, con);
+	fieldPanel.add(lab);
+	con.weighty = 1;
+	gbl.setConstraints(optSP, con);
+
+	fieldPanel.add(reqSP);
+	fieldPanel.add(optSP);
+
+	con.gridwidth = GridBagConstraints.REMAINDER;
+	con.weighty = 0;
+	gbl.setConstraints(typePanel, con);
+	con.weighty = 1;
+	gbl.setConstraints(fieldPanel, con);
+	con.weighty = 0;
+	gbl.setConstraints(messageLabel, con);
+	panel.add(typePanel);
+	panel.add(fieldPanel);
+	panel.add(messageLabel);
+
+        // Key bindings:
+        ActionMap am = panel.getActionMap();
+        InputMap im = panel.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
+        im.put(Globals.prefs.getKey("Close dialog"), "close");
+        am.put("close", new AbstractAction() {
+          public void actionPerformed(ActionEvent e) {
+            dispose();
+          }
+        });
+        pack();
+	name.requestFocus();
+    }
+
+    public EntryCustomizationDialog(JabRefFrame parent,
+				    BibtexEntryType type_) {
+	this(parent);
+	type = type_;
+
+    }
+
+    void initialize(){
+
+	getContentPane().setLayout(new BorderLayout());
+	getContentPane().add( buttonPanel, BorderLayout.SOUTH);
+	getContentPane().add( panel, BorderLayout.CENTER);
+
+	messageLabel.setForeground(Color.black);
+	messageLabel.setText(Globals.lang("Delimit fields with semicolon, ex.")
+			     +": author;title;journal");
+
+	types_cb.addItemListener(this);
+    }
+
+    void save()
+    {
+      String typeName = name.getText().trim();
+      if (typeName.indexOf(" ") >= 0) {
+        JOptionPane.showMessageDialog(ths, Globals.lang("The type name can not contain spaces."),
+                                      Globals.lang("Illegal type name"), JOptionPane.ERROR_MESSAGE);
+        return;
+      }
+
+
+	String
+	    reqStr = req_ta.getText().replaceAll("\\s+","")
+	    .replaceAll("\\n+","").trim(),
+	    optStr = opt_ta.getText().replaceAll("\\s+","")
+	    .replaceAll("\\n+","").trim();
+
+
+	if(! typeName.equals("")) {
+	    CustomEntryType typ = new CustomEntryType
+		(Util.nCase(typeName), reqStr, optStr);
+	    BibtexEntryType.ALL_TYPES.put(typeName.toLowerCase(), typ);
+	    updateTypesForEntries(typ.getName());
+	    setTypeSelection();
+	    messageLabel.setText(Globals.lang("Stored definition for type")+
+				 " '"+Util.nCase(typ.getName())
+				 +"'.");
+	}
+	else{
+	    messageLabel.setText(Globals.lang("You must fill in a name for the entry type."));
+	}
+
+    }
+
+    private void setTypeSelection() {
+	types_cb.removeAllItems();
+	types_cb.addItem("<new>");
+	Iterator i = BibtexEntryType.ALL_TYPES.keySet().iterator();
+	BibtexEntryType type;
+	String toSet;
+	while (i.hasNext()) {
+	    type = BibtexEntryType.getType((String)i.next());
+	    toSet = Util.nCase(type.getName());
+	    if (type instanceof CustomEntryType)
+		toSet = toSet + " *";
+	    types_cb.addItem(toSet);
+
+	}
+    }
+
+    void makeButtons(){
+	ok = new JButton(Globals.lang("Store"));
+	cancel=new JButton(Globals.lang("Close"));
+	delete = new JButton(Globals.lang("Delete custom"));
+        //genFields = new JButton(Globals.lang("Set general fields"));
+	importTypes = new JButton(Globals.lang("Import"));
+	exportTypes = new JButton(Globals.lang("Export"));
+        buttonPanel.add( ok );
+	buttonPanel.add(delete);
+        buttonPanel.add(Box.createHorizontalStrut(5));
+        //buttonPanel.add(genFields);
+	buttonPanel.add(importTypes);
+	buttonPanel.add(exportTypes);
+        buttonPanel.add(Box.createHorizontalStrut(5));
+	buttonPanel.add( cancel);
+	ok.addActionListener(new ActionListener() {
+		public void actionPerformed(ActionEvent e) {
+		    save();
+		}
+	    });
+	cancel.addActionListener(new ActionListener() {
+		public void actionPerformed(ActionEvent e) {
+		    dispose();
+		}
+	    });
+        /*genFields.addActionListener(new ActionListener() {
+          public void actionPerformed(ActionEvent e) {
+            GenFieldsCustomizer gf = new GenFieldsCustomizer(parent, ths);
+            Util.placeDialog(gf, parent);
+            gf.show();
+          }
+        });*/
+	delete.addActionListener(new ActionListener() {
+		public void actionPerformed(ActionEvent e) {
+		    BibtexEntryType type = BibtexEntryType
+			.getType(name.getText());
+		    if (type == null)
+			messageLabel.setText(Globals.lang("There is no entry type")+
+					     " '"+Util.nCase(name.getText())+
+					     "' "+Globals.lang("defined."));
+		    else if (!(type instanceof CustomEntryType))
+			messageLabel.setText("'"+type.getName()+"' "+
+					     Globals.lang("is a standard type."));
+		    else {
+			String nm = name.getText();
+			if (BibtexEntryType.getStandardType(nm) == null) {
+			    int reply = JOptionPane.showConfirmDialog
+				(parent, Globals.lang("All entries of this "
+						      +"type will be declared "
+						      +"typeless. Continue?"),
+				 Globals.lang("Delete custom format")+
+				 " '"+Util.nCase(nm)+"'", JOptionPane.YES_NO_OPTION,
+				 JOptionPane.WARNING_MESSAGE);
+			    if (reply != JOptionPane.YES_OPTION)
+				return;
+			}
+			BibtexEntryType.removeType(nm);
+			setTypeSelection();
+			updateTypesForEntries(Util.nCase(nm));
+			messageLabel.setText
+			    (Globals.lang("Removed entry type."));
+		    }
+		}
+	    });
+
+	exportTypes.addActionListener(new ActionListener() {
+		public void actionPerformed(ActionEvent e) {
+		    String filename = Globals.getNewFile
+			(parent, Globals.prefs, new File(System.getProperty("user.home")), 
+			 ".txt", JFileChooser.SAVE_DIALOG, false);
+		    if (filename == null) 
+			return;
+		    File file = new File(filename);
+		    if (!file.exists() ||  
+			(JOptionPane.showConfirmDialog
+                         (ths, "'"+file.getName()+"' "+Globals.lang("exists. Overwrite file?"),
+                          Globals.lang("Export entry types"), JOptionPane.OK_CANCEL_OPTION)
+                         == JOptionPane.OK_OPTION)) {
+
+			try {
+			    FileWriter out = new FileWriter(file);
+			    Iterator i=BibtexEntryType.ALL_TYPES.keySet().iterator();
+			    while (i.hasNext()) {
+				Object o=BibtexEntryType.ALL_TYPES.get(i.next());
+				if (o instanceof CustomEntryType) {
+				    // Store this entry type.
+				    ((CustomEntryType)o).save(out);
+				}
+			    }
+			    out.close();
+			} catch (IOException ex) {
+			    JOptionPane.showMessageDialog
+				(ths, Globals.lang("Could not export entry types")+": "+ex.getMessage(), Globals.lang("Export preferences"), JOptionPane.ERROR_MESSAGE);
+			    //ex.printStackTrace();
+			}
+		    }
+
+		}
+	    });
+
+	importTypes.addActionListener(new ActionListener() {
+		public void actionPerformed(ActionEvent e) {
+		    String filename = Globals.getNewFile
+			(parent, Globals.prefs, new File(System.getProperty("user.home")), 
+			 ".txt", JFileChooser.OPEN_DIALOG, false);
+		    if (filename == null) 
+			return;
+
+		    try {
+			BufferedReader in = new BufferedReader(new FileReader(new File(filename)));
+			String line;
+			int count = 0;
+			while ((line = in.readLine()) != null) {
+			    line = line.trim();
+			    if ((line.length() > 9+GUIGlobals.ENTRYTYPE_FLAG.length())
+				&& line.substring(0, 9+GUIGlobals.ENTRYTYPE_FLAG.length()).equals("@comment{"+GUIGlobals.ENTRYTYPE_FLAG)
+				&& line.substring(line.length()-1).equals("}")) {
+				// Matches a @comment{jabref-entrytype: ...} section.
+				CustomEntryType type = CustomEntryType.parseEntryType(line.substring(9, line.length()-1));
+				if (type != null) {
+				    // Parsing succeeded.
+				    BibtexEntryType.ALL_TYPES.put(type.getName().toLowerCase(), type);
+				    count++;
+				}
+			    }
+
+			    if (count > 0) {
+				setTypeSelection();
+				req_ta.setText("");
+				opt_ta.setText("");
+				name.setText("");
+				messageLabel.setText(Globals.lang("Imported entry types")+": "+count);
+			    }
+			}
+		    } catch (IOException ex) {
+			JOptionPane.showMessageDialog
+			    (ths, Globals.lang("Could not import entry types")+": "+ex.getMessage(), Globals.lang("Import entry types"), JOptionPane.ERROR_MESSAGE);
+			//ex.printStackTrace();
+		    }
+		}
+
+		
+	    });
+    }
+
+    /**
+     * Cycle through all databases, and make sure everything is updated with
+     * the new type customization. This includes making sure all entries have
+     * a valid type, that no obsolete entry editors are around, and that
+     * the right-click menus' change type menu is up-to-date.
+     */
+    private void updateTypesForEntries(String typeName) {
+	if (parent.tabbedPane.getTabCount() == 0)
+	    return;
+	messageLabel.setText(Globals.lang("Updating entries..."));
+	BibtexDatabase base;
+	Iterator iter;
+	for (int i=0; i<parent.tabbedPane.getTabCount(); i++) {
+	    BasePanel bp = (BasePanel)parent.tabbedPane.getComponentAt(i);
+	    boolean anyChanges = false;
+	    bp.entryEditors.remove(typeName);
+	    //bp.rcm.populateTypeMenu(); // Update type menu for change type.
+	    base = bp.database;
+	    iter = base.getKeySet().iterator();
+	    while (iter.hasNext()) {
+		anyChanges = anyChanges |
+		    !(base.getEntryById((String)iter.next())).updateType();
+	    }
+	    if (anyChanges) {
+		bp.markBaseChanged();
+	    }
+	}
+    }
+
+    public void itemStateChanged(ItemEvent e) {
+	if (types_cb.getSelectedIndex() > 0) {
+	    // User has selected one of the existing types.
+	    String name = (String)types_cb.getSelectedItem();
+	    updateToType((name.split(" "))[0]);
+	} else {
+	    name.setText("");
+	    req_ta.setText("");
+	    opt_ta.setText("");
+	    name.requestFocus();
+	}
+    }
+
+    public void updateToType(String o) {
+
+	BibtexEntryType type = BibtexEntryType.getType(o);
+	name.setText(type.getName());
+	req_ta.setText(Util.stringArrayToDelimited
+		       (type.getRequiredFields(), ";\n"));
+	opt_ta.setText(Util.stringArrayToDelimited
+		       (type.getOptionalFields(), ";\n"));
+
+	req_ta.requestFocus();
+    }
+}
diff --git a/src/java/net/sf/jabref/EntryEditor.java b/src/java/net/sf/jabref/EntryEditor.java
new file mode 100644
index 0000000..ea5d954
--- /dev/null
+++ b/src/java/net/sf/jabref/EntryEditor.java
@@ -0,0 +1,1379 @@
+/*
+ * 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.
+ *
+ * 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.awt.*;
+import java.awt.datatransfer.StringSelection;
+import java.awt.dnd.*;
+import java.awt.event.*;
+import java.beans.*;
+import java.io.*;
+import java.util.*;
+import java.util.List;
+import java.util.logging.Logger;
+
+import javax.swing.*;
+import javax.swing.event.*;
+import javax.swing.text.JTextComponent;
+
+import net.sf.jabref.export.LatexFieldFormatter;
+import net.sf.jabref.groups.*;
+import net.sf.jabref.imports.BibtexParser;
+import net.sf.jabref.labelPattern.LabelPatternUtil;
+import net.sf.jabref.undo.*;
+import net.sf.jabref.external.ExternalFilePanel;
+import net.sf.jabref.journals.JournalAbbreviations;
+import net.sf.jabref.gui.MainTableSelectionListener;
+
+import java.text.*;
+
+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"),
+          new ImageIcon(GUIGlobals.showReqIconFile), 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"),
+              new ImageIcon(GUIGlobals.showOptIconFile), 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), new ImageIcon(GUIGlobals.showGenIconFile), newTab.getPane());
+        tabs.add(newTab);
+    }
+
+    srcPanel.setName(Globals.lang("BibTeX source"));
+    if (Globals.prefs.getBoolean("showSource")) {
+        tabbed.addTab(Globals.lang("BibTeX source"),
+              new ImageIcon(GUIGlobals.sourceIconFile), 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 GUIGlobals.FIELD_EXTRAS. 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;
+    Object o = GUIGlobals.FIELD_EXTRAS.get(string);
+    final String fieldName = editor.getFieldName();
+
+    //if (o == null)
+    //  return null;
+    String s = (String) o;
+    //addedByMoritz
+      if (fieldName.equals(Globals.prefs.get("timeStampField"))){
+    //if (fieldName.equals("dateadded")){
+        ((JTextArea) ed).addMouseListener(new MouseAdapter(){
+            public void mouseClicked(MouseEvent e){
+                if(e.getClickCount()==2){
+                    String date = Util.easyDateFormat();
+                    ed.setText(date);
+                    //DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
+                    //ed.setText(df.format(new Date()));
+                }
+            }
+        });
+    }
+    //END_OF addedByMoritz
+    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, prefs, 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, 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();
+         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 (GUIGlobals.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());
+    }
+  }
+
+
+  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"), new ImageIcon(GUIGlobals.removeIconFile));
+      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"), new ImageIcon(GUIGlobals.closeIconFile));
+      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", new ImageIcon(GUIGlobals.copyKeyIconFile));
+      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) {
+        //Util.pr("EntryEditor.StoreFieldAction: "+entry.getCiteKey());
+        //Util.pr("..EntryEditor.StoreFieldAction: "+this.toString());
+
+      if (e.getSource() instanceof FieldTextArea) {
+        String toSet = null;
+        FieldEditor fe = (FieldEditor) e.getSource();
+        boolean set;
+          //Util.pr("....EntryEditor.StoreFieldAction: "+fe.getFieldName());
+        //Util.pr("...."+fe.getText()+"....");
+        // Trim the whitespace off this value
+        fe.setText(fe.getText().trim());
+
+        if (fe.getText().length() > 0) {
+          toSet = fe.getText();
+
+          // 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();
+          } 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);
+        }
+
+        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"), new ImageIcon(GUIGlobals.downIconFile));
+
+      putValue(SHORT_DESCRIPTION, Globals.lang("Next entry"));
+    }
+
+    public void actionPerformed(ActionEvent e) {
+
+      int thisRow = panel.mainTable.findEntry(entry);
+      String id = null;
+      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"), new ImageIcon(GUIGlobals.upIconFile));
+
+      putValue(SHORT_DESCRIPTION, Globals.lang("Previous entry"));
+    }
+
+    public void actionPerformed(ActionEvent e) {
+      int thisRow = panel.mainTable.findEntry(entry);
+      String id = null;
+      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"), new ImageIcon(GUIGlobals.genKeyIconFile));
+      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(GUIGlobals.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(GUIGlobals.KEY_FIELD)));
+
+        // here we update the field
+        String bibtexKeyData = (String) entry.getField(Globals.KEY_FIELD);
+
+        // set the field named for "bibtexkey"
+        setField(Globals.KEY_FIELD, bibtexKeyData);
+        updateSource();
+        panel.markBaseChanged();
+      } catch (Throwable t) {
+        System.err.println("error setting key: " + t);
+      }
+    }
+  }
+
+  class UndoAction extends AbstractAction {
+    public UndoAction() {
+      super("Undo", new ImageIcon(GUIGlobals.undoIconFile));
+      putValue(SHORT_DESCRIPTION, "Undo");
+    }
+
+    public void actionPerformed(ActionEvent e) {
+      try {
+        panel.runCommand("undo");
+      } catch (Throwable ex) {
+      }
+    }
+  }
+
+  class RedoAction extends AbstractAction {
+    public RedoAction() {
+      super("Undo", new ImageIcon(GUIGlobals.redoIconFile));
+      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(link, tf.getFieldName(), prefs);
+        } 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
new file mode 100644
index 0000000..b89805c
--- /dev/null
+++ b/src/java/net/sf/jabref/EntryEditorTab.java
@@ -0,0 +1,293 @@
+/*
+ * 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.
+ *
+ * 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 javax.swing.*;
+import javax.swing.text.JTextComponent;
+import java.util.*;
+import java.util.List;
+import java.awt.*;
+import java.awt.event.*;
+
+public class EntryEditorTab {
+
+    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);
+
+        // The following line makes sure focus cycles inside tab instead of being lost
+        // to other parts of the frame:
+        panel.setFocusCycleRoot(true);
+
+    }
+
+
+    private final void setupPanel(boolean addKeyField, String title) {
+	GridBagLayout gbl = new GridBagLayout();
+	GridBagConstraints con = new GridBagConstraints();
+	panel.setLayout(gbl);
+	double totalWeight = 0;
+	
+	//panel.setOpaque(true);
+	//panel.setBackground(java.awt.Color.white);
+
+	for (int i=0; i<fields.length; i++) {
+
+	    // 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));
+
+	    // 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 = GUIGlobals.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;
+	    FieldTextField tf = new FieldTextField(Globals.KEY_FIELD, (String) parent.getEntry().getField(Globals.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);
+	}
+
+
+    }
+
+
+    public void setActive(FieldEditor c) {
+	activeField = c;
+	//System.out.println(c.toString());
+    }
+    
+    public FieldEditor getActive() {
+	return activeField;
+    }
+
+    public List getFields() {
+	return java.util.Arrays.asList(fields);
+    }
+
+    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);
+        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);
+	}
+	
+    }
+
+
+    /*
+     * Focus listener that fires the storeFieldAction when a FieldTextArea loses
+     * focus.
+     */
+    class FieldListener extends FocusAdapter {
+
+	FieldEditor fe;
+
+	public FieldListener(FieldEditor fe) {
+	    this.fe = fe;
+	}
+
+	public void focusGained(FocusEvent e) {
+	    setActive(fe);
+	}
+	
+	public void focusLost(FocusEvent e) {
+  	    if (!e.isTemporary())
+		parent.updateField(fe);
+	}
+    }
+    
+}
+
diff --git a/src/java/net/sf/jabref/EntryEditorTabList.java b/src/java/net/sf/jabref/EntryEditorTabList.java
new file mode 100644
index 0000000..a8e6116
--- /dev/null
+++ b/src/java/net/sf/jabref/EntryEditorTabList.java
@@ -0,0 +1,45 @@
+package net.sf.jabref;
+
+import java.util.*;
+
+/**
+ * Class for holding the information about customizable entry editor tabs.
+ */
+public final class EntryEditorTabList {
+
+    private List list = null;
+    private List names = null;
+
+    public EntryEditorTabList() {
+	init();
+    }
+
+    private void init() {
+	list = new ArrayList();
+	names = new ArrayList();
+	int i=0;
+	String name=null;
+	String[] fields=null;
+	while ((name=Globals.prefs.get(Globals.prefs.CUSTOM_TAB_NAME+i)) != null) {
+
+	    fields = Globals.prefs.get(Globals.prefs.CUSTOM_TAB_FIELDS+i).split(";");
+	    List entry = Arrays.asList(fields);
+	    names.add(name);
+	    list.add(entry);
+	    i++;
+	}
+	
+    }
+
+    public int getTabCount() {
+	return list.size();
+    }
+
+    public String getTabName(int tab) {
+	return (String)names.get(tab);
+    }
+
+    public List getTabFields(int tab) {
+	return (List)list.get(tab);
+    }
+}
diff --git a/src/java/net/sf/jabref/EntrySorter.java b/src/java/net/sf/jabref/EntrySorter.java
new file mode 100644
index 0000000..1810a9b
--- /dev/null
+++ b/src/java/net/sf/jabref/EntrySorter.java
@@ -0,0 +1,188 @@
+/*
+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;
+
+import java.util.*;
+
+public class EntrySorter implements DatabaseChangeListener {
+
+    //TreeSet set;
+    final ArrayList set;
+    Comparator comp;
+    String[] idArray;
+    BibtexEntry[] entryArray;
+    //static BibtexEntry[] DUMMY = new BibtexEntry[0];
+    private boolean outdated = false;
+    private boolean changed = false;
+
+    public EntrySorter(Map entries, Comparator comp) {
+	    //set = new TreeSet(comp);
+        set = new ArrayList();
+        this.comp = comp;
+        Set keySet = entries.keySet();
+	    if (keySet != null) {
+    	    Iterator i = keySet.iterator();
+    	    while (i.hasNext()) {
+    		    set.add(entries.get(i.next()));
+            }
+            //Collections.sort(set, comp);
+            changed = true;
+            index();
+	    }
+    }
+
+    public void index() {
+
+        /*  Old version, from when set was a TreeSet.
+
+        // The boolean "changing" is true in the situation that an entry is about to change,
+        // and has temporarily been removed from the entry set in this sorter. So, if we index
+        // now, we will cause exceptions other places because one entry has been left out of
+        // the indexed array. Simply waiting foth this to change can lead to deadlocks,
+        // so we have no other choice than to return without indexing.
+        if (changing)
+            return;
+        */
+
+
+        synchronized(set) {
+
+            // Resort if necessary:
+            if (changed) {
+                Collections.sort(set, comp);
+                changed = false;
+            }
+
+            // Create an array of IDs for quick access, since getIdAt() is called by
+            // getValueAt() in EntryTableModel, which *has* to be efficient.
+
+	        int count = set.size();
+            idArray = new String[count];
+            entryArray = new BibtexEntry[count];
+	        int piv = 0;
+	        for (Iterator i=set.iterator(); i.hasNext();) {
+	            //        for (int i=0; i<idArray.length; i++) {
+    	        BibtexEntry entry = (BibtexEntry)i.next();
+    	        idArray[piv] = entry.getId();
+    	        entryArray[piv] = entry;
+    	        piv++;
+            }
+        }
+    }
+
+    public boolean isOutdated() {
+	return outdated;
+    }
+
+    public String getIdAt(int pos) {
+        synchronized(set) {
+            return idArray[pos];
+        }
+	//return ((BibtexEntry)(entryArray[pos])).getId();
+    }
+
+    public BibtexEntry getEntryAt(int pos) {
+        synchronized(set) {
+            return entryArray[pos];
+        }
+    }
+
+    public int getEntryCount() {
+        synchronized(set) {
+	        if (entryArray != null)
+	            return entryArray.length;
+	        else
+	        return 0;
+        }
+    }
+
+    public void databaseChanged(DatabaseChangeEvent e) {
+        synchronized(set) {
+	        if (e.getType() == DatabaseChangeEvent.ADDED_ENTRY) {
+                int pos = -Collections.binarySearch(set, e.getEntry(), comp) - 1;
+                set.add(pos, e.getEntry());
+                //addEntry(e.getEntry());
+                //set.add(e.getEntry());
+                //changed = true;
+                //Collections.sort(set, comp);
+            }
+	        else if (e.getType() == DatabaseChangeEvent.REMOVED_ENTRY) {
+	            set.remove(e.getEntry());
+                changed = true;
+            }
+	        else if (e.getType() == DatabaseChangeEvent.CHANGED_ENTRY) {
+                // Entry changed. Resort list:
+                //Collections.sort(set, comp);
+                int pos = Collections.binarySearch(set, e.getEntry(), comp);
+                int posOld = set.indexOf(e.getEntry());
+                if (pos < 0) {
+                    set.remove(posOld);
+                    set.add(-pos-1, e.getEntry());
+                }
+                //changed = true;
+            }
+
+    	}
+
+    }
+
+    /** Add an entry to the sorted set, making sure it is put in the right position
+     *
+     * @param entry The entry to add
+     */
+    private void addEntry(BibtexEntry entry) {
+        int pos = -Collections.binarySearch(set, entry, comp) - 1;
+        set.add(pos, entry);
+    }
+
+/* Old version, from when set was a TreeSet.
+
+    public void databaseChanged(DatabaseChangeEvent e) {
+    synchronized(set) {
+        if (e.getType() == DatabaseChangeEvent.ADDED_ENTRY) {
+            set.add(e.getEntry());
+        }
+        else if (e.getType() == DatabaseChangeEvent.REMOVED_ENTRY) {
+            set.remove(e.getEntry());
+        }
+        else if (e.getType() == DatabaseChangeEvent.CHANGING_ENTRY) {
+            set.remove(e.getEntry());
+            changing = true;
+        }
+        else if (e.getType() == DatabaseChangeEvent.CHANGED_ENTRY) {
+            // Remove and re-add the entry, to make sure it is in the
+            // correct sort position.
+            set.add(e.getEntry());
+            changing = false;
+        }
+
+    }
+
+}
+*/
+}
diff --git a/src/java/net/sf/jabref/EntryTable.java b/src/java/net/sf/jabref/EntryTable.java
new file mode 100644
index 0000000..b90389c
--- /dev/null
+++ b/src/java/net/sf/jabref/EntryTable.java
@@ -0,0 +1,845 @@
+/*
+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.
+
+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.awt.*;
+import java.awt.event.*;
+import java.io.IOException;
+import java.util.Set;
+import java.util.HashSet;
+
+import javax.swing.*;
+import javax.swing.border.Border;
+import javax.swing.event.*;
+import javax.swing.plaf.basic.BasicTableUI;
+import javax.swing.table.*;
+
+import net.sf.jabref.groups.EntryTableTransferHandler;
+
+public class EntryTable extends JTable {
+
+    final int PREFERRED_WIDTH = 400, PREFERRED_HEIGHT = 30;
+
+    // We use a subclassed JScrollPane with setBorder() overridden as
+    // a no-op. This is done to avoid the JTable setting its border,
+    // which it does whether we want it or not. And we don't. :)
+    JScrollPane sp = new JScrollPane((JTable)this) {
+            public void setBorder(Border b) {}
+        };
+
+    JPopupMenu rightClickMenu = null;
+    EntryTableModel tableModel;
+    JabRefPreferences prefs;
+    protected boolean showingSearchResults = false,
+        showingGroup = false;
+    private boolean antialiasing = Globals.prefs.getBoolean("antialias"),
+        ctrlClick = false,
+        selectionListenerOn = true,
+        tableColorCodes = true;
+    //RenderingHints renderingHints;
+    private BasePanel panel;
+    Set lastSelection = new HashSet();
+
+    private ListSelectionListener previewListener = null;
+    private int activeRow = -1;
+    
+    ListSelectionListener groupsHighlightListener;
+    
+    public EntryTable(EntryTableModel tm_, BasePanel panel_, JabRefPreferences prefs_) {
+        super(tm_);
+        this.tableModel = tm_;
+        setBorder(null);
+        panel = panel_;
+        // Add the global focus listener, so a menu item can see if this table was focused when
+        // an action was called.
+        addFocusListener(Globals.focusListener);
+
+        // enable DnD
+        setDragEnabled(true);
+        // The following line is commented because EntryTableTransferHandler's
+	// constructor now only accepts MainTable which has replaced EntryTable.
+	// setTransferHandler(new EntryTableTransferHandler(this));
+
+  //renderingHints = g2.getRenderingHints();
+         //renderingHints.put(RenderingHints.KEY_ANTIALIASING,
+        //		   RenderingHints.VALUE_ANTIALIAS_ON);
+        //renderingHints.put(RenderingHints.KEY_RENDERING,
+        //		   RenderingHints.VALUE_RENDER_QUALITY);
+        prefs = prefs_;
+        //antialiasing =
+        //System.out.println(antialiasing);
+        ctrlClick = prefs.getBoolean("ctrlClick");
+        tableColorCodes = prefs.getBoolean("tableColorCodesOn");
+        getTableHeader().setReorderingAllowed(false); // To prevent color bugs. Must be fixed.
+        setGridColor(Globals.prefs.getColor("gridColor"));
+        setShowVerticalLines(true);
+        setShowHorizontalLines(true);
+        //setColumnSelectionAllowed(true);
+        setColumnSelectionAllowed(false);
+        setRowSelectionAllowed(true);
+        setAutoResizeMode(prefs.getInt("autoResizeMode"));
+        DefaultCellEditor dce = new DefaultCellEditor(new JTextField());
+        dce.setClickCountToStart(2);
+        setDefaultEditor(String.class, dce);
+        getTableHeader().addMouseListener(new MouseAdapter() {
+          public void mouseClicked(MouseEvent e)
+          {
+            int col = getTableHeader().columnAtPoint(e.getPoint());
+            if (col >= 1) { //tableModel.padleft) { // A valid column, but not the first.
+              String s = tableModel.getFieldName(col);
+              /*
+               * If the user adjusts the header size the sort event is
+               * always triggered.
+               * To avoid this behaviour we check if the mouse is
+               * inside the label's bounds and has a certain distance (offset)
+               * to the label border.
+               *
+               * Sascha Hunold <hunoldinho at users.sourceforge.net>
+               */
+
+              Point p = e.getPoint();
+              int colindex = getTableHeader().columnAtPoint(p);
+              if( colindex >= 0 ) {
+                  final int initoffset = 3;
+                  int xoffset = initoffset;
+                  for (int i = 0; i < colindex; i++) {
+                      xoffset += getColumnModel().getColumn(i).getWidth();
+                  }
+                  TableColumn column = getColumnModel().getColumn(col);
+                  int cw = column.getWidth();
+                  int ch = getTableHeader().getHeight();
+
+                  Rectangle r = new Rectangle();
+
+                  r.setBounds(xoffset, 0/*offset*/, cw-2*initoffset, ch/*-2*offset*/);
+
+                  if (!r.contains(p)) {
+                      return;
+                  }
+              }
+
+              if (!s.equals(prefs.get("priSort"))) {
+                prefs.put("priSort", s);
+                  // Now, if the selected column is an icon column, set the sort to binary mode,
+                  // meaning that it only separates set fields from empty fields, and does no
+                  // internal sorting of set fields:
+                  if (tableModel.getIconTypeForColumn(col) == null)
+                      prefs.putBoolean("priBinary", false);
+                  else
+                      prefs.putBoolean("priBinary", true);
+              }
+                // ... or change sort direction
+              else prefs.putBoolean("priDescending",
+                                    !prefs.getBoolean("priDescending"));
+              tableModel.remap();
+              
+            }
+          }
+        });
+
+        addMouseListener(new TableClickListener()); // Add the listener that responds to clicks on the table.
+
+        // Trying this to get better handling of the row selection stuff.
+        setSelectionModel(new javax.swing.DefaultListSelectionModel() {
+          public void setSelectionInterval(int index0, int index1) {
+            // Prompt user here
+            //Util.pr("Selection model: "+panel.entryEditorAllowsChange());
+            if (panel.entryEditorAllowsChange() == false) {
+              panel.moveFocusToEntryEditor();
+              return;
+            }
+            super.setSelectionInterval(index0, index1);
+          }
+        });
+
+        addSelectionListener(); // Add the listener that responds to new entry selection.
+
+        groupsHighlightListener = new ListSelectionListener() {
+            public void valueChanged(ListSelectionEvent e) {
+                /*
+                if (Globals.prefs.getBoolean("highlightGroupsMatchingAny"))
+                    panel.getGroupSelector().showMatchingGroups(
+                            panel.getSelectedEntries(), false);
+                else if (Globals.prefs.getBoolean("highlightGroupsMatchingAll"))
+                    panel.getGroupSelector().showMatchingGroups(
+                            panel.getSelectedEntries(), true);
+                else // no highlight
+                    panel.getGroupSelector().showMatchingGroups(null, true);
+                    */
+            }
+        };
+        getSelectionModel().addListSelectionListener(groupsHighlightListener);
+        
+        // (to update entry editor or preview)
+        setWidths();
+        sp.getViewport().setBackground(Globals.prefs.getColor("tableBackground"));
+        updateFont();
+      }
+
+    /**
+     * Get the row number for the row that is active, in the sense that the preview or
+     * entry editor should show the corresponding entry.
+     * @return The active row number, or -1 if no row is active.
+     */
+    public int getActiveRow() {
+        return activeRow;
+    }
+
+
+    /**
+     * Get the active entry, in the sense that the preview or entry editor should
+     * show it.
+     * @return The active entry, or null if no row is active.
+     */
+
+    public BibtexEntry getActiveEntry() {
+        //System.out.println("EntryTable.getActiveEntry: "+activeRow);
+        return ((activeRow >= 0) && (activeRow < getRowCount())) ? tableModel.getEntryForRow(activeRow) : null;
+    }
+
+
+    /**
+     * Updates our Set containing the last row selection. Ckecks which rows were ADDED
+     * to the selection, to see what new entry should be previewed.
+     * Returns the number of the row that should be considered active, or -1 if none.
+     *
+     * This method may have some potential for optimization.
+     *
+     * @param rows
+     * @return
+     */
+    private int resolveNewSelection(int[] rows) {
+        HashSet newSel = new HashSet();
+        for (int i=0; i<rows.length; i++) {
+            Integer row = new Integer(rows[i]);
+            newSel.add(row);
+        }
+        // Store a clone of this Set:
+        HashSet tmp = new HashSet(newSel);
+        newSel.removeAll(lastSelection);
+        // Set the new selection as the last:
+        lastSelection = tmp;
+        // We return an appropriate row number if a single additional entry was selected:
+        int result = -1;
+        if (newSel.size()==1)
+            result = ((Integer)newSel.iterator().next()).intValue();
+
+        // .. or if the current selection is only one entry:
+        if ((result<0) && (rows.length == 1))
+            result = rows[0];
+        return result;
+    }
+
+      /**
+       * A ListSelectionListener for updating the preview panel when the user selects an
+       * entry. Should only be active when preview is enabled.
+       */
+      public void addSelectionListener() {
+        if (previewListener == null)
+          previewListener = new ListSelectionListener() {
+            public void valueChanged(final ListSelectionEvent e) {
+              if (!selectionListenerOn) return;
+              if (!e.getValueIsAdjusting()) {
+                  // We must use invokeLater() to postpone the updating. This is because of
+                  // the situation where an EntryEditor has changes in one of the FieldEditors
+                  // that need to be stored. This storage is initiated by a focusLost() call,
+                  // and results in a call to refreshTable() in BasePanel, which messes
+                  // with the table selection. After that chain has finished, the selection
+                  // will have been reset correctly, so we make sure everything is ok by
+                  // putting the updating based on table selection behind it in the event queue.
+                  SwingUtilities.invokeLater(new Thread() {
+                          public void run() {
+                              // If a single new row was selected, set it as the active row:
+                              activeRow = resolveNewSelection(getSelectedRows());
+
+                              if (getSelectedRowCount() == 1) {
+                                  //int row = getSelectedRow(); //e.getFirstIndex();
+                                  //if (row >= 0) {
+                                      // Update the value for which entry is shown:
+                                    //  activeRow = row;
+
+                                    //panel.updateViewToSelected();
+                                    // guarantee that the the entry is visible
+                                    ensureVisible(activeRow);
+
+                              } else {
+                                  /* With a multiple selection, there are three alternative behaviours:
+                                     1. Disable the entry editor. Do not update it.
+                                     2. Do not disable the entry editor, and do not update it.
+                                     3. Update the entry editor, and keep it enabled.
+
+                                     We currently implement 1 and 2, and choose between them based on
+                                     prefs.getBoolean("disableOnMultipleSelection");
+                                  */
+                                  if (prefs.getBoolean("disableOnMultipleSelection")) { // 1.
+                                      panel.setEntryEditorEnabled(false);
+                                  }
+                                  // We want the entry preview to update when the user expands the
+                                  // selection one entry at a time:
+                                  //if ((e.getLastIndex()-e.getFirstIndex()) <= 1) {
+                                  //if (activeRow >= 0)
+                                    //panel.updateViewToSelected();
+                                  //}
+                                  // 2. Do nothing.
+                              }
+
+                              if (Globals.prefs.getBoolean("highlightGroupsMatchingAny"))
+                                panel.getGroupSelector().showMatchingGroups(
+                                    panel.getSelectedEntries(), false);
+                            else if (Globals.prefs.getBoolean("highlightGroupsMatchingAll"))
+                                panel.getGroupSelector().showMatchingGroups(
+                                    panel.getSelectedEntries(), true);
+                            else // no highlight
+                                panel.getGroupSelector().showMatchingGroups(null, true);
+                          }
+                      });
+              }
+            }
+              };
+        getSelectionModel().addListSelectionListener(previewListener);
+      }
+
+      /**
+       * Remove the preview listener.
+       */
+      public void disablePreviewListener() {
+        getSelectionModel().removeListSelectionListener(previewListener);
+      }
+
+      /**
+       * This method overrides the superclass' to disable the selection listener while the
+       * row selection is adjusted.
+       */
+      public void setRowSelectionInterval(int row1, int row2) {
+        boolean oldState = selectionListenerOn;
+        selectionListenerOn = false;
+        // Introducing a try-catch here to maybe track down the preview update bug
+        // that occurs sometimes (20050405 M. Alver):
+        try {
+            super.setRowSelectionInterval(row1, row2);
+            activeRow = resolveNewSelection(getSelectedRows());
+            selectionListenerOn = oldState;
+        } catch (IllegalArgumentException ex) {
+            ex.printStackTrace();
+            System.out.println("Error occured. Trying to recover...");
+            // Maybe try to remap the entry table:
+            tableModel.remap();
+            clearSelection();
+            selectionListenerOn = oldState;
+        }
+      }
+
+      public void addRowSelectionIntervalQuietly(int row1, int row2) {
+          boolean oldState = selectionListenerOn;
+          selectionListenerOn = false;
+          //if (row2 < getModel().getRowCount()) {
+          try {
+            super.addRowSelectionInterval(row1, row2);
+            selectionListenerOn = oldState;
+          } catch (IllegalArgumentException ex) {
+              ex.printStackTrace();
+              System.out.println("Error occured. Trying to recover...");
+            // Maybe try to remap the entry table:
+            tableModel.remap();
+            clearSelection();
+              selectionListenerOn = oldState;
+          }
+
+      }
+
+    /*public boolean surrendersFocusOnKeystroke() {
+        return true;
+        }*/
+
+      /**
+       * This method overrides the superclass' to disable the selection listener while the
+       * selection is cleared.
+       */
+      public void clearSelection() {
+        boolean oldState = selectionListenerOn;
+        selectionListenerOn = false;
+        super.clearSelection();
+        selectionListenerOn = oldState;
+      }
+
+      /**
+       * Enables or disables the selectionlistener. Useful if the selection needs to be
+       * updated in several steps, without the table responding between each.
+       * @param enabled boolean
+       */
+      public void setSelectionListenerEnabled(boolean enabled) {
+        selectionListenerOn = enabled;
+      }
+
+      /**
+       * Turns off any cell editing going on.
+       */
+      protected void assureNotEditing() {
+        if (isEditing()) {
+          int col = getEditingColumn(),
+              row = getEditingRow();
+          getCellEditor(row, col).stopCellEditing();
+        }
+      }
+
+
+    public void setWidths() {
+        // Setting column widths:
+        int ncWidth = prefs.getInt("numberColWidth");
+        String[] widths = prefs.getStringArray("columnWidths");
+        TableColumnModel cm = getColumnModel();
+        cm.getColumn(0).setPreferredWidth(ncWidth);
+        for (int i=1; i<tableModel.padleft; i++) {
+          // Lock the width of icon columns.
+          cm.getColumn(i).setPreferredWidth(GUIGlobals.WIDTH_ICON_COL);
+          cm.getColumn(i).setMinWidth(GUIGlobals.WIDTH_ICON_COL);
+          cm.getColumn(i).setMaxWidth(GUIGlobals.WIDTH_ICON_COL);
+        }
+        for (int i=tableModel.padleft; i<getModel().getColumnCount(); i++) {
+            try {
+                cm.getColumn(i).setPreferredWidth(Integer.parseInt(widths[i-tableModel.padleft]));
+            } catch (Throwable ex) {
+                Globals.logger("Exception while setting column widths. Choosing default.");
+                cm.getColumn(i).setPreferredWidth(GUIGlobals.DEFAULT_FIELD_LENGTH);
+            }
+            //cm.getColumn(i).setPreferredWidth(GUIGlobals.getPreferredFieldLength(getModel().getColumnName(i)));
+        }
+    }
+
+    public JScrollPane getPane() {
+                return sp;
+    }
+
+    /*public void setShowingSearchResults(boolean search,
+                                        boolean group) {
+        showingSearchResults = search;
+        showingGroup = group;
+    }
+*/
+    public void setRightClickMenu(JPopupMenu rcm) {
+        rightClickMenu = rcm;
+    }
+
+  /**
+   * This class handles clicks on the EntryTable that should trigger specific
+   * events, like opening an entry editor, the context menu or a pdf file.
+   */
+  class TableClickListener extends MouseAdapter {
+      public void mouseReleased(MouseEvent e) {
+          // First find the column on which the user has clicked.
+          final int col = columnAtPoint(e.getPoint()),
+              row = rowAtPoint(e.getPoint());
+          // Check if the user has right-clicked. If so, open the right-click menu.
+          if (e.isPopupTrigger()) {
+            processPopupTrigger(e, row, col);
+            return;
+          }
+      }
+      protected void processPopupTrigger(MouseEvent e, int row, int col) {
+          int selRow = getSelectedRow();
+          if (selRow == -1 ||// (getSelectedRowCount() == 0))
+                  !isRowSelected(rowAtPoint(e.getPoint()))) {
+            setRowSelectionInterval(row, row);
+            //panel.updateViewToSelected();
+          }
+          rightClickMenu = new RightClickMenu(panel, panel.metaData);
+          rightClickMenu.show(EntryTable.this, e.getX(), e.getY());
+      }
+      public void mousePressed(MouseEvent e) {
+
+        // First find the column on which the user has clicked.
+        final int col = columnAtPoint(e.getPoint()),
+            row = rowAtPoint(e.getPoint());
+
+
+        // A double click on an entry should open the entry's editor.
+        if (/*(col == 0)*/!isCellEditable(row, col) && (e.getClickCount() == 2)) {
+          try{ panel.runCommand("edit");
+              return;
+              /*showEntry(be);
+
+                    if (splitPane.getBottomComponent() != null) {
+                        new FocusRequester(splitPane.getBottomComponent());
+                    }                                                      */
+          } catch (Throwable ex) {
+            ex.printStackTrace();
+          }
+        }
+
+        // Check if the user has right-clicked. If so, open the right-click menu.
+        if (e.isPopupTrigger()) {
+          processPopupTrigger(e, row, col);
+          return;
+        }
+
+        // Check if the user has clicked on an icon cell to open url or pdf.
+        if (tableModel.getCellStatus(0, col) == EntryTableModel.ICON_COL) {
+
+          // Get the row number also:
+          Object value = getValueAt(row, col);
+          if (value == null) return; // No icon here, so we do nothing.
+          /*Util.pr("eouaeou");
+          JButton button = (JButton)value;
+
+          MouseEvent buttonEvent =
+              (MouseEvent)SwingUtilities.convertMouseEvent(ths, e, button);
+          button.dispatchEvent(buttonEvent);
+          // This is necessary so that when a button is pressed and released
+          // it gets rendered properly.  Otherwise, the button may still appear
+          // pressed down when it has been released.
+          ths.repaint();
+
+          */
+
+
+
+          // Get the icon type. Corresponds to the field name.
+          final String[] iconType = tableModel.getIconTypeForColumn(col);
+          int hasField = -1;
+          for (int i=iconType.length-1; i>= 0; i--)
+            if (tableModel.hasField(row, iconType[i]))
+              hasField = i;
+          if (hasField == -1)
+            return;
+          final String fieldName = iconType[hasField];
+
+          // Open it now. We do this in a thread, so the program won't freeze during the wait.
+          (new Thread() {
+            public void run() {
+              panel.output(Globals.lang("External viewer called") + ".");
+              BibtexEntry be = panel.database().getEntryById(tableModel.
+                      getIdForRow(row));
+              if (be == null) {
+                Globals.logger("Error: could not find entry.");
+                return;
+              }
+
+              Object link = be.getField(fieldName);
+              if (iconType == null) {
+                Globals.logger("Error: no link to " + fieldName + ".");
+                return; // There is an icon, but the field is not set.
+              }
+
+              try {
+                Util.openExternalViewer( (String) link, fieldName, prefs);
+              }
+              catch (IOException ex) {
+                panel.output(Globals.lang("Error")+": "+ex.getMessage());
+              }
+            }
+
+          }).start();
+        }
+      }
+    }
+
+    public TableCellRenderer getCellRenderer(int row, int column) {
+
+        // This method asks the table model whether the given cell represents a
+        // required or optional field, and returns the appropriate renderer.
+        int score = -3;
+        TableCellRenderer renderer;
+
+        int status;
+        try { // This try clause is here to contain a bug.
+          status = tableModel.getCellStatus(row, column);
+        } catch (ArrayIndexOutOfBoundsException ex) {
+            Globals.logger("Error happened in getCellRenderer method of EntryTable, for cell ("+row+","+column+").");
+            return defRenderer; // This should not occur.
+        }
+
+
+        if (!panel.coloringBySearchResults ||
+            tableModel.nonZeroField(row, Globals.SEARCH))
+            score++;
+        if (!panel.coloringByGroup ||
+            tableModel.nonZeroField(row, Globals.GROUPSEARCH))
+            score+=2;
+
+        // Now, a grayed out renderer is for entries with -1, and
+        // a very grayed out one for entries with -2
+        if (score < -1)
+            renderer = veryGrayedOutRenderer;
+        else if (score == -1)
+            renderer = grayedOutRenderer;
+
+        else if (!tableColorCodes)
+            renderer = defRenderer;
+        else if (column == 0) {
+            // Return a renderer with red background if the entry is incomplete.
+            renderer = defRenderer;
+            if (tableModel.isComplete(row))
+                renderer = defRenderer;
+            else {
+              //if (tableModel.hasCrossRef(row))
+              //  renderer = maybeIncRenderer;
+              //else
+              renderer = incRenderer;//incompleteEntryRenderer;
+            }
+
+            //return (tableModel.isComplete(row) ? defRenderer: incRenderer);
+        }
+        else if (status == EntryTableModel.REQUIRED)
+            renderer = reqRenderer;
+        else if (status == EntryTableModel.OPTIONAL)
+            renderer = optRenderer;
+        else if (status == EntryTableModel.BOOLEAN)
+          renderer = getDefaultRenderer(Boolean.class);
+        else renderer = defRenderer;
+        //Util.pr("("+row+","+column+"). "+status+" "+renderer.toString());
+
+        // For MARKED feature:
+        if (tableModel.isMarked(row) && (renderer != incRenderer)) {
+          return markedRenderer;
+        }
+
+        return renderer;
+
+        /*
+        int test = row - 4*(row/4);
+        if (test <= 1)
+            return renderer;
+        else {
+            return renderer.darker();
+            }*/
+    }
+
+    public void scrollTo(int y) {
+        JScrollBar scb = sp.getVerticalScrollBar();
+        scb.setValue(y*scb.getUnitIncrement(1));
+    }
+
+    public BibtexEntry[] getSelectedEntries() {
+        BibtexEntry[] bes = null;
+        int[] rows = getSelectedRows();
+        //int[] cols = getSelectedColumns();
+
+        // Entries are selected if only the first or multiple
+        // columns are selected.
+        //if (((cols.length == 1) && (cols[0] == 0)) ||
+        //(cols.length > 1)) { // entryTable.getColumnCount())) {
+        if (rows.length > 0) {
+            bes = new BibtexEntry[rows.length];
+            for (int i=0; i<rows.length; i++) {
+                bes[i] = tableModel.db.getEntryById(tableModel.getIdForRow(rows[i]));
+            }
+        }
+        return bes;
+    }
+
+
+    // The following classes define the renderers used to render required
+    // and optional fields in the table. The purpose of these renderers is
+    // to visualize which fields are needed for each entry.
+   private GeneralRenderer defRenderer = new GeneralRenderer(Globals.prefs.getColor("tableBackground"),
+            Globals.prefs.getColor("tableText"), antialiasing),
+        reqRenderer = new GeneralRenderer(Globals.prefs.getColor("tableReqFieldBackground"), Globals.prefs.getColor("tableText"), antialiasing),
+        optRenderer = new GeneralRenderer(Globals.prefs.getColor("tableOptFieldBackground"), Globals.prefs.getColor("tableText"), antialiasing),
+        incRenderer = new IncompleteRenderer(this, antialiasing),
+            //new Renderer(GUIGlobals.tableIncompleteEntryBackground),
+            //Globals.lang("This entry is incomplete")),
+        grayedOutRenderer = new GeneralRenderer(Globals.prefs.getColor("grayedOutBackground"),
+                                         Globals.prefs.getColor("grayedOutText"), antialiasing),
+        veryGrayedOutRenderer = new GeneralRenderer(Globals.prefs.getColor("veryGrayedOutBackground"),
+                                             Globals.prefs.getColor("veryGrayedOutText"), antialiasing),
+        markedRenderer = new GeneralRenderer(Globals.prefs.getColor("markedEntryBackground"),
+                Globals.prefs.getColor("tableText"), antialiasing);
+
+    class IncompleteRenderer extends GeneralRenderer {
+        public IncompleteRenderer(JTable table, boolean antialiasing) {
+            super(Globals.prefs.getColor("incompleteEntryBackground"), antialiasing);
+        }
+        protected void setValue(Object value) {
+            super.setValue(value);
+            super.setToolTipText(Globals.lang("This entry is incomplete"));
+        }
+    }
+
+    /* public TableCellRenderer iconRenderer = new IconCellRenderer();
+        //new JTableButtonRenderer(getDefaultRenderer(JButton.class));
+    class IconCellRenderer extends DefaultTableCellRenderer {
+        protected void setValue(Object value) {
+            if (value instanceof Icon) {
+                setIcon((Icon)value);
+                super.setValue(null);
+            } else {
+                setIcon(null);
+                super.setValue(value);
+            }
+        }
+    }
+
+
+   class JTableButtonRenderer implements TableCellRenderer {
+      private TableCellRenderer __defaultRenderer;
+
+      public JTableButtonRenderer(TableCellRenderer renderer) {
+        __defaultRenderer = renderer;
+      }
+
+      public Component getTableCellRendererComponent(JTable table, Object value,
+                                                     boolean isSelected,
+                                                     boolean hasFocus,
+                                                     int row, int column)
+      {
+        if(value instanceof Component)
+          return (Component)value;
+        return __defaultRenderer.getTableCellRendererComponent(
+      table, value, isSelected, hasFocus, row, column);
+      }
+    }*/
+
+
+    public void ensureVisible(int row) {
+        JScrollBar vert = sp.getVerticalScrollBar();
+        int y = row*getRowHeight();
+        if ((y < vert.getValue()) || (y > vert.getValue()+vert.getVisibleAmount()))
+            scrollToCenter(row, 1);
+    }
+
+        public void scrollToCenter( int rowIndex, int vColIndex) {
+        if (!(this.getParent() instanceof JViewport)) {
+            return;
+        }
+
+        JViewport viewport = (JViewport)this.getParent();
+
+        // This rectangle is relative to the table where the
+        // northwest corner of cell (0,0) is always (0,0).
+        Rectangle rect = this.getCellRect(rowIndex, vColIndex, true);
+
+        // The location of the view relative to the table
+        Rectangle viewRect = viewport.getViewRect();
+
+         // Translate the cell location so that it is relative
+        // to the view, assuming the northwest corner of the
+        // view is (0,0).
+        rect.setLocation(rect.x-viewRect.x, rect.y-viewRect.y);
+
+        // Calculate location of rect if it were at the center of view
+        int centerX = (viewRect.width-rect.width)/2;
+        int centerY = (viewRect.height-rect.height)/2;
+
+        // Fake the location of the cell so that scrollRectToVisible
+        // will move the cell to the center
+        if (rect.x < centerX) {
+            centerX = -centerX;
+        }
+        if (rect.y < centerY) {
+            centerY = -centerY;
+        }
+        rect.translate(centerX, centerY);
+
+        // Scroll the area into view.
+        viewport.scrollRectToVisible(rect);
+
+        revalidate();
+        repaint();
+    }
+
+  /**
+   * updateFont
+   */
+  public void updateFont() {
+      setFont(GUIGlobals.CURRENTFONT);
+      setRowHeight(GUIGlobals.TABLE_ROW_PADDING+GUIGlobals.CURRENTFONT.getSize());
+  }
+
+  public void updateUI() {
+      super.updateUI();
+      setUI(new CustomTableUI());
+  }
+
+
+
+  class CustomTableUI extends BasicTableUI {
+    public void installUI(JComponent c) {
+      super.installUI(c);
+      c.remove(rendererPane);
+      rendererPane = new CustomCellRendererPane();
+      c.add(rendererPane);
+    }
+
+    /**
+     * Overrides paintComponent to NOT clone the Graphics
+     * passed in and NOT validate the Component passed in.
+     * This is done for performance reasons.
+     */
+    private class CustomCellRendererPane extends CellRendererPane {
+        private Rectangle tmpRect = new Rectangle();
+
+        public void repaint() {
+        }
+
+        public void repaint(int x, int y, int width, int height) {
+        }
+
+        public void paintComponent(Graphics g, Component c, Container p,
+                                   int x, int y, int w, int h,
+                                   boolean shouldValidate) {
+          if (c == null) {
+            if (p != null) {
+              Color oldColor = g.getColor();
+              g.setColor(p.getBackground());
+              g.fillRect(x, y, w, h);
+              g.setColor(oldColor);
+            }
+            return;
+          }
+          if (c.getParent() != this) {
+            this.add(c);
+          }
+
+          c.setBounds(x, y, w, h);
+
+          boolean wasDoubleBuffered = false;
+          JComponent jc = (c instanceof JComponent) ? (JComponent)c : null;
+          if (jc != null && jc.isDoubleBuffered()) {
+            wasDoubleBuffered = true;
+            jc.setDoubleBuffered(false);
+          }
+
+          // Don't create a new Graphics, reset the clip and translate
+          // the origin.
+          Rectangle clip = g.getClipBounds(tmpRect);
+          g.clipRect(x, y, w, h);
+          g.translate(x, y);
+          c.paint(g);
+          g.translate(-x, -y);
+          g.setClip(clip.x, clip.y, clip.width, clip.height);
+          if (wasDoubleBuffered) {
+            jc.setDoubleBuffered(true);
+          }
+          c.setBounds(-w, -h, 0, 0);
+        }
+      }
+
+    }
+
+}
+
diff --git a/src/java/net/sf/jabref/EntryTableModel.java b/src/java/net/sf/jabref/EntryTableModel.java
new file mode 100644
index 0000000..ebf0026
--- /dev/null
+++ b/src/java/net/sf/jabref/EntryTableModel.java
@@ -0,0 +1,587 @@
+/*
+ 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.
+
+ 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 javax.swing.*;
+import javax.swing.table.*;
+import net.sf.jabref.export.LatexFieldFormatter;
+import java.util.*;
+
+public class EntryTableModel
+    extends AbstractTableModel {
+
+  BibtexDatabase db;
+  BasePanel panel;
+  JabRefFrame frame;
+  String[] columns; // Contains the current column names.
+  private EntrySorter sorter;
+  private int visibleRows = 0;
+
+
+  // Testing something:
+  Object[][] allCache = null;
+
+  //private Object[] entryIDs; // Temporary
+
+  // Constants used to define how a cell should be rendered.
+  public static final int REQUIRED = 1, OPTIONAL = 2,
+      REQ_STRING = 1,
+      REQ_NUMBER = 2,
+      OPT_STRING = 3,
+      OTHER = 3,
+      BOOLEAN = 4,
+      //PDF_COL = 1, // The column displaying icons for linked pdfs.
+      ICON_COL = 8; // Constant to indicate that an icon cell renderer should be used.
+  public static final String[]
+      PDF = {"pdf", "ps"},
+      URL_ = {"url", "doi"},
+        CITESEER = {"citeseerurl"};
+
+  public int padleft = -1; // padleft indicates how many columns (starting from left) are
+  // special columns (number column or icon column).
+  private HashMap iconCols = new HashMap();
+  int[] nameCols = null;
+  boolean showShort, namesNatbib, namesLastOnly;                               //MK:
+  boolean namesAsIs, namesFf, namesLf, abbr_names;              //MK:
+
+    //ImageIcon pdfIcon = new ImageIcon(GUIGlobals.pdfSmallIcon);
+
+  public EntryTableModel(JabRefFrame frame_,
+                         BasePanel panel_,
+                         BibtexDatabase db_) {
+    panel = panel_;
+    frame = frame_;
+    db = db_;
+
+    columns = Globals.prefs
+        .getStringArray("columnNames"); // This must be done again if the column
+    // preferences get changed.
+
+    remap();
+  }
+
+  /* This is the old getColumnName().
+   * This function now returns the field name
+   * with the original lower/upper case of the field name */
+  public String getFieldName(int col) {
+    if (col == 0) {
+      return GUIGlobals.NUMBER_COL;
+    }
+    else if (getIconTypeForColumn(col) != null) {
+      return getIconTypeForColumn(col)[0];
+    }
+    return columns[col - padleft];
+  }
+
+  public String getColumnName(int col) {
+      if (col == 0) {
+      return GUIGlobals.NUMBER_COL;
+    }
+    else if (getIconTypeForColumn(col) != null) {
+      return "";
+    }
+    else if(GUIGlobals.FIELD_DISPLAYS.get(columns[col - padleft]) != null) {
+        return((String) GUIGlobals.FIELD_DISPLAYS.get(columns[col - padleft]));
+    }
+    return Util.nCase(columns[col - padleft]);
+  }
+
+    public void showAllEntries() {
+    visibleRows = sorter.getEntryCount();
+    }
+
+    public void setRowCount(int rows) {
+    visibleRows = rows;
+    }
+
+  public int getRowCount() {
+    //Util.pr("rc "+sorter.getEntryCount());
+    //return sorter.getEntryCount();
+      return visibleRows;
+    //entryIDs.length;  // Temporary?
+  }
+
+  public int getColumnCount() {
+    return padleft + columns.length;
+  }
+
+  public Class getColumnClass(int column) {
+
+    //return (getIconTypeForColumn(column) != null ? Icon.class : String.class);
+      if (column == 0)
+      return Boolean.class;
+      else
+      return (getIconTypeForColumn(column) != null ? JLabel.class : String.class);
+  }
+
+  public Object getValueAt_(int row, int col) {
+      return allCache[row][col];
+  }
+
+  public void updateAllCache() {
+      /*long start = System.currentTimeMillis();
+      int rows = getRowCount();
+      int cols = getColumnCount();
+      allCache = new Object[rows][cols];
+      for (int row=0; row<rows; row++)
+          for (int col=0; col<cols; col++)
+              allCache[row][col] = getValueAt_old(row, col);
+      Globals.logger("Time spent: "+(System.currentTimeMillis()-start));*/
+  }
+
+  public Object getValueAt(int row, int col) {
+    // Return the field named frame.prefs.columnNames[col] from the Entry
+    // corresponding to the row.
+    Object o;
+    BibtexEntry be = sorter.getEntryAt(row);
+    String[] iconType = getIconTypeForColumn(col); // If non-null, indicates an icon column's type.
+    if (col == 0) {
+        o = "" + (row + 1);
+    }
+/*      if (!isComplete(row)) {
+      	//JLabel incomplete = new JLabel("" + (row + 1),GUIGlobals.incompleteLabel.getIcon(), JLabel.RIGHT);
+        //JLabel incomplete = new JLabel("" + (row + 1));
+        //incomplete.setToolTipText(Globals.lang("This entry is incomplete"));
+        //return incomplete;        
+      } else
+*/
+
+    else if (iconType != null) {
+      int hasField = -1;
+      for (int i=iconType.length-1; i>= 0; i--)
+        if (hasField(row, iconType[i]))
+          hasField = i;
+      if (hasField < 0)
+        return null;
+
+      // Ok, so we are going to display an icon. Find out which one, and return it:
+      return GUIGlobals.getTableIcon(iconType[hasField]);
+    }
+    //  if (col == 1)
+    //  o = be.getType().getName();
+    //else {
+    else if (columns[col - padleft].equals(GUIGlobals.TYPE_HEADER)) {
+      o = be.getType().getName();
+    }
+    //else if (columns[col-PADLEFT].equals(GUIGlobals.NUMBER_COL)) {
+    //  o = ""+(row+1);
+    //}
+    else {
+
+    //MK:vvv
+    o = null; if (showShort) o = be.getField("short"+columns[col-padleft]);   //MK:vvv
+       if (o==null) {
+         o = be.getField(columns[col - padleft]);
+         for (int i = 0; i < nameCols.length; i++) {
+           if (col - padleft == nameCols[i]) {
+             if (o == null) { return null; }
+             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);
+
+             return o;
+ //            if (!namesAsIs) {
+ //              if (namesFf) {
+ //                return ImportFormatReader.fixAuthor_firstNameFirst( (String) o);
+ //              }
+ //              else {
+ //                return ImportFormatReader.fixAuthor_lastNameFirst( (String)o);
+ //              }
+ //            }
+  //MK:^^^
+          }
+     }
+       }
+    }
+    /*if (o != null) {
+        String processed = Globals.getCached((String)o);
+        if (processed == null) {
+            StringBuffer sb = new StringBuffer("");//"<html>");
+            sb.append((String)o);
+            //sb.append("</html>");
+            processed = sb.toString();
+            Globals.cache((String)o, processed);
+            o = processed;
+        } else
+            o = processed;
+        
+            
+    }*/
+    return o;
+  }
+
+  /**
+   * This method returns a string array indicating the types of icons to be displayed in the given column.
+   * It returns null if the column is not an icon column, and thereby also serves to identify icon
+   * columns.
+   */
+  public String[] getIconTypeForColumn(int col) {
+    Object o = iconCols.get(new Integer(col));
+    if (o != null)
+      return (String[])o;
+    else
+      return null;
+  }
+
+  public int getCellStatus(int row, int col) {
+    //if ((col == 0)  || (col == 1)) return OTHER;
+    if (col == 0) {
+      return BOOLEAN;
+    }
+    if (getIconTypeForColumn(col) != null) {
+      return ICON_COL;
+    }
+
+    BibtexEntryType type = (db.getEntryById(getIdForRow(row)))
+        .getType();
+    if (columns[col - padleft].equals(GUIGlobals.KEY_FIELD)
+        || type.isRequired(columns[col - padleft])) {
+      return REQUIRED;
+    }
+    if (type.isOptional(columns[col - padleft])) {
+      return OPTIONAL;
+    }
+    return OTHER;
+  }
+
+  public boolean isComplete(int row) {
+    BibtexEntry be = db.getEntryById(getIdForRow(row));
+    return (be != null ? be.hasAllRequiredFields() : false);
+  }
+
+  public boolean hasCrossRef(int row) {
+    BibtexEntry be = db.getEntryById(getIdForRow(row));
+    return (be.getField("crossref") != null);
+  }
+
+  public boolean nonZeroField(int row, String field) {
+    // Returns true iff the entry has a nonzero value in its
+    // 'search' field.
+    BibtexEntry be = db.getEntryById(getIdForRow(row));
+    if (be == null)
+        return false; // TODO: JZ: I think this should never happen, but it does
+    String o = (String) (be.getField(field));
+    return ( (o != null) && !o.equals("0"));
+  }
+
+  public boolean hasField(int row, String field) {
+    // Returns true iff the entry has a nonzero value in its
+    // 'search' field.
+    BibtexEntry be = db.getEntryById(getIdForRow(row));
+    return ((be != null) && (be.getField(field) != null));
+  }
+
+  private void updateSorter() {
+
+    // Set the icon columns, indicating the number of special columns to the left.
+    // We add those that are enabled in preferences.
+    iconCols.clear();
+    int coln = 1;
+    if (Globals.prefs.getBoolean("pdfColumn"))
+      iconCols.put(new Integer(coln++), PDF);
+    if (Globals.prefs.getBoolean("urlColumn"))
+      iconCols.put(new Integer(coln++), URL_);
+    if (Globals.prefs.getBoolean("citeseerColumn"))
+        iconCols.put(new Integer(coln++), CITESEER);
+
+    // Add 1 to the number of icon columns to get padleft.
+    padleft = 1+iconCols.size();
+
+    // Set up the int[] nameCols, to mark which columns should be
+    // treated as lists of names. This is to provide a correct presentation
+    // of names as efficiently as possible.
+    Vector tmp = new Vector(2, 1);
+    for (int i = 0; i < columns.length; i++) {
+      if (columns[i].equals("author")
+          || columns[i].equals("editor")) {
+        tmp.add(new Integer(i));
+      }
+    }
+    nameCols = new int[tmp.size()];
+    for (int i = 0; i < nameCols.length; i++) {
+      nameCols[i] = ( (Integer) tmp.elementAt(i)).intValue();
+    }
+    showShort = Globals.prefs.getBoolean("showShort");        //MK:
+    namesNatbib = Globals.prefs.getBoolean("namesNatbib");    //MK:
+    namesLastOnly = Globals.prefs.getBoolean("namesLastOnly");
+
+    namesAsIs = Globals.prefs.getBoolean("namesAsIs");
+    abbr_names = Globals.prefs.getBoolean("abbrAuthorNames"); //MK:
+    namesFf = Globals.prefs.getBoolean("namesFf");
+    namesLf = !(namesAsIs || namesFf || namesNatbib || namesLastOnly); // None of the above.
+        //namesLastOnly = Globals.prefs.getBoolean("namesLastOnly");
+    // Build a vector of prioritized search objectives,
+    // then pick the 3 first.
+    List fields = new ArrayList(6),
+        directions = new ArrayList(6),
+        binary = new ArrayList(6); // Signifies whether the sort criterion should only separate on/off or
+                                    // also sort within set field values.
+
+    // For testing MARKED feature. With this IF clause, the marked entries will only float to the top when
+    // no sorting/grouping reordering is active.
+    if  (!panel.sortingBySearchResults && !panel.sortingByCiteSeerResults && !panel.sortingByGroup) {
+        fields.add(Globals.MARKED);
+        directions.add(Boolean.TRUE);
+        binary.add(Boolean.FALSE);
+    }
+    if (panel.sortingByGroup) {
+      // Group search has the highest priority if active.
+      fields.add(Globals.GROUPSEARCH);
+      directions.add(Boolean.TRUE);
+        binary.add(Boolean.FALSE);
+    }
+    if (panel.sortingBySearchResults) {
+      // Normal search has priority over regular sorting.
+      fields.add(Globals.SEARCH);
+      directions.add(Boolean.TRUE);
+        binary.add(Boolean.FALSE);
+    }
+    if(panel.sortingByCiteSeerResults) {
+        fields.add("citeseercitationcount");
+        directions.add(Boolean.TRUE);
+        binary.add(Boolean.FALSE);
+    }
+
+    // Then the sort options:
+    directions.add(Boolean.valueOf(frame.prefs.getBoolean("priDescending")));
+    directions.add(Boolean.valueOf(frame.prefs.getBoolean("secDescending")));
+    directions.add(Boolean.valueOf(frame.prefs.getBoolean("terDescending")));
+    fields.add(frame.prefs.get("priSort"));
+    fields.add(frame.prefs.get("secSort"));
+    fields.add(frame.prefs.get("terSort"));
+    binary.add(Boolean.valueOf(Globals.prefs.getBoolean("priBinary"))); // TRUE if we are sorting on an icon.
+    binary.add(Boolean.FALSE);
+    binary.add(Boolean.FALSE);
+
+    // Remove the old sorter as change listener for the database:
+    if (sorter != null)
+    db.removeDatabaseChangeListener(sorter);
+
+    // Then pick the up to four highest ranking ones, and go.
+      int piv = Math.min(directions.size()-1, 3);
+      Comparator comp = new EntryComparator(
+              ((Boolean)binary.get(piv)).booleanValue(),
+              ((Boolean)directions.get(piv)).booleanValue(),
+              (String)fields.get(piv));
+      piv--;
+      while (piv >= 0) {
+          // Loop down towards the highest ranking criterion, wrapping new sorters around the
+          // ones we have:
+          String field = (String)fields.get(piv);
+          if (field.equals(Globals.MARKED)) {
+                comp = new MarkedComparator(comp);
+          }
+          else
+            comp = new EntryComparator(
+                  ((Boolean)binary.get(piv)).booleanValue(),
+                  ((Boolean)directions.get(piv)).booleanValue(),
+                  field,
+                  comp);
+          piv--;
+      }
+
+      sorter = db.getSorter(comp);
+
+
+  }
+
+    /**
+     * Remaps and resorts the table model.
+     */
+    public void remap() {
+    updateSorter();
+    showAllEntries(); // Update the visible row count.
+        updateAllCache();
+    fireTableDataChanged();
+
+    }
+
+    /**
+     * Remaps and resorts the table model, and restricts the row number
+     * as directed.
+     */
+    public void remap(int rows) {
+    updateSorter();
+    setRowCount(rows);
+        updateAllCache();
+    fireTableDataChanged();
+    }
+
+    /**
+     * Quick remap of the table model. Sufficient for all operations except
+     * those that require a changed sort regime.
+     */
+    public void update() {
+    sorter.index();
+    showAllEntries();
+        updateAllCache();
+    fireTableDataChanged();
+
+    }
+
+    /**
+     * Quick remap of the table model. Sufficient for all operations except
+     * those that require a changed sort regime.
+     * Restricts the row number as directed.
+     */
+    public void update(int rows) {
+    sorter.index();
+    setRowCount(rows);
+        updateAllCache();
+    fireTableDataChanged();
+    }
+
+  public boolean isCellEditable(int row, int col) {
+    if (!Globals.prefs.getBoolean("allowTableEditing"))
+      return false;
+
+    if (col < padleft) {
+      return false;
+    }
+    // getColumnClass will throw a NullPointerException if there is no
+    // entry in FieldTypes.GLOBAL_FIELD_TYPES for the column.
+    try {
+      if (!getFieldName(col).equals(GUIGlobals.TYPE_HEADER)) {
+
+//	    getColumnClass(col);
+        return true;
+      }
+      else {
+        return false;
+      }
+    }
+    catch (NullPointerException ex) {
+      return false;
+    }
+  }
+
+  public void setValueAt(Object value, int row, int col) {
+    // Called by the table cell editor when the user has edited a
+    // field. From here the edited value is stored.
+
+    BibtexEntry be = db.getEntryById(getIdForRow(row));
+    boolean set = false;
+    String toSet = null,
+        fieldName = getFieldName(col),
+        text;
+    if (value != null) {
+      text = value.toString();
+      if (text.length() > 0) {
+        toSet = text;
+        Object o;
+        if ( ( (o = be.getField(fieldName)) == null)
+            || ( (o != null)
+                && !o.toString().equals(toSet))) {
+          set = true;
+        }
+      }
+      else if (be.getField(fieldName) != null) {
+        set = true;
+      }
+    }
+    if (set) {
+      try {
+        if (toSet != null) {
+          (new LatexFieldFormatter()).format
+              (toSet, fieldName);
+        }
+
+        // Store this change in the UndoManager to facilitate undo.
+        Object oldVal = be.getField(fieldName);
+        panel.undoManager.addEdit
+            (new net.sf.jabref.undo.UndoableFieldChange
+             (be, fieldName.toLowerCase(), oldVal, toSet));
+        // .. ok.
+
+        be.setField(fieldName, toSet);
+        panel.markBaseChanged();
+        //panel.updateViewToSelected();
+        //panel.updateEntryEditorIfShowing();
+        // Should the table also be scheduled for repaint?
+      }
+      catch (IllegalArgumentException ex) {
+        //frame.output("Invalid field format. Use '#' only in pairs wrapping "
+        //	  +"string names.");
+        frame.output("Invalid field format: " + ex.getMessage());
+      }
+    }
+  }
+
+   /**
+    * Returns the internal ID of the entry at the given row.
+    * @param number The row number.
+    * @return The ID for the entry at the given row.
+    */
+  public String getIdForRow(int number) {
+    // Return the name of the Entry corresponding to the row. The
+    // Entry will be retrieved from a DatabaseQuery. This is just
+    // a temporary implementation.
+    return sorter.getIdAt(number);
+    //entryIDs[number].toString();
+  }
+
+    /**
+     * Returns the entry currently displayed at the given row.
+     * @param row The row.
+     * @return The entry at the given row.
+     */
+  public BibtexEntry getEntryForRow(int row) {
+      return sorter.getEntryAt(row);
+  }
+
+  public int getNumberFromName(String name) {
+    // Not very fast. Intended for use only in highlighting erronous
+    // entry if save fails.
+    int res = -1, i = 0;
+    while ( (i < sorter.getEntryCount()) && (res < 0)) {
+      if (name.equals(sorter.getIdAt(i))) {
+        res = i;
+      }
+      i++;
+    }
+    return res;
+  }
+
+    /**
+     * Returns true iff the entry's Globals.MARKED field contains the
+     * current user's wrapped username.
+     * @param row The table row where the entry is.
+     * @return true if the MARKED field contains the wrapped username.
+     */
+    public boolean isMarked(int row) {
+        BibtexEntry be = db.getEntryById(getIdForRow(row));
+        if (be == null)
+            return false;
+        return Util.isMarked(be);
+
+    }
+
+
+}
diff --git a/src/java/net/sf/jabref/EntryTypeDialog.java b/src/java/net/sf/jabref/EntryTypeDialog.java
new file mode 100644
index 0000000..dad1619
--- /dev/null
+++ b/src/java/net/sf/jabref/EntryTypeDialog.java
@@ -0,0 +1,149 @@
+/*
+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;
+
+import javax.swing.*;
+import java.awt.event.*;
+import java.awt.*;
+import java.util.*;
+
+public class EntryTypeDialog extends JDialog implements ActionListener {
+
+    /*
+     * Dialog that prompts the user to choose a type for an entry.
+     * Returns null if cancelled.
+     */
+
+    BibtexEntryType type = null;
+    CancelAction cancelAction = new CancelAction();
+    private final int COLNUM = 3;
+
+    class TypeButton extends JButton implements Comparable {
+	BibtexEntryType type;
+	public TypeButton(String label, BibtexEntryType type_) {
+	    super(label);
+	    type = type_;
+	}
+	public int compareTo(Object o) {
+	    if (! (o instanceof TypeButton))
+		throw new ClassCastException();
+	    return type.getName().compareTo(((TypeButton)o).type.getName());
+	}
+    }
+
+    public EntryTypeDialog(JabRefFrame baseFrame_) {
+	super(baseFrame_, true); // Set modal on.
+
+
+	setTitle(Globals.lang("Select entry type"));
+
+	addWindowListener(new WindowAdapter() {
+		public void windowClosing(WindowEvent e) {
+		    cancelAction.actionPerformed(null);
+		}
+	    });
+
+	getContentPane().setLayout(new BorderLayout());
+	JPanel pan = new JPanel();
+	getContentPane().add(pan, BorderLayout.CENTER);
+	JPanel lower = new JPanel();
+	JButton // ok = new JButton("Ok"),
+	    cancel = new JButton(Globals.lang("Cancel"));
+	//ok.addActionListener(this);
+	cancel.addActionListener(this);
+
+        //pan.setBackground(GUIGlobals.lightGray);
+        //lower.setBackground(GUIGlobals.lightGray);
+	// Make ESC close dialog, equivalent to clicking Cancel.
+	cancel.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW)
+	    .put(baseFrame_.prefs.getKey("Close dialog"), "close");
+	cancel.getActionMap().put("close", cancelAction);
+
+	//lower.add(ok);
+	lower.add(cancel);
+	getContentPane().add(lower, BorderLayout.SOUTH);
+	GridBagLayout gbl = new GridBagLayout();
+	pan.setLayout(gbl);
+	GridBagConstraints con = new GridBagConstraints();
+	con.anchor = GridBagConstraints.WEST;
+	con.fill = GridBagConstraints.HORIZONTAL;
+	con.insets = new Insets(4, 4, 4, 4);
+	int col = 0;
+
+	Iterator iter = BibtexEntryType.ALL_TYPES.keySet().iterator();
+	while (iter.hasNext()) {
+	    BibtexEntryType tp = BibtexEntryType.getType((String)iter.next());
+            //System.out.println(tp.getName()+"\n"+tp);
+	    TypeButton b = new TypeButton(Util.nCase(tp.getName()), tp);
+	    b.setAlignmentX(SwingConstants.LEFT);
+	    b.addActionListener(this);
+	    // Check if we should finish the row.
+	    col++;
+	    if (col == COLNUM) {
+		col = 0;
+		con.gridwidth = GridBagConstraints.REMAINDER;
+	    } else
+		con.gridwidth = 1;
+	    gbl.setConstraints(b, con);
+	    pan.add(b);
+	}
+	pan.setBorder(BorderFactory.createTitledBorder
+		      (BorderFactory.createEtchedBorder(),
+		       Globals.lang("Entry types")));
+	//pan.setBackground(Color.white);
+	//lower.setBackground(Color.white);
+	pack();
+	setResizable(false);
+    }
+
+    public void actionPerformed(ActionEvent e) {
+	if (e.getSource() instanceof TypeButton) {
+	    type = ((TypeButton)e.getSource()).type;
+	}
+	dispose();
+    }
+
+    public BibtexEntryType getChoice() {
+	//return type;
+	return type;
+    }
+
+    class CancelAction extends AbstractAction {
+	public CancelAction() {
+	    super("Cancel");
+	    //  new ImageIcon(GUIGlobals.imagepath+GUIGlobals.closeIconFile));
+	    //putValue(SHORT_DESCRIPTION, "Cancel");
+	    //putValue(MNEMONIC_KEY, GUIGlobals.closeKeyCode);
+	}
+	public void actionPerformed(ActionEvent e) {
+	    dispose();
+	}
+    }
+
+
+}
diff --git a/src/java/net/sf/jabref/ErrorMessageDisplay.java b/src/java/net/sf/jabref/ErrorMessageDisplay.java
new file mode 100644
index 0000000..e7ea49d
--- /dev/null
+++ b/src/java/net/sf/jabref/ErrorMessageDisplay.java
@@ -0,0 +1,25 @@
+package net.sf.jabref;
+
+/**
+ * A class implementing this interface can provided as a receiver for error messages originating
+ * in a thread that can't return any value or throw any exceptions. E.g. net.sf.jabref.DatabaseSearch.
+ *
+ * The point is that the worker thread doesn't need to know what interface it is working against,
+ * since the ErrorMessageDisplay implementer will be responsible for displaying the error message.
+ */
+public interface ErrorMessageDisplay {
+
+    /**
+     * An error has occured.
+     * @param errorMessage Error message.
+     */
+    public void reportError(String errorMessage);
+
+    /**
+     * An error has occured.
+     * @param errorMessage Error message.
+     * @param exception Exception representing the error condition.
+     */
+    public void reportError(String errorMessage, Exception exception);
+
+}
diff --git a/src/java/net/sf/jabref/ExternalProgramsTab.java b/src/java/net/sf/jabref/ExternalProgramsTab.java
new file mode 100644
index 0000000..bd932b3
--- /dev/null
+++ b/src/java/net/sf/jabref/ExternalProgramsTab.java
@@ -0,0 +1,134 @@
+package net.sf.jabref;
+
+import javax.swing.*;
+import javax.swing.table.*;
+import java.awt.*;
+import java.awt.event.*;
+import java.io.File;
+
+class ExternalProgramsTab extends JPanel implements PrefsTab {
+
+    JabRefPreferences _prefs;
+    private GridBagLayout gbl = new GridBagLayout();
+    private GridBagConstraints con = new GridBagConstraints();
+    JTextField
+	pdf, ps, html, lyx;
+
+    public ExternalProgramsTab (JabRefPreferences prefs) {
+	_prefs = prefs;
+
+	pdf = new JTextField(_prefs.get("pdfviewer"), 30);
+	ps = new JTextField(_prefs.get("psviewer"), 30);
+	html = new JTextField(_prefs.get("htmlviewer"), 30);
+	lyx = new JTextField(_prefs.get("lyxpipe"), 30);
+
+	/*setBorder(BorderFactory.createTitledBorder
+		  (BorderFactory.createEtchedBorder(),
+		  Globals.lang("Paths to external programs")));*/
+	JLabel lab;
+	setLayout(gbl);
+	con.weightx = 0;
+	con.insets = new Insets(10, 10, 10, 10);
+	con.fill = GridBagConstraints.HORIZONTAL;
+	lab = new JLabel(Globals.lang("Path to PDF viewer")+":");
+	gbl.setConstraints(lab, con);
+        add(lab);
+	con.weightx = 1;
+	gbl.setConstraints(pdf, con);
+	add(pdf);
+	con.weightx = 0;
+        con.gridwidth = GridBagConstraints.REMAINDER;
+        JButton browse = new JButton(Globals.lang("Browse"));
+        browse.addActionListener(new BrowseAction(pdf));
+        gbl.setConstraints(browse, con);
+        add(browse);
+        con.gridwidth = 1;
+	con.fill = GridBagConstraints.HORIZONTAL;
+	lab = new JLabel(Globals.lang("Path to PS viewer")+":");
+	gbl.setConstraints(lab, con);
+	add(lab);
+	con.weightx = 1;
+	gbl.setConstraints(ps, con);
+	add(ps);
+	con.weightx = 0;
+        con.gridwidth = GridBagConstraints.REMAINDER;
+        browse = new JButton(Globals.lang("Browse"));
+        browse.addActionListener(new BrowseAction(ps));
+        gbl.setConstraints(browse, con);
+        add(browse);
+	con.gridwidth = 1;
+	lab = new JLabel(Globals.lang("Path to HTML viewer")+":");
+	gbl.setConstraints(lab, con);
+	add(lab);
+	con.weightx = 1;
+	gbl.setConstraints(html, con);
+	add(html);
+        con.gridwidth = GridBagConstraints.REMAINDER;
+	con.weightx = 0;
+        browse = new JButton(Globals.lang("Browse"));
+        browse.addActionListener(new BrowseAction(html));
+        gbl.setConstraints(browse, con);
+        add(browse);
+	con.gridwidth = 1;
+	con.fill = GridBagConstraints.HORIZONTAL;
+	lab = new JLabel(Globals.lang("Path to LyX pipe")+":");
+	gbl.setConstraints(lab, con);
+	add(lab);
+        con.weightx = 1;
+	gbl.setConstraints(lyx, con);
+	add(lyx);
+        con.weightx = 0;
+        browse = new JButton(Globals.lang("Browse"));
+        browse.addActionListener(new BrowseAction(lyx));
+        gbl.setConstraints(browse, con);
+        add(browse);
+
+    }
+
+  /**
+   * Action used to produce a "Browse" button for one of the text fields.
+   */
+  class BrowseAction extends AbstractAction {
+      JTextField comp;
+      public BrowseAction(JTextField tc) {
+        super(Globals.lang("Browse"));
+        comp = tc;
+      }
+      public void actionPerformed(ActionEvent e) {
+        JabRefFileChooser chooser = new JabRefFileChooser(new File(comp.getText()));
+        //chooser.addChoosableFileFilter(new OpenFileFilter()); //nb nov2
+        int returnVal = chooser.showOpenDialog(null);
+        if (returnVal == JFileChooser.APPROVE_OPTION) {
+          File newFile = chooser.getSelectedFile();
+          comp.setText(newFile.getPath());
+        }
+      }
+    }
+
+    public void setValues() {
+
+    }
+
+    /**
+     * Store changes to table preferences. This method is called when
+     * the user clicks Ok.
+     *
+     */
+    public void storeSettings() {
+
+	// We should maybe do some checking on the validity of the contents?
+
+	_prefs.put("pdfviewer", pdf.getText());
+	_prefs.put("psviewer", ps.getText());
+	_prefs.put("htmlviewer", html.getText());
+	_prefs.put("lyxpipe", lyx.getText());
+    }
+
+    public boolean readyToClose() {
+	return true;
+    }
+
+}
+
+
+
diff --git a/src/java/net/sf/jabref/ExternalTab.java b/src/java/net/sf/jabref/ExternalTab.java
new file mode 100644
index 0000000..fc7b896
--- /dev/null
+++ b/src/java/net/sf/jabref/ExternalTab.java
@@ -0,0 +1,186 @@
+package net.sf.jabref;
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.*;
+import java.util.Iterator;
+import java.io.File;
+
+import com.jgoodies.forms.layout.*;
+import com.jgoodies.forms.factories.*;
+import com.jgoodies.forms.builder.*;
+
+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(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(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(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(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(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(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(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);
+    }
+
+    /**
+     * Action used to produce a "Browse" button for one of the text fields.
+     */
+    class BrowseAction extends AbstractAction {
+        JTextField comp;
+        boolean dir;
+
+        public BrowseAction(JTextField tc, boolean dir) {
+            super(Globals.lang("Browse"));
+            this.dir = dir;
+            comp = tc;
+        }
+
+        public void actionPerformed(ActionEvent e) {
+            String chosen = null;
+            if (dir)
+                chosen = Globals.getNewDir(_frame, _prefs, new File(comp.getText()), Globals.NONE,
+                        JFileChooser.OPEN_DIALOG, false);
+            else
+                chosen = Globals.getNewFile(_frame, _prefs, new File(comp.getText()), Globals.NONE,
+                        JFileChooser.OPEN_DIALOG, false);
+            if (chosen != null) {
+                File newFile = new File(chosen);
+                comp.setText(newFile.getPath());
+            }
+        }
+    }
+
+    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;
+    }
+
+}
diff --git a/src/java/net/sf/jabref/FieldComparator.java b/src/java/net/sf/jabref/FieldComparator.java
new file mode 100644
index 0000000..61fc2ad
--- /dev/null
+++ b/src/java/net/sf/jabref/FieldComparator.java
@@ -0,0 +1,80 @@
+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.
+ */
+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);
+	    }
+        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;
+
+	    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;
+    }
+
+}
diff --git a/src/java/net/sf/jabref/FieldComparatorStack.java b/src/java/net/sf/jabref/FieldComparatorStack.java
new file mode 100644
index 0000000..ec4d3ef
--- /dev/null
+++ b/src/java/net/sf/jabref/FieldComparatorStack.java
@@ -0,0 +1,29 @@
+package net.sf.jabref;
+
+import java.util.Comparator;
+import java.util.List;
+import java.util.Iterator;
+
+/**
+ * This class represents a list of comparators. The first Comparator takes precedence,
+ * and each time a Comparator returns 0, the next one is attempted. If all comparators
+ * return 0 the final result will be 0.
+ */
+public class FieldComparatorStack implements Comparator {
+
+    List comparators;
+
+    public FieldComparatorStack(List comparators) {
+        this.comparators = comparators;
+    }
+
+    public int compare(Object o1, Object o2) {
+        for (Iterator i=comparators.iterator(); i.hasNext();) {
+            int res = ((Comparator)i.next()).compare(o1, o2);
+            if (res != 0)
+                return res;
+        }
+        return 0;
+    }
+
+}
diff --git a/src/java/net/sf/jabref/FieldContentSelector.java b/src/java/net/sf/jabref/FieldContentSelector.java
new file mode 100644
index 0000000..8150ca8
--- /dev/null
+++ b/src/java/net/sf/jabref/FieldContentSelector.java
@@ -0,0 +1,240 @@
+/*
+ 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.
+
+ 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.awt.*;
+import java.awt.event.*;
+import java.util.Vector;
+
+import javax.swing.*;
+
+import com.jgoodies.forms.layout.Sizes;
+
+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);
+
+        /*
+         * 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.show();
+                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"); }
+     */
+}
diff --git a/src/java/net/sf/jabref/FieldEditor.java b/src/java/net/sf/jabref/FieldEditor.java
new file mode 100644
index 0000000..9194670
--- /dev/null
+++ b/src/java/net/sf/jabref/FieldEditor.java
@@ -0,0 +1,52 @@
+/*
+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.
+
+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;
+
+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() ;
+}
diff --git a/src/java/net/sf/jabref/FieldEditorFocusListener.java b/src/java/net/sf/jabref/FieldEditorFocusListener.java
new file mode 100644
index 0000000..9b92dd4
--- /dev/null
+++ b/src/java/net/sf/jabref/FieldEditorFocusListener.java
@@ -0,0 +1,30 @@
+package net.sf.jabref;
+
+import java.awt.event.FocusListener;
+import java.awt.event.FocusEvent;
+import java.awt.*;
+
+
+/**
+ * Focus listener that changes the color of the text area when it has focus.
+ * Created by IntelliJ IDEA.
+ * User: alver
+ * Date: 18.mar.2005
+ * Time: 18:20:14
+ * To change this template use File | Settings | File Templates.
+ */
+public class FieldEditorFocusListener implements FocusListener {
+
+    public FieldEditorFocusListener() {
+    }
+
+    public void focusGained(FocusEvent event) {
+        ((Component)event.getSource()).setBackground(GUIGlobals.activeEditor);
+    }
+
+
+    public void focusLost(FocusEvent event) {
+        ((Component)event.getSource()).setBackground(Color.white);
+    }
+
+}
diff --git a/src/java/net/sf/jabref/FieldNameLabel.java b/src/java/net/sf/jabref/FieldNameLabel.java
new file mode 100644
index 0000000..13ec080
--- /dev/null
+++ b/src/java/net/sf/jabref/FieldNameLabel.java
@@ -0,0 +1,28 @@
+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 javax.swing.BorderFactory;
+
+public class FieldNameLabel extends JLabel {
+
+  public FieldNameLabel(String name) {
+    super(name, JLabel.CENTER);
+    //setFont(GUIGlobals.fieldNameFont);
+    setForeground(GUIGlobals.validFieldColor);
+    setBorder(BorderFactory.createEtchedBorder());
+  }
+
+  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);
+  }
+
+}
diff --git a/src/java/net/sf/jabref/FieldTextArea.java b/src/java/net/sf/jabref/FieldTextArea.java
new file mode 100644
index 0000000..979ea67
--- /dev/null
+++ b/src/java/net/sf/jabref/FieldTextArea.java
@@ -0,0 +1,193 @@
+/*
+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.
+
+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 javax.swing.*;
+import javax.swing.border.EtchedBorder;
+import java.awt.*;
+//import java.awt.Color;
+import java.awt.event.*;
+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) {
+    }
+}
diff --git a/src/java/net/sf/jabref/FieldTextField.java b/src/java/net/sf/jabref/FieldTextField.java
new file mode 100644
index 0000000..2b778db
--- /dev/null
+++ b/src/java/net/sf/jabref/FieldTextField.java
@@ -0,0 +1,97 @@
+/*
+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.
+
+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 javax.swing.*;
+import java.awt.*;
+import java.awt.event.FocusListener;
+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);
+  }
+
+}
diff --git a/src/java/net/sf/jabref/FieldTextMenu.java b/src/java/net/sf/jabref/FieldTextMenu.java
new file mode 100644
index 0000000..4db9165
--- /dev/null
+++ b/src/java/net/sf/jabref/FieldTextMenu.java
@@ -0,0 +1,268 @@
+/*
+ Copyright (C) 2004 R. Nagel
+
+ 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
+
+ */
+
+// created by : r.nagel 19.10.2004
+//
+// function : a popupmenu for bibtex fieldtext editors
+//
+//
+// modified :
+
+
+package net.sf.jabref ;
+
+import java.awt.* ;
+import java.awt.event.*;
+import javax.swing.*;
+import javax.swing.text.JTextComponent;
+import java.net.*;
+import java.awt.datatransfer.*;
+import net.sf.jabref.util.*;
+
+public class FieldTextMenu implements MouseListener
+{
+  private FieldEditor myFieldName ;
+  private JPopupMenu inputMenu = new JPopupMenu() ;
+  private CopyAction copyAct = new CopyAction() ;
+  private PasteAction pasteAct = new PasteAction() ;
+
+  public FieldTextMenu(FieldEditor fieldComponent)
+  {
+    myFieldName = fieldComponent ;
+
+    // copy/paste Menu
+    inputMenu.add( pasteAct ) ;
+    inputMenu.add( copyAct ) ;
+    inputMenu.addSeparator();
+    //inputMenu.add(new ReplaceAction());
+    inputMenu.add(new CaseChangeMenu((JTextComponent) myFieldName.getTextComponent()));
+  }
+
+  public void mouseClicked(MouseEvent e)
+  {
+  }
+
+  public void mouseEntered(MouseEvent e)
+  {
+  }
+
+  public void mouseExited(MouseEvent e)
+  {
+  }
+
+  public void mousePressed(MouseEvent e)
+  {
+    maybeShowPopup( e ) ;
+  }
+
+  public void mouseReleased(MouseEvent e)
+  {
+    maybeShowPopup( e ) ;
+  }
+
+  private void maybeShowPopup( MouseEvent e )
+  {
+    if ( e.isPopupTrigger() )
+    {
+      if (myFieldName != null)
+      {
+          myFieldName.requestFocus();
+
+        // enable/disable copy to clipboard if selected text available
+        String txt = myFieldName.getSelectedText() ;
+        boolean cStat = false ;
+        if (txt != null)
+          if (txt.length() > 0)
+            cStat = true ;
+
+        copyAct.setEnabled(cStat);
+        inputMenu.show( e.getComponent(), e.getX(), e.getY() ) ;
+      }
+    }
+  }
+
+
+// ---------------------------------------------------------------------------
+  abstract class BasicAction extends AbstractAction
+  {
+    public BasicAction(String text, String description, URL icon)
+    {
+      super(Globals.lang(text), new ImageIcon(icon));
+      putValue(SHORT_DESCRIPTION, Globals.lang(description));
+    }
+
+    public BasicAction(String text, String description, URL icon, KeyStroke key)
+    {
+      super(Globals.lang(text), new ImageIcon(icon));
+      putValue(ACCELERATOR_KEY, key);
+      putValue(SHORT_DESCRIPTION, Globals.lang(description));
+    }
+
+    public BasicAction(String text)
+    {
+      super(Globals.lang(text));
+    }
+
+    public BasicAction(String text, KeyStroke key)
+    {
+      super(Globals.lang(text));
+      putValue(ACCELERATOR_KEY, key);
+    }
+
+    public abstract void actionPerformed(ActionEvent e) ;
+  }
+//---------------------------------------------------------------
+  /*class MenuHeaderAction extends BasicAction
+  {
+    public MenuHeaderAction(String comment)
+    {
+      super("Edit -" +comment);
+      this.setEnabled(false);
+    }
+
+    public void actionPerformed(ActionEvent e) { }
+  }
+    */
+
+// ---------------------------------------------------------------------------
+  class PasteAction extends BasicAction
+  {
+    public PasteAction()
+    {
+      super("Paste from clipboard", "Paste from clipboard", GUIGlobals.pasteIconFile);
+    }
+
+    public void actionPerformed(ActionEvent e)
+    {
+      Clipboard systemClip = Toolkit.getDefaultToolkit().getSystemClipboard();
+
+      try
+      {
+//        String data = ( String ) systemClip.getContents( null ).getTransferData(
+//            DataFlavor.stringFlavor ) ;
+        String data = ClipBoardManager.clipBoard.getClipboardContents() ;
+        if (data != null)
+          if (data.length() > 0)
+            if (myFieldName != null)
+              myFieldName.paste(data);
+      }
+      catch (Exception ex) {}
+    }
+  }
+// ---------------------------------------------------------------------------
+  class CopyAction extends BasicAction
+  {
+    public CopyAction()
+    {
+      super("Copy to clipboard", "Copy to clipboard", GUIGlobals.copyIconFile);
+    }
+
+    public void actionPerformed(ActionEvent e)
+    {
+      try
+      {
+//        String data = ( String ) systemClip.getContents( null ).getTransferData(
+//            DataFlavor.stringFlavor ) ;
+        if (myFieldName != null)
+        {
+          String data = myFieldName.getSelectedText() ;
+          if (data != null)
+            if (data.length() > 0)
+              ClipBoardManager.clipBoard.setClipboardContents(data);
+        }
+      }
+      catch (Exception ex) {}
+    }
+  }
+
+  class ReplaceAction extends BasicAction{
+    public ReplaceAction(){
+        super("Replace comma by and where appropriate");
+    }
+    public void actionPerformed(ActionEvent evt){
+        if (myFieldName.getText().equals("")){
+            return;
+        }
+        //myFieldName.selectAll();
+        String input = myFieldName.getText();
+        //myFieldName.setText(input.replaceAll(","," and"));
+        myFieldName.setText(generalFixAuthor(input));
+    }
+  }
+
+ public static String generalFixAuthor(String in){
+        String author;
+        String[] authors = in.split("( |,)and ",-1);
+        for (int i = 0; i < authors.length; i++){
+            authors[i].trim();
+        }
+        /* determine whether the last author name includes a comma
+         * 0 is intentional (consider -1 as alternative) */
+        author = authors[authors.length-1];
+        boolean lnfn = (author.indexOf(",") > 0);
+        StringBuffer sb = new StringBuffer();
+        /*not tested!*/
+        if(lnfn){
+            String[] parts;
+            for (int i = 0; i < authors.length; i++){
+                parts = authors[i].split(",",-1);
+                if(parts.length == 2){
+                    parts[0] = parts[0].trim().replaceAll(" ","~");
+                    parts[1] = parts[1].trim().replaceAll(" ","~");
+                    sb.append(parts[1]+" "+ parts[0]);
+                } else {
+                    sb.append(authors[i]);
+                }
+                if(i < authors.length -1){
+                    sb.append(" and ");
+                }
+            }
+        } else {
+            for (int i = 0; i < authors.length; i++){
+                String[] iAuthors = authors[i].split(",");
+                String[] ijparts;
+                for (int j=0; j<iAuthors.length; j++){
+                    iAuthors[j] = iAuthors[j].trim();
+                    ijparts = iAuthors[j].split(" ",-1);
+                    for (int k=0; k<ijparts.length; k++){
+                        sb.append(ijparts[k]);
+                        if(k < ijparts.length-2){
+                            sb.append('~');
+                        } else if (k == ijparts.length-2){
+                            sb.append(' ');
+                        }
+                    }
+                    if (j < iAuthors.length -1 || i < authors.length -1){
+                        sb.append(" and ");
+                    }
+                } /* end of j-loop (authors split by ,) */
+            } /* end of i-loop (authors split by and)*/
+        }
+        return sb.toString();
+    }
+
+}
diff --git a/src/java/net/sf/jabref/FileHistory.java b/src/java/net/sf/jabref/FileHistory.java
new file mode 100644
index 0000000..00ef600
--- /dev/null
+++ b/src/java/net/sf/jabref/FileHistory.java
@@ -0,0 +1,121 @@
+package net.sf.jabref;
+
+import java.awt.event.*;
+import javax.swing.*;
+import java.util.LinkedList;
+import java.util.Iterator;
+import java.io.File;
+
+public class FileHistory extends JMenu implements ActionListener {
+
+    JabRefPreferences prefs;
+    LinkedList history = new LinkedList();
+    JabRefFrame frame;
+
+    public FileHistory(JabRefPreferences prefs, JabRefFrame frame) {
+        String name = Globals.menuTitle("Recent files");
+        int i = name.indexOf('&');
+        if (i >= 0) {
+            setText(name.substring(0, i) + name.substring(i + 1));
+            char mnemonic = Character.toUpperCase(name.charAt(i + 1));
+            setMnemonic((int) mnemonic);
+        } else
+            setText(name);
+
+        this.prefs = prefs;
+        this.frame = frame;
+        String[] old = prefs.getStringArray("recentFiles");
+        if ((old != null) && (old.length > 0)) {
+            for (i = 0; i < old.length; i++) {
+                history.addFirst(old[i]);
+            }
+            setItems();
+        } else
+            setEnabled(false);
+    }
+
+    /**
+     * Adds the file name to the top of the menu. If it already is in
+     * the menu, it is merely moved to the top.
+     *
+     * @param filename a <code>String</code> value
+     */
+    public void newFile(String filename) {
+        int i = 0;
+        while (i < history.size()) {
+            if (((String) history.get(i)).equals(filename))
+                history.remove(i--);
+            i++;
+        }
+        history.addFirst(filename);
+        while (history.size() > prefs.getInt("historySize")) {
+            history.removeLast();
+        }
+        setItems();
+        if (!isEnabled())
+            setEnabled(true);
+    }
+
+    private void setItems() {
+        removeAll();
+        Iterator i = history.iterator();
+        int count = 1;
+        while (i.hasNext()) {
+            addItem((String) i.next(), count++);
+        }
+    }
+
+    private void addItem(String filename, int num) {
+        String number = num + "";
+        JMenuItem item = new JMenuItem(number + ". " + filename);
+        char mnemonic = Character.toUpperCase(number.charAt(0));
+        item.setMnemonic((int) mnemonic);
+        item.addActionListener(this);
+        add(item);
+        //history.addFirst(item);
+    }
+
+    private void removeItem(String filename) {
+        int i=0;
+        while (i < history.size()) {
+            if (((String) history.get(i)).equals(filename)) {
+                history.remove(i);
+                setItems();
+                return;
+            }
+            i++;
+        }
+    }
+
+    public void storeHistory() {
+        if (history.size() > 0) {
+            String[] names = new String[history.size()];
+            for (int i = 0; i < names.length; i++)
+                names[i] = (String) history.get(i);
+            prefs.putStringArray("recentFiles", names);
+        }
+    }
+
+    public void actionPerformed(ActionEvent e) {
+        String name = ((JMenuItem) e.getSource()).getText();
+        int pos = name.indexOf(" ");
+        name = name.substring(pos + 1);
+        //Util.pr("'"+name+"'");
+        final File fileToOpen = new File(name);
+
+        if (!fileToOpen.exists()) {
+            JOptionPane.showMessageDialog(frame, Globals.lang("File not found")+": "+fileToOpen.getName(),
+                    "Error", JOptionPane.ERROR_MESSAGE);
+            removeItem(name);
+            return;
+        }
+        (new Thread() {
+            public void run() {
+                frame.open.openIt(fileToOpen, true);
+            }
+        }).start();
+
+    }
+
+
+}
diff --git a/src/java/net/sf/jabref/FocusRequester.java b/src/java/net/sf/jabref/FocusRequester.java
new file mode 100644
index 0000000..2949474
--- /dev/null
+++ b/src/java/net/sf/jabref/FocusRequester.java
@@ -0,0 +1,25 @@
+package net.sf.jabref;
+
+import javax.swing.SwingUtilities;
+import java.awt.Component;
+
+public class FocusRequester implements Runnable {
+    private Component comp;
+
+    public FocusRequester(Component comp) {
+       if (comp == null)
+               Thread.dumpStack();
+
+        //System.out.println("FocusRequester: "+comp.toString());
+	this.comp = comp;
+	try {
+	    SwingUtilities.invokeLater(this);
+	} catch(Exception e) {
+	    e.printStackTrace();
+	}
+    }
+    public void run() {
+
+    comp.requestFocus();
+    }
+}
diff --git a/src/java/net/sf/jabref/FontSelectorDialog.java b/src/java/net/sf/jabref/FontSelectorDialog.java
new file mode 100644
index 0000000..41bc0cb
--- /dev/null
+++ b/src/java/net/sf/jabref/FontSelectorDialog.java
@@ -0,0 +1,419 @@
+package net.sf.jabref;
+/*
+  Taken from JpicEdt
+modified slightly by nizar batada for JabRef
+
+ EepicViewFactory.java - February 11, 2002 - jPicEdt, a picture editor for LaTeX.
+ copyright (C) 1999-2002 Sylvain Reynal
+ Portions copyright (C) 2000, 2001 Slava Pestov
+ Portions copyright (C) 1999 Jason Ginchereau
+
+ D\uFFFDpartement de Physique
+ Ecole Nationale Sup\uFFFDrieure de l'Electronique et de ses Applications (ENSEA)
+ 6, avenue du Ponceau
+ F-95014 CERGY CEDEX
+
+ Tel : +33 130 736 245
+ Fax : +33 130 736 667
+ e-mail : reynal at ensea.fr
+ jPicEdt web page : http://trashx.ensea.fr/jpicedt/
+
+ 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 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.
+ */
+
+import java.awt.event.*;
+import java.awt.*;
+import java.util.Vector;
+import javax.swing.border.*;
+import javax.swing.event.*;
+import javax.swing.*;
+
+/**
+ * A font chooser widget.
+ * @author Slava Pestov (jEdit), Sylvain Reynal
+ * @since jpicedt 1.3.2.beta-9
+ * @version $Id: FontSelectorDialog.java,v 1.6 2004/02/27 23:28:41 mortenalver Exp $
+ * <p>
+ * $Log: FontSelectorDialog.java,v $
+ * Revision 1.6  2004/02/27 23:28:41  mortenalver
+ * Some code tidying, no effect on behaviour (hopefully)
+ *
+ * Revision 1.5  2004/02/24 23:30:18  mortenalver
+ * Added more translations, and started work on a Replace string feature
+ *
+ * Revision 1.4  2004/02/17 09:14:02  mortenalver
+ * Similar update in FontSelector preview.
+ *
+ * Revision 1.3  2004/02/17 07:35:22  mortenalver
+ * Experimenting with antialiasing in table.
+ *
+ * Revision 1.2  2003/12/14 23:48:02  mortenalver
+ * .
+ *
+ * Revision 1.1  2003/11/07 22:18:07  nbatada
+ * modified it slightly from initial version
+ *
+ * Revision 1.1  2003/11/07 22:14:34  nbatada
+ * modified it from initial version
+ *
+ * Revision 1.4  2003/11/02 01:51:06  reynal
+ * Cleaned-up i18n labels
+ *
+ * Revision 1.3  2003/08/31 22:05:40  reynal
+ *
+ * Enhanced class interface for some widgets.
+ *
+
+ */
+
+class FontSelector extends JButton {
+
+	static final String PLAIN="plain";
+	static final String BOLD="bold";
+	static final String BOLD_ITALIC="bold-italic";
+	static final String ITALIC="italic";
+
+	/** init with a default font */
+	public FontSelector(){
+		this(new Font("SansSerif", Font.PLAIN, 10));
+	}
+
+	/** init with the given font */
+	public FontSelector(Font font){
+		setFont(font);
+		setRequestFocusEnabled(false);
+		addActionListener(new ActionHandler());
+	}
+
+	public void setFont(Font font){
+		super.setFont(font);
+		updateText();
+	}
+
+	/**
+	 * update button's text content from the current button's font.
+	 */
+	private void updateText(){
+		Font font = getFont();
+		String styleString;
+		switch(font.getStyle()){
+		case Font.PLAIN:
+			styleString = PLAIN;
+			break;
+		case Font.BOLD:
+			styleString = BOLD;
+			break;
+		case Font.ITALIC:
+			styleString = ITALIC;
+			break;
+		case Font.BOLD | Font.ITALIC:
+			styleString = BOLD_ITALIC;
+			break;
+		default:
+			styleString = "UNKNOWN!!!???";
+			break;
+		}
+
+		setText(font.getFamily() + " " + font.getSize() + " " + styleString);
+	}
+
+	/**
+	 * button's action-listener ; open a FontSelectorDialog
+	 */
+	class ActionHandler implements ActionListener {
+		public void actionPerformed(ActionEvent evt) {
+			Font font = new FontSelectorDialog(FontSelector.this,getFont()).getSelectedFont();
+			if(font != null){
+				setFont(font);
+			}
+		}
+	}
+
+}
+
+
+
+///////////////////////////////////////////////////////////////////////////////
+
+/**
+ *
+ */
+public class FontSelectorDialog extends JDialog {
+
+	/**
+	 *
+	 */
+    	static final String PLAIN="plain";
+	static final String BOLD="bold";
+	static final String BOLD_ITALIC="bold-italic";
+	static final String ITALIC="italic";
+
+	public FontSelectorDialog(Component comp, Font font) {
+
+	    //super(JOptionPane.getFrameForComponent(comp),jpicedt.Localizer.currentLocalizer().get("widget.FontSelector"),true); //
+	    super(JOptionPane.getFrameForComponent(comp),Globals.lang("FontSelector"),true); //
+		JPanel content = new JPanel(new BorderLayout());
+		content.setBorder(new EmptyBorder(12,12,12,12));
+		setContentPane(content);
+
+		JPanel listPanel = new JPanel(new GridLayout(1,3,6,6));
+
+		JPanel familyPanel = createTextFieldAndListPanel(
+								 Globals.lang("Font Family"),
+								 familyField = new JTextField(),
+								 familyList = new JList(getFontList()));
+		listPanel.add(familyPanel);
+
+		String[] sizes = { "9", "10", "12", "14", "16", "18", "24" };
+		JPanel sizePanel = createTextFieldAndListPanel(
+							       Globals.lang("Font Size"),
+		                       sizeField = new JTextField(),
+		                       sizeList = new JList(sizes));
+		listPanel.add(sizePanel);
+
+		String[] styles = {PLAIN,BOLD,ITALIC,BOLD_ITALIC};
+
+		JPanel stylePanel = createTextFieldAndListPanel(
+								Globals.lang("Font Style"),
+		                        styleField = new JTextField(),
+		                        styleList = new JList(styles));
+		styleField.setEditable(false);
+		listPanel.add(stylePanel);
+
+		familyList.setSelectedValue(font.getFamily(),true);
+		familyField.setText(font.getFamily());
+		sizeList.setSelectedValue(String.valueOf(font.getSize()),true);
+		sizeField.setText(String.valueOf(font.getSize()));
+		styleList.setSelectedIndex(font.getStyle());
+		styleField.setText((String)styleList.getSelectedValue());
+
+		ListHandler listHandler = new ListHandler();
+		familyList.addListSelectionListener(listHandler);
+		sizeList.addListSelectionListener(listHandler);
+		styleList.addListSelectionListener(listHandler);
+
+		content.add(BorderLayout.NORTH,listPanel);
+
+		//preview = new JLabel("Font Preview");
+		
+		/* --------------------------------------------------------
+		   |  Experimental addition by Morten Alver. I want to    |
+		   |  enable antialiasing in the preview field, since I'm |
+		   |  working on introducing this in the table view.      |
+		   -------------------------------------------------------- */
+		preview = new JLabel(Globals.lang("Font Preview")) {
+			public void paint(Graphics g) {
+			    Graphics2D g2 = (Graphics2D)g;
+			    g2.setRenderingHint
+				(RenderingHints.KEY_ANTIALIASING,
+				 RenderingHints.VALUE_ANTIALIAS_ON);
+			    super.paint(g2);
+			}
+
+		    };
+
+
+
+		preview.setBorder(new TitledBorder(Globals.lang("Font Preview")));
+
+		updatePreview();
+
+		Dimension prefSize = preview.getPreferredSize();
+		prefSize.height = 50;
+		preview.setPreferredSize(prefSize);
+
+		content.add(BorderLayout.CENTER,preview);
+
+		JPanel buttons = new JPanel();
+		buttons.setLayout(new BoxLayout(buttons,BoxLayout.X_AXIS));
+		buttons.setBorder(new EmptyBorder(12,0,0,0));
+		buttons.add(Box.createGlue());
+
+		ok = new JButton(Globals.lang("OK"));
+		ok.addActionListener(new ActionHandler());
+		getRootPane().setDefaultButton(ok);
+		buttons.add(ok);
+
+		buttons.add(Box.createHorizontalStrut(6));
+
+		cancel = new JButton(Globals.lang("Cancel"));
+		cancel.addActionListener(new ActionHandler());
+		buttons.add(cancel);
+
+		buttons.add(Box.createGlue());
+
+		content.add(BorderLayout.SOUTH,buttons);
+
+		pack();
+		setLocationRelativeTo(JOptionPane.getFrameForComponent(comp));
+		show();
+	}
+
+	public void ok(){
+		isOK = true;
+		dispose();
+	}
+
+	public void cancel(){
+		dispose();
+	}
+
+	public Font getSelectedFont(){
+		if(!isOK)
+			return null;
+
+		int size;
+		try{
+			size = Integer.parseInt(sizeField.getText());
+		}
+		catch(Exception e){
+			size = 14;
+		}
+
+		return new Font(familyField.getText(),styleList.getSelectedIndex(),size);
+	}
+
+	// private members
+	private boolean isOK;
+	private JTextField familyField;
+	private JList familyList;
+	private JTextField sizeField;
+	private JList sizeList;
+	private JTextField styleField;
+	private JList styleList;
+	private JLabel preview;
+	private JButton ok;
+	private JButton cancel;
+
+	/**
+	 * For some reason the default Java fonts show up in the
+	 * list with .bold, .bolditalic, and .italic extensions.
+	 */
+	private static final String[] HIDEFONTS = {".bold",".italic"};
+
+	// [pending] from GeneralCustomizer :
+	// GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames()
+	private String[] getFontList(){
+		try{
+			Class GEClass = Class.forName("java.awt.GraphicsEnvironment");
+			Object GEInstance = GEClass.getMethod("getLocalGraphicsEnvironment", null).invoke(null, null);
+
+			String[] nameArray = (String[])GEClass.getMethod("getAvailableFontFamilyNames", null).invoke(GEInstance, null);
+			Vector nameVector = new Vector(nameArray.length);
+
+			for(int i = 0, j; i < nameArray.length; i++){
+				for(j = 0; j < HIDEFONTS.length; j++){
+					if(nameArray[i].indexOf(HIDEFONTS[j]) >= 0) break;
+				}
+
+				if(j == HIDEFONTS.length) nameVector.addElement(nameArray[i]);
+			}
+
+			String[] _array = new String[nameVector.size()];
+			nameVector.copyInto(_array);
+			return _array;
+		}
+		catch(Exception ex){
+		    return null;//return Toolkit.getDefaultToolkit().getFontList();
+		}
+	}
+
+	private JPanel createTextFieldAndListPanel(String label,JTextField textField, JList list){
+		GridBagLayout layout = new GridBagLayout();
+		JPanel panel = new JPanel(layout);
+
+		GridBagConstraints cons = new GridBagConstraints();
+		cons.gridx = cons.gridy = 0;
+		cons.gridwidth = cons.gridheight = 1;
+		cons.fill = GridBagConstraints.BOTH;
+		cons.weightx = 1.0f;
+
+		JLabel _label = new JLabel(label);
+		layout.setConstraints(_label,cons);
+		panel.add(_label);
+
+		cons.gridy = 1;
+		Component vs = Box.createVerticalStrut(6);
+		layout.setConstraints(vs,cons);
+		panel.add(vs);
+
+		cons.gridy = 2;
+		layout.setConstraints(textField,cons);
+		panel.add(textField);
+
+		cons.gridy = 3;
+		vs = Box.createVerticalStrut(6);
+		layout.setConstraints(vs,cons);
+		panel.add(vs);
+
+		cons.gridy = 4;
+		cons.gridheight = GridBagConstraints.REMAINDER;
+		cons.weighty = 1.0f;
+		JScrollPane scroller = new JScrollPane(list);
+		layout.setConstraints(scroller,cons);
+		panel.add(scroller);
+
+		return panel;
+	}
+
+	private void updatePreview(){
+		String family = familyField.getText();
+		int size;
+		try{
+			size = Integer.parseInt(sizeField.getText());
+		}
+		catch(Exception e){
+			size = 14;
+		}
+		int style = styleList.getSelectedIndex();
+		preview.setFont(new Font(family,style,size));
+	}
+
+	class ActionHandler implements ActionListener {
+		public void actionPerformed(ActionEvent evt){
+			if(evt.getSource() == ok)ok();
+			else if(evt.getSource() == cancel)cancel();
+		}
+	}
+
+	class ListHandler implements ListSelectionListener {
+		public void valueChanged(ListSelectionEvent evt)
+		{
+			Object source = evt.getSource();
+			if(source == familyList) {
+				String family = (String)familyList.getSelectedValue();
+				if(family != null)
+					familyField.setText(family);
+			}
+			else if(source == sizeList) {
+				String size = (String)sizeList.getSelectedValue();
+				if(size != null)
+					sizeField.setText(size);
+			}
+			else if(source == styleList) {
+				String style = (String)styleList.getSelectedValue();
+				if(style != null)
+					styleField.setText(style);
+			}
+			updatePreview();
+		}
+	}
+    /*public static void main(String args[])
+	{
+	    Font font = new FontSelectorDialog(null,new Font("Times",Font.PLAIN,12)).getSelectedFont();
+
+	}
+    */
+}
diff --git a/src/java/net/sf/jabref/GUIGlobals.java b/src/java/net/sf/jabref/GUIGlobals.java
new file mode 100644
index 0000000..e311f28
--- /dev/null
+++ b/src/java/net/sf/jabref/GUIGlobals.java
@@ -0,0 +1,565 @@
+/*
+  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
+
+  Note:
+  Modified for use in JabRef.
+
+ */
+
+package net.sf.jabref;
+
+import java.awt.*;
+import java.util.*;
+import java.util.List;
+import java.net.URL;
+import javax.swing.*;
+
+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.plaf.plastic.Plastic3DLookAndFeel",
+      //"com.shfarr.ui.plaf.fh.FhLookAndFeel",
+//"net.sourceforge.mlf.metouia.MetouiaLookAndFeel",
+//"org.compiere.plaf.CompiereLookAndFeel",
+      windowsDefaultLookAndFeel = "com.jgoodies.plaf.windows.ExtWindowsLookAndFeel";
+
+  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 JLabel incompleteLabel; // JLabel with icon signaling an incomplete entry.
+    public static Color activeEditor = new Color(230, 230, 255);
+    public static final String[] DEFAULT_INSPECTION_FIELDS = new String[]
+        {"author", "title", "year"};
+
+    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;
+    }
+
+
+  public static URL
+
+          openIconFile = GUIGlobals.class.getResource(pre + "fldr_obj.gif"),
+          editIconFile = GUIGlobals.class.getResource(pre + "edittsk_tsk.gif"),
+          saveIconFile = GUIGlobals.class.getResource(pre + "save_edit.gif"),
+          saveAsIconFile = GUIGlobals.class.getResource(pre + "saveas_edit.gif"),
+          prefsIconFile = GUIGlobals.class.getResource(pre + "configure2.png"),
+          newIconFile = GUIGlobals.class.getResource(pre + "new_page.gif"),
+          undoIconFile = GUIGlobals.class.getResource(pre + "undo_edit.gif"),
+          redoIconFile = GUIGlobals.class.getResource(pre + "redo_edit.gif"),
+          preambleIconFile = GUIGlobals.class.getResource(pre + "preamble.png"),
+          addIconFile = GUIGlobals.class.getResource(pre + "plus.gif"),
+          delRowIconFile = GUIGlobals.class.getResource(pre + "minus.gif"),
+          showReqIconFile = GUIGlobals.class.getResource(pre + "reqIcon.png"),
+          showOptIconFile = GUIGlobals.class.getResource(pre + "optIcon.png"),
+          showGenIconFile = GUIGlobals.class.getResource(pre + "absIcon.png"),
+          showAbsIconFile = GUIGlobals.class.getResource(pre + "genIcon.png"),
+          sourceIconFile = GUIGlobals.class.getResource(pre + "viewsource.gif"),
+          copyIconFile = GUIGlobals.class.getResource(pre + "copy_edit.gif"),
+          cutIconFile = GUIGlobals.class.getResource(pre + "cut_edit.gif"),
+          copyKeyIconFile = GUIGlobals.class.getResource(pre + "copy_edit.gif"),
+          genKeyIconFile = GUIGlobals.class.getResource(pre + "wizard.png"),
+          lyxIconFile = GUIGlobals.class.getResource(pre + "lyx2.png"),
+          backIconFile = GUIGlobals.class.getResource(pre + "backward_nav.gif"),
+          forwardIconFile = GUIGlobals.class.getResource(pre + "forward_nav.gif"),
+          contentsIconFile = GUIGlobals.class.getResource(pre + "toc_closed.gif"),
+          removeIconFile = GUIGlobals.class.getResource(pre + "delete_edit.gif"),
+          upIconFile = GUIGlobals.class.getResource(pre + "prev_nav.gif"),
+          downIconFile = GUIGlobals.class.getResource(pre + "next_nav.gif"),
+          stringsIconFile = GUIGlobals.class.getResource(pre + "strings.png"),
+          groupsIconFile = GUIGlobals.class.getResource(pre + "queue.png"),
+          groupsHighlightMatchingAnyFile = GUIGlobals.class.getResource(pre + "groupsHighlightAny.png"),
+          groupsHighlightMatchingAllFile = GUIGlobals.class.getResource(pre + "groupsHighlightAll.png"),
+          closeIconFile = GUIGlobals.class.getResource(pre + "fileclose.png"),
+          close2IconFile = GUIGlobals.class.getResource(pre + "fileclose2.png"),
+          refreshSmallIconFile = GUIGlobals.class.getResource(pre + "refresh_nav.gif"),
+          helpSmallIconFile = GUIGlobals.class.getResource(pre + "view.gif"),
+          helpIconFile = GUIGlobals.class.getResource(pre + "view.gif"),
+          aboutIcon = GUIGlobals.class.getResource(pre + "view.gif"),
+          helpContentsIconFile = GUIGlobals.class.getResource(pre + "contents2.png"),
+          newSmallIconFile = GUIGlobals.class.getResource(pre + "new_page.gif"),
+          pasteIconFile = GUIGlobals.class.getResource(pre + "paste_edit.gif"),
+          editEntryIconFile = GUIGlobals.class.getResource(pre + "DocumentDraw.gif"),
+          searchIconFile = GUIGlobals.class.getResource(pre + "search.gif"),
+          previewIconFile = GUIGlobals.class.getResource(pre + "preview.png"),
+          autoGroupIcon = GUIGlobals.class.getResource(pre + "addtsk_tsk.gif"),
+          wwwIcon = GUIGlobals.class.getResource(pre + "www.png"),
+          wwwCiteSeerIcon = GUIGlobals.class.getResource(pre + "wwwciteseer.png"),
+          fetchMedlineIcon = GUIGlobals.class.getResource(pre + "goto.png"),
+          fetchHourglassIcon = GUIGlobals.class.getResource(pre + "Hourglass.png"),
+          pdfIcon = GUIGlobals.class.getResource(pre + "pdf.png"),
+          pdfSmallIcon = GUIGlobals.class.getResource(pre + "pdf_small.gif"),
+          sheetIcon = GUIGlobals.class.getResource(pre + "defaults_ps.gif"),
+          doiIcon = GUIGlobals.class.getResource(pre + "doi.png"),
+          doiSmallIcon = GUIGlobals.class.getResource(pre + "doismall.png"),
+          psIcon = GUIGlobals.class.getResource(pre + "postscript.png"),
+          incompleteIcon = GUIGlobals.class.getResource(pre + "exclamation.gif"),
+          winEdtIcon = GUIGlobals.class.getResource(pre + "winedt.png"),
+          jabreflogo = GUIGlobals.class.getResource(pre + "JabRef-icon.png"),
+          completeTagIcon = GUIGlobals.class.getResource(pre + "completeItem.png"),
+          wrongTagIcon = GUIGlobals.class.getResource(pre + "wrongItem.png"),
+          clearInputArea = GUIGlobals.class.getResource(pre + "new_page.gif"),
+          markIcon = GUIGlobals.class.getResource(pre + "mark.png"),
+          unmarkIcon = GUIGlobals.class.getResource(pre + "unmark.png"),
+          newBibFile = GUIGlobals.class.getResource(pre + "newBibFile.png"),
+          integrityCheck = GUIGlobals.class.getResource(pre + "integrity.png"),
+          integrityInfo = GUIGlobals.class.getResource(pre + "messageInfo.png"),
+          integrityWarn = GUIGlobals.class.getResource(pre + "messageWarn.png"),
+          integrityFail = GUIGlobals.class.getResource(pre + "messageFail.png"),
+          duplicateIcon = GUIGlobals.class.getResource(pre + "duplicate.png"),
+          emacsIcon = GUIGlobals.class.getResource(pre + "emacs.png");
+  
+  public static ImageIcon
+  	groupRefiningIcon = new ImageIcon(GUIGlobals.class.getResource(pre +"groupRefining.png")),
+  	groupIncludingIcon = new ImageIcon(GUIGlobals.class.getResource(pre +"groupIncluding.png")),
+  	groupRegularIcon = null;
+
+    /*public static incompleteEntryIcon = new ImageIcon(incompleteIcon);
+    static {
+      incompleteEntryIcon.setTool
+    }*/
+
+// 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",
+        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.
+//	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: ";
+  public static String KEY_FIELD = "bibtexkey";
+  public static String[] ALL_FIELDS = new String[] {
+      "author",
+      "editor",
+      "title",
+      "year",
+      "pages",
+      "publisher",
+      "journal",
+      "volume",
+      "month",
+      "note",
+      "edition",
+      "number",
+      "chapter",
+      "series",
+      "type",
+      "address",
+      "location",
+      "annote",
+      "booktitle",
+      "crossref",
+      "howpublished",
+      "institution",
+      "key",
+      "organization",
+      "school",
+      "abstract",
+      "url",
+          "citeseerurl",
+      "pdf",
+      "comment",
+      "bibtexkey",
+      "keywords",
+      "doi",
+      "eid",
+      "search",
+          "citeseercitationcount"
+  };
+
+  public static final Map FIELD_DISPLAYS;
+  static {
+      Arrays.sort(ALL_FIELDS);
+          FIELD_DISPLAYS = new HashMap();
+          FIELD_DISPLAYS.put("citeseercitationcount","Popularity");
+  }
+
+
+// These are the fields that BibTex might want to treat, so these
+// must conform to BibTex rules.
+  public static String[] BIBTEX_STANDARD_FIELDS = new String[] {
+      "author",
+      "editor",
+      "title",
+      "year",
+      "pages",
+      "month",
+      "note",
+      "publisher",
+      "journal",
+      "volume",
+      "edition",
+      "number",
+      "chapter",
+      "series",
+      "type",
+      "address",
+      //? "annote",
+      "booktitle",
+      "crossref",
+      "howpublished",
+      "institution",
+      "key",
+      "organization",
+      "school",
+      "bibtexkey",
+      "doi",
+      "eid",
+      "date"
+  };
+
+  // These fields will not be saved to the .bib file.
+  public static String[] NON_WRITABLE_FIELDS = new String[] {
+      Globals.SEARCH,
+      Globals.GROUPSEARCH
+  };
+
+  // These fields will not be shown inside the source editor panel.
+  public static String[] NON_DISPLAYABLE_FIELDS = new String[] {
+      Globals.MARKED,
+      Globals.SEARCH,
+      Globals.GROUPSEARCH
+  };
+
+     public static boolean isWriteableField(String field) {
+       for (int i = 0; i < NON_WRITABLE_FIELDS.length; i++) {
+         if (NON_WRITABLE_FIELDS[i].equals(field)) {
+           return false;
+         }
+       }
+       return true;
+     }
+
+     public static boolean isDisplayableField(String field) {
+       for (int i = 0; i < NON_DISPLAYABLE_FIELDS.length; i++) {
+         if (NON_DISPLAYABLE_FIELDS[i].equals(field)) {
+           return false;
+         }
+       }
+       return true;
+     }
+
+  /**
+   * Returns true if the given field is a standard Bibtex field.
+   *
+   * @param field a <code>String</code> value
+   * @return a <code>boolean</code> value
+   */
+  public static boolean isStandardField(String field) {
+    for (int i = 0; i < BIBTEX_STANDARD_FIELDS.length; i++) {
+      if (BIBTEX_STANDARD_FIELDS[i].equals(field)) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  public static double DEFAULT_FIELD_WEIGHT = 1,
+        MAX_FIELD_WEIGHT = 2;
+
+  public static Double
+      SMALL_W = new Double(0.30),
+      MEDIUM_W = new Double(0.5),
+      LARGE_W = new Double(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 FIELD_WEIGHT;
+  public static final Map FIELD_EXTRAS, LANGUAGES;
+  public static Map fieldLength = new HashMap();
+  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("Norsk", "no");
+
+    FIELD_EXTRAS = new HashMap();
+    // fieldExtras contains mappings to tell the EntryEditor to add a specific
+    // function to this field, for instance a "browse" button for the "pdf" field.
+    FIELD_EXTRAS.put("pdf", "browseDoc");
+    FIELD_EXTRAS.put("ps", "browseDocZip");
+    FIELD_EXTRAS.put("url", "external");
+    FIELD_EXTRAS.put("citeseerurl", "external");
+    FIELD_EXTRAS.put("doi", "external");
+    FIELD_EXTRAS.put("journal", "journalNames");
+    //FIELD_EXTRAS.put("keywords", "selector");
+
+
+    fieldLength.put("author", new Integer(280));
+    fieldLength.put("editor", new Integer(280));
+    fieldLength.put("title", new Integer(400));
+    fieldLength.put("abstract", new Integer(400));
+    fieldLength.put("booktitle", new Integer(175));
+    fieldLength.put("year", new Integer(60));
+    fieldLength.put("volume", new Integer(60));
+    fieldLength.put("number", new Integer(60));
+    fieldLength.put("entrytype", new Integer(75));
+    fieldLength.put("search", new Integer(75));
+    fieldLength.put("citeseercitationcount", new Integer(75));
+    fieldLength.put(NUMBER_COL, new Integer(32));
+
+    FIELD_WEIGHT = new HashMap();
+    FIELD_WEIGHT.put("author", MEDIUM_W);
+    FIELD_WEIGHT.put("year", SMALL_W);
+    FIELD_WEIGHT.put("pages", SMALL_W);
+    FIELD_WEIGHT.put("month", SMALL_W);
+    FIELD_WEIGHT.put("url", SMALL_W);
+    FIELD_WEIGHT.put("citeseerurl", SMALL_W);
+    FIELD_WEIGHT.put("crossref", SMALL_W);
+    FIELD_WEIGHT.put("note", MEDIUM_W);
+    FIELD_WEIGHT.put("publisher", MEDIUM_W);
+    FIELD_WEIGHT.put("journal", SMALL_W);
+    FIELD_WEIGHT.put("volume", SMALL_W);
+    FIELD_WEIGHT.put("edition", SMALL_W);
+    FIELD_WEIGHT.put("keywords", SMALL_W);
+    FIELD_WEIGHT.put("doi", SMALL_W);
+    FIELD_WEIGHT.put("eid", SMALL_W);
+    FIELD_WEIGHT.put("pdf", SMALL_W);
+    FIELD_WEIGHT.put("number", SMALL_W);
+    FIELD_WEIGHT.put("chapter", SMALL_W);
+    FIELD_WEIGHT.put("editor", MEDIUM_W);
+    FIELD_WEIGHT.put("series", SMALL_W);
+    FIELD_WEIGHT.put("type", SMALL_W);
+    FIELD_WEIGHT.put("address", SMALL_W);
+    FIELD_WEIGHT.put("howpublished", MEDIUM_W);
+    FIELD_WEIGHT.put("institution", MEDIUM_W);
+    FIELD_WEIGHT.put("organization", MEDIUM_W);
+    FIELD_WEIGHT.put("school", MEDIUM_W);
+    FIELD_WEIGHT.put("comment", MEDIUM_W);
+    FIELD_WEIGHT.put("abstract", LARGE_W);
+    FIELD_WEIGHT.put("annote", LARGE_W);
+    FIELD_WEIGHT.put("citeseercitationcount", SMALL_W);
+    FIELD_WEIGHT.put("owner", SMALL_W);
+    FIELD_WEIGHT.put("timestamp", SMALL_W);
+    //FIELD_WEIGHT = Collections.unmodifiableMap(FIELD_WEIGHT);
+  }
+
+    /*
+    public static int getPreferredFieldLength(String name) {
+    int l = DEFAULT_FIELD_LENGTH;
+    Object o = fieldLength.get(name.toLowerCase());
+    if (o != null)
+    l = ((Integer)o).intValue();
+    return l;
+    }*/
+
+  public static double getFieldWeight(String name) {
+    double l = DEFAULT_FIELD_WEIGHT;
+    Object o = FIELD_WEIGHT.get(name.toLowerCase());
+    if (o != null) {
+      l = ( (Double) o).doubleValue();
+    }
+    return l;
+  }
+
+  public static void setFieldWeight(String fieldName, double weight) {
+      FIELD_WEIGHT.put(fieldName, new Double(weight));
+  }
+
+  /** 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);
+    incompleteLabel = new JLabel(new ImageIcon(GUIGlobals.incompleteIcon));
+    incompleteLabel.setToolTipText(Globals.lang("Entry is incomplete"));
+    JLabel lab;
+    lab = new JLabel(new ImageIcon(pdfIcon));
+    lab.setToolTipText(Globals.lang("Open")+" PDF");
+    tableIcons.put("pdf", lab);
+    lab = new JLabel(new ImageIcon(wwwIcon));
+    lab.setToolTipText(Globals.lang("Open")+" URL");
+    tableIcons.put("url", lab);
+    lab = new JLabel(new ImageIcon(wwwCiteSeerIcon));
+    lab.setToolTipText(Globals.lang("Open")+" CiteSeer URL");
+    tableIcons.put("citeseerurl", lab);
+    lab = new JLabel(new ImageIcon(doiSmallIcon));
+    lab.setToolTipText(Globals.lang("Open")+" DOI "+Globals.lang("web link"));
+    tableIcons.put("doi", lab);
+    lab = new JLabel(new ImageIcon(psIcon));
+    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/GeneralRenderer.java b/src/java/net/sf/jabref/GeneralRenderer.java
new file mode 100644
index 0000000..f9404c8
--- /dev/null
+++ b/src/java/net/sf/jabref/GeneralRenderer.java
@@ -0,0 +1,73 @@
+package net.sf.jabref;
+
+import javax.swing.table.DefaultTableCellRenderer;
+import javax.swing.*;
+import java.awt.*;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: alver
+ * Date: May 30, 2005
+ * Time: 9:43:45 PM
+ * To change this template use File | Settings | File Templates.
+ */
+public class GeneralRenderer /*extends JTable implements TableCellRenderer {*/ extends DefaultTableCellRenderer {
+    private boolean antialiasing;
+
+    public GeneralRenderer(Color c, boolean antialiasing) {
+        super();
+        this.antialiasing = antialiasing;
+        setBackground(c);
+    }
+
+
+    public GeneralRenderer(Color c, Color fg, boolean antialiasing) {
+        this(c, antialiasing);
+        setForeground(fg);
+    }
+
+    public void firePropertyChange(String propertyName, boolean old, boolean newV) {}
+    public void firePropertyChange(String propertyName, Object old, Object newV) {}
+
+    /* For enabling the renderer to handle icons. */
+    protected void setValue(Object value) {
+        //System.out.println(""+value);
+        if (value instanceof Icon) {
+            setIcon((Icon)value);
+            setText(null);
+            //super.setValue(null);
+        } else if (value instanceof JLabel) {
+          JLabel lab = (JLabel)value;
+          setIcon(lab.getIcon());
+          //table.setToolTipText(lab.getToolTipText());
+          setToolTipText(lab.getToolTipText());
+          if (lab.getIcon() != null)
+            setText(null);
+        } else {
+
+            setIcon(null);
+            //table.setToolTipText(null);
+            setToolTipText(null);
+            if (value != null)
+                setText(value.toString());
+            else
+                setText(null);
+        }
+    }
+
+      public void paint(Graphics g) {
+        Graphics2D g2 = (Graphics2D)g;
+        //System.out.println(antialiasing);
+        if (antialiasing) {
+            RenderingHints rh = g2.getRenderingHints();
+            rh.put(RenderingHints.KEY_ANTIALIASING,
+                RenderingHints.VALUE_ANTIALIAS_ON);
+            rh.put(RenderingHints.KEY_RENDERING,
+                RenderingHints.VALUE_RENDER_QUALITY);
+            g2.setRenderingHints(rh);
+        }
+          super.paint(g2);
+
+    }
+
+}
diff --git a/src/java/net/sf/jabref/GeneralTab.java b/src/java/net/sf/jabref/GeneralTab.java
new file mode 100644
index 0000000..88c7b9b
--- /dev/null
+++ b/src/java/net/sf/jabref/GeneralTab.java
@@ -0,0 +1,342 @@
+package net.sf.jabref;
+
+import javax.swing.*;
+import javax.swing.event.ChangeListener;
+import javax.swing.event.ChangeEvent;
+import java.awt.*;
+import java.util.Iterator;
+import java.text.SimpleDateFormat;
+
+import com.jgoodies.forms.layout.*;
+import com.jgoodies.forms.builder.*;
+
+public class GeneralTab extends JPanel implements PrefsTab {
+
+    private JCheckBox autoOpenForm, backup, openLast, showSource,
+    defSource, editSource, defSort, ctrlClick, disableOnMultiple,
+    useOwner, keyDuplicateWarningDialog, keyEmptyWarningDialog, autoDoubleBraces,
+    confirmDelete, saveInStandardOrder, allowEditing, /*preserveFormatting, */useImportInspector,
+    useImportInspectorForSingle, inspectionWarnDupli, useTimeStamp;
+    private JTextField defOwnerField, timeStampFormat, timeStampField,
+            bracesAroundCapitalsFields, nonWrappableFields;
+    JabRefPreferences _prefs;
+    JabRefFrame _frame;
+    private JComboBox language = new JComboBox(GUIGlobals.LANGUAGES.keySet().toArray()),
+    encodings = new JComboBox(Globals.ENCODINGS);
+    private HelpAction ownerHelp, timeStampHelp;
+
+    public GeneralTab(JabRefFrame frame, JabRefPreferences prefs) {
+        _prefs = prefs;
+        _frame = frame;
+        setLayout(new BorderLayout());
+
+        autoOpenForm = new JCheckBox(Globals.lang("Open editor when a new entry is created"));
+        openLast = new JCheckBox(Globals.lang("Open last edited databases at startup"));
+        allowEditing = new JCheckBox(Globals.lang("Allow editing in table cells"));
+        backup = new JCheckBox(Globals.lang("Backup old file when saving"));
+        defSource = new JCheckBox(Globals.lang("Show BibTeX source by default"));
+        showSource = new JCheckBox(Globals.lang("Show BibTeX source panel"));
+        editSource = new JCheckBox(Globals.lang("Enable source editing"));
+        defSort = new JCheckBox(Globals.lang("Sort Automatically"));
+        ctrlClick = new JCheckBox(Globals.lang("Open right-click menu with Ctrl+left button"));
+        disableOnMultiple = new JCheckBox(Globals.lang("Disable entry editor when multiple entries are selected"));
+        useOwner = new JCheckBox(Globals.lang("Mark new entries with owner name") + ":");
+        useTimeStamp = new JCheckBox(Globals.lang("Mark new entries with addition date") + ". "
+            +Globals.lang("Date format")+ ":");
+        keyDuplicateWarningDialog = new JCheckBox(Globals.lang("Show warning dialog when a duplicate BibTeX key is entered"));
+        keyEmptyWarningDialog = new JCheckBox(Globals.lang("Show warning dialog when an empty BibTeX key is entered")); // JZTODO lyrics
+        confirmDelete = new JCheckBox(Globals.lang("Show confirmation dialog when deleting entries"));
+        saveInStandardOrder = new JCheckBox(Globals.lang("Always save database ordered by author name"));
+        autoDoubleBraces = new JCheckBox(
+                //+ Globals.lang("Store fields with double braces, and remove extra braces when loading.<BR>"
+                //+ "Double braces signal that BibTeX should preserve character case.") + "</HTML>");
+                Globals.lang("Remove double braces around BibTeX fields when loading."));
+        useImportInspector = new JCheckBox(Globals.lang("Display imported entries in an inspection window before they are added."));
+        useImportInspectorForSingle = new JCheckBox(Globals.lang("Use inspection window also when a single entry is imported.")); 
+        JPanel general = new JPanel();
+        defOwnerField = new JTextField();
+        timeStampFormat = new JTextField();
+        timeStampField = new JTextField();
+        ownerHelp = new HelpAction(frame.helpDiag, GUIGlobals.ownerHelp,
+                "Help", GUIGlobals.helpSmallIconFile);
+        timeStampHelp = new HelpAction(frame.helpDiag, GUIGlobals.timeStampHelp, "Help",
+                GUIGlobals.helpSmallIconFile);
+        inspectionWarnDupli = new JCheckBox(Globals.lang("Warn about unresolved duplicates when closing inspection window"));
+
+        Insets marg = new Insets(0,12,3,0);
+        useImportInspectorForSingle.setMargin(marg);
+        editSource.setMargin(marg);
+        defSource.setMargin(marg);
+        inspectionWarnDupli.setMargin(marg);
+        bracesAroundCapitalsFields = new JTextField(30);
+        nonWrappableFields = new JTextField(30);
+        // We need a listener on showSource to enable and disable the source panel-related choices:
+        showSource.addChangeListener(new ChangeListener() {
+            public void stateChanged(ChangeEvent event) {
+                defSource.setEnabled(showSource.isSelected());
+                editSource.setEnabled(showSource.isSelected());
+            }
+        }
+        );
+        // We need a listener on useImportInspector to enable and disable the
+        // import inspector related choices;
+        useImportInspector.addChangeListener(new ChangeListener() {
+            public void stateChanged(ChangeEvent event) {
+                useImportInspectorForSingle.setEnabled(useImportInspector.isSelected());
+                inspectionWarnDupli.setEnabled(useImportInspector.isSelected());
+            }
+        }
+        );
+
+        FormLayout layout = new FormLayout
+                ("1dlu, 8dlu, left:pref, 4dlu, fill:60dlu, 4dlu, fill:pref", // 4dlu, left:pref, 4dlu",
+                        "");
+        DefaultFormBuilder builder = new DefaultFormBuilder(layout);
+        JPanel pan = new JPanel();
+        builder.appendSeparator(Globals.lang("File"));
+        builder.nextLine();
+        builder.append(pan);
+        builder.append(openLast);
+        builder.nextLine();
+        builder.append(pan);
+        builder.append(backup);
+        builder.nextLine();
+        builder.append(pan);
+        builder.append(saveInStandardOrder);
+        builder.nextLine();
+        builder.append(pan);
+        //builder.append(preserveFormatting);
+        //builder.nextLine();
+        //builder.append(pan);
+        builder.append(autoDoubleBraces);
+        builder.nextLine();
+        JLabel label = new JLabel(Globals.lang("Store the following fields with braces around capital letters")+":");
+        DefaultFormBuilder builder3 = new DefaultFormBuilder(new FormLayout("left:pref, 4dlu, fill:pref",""));
+        //panel.setLayout
+        builder3.append(label);
+        builder3.append(bracesAroundCapitalsFields);
+        //
+        //builder.append(panel);
+        //builder.nextLine();
+        label = new JLabel(Globals.lang("Do not wrap the following fields when saving")+":");
+        builder3.append(label);
+        builder3.append(nonWrappableFields);
+        builder.append(pan);
+        builder.append(builder3.getPanel());
+        //builder.append(panel);
+        builder.nextLine();
+
+        //builder.appendSeparator(Globals.lang("Miscellaneous"));
+        //builder.nextLine();
+        builder.appendSeparator(Globals.lang("Entry editor"));
+        builder.nextLine();
+        builder.append(pan);
+        builder.append(autoOpenForm);
+        builder.nextLine();
+        builder.append(pan);
+        builder.append(disableOnMultiple);
+        builder.nextLine();
+        builder.append(pan);
+        builder.append(showSource);
+        builder.nextLine();
+        builder.append(pan);
+        builder.append(defSource);
+        builder.nextLine();
+        builder.appendSeparator(Globals.lang("Miscellaneous"));
+        builder.append(pan);
+        builder.append(useImportInspector);
+        builder.nextLine();
+        builder.append(pan);
+        builder.append(useImportInspector);
+        builder.nextLine();
+        builder.append(pan);
+        builder.append(useImportInspectorForSingle);
+        builder.nextLine();
+        builder.append(pan);
+        builder.append(inspectionWarnDupli);
+        builder.nextLine();
+        builder.append(pan);
+        builder.append(ctrlClick);
+        builder.nextLine();
+        builder.append(pan);
+        builder.append(confirmDelete);
+        builder.nextLine();
+        builder.append(pan);
+        builder.append(keyDuplicateWarningDialog);
+        builder.nextLine();
+        builder.append(pan);
+        builder.append(keyEmptyWarningDialog);
+        builder.nextLine();
+        // Create a new panel with its own FormLayout for the last items:
+        FormLayout layout2 = new FormLayout
+                ("left:pref, 8dlu, fill:60dlu, 4dlu, left:pref, 4dlu, fill:60dlu, 4dlu, fill:pref", "");
+        DefaultFormBuilder builder2 = new DefaultFormBuilder(layout2);
+        builder2.append(useOwner);
+        builder2.append(defOwnerField);
+        JButton hlp = new JButton(ownerHelp);
+        hlp.setText(null);
+        hlp.setPreferredSize(new Dimension(24, 24));
+        builder2.append(hlp);
+        builder2.nextLine();
+        builder2.append(useTimeStamp);
+        builder2.append(timeStampFormat);
+        builder2.append(Globals.lang("Field name")+":");
+        builder2.append(timeStampField);
+        hlp = new JButton(timeStampHelp);
+        hlp.setText(null);
+        hlp.setPreferredSize(new Dimension(24, 24));
+        builder2.append(hlp);
+        builder2.nextLine();
+        JLabel lab;
+        lab = new JLabel(Globals.lang("Language") + ":");
+        builder2.append(lab);
+        builder2.append(language);
+        builder2.nextLine();
+        lab = new JLabel(Globals.lang("Default encoding") + ":");
+        builder2.append(lab);
+        builder2.append(encodings);
+        builder.append(pan);
+        builder.append(builder2.getPanel());
+        builder.nextLine();
+        //builder.appendSeparator();
+
+        pan = builder.getPanel();
+        pan.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
+        add(pan, BorderLayout.CENTER);
+
+    }
+
+    public void setValues() {
+        autoOpenForm.setSelected(_prefs.getBoolean("autoOpenForm"));
+        openLast.setSelected(_prefs.getBoolean("openLastEdited"));
+        allowEditing.setSelected(_prefs.getBoolean("allowTableEditing"));
+        backup.setSelected(_prefs.getBoolean("backup"));
+        defSource.setSelected(_prefs.getBoolean("defaultShowSource"));
+        showSource.setSelected(_prefs.getBoolean("showSource"));
+        editSource.setSelected(_prefs.getBoolean("enableSourceEditing"));
+        defSort.setSelected(_prefs.getBoolean("defaultAutoSort"));
+        ctrlClick.setSelected(_prefs.getBoolean("ctrlClick"));
+        disableOnMultiple.setSelected(_prefs.getBoolean("disableOnMultipleSelection"));
+        useOwner.setSelected(_prefs.getBoolean("useOwner"));
+        useTimeStamp.setSelected(_prefs.getBoolean("useTimeStamp"));
+        keyDuplicateWarningDialog.setSelected(_prefs.getBoolean("dialogWarningForDuplicateKey"));
+        keyEmptyWarningDialog.setSelected(_prefs.getBoolean("dialogWarningForEmptyKey"));
+        confirmDelete.setSelected(_prefs.getBoolean("confirmDelete"));
+        saveInStandardOrder.setSelected(_prefs.getBoolean("saveInStandardOrder"));
+        //preserveFormatting.setSelected(_prefs.getBoolean("preserveFieldFormatting"));
+        autoDoubleBraces.setSelected(_prefs.getBoolean("autoDoubleBraces"));
+        defOwnerField.setText(_prefs.get("defaultOwner"));
+        timeStampFormat.setText(_prefs.get("timeStampFormat"));
+        timeStampField.setText(_prefs.get("timeStampField"));
+        useImportInspector.setSelected(_prefs.getBoolean("useImportInspectionDialog"));
+        useImportInspectorForSingle.setSelected(_prefs.getBoolean("useImportInspectionDialogForSingle"));
+        inspectionWarnDupli.setSelected(_prefs.getBoolean("warnAboutDuplicatesInInspection"));
+        // Two choices only make sense when the source panel is visible:
+        defSource.setEnabled(showSource.isSelected());
+        editSource.setEnabled(showSource.isSelected());
+        useImportInspectorForSingle.setEnabled(useImportInspector.isSelected());
+        inspectionWarnDupli.setEnabled(useImportInspector.isSelected());
+        bracesAroundCapitalsFields.setText(_prefs.get("putBracesAroundCapitals"));
+        nonWrappableFields.setText(_prefs.get("nonWrappableFields"));
+
+        String enc = _prefs.get("defaultEncoding");
+        outer: for (int i = 0; i < Globals.ENCODINGS.length; i++) {
+            if (Globals.ENCODINGS[i].equalsIgnoreCase(enc)) {
+                encodings.setSelectedIndex(i);
+                break outer;
+            }
+        }
+        String oldLan = _prefs.get("language");
+
+        // Language choice
+        int ilk = 0;
+        for (Iterator i = GUIGlobals.LANGUAGES.keySet().iterator(); i.hasNext();) {
+            if (GUIGlobals.LANGUAGES.get(i.next()).equals(oldLan)) {
+                language.setSelectedIndex(ilk);
+            }
+            ilk++;
+        }
+
+    }
+
+    public void storeSettings() {
+        _prefs.putBoolean("autoOpenForm", autoOpenForm.isSelected());
+        _prefs.putBoolean("backup", backup.isSelected());
+        _prefs.putBoolean("openLastEdited", openLast.isSelected());
+        _prefs.putBoolean("defaultShowSource", defSource.isSelected());
+        _prefs.putBoolean("enableSourceEditing", editSource.isSelected());
+        _prefs.putBoolean("disableOnMultipleSelection", disableOnMultiple.isSelected());
+        _prefs.putBoolean("useOwner", useOwner.isSelected());
+        _prefs.putBoolean("useTimeStamp", useTimeStamp.isSelected());
+        _prefs.putBoolean("dialogWarningForDuplicateKey", keyDuplicateWarningDialog.isSelected());
+        _prefs.putBoolean("dialogWarningForEmptyKey", keyEmptyWarningDialog.isSelected());
+        _prefs.putBoolean("confirmDelete", confirmDelete.isSelected());
+        _prefs.putBoolean("saveInStandardOrder", saveInStandardOrder.isSelected());
+        _prefs.putBoolean("allowTableEditing", allowEditing.isSelected());
+        _prefs.putBoolean("ctrlClick", ctrlClick.isSelected());
+        //_prefs.putBoolean("preserveFieldFormatting", preserveFormatting.isSelected());
+        _prefs.putBoolean("autoDoubleBraces", autoDoubleBraces.isSelected());
+        _prefs.putBoolean("useImportInspectionDialog", useImportInspector.isSelected());
+        _prefs.putBoolean("useImportInspectionDialogForSingle", useImportInspectorForSingle.isSelected());
+        _prefs.putBoolean("warnAboutDuplicatesInInspection", inspectionWarnDupli.isSelected());
+        //_prefs.putBoolean("defaultAutoSort", defSorrrt.isSelected());
+        String owner = defOwnerField.getText().trim();
+        _prefs.put("defaultOwner", owner);
+        _prefs.WRAPPED_USERNAME = "["+owner+"]";
+        _prefs.put("timeStampFormat", timeStampFormat.getText().trim());
+        _prefs.put("timeStampField", timeStampField.getText().trim());
+        _prefs.put("defaultEncoding", (String) encodings.getSelectedItem());
+        boolean updateSpecialFields = false;
+        if (!bracesAroundCapitalsFields.getText().trim().equals(_prefs.get("putBracesAroundCapitals"))) {
+            _prefs.put("putBracesAroundCapitals", bracesAroundCapitalsFields.getText());
+            updateSpecialFields = true;
+        }
+        if (!nonWrappableFields.getText().trim().equals(_prefs.get("nonWrappableFields"))) {
+            _prefs.put("nonWrappableFields", nonWrappableFields.getText());
+            updateSpecialFields = true;
+        }
+        // If either of the two last entries were changed, run the update for special field handling:
+        if (updateSpecialFields)
+                _prefs.updateSpecialFieldHandling();
+
+        // We want to know if the following setting has been modified:
+        boolean oldShowSource = _prefs.getBoolean("showSource");
+        _prefs.putBoolean("showSource", showSource.isSelected());
+        if (oldShowSource != showSource.isSelected()) {
+            // The source panel has been enabled or disabled, so we need to
+            // remove all entry editors from cache:
+            for (int j=0; j<_frame.getTabbedPane().getTabCount(); j++) {
+	            BasePanel bp = (BasePanel)_frame.getTabbedPane().getComponentAt(j);
+	            bp.entryEditors.clear();
+            }
+        }
+
+
+        if (!GUIGlobals.LANGUAGES.get(language.getSelectedItem()).equals(_prefs.get("language"))) {
+            _prefs.put("language", GUIGlobals.LANGUAGES.get(language.getSelectedItem()).toString());
+            Globals.setLanguage(GUIGlobals.LANGUAGES.get(language.getSelectedItem()).toString(), "");
+            JOptionPane.showMessageDialog(null, Globals.lang("You have changed the language setting. "
+                    + "You must restart JabRef for this to come into effect."), Globals.lang("Changed language settings"),
+                    JOptionPane.WARNING_MESSAGE);
+        }
+
+
+
+    }
+
+    public boolean readyToClose() {
+        try {
+            // Test if date format is legal:
+            SimpleDateFormat sdf = new SimpleDateFormat(timeStampFormat.getText());
+
+        } catch (IllegalArgumentException ex2) {
+            JOptionPane.showMessageDialog
+                    (null, Globals.lang("The chosen date format for new entries is not valid"),
+                            Globals.lang("Invalid date format"),
+                            JOptionPane.ERROR_MESSAGE);
+            return false;
+        }
+        return true;
+    }
+
+}
diff --git a/src/java/net/sf/jabref/GlobalFocusListener.java b/src/java/net/sf/jabref/GlobalFocusListener.java
new file mode 100644
index 0000000..eb32a82
--- /dev/null
+++ b/src/java/net/sf/jabref/GlobalFocusListener.java
@@ -0,0 +1,27 @@
+package net.sf.jabref;
+
+import java.awt.event.FocusListener;
+import java.awt.event.FocusEvent;
+import java.awt.*;
+import javax.swing.*;
+
+public class GlobalFocusListener implements FocusListener {
+  Component focused = null;
+
+  public GlobalFocusListener() {
+  }
+  public void focusGained(FocusEvent e) {
+    if (!e.isTemporary())
+      focused = (Component)e.getSource();
+  }
+  public void focusLost(FocusEvent e) {
+  }
+
+  public JComponent getFocused() {
+    return (JComponent)focused;
+  }
+
+  public void setFocused(Component c) {
+    focused = c;
+  }
+}
diff --git a/src/java/net/sf/jabref/Globals.java b/src/java/net/sf/jabref/Globals.java
new file mode 100644
index 0000000..de7fa4e
--- /dev/null
+++ b/src/java/net/sf/jabref/Globals.java
@@ -0,0 +1,965 @@
+/* (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.util.* ;
+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" ;
+  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 String VERSION,
+                       BUILD,
+                       BUILD_DATE ;
+
+  static
+  {
+    TBuildInfo bi = new TBuildInfo(buildInfos) ;
+    VERSION = bi.getBUILD_VERSION() ;
+    BUILD = bi.getBUILD_NUMBER() ;
+    BUILD_DATE = bi.getBUILD_DATE() ;
+  }
+
+
+
+  //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 = 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");
+  }
+
+
+  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;
+      }
+    });
+  }
+
+  /**
+   * String constants.
+   */
+  public static final String
+      KEY_FIELD = "bibtexkey",
+      SEARCH = "__search",
+      GROUPSEARCH = "__groupsearch",
+      MARKED = "__markedentry",
+      OWNER = "owner",
+        // Using this when I have no database open when I read
+      // non bibtex file formats (used byte ImportFormatReader.java
+      DEFAULT_BIBTEXENTRY_ID = "__ID";
+
+  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;
+      //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 getNewFile(JFrame owner, JabRefPreferences prefs,
+                                  File directory, String extension,
+                                  int dialogType,
+                                  boolean updateWorkingDirectory) {
+    return getNewFile(owner, prefs, directory, extension, null, dialogType,
+                      updateWorkingDirectory, false);
+  }
+
+    
+  public static String getNewFile(JFrame owner, JabRefPreferences prefs,
+                                  File directory, String extension,
+                                  String description,
+                                  int dialogType,
+                                  boolean updateWorkingDirectory) {
+    return getNewFile(owner, prefs, directory, extension, description, dialogType,
+                      updateWorkingDirectory, false);
+  }
+
+    
+  public static String getNewFile(JFrame owner, JabRefPreferences prefs,
+                                  File directory, String extension, OpenFileFilter off,
+                                  int dialogType,
+                                  boolean updateWorkingDirectory) {
+    return getNewFile(owner, prefs, directory, extension, null, off, dialogType,
+                      updateWorkingDirectory, false);
+  }
+
+  public static String getNewDir(JFrame owner, JabRefPreferences prefs,
+                                 File directory, String extension,
+                                 int dialogType, boolean updateWorkingDirectory) {
+    return getNewFile(owner, prefs, directory, extension, null, dialogType,
+                      updateWorkingDirectory, true);
+  }
+
+  public static String getNewDir(JFrame owner, JabRefPreferences prefs,
+                                 File directory, String extension,
+                                 String description,
+                                 int dialogType, boolean updateWorkingDirectory) {
+    return getNewFile(owner, prefs, directory, extension, description, dialogType,
+                      updateWorkingDirectory, true);
+  }
+
+  private static String getNewFile(JFrame owner, JabRefPreferences prefs,
+                                   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 getNewFile(owner, prefs, directory, extension, description, off, dialogType, updateWorkingDirectory, dirOnly);
+  }
+
+  private static String getNewFile(JFrame owner, JabRefPreferences prefs,
+                                   File directory, String extension, 
+                                   String description,
+                                   OpenFileFilter off,
+                                   int dialogType,
+                                   boolean updateWorkingDirectory,
+                                   boolean dirOnly) {
+
+    if (ON_MAC) {
+      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.addChoosableFileFilter(off);
+    fc.setDialogType(dialogType);
+    int dialogResult = JFileChooser.CANCEL_OPTION ;
+    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());
+    }
+    return selectedFile.getAbsolutePath();
+  }
+
+  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.show();
+
+    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(),
+      UNICODE_CHARS = new HashMap(),
+      RTFCHARS = 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) {
+
+    }
+    /*
+    HTML_CHARS.put("\\{\\\\\\\"\\{a\\}\\}", "ä");
+    HTML_CHARS.put("\\{\\\\\\\"\\{A\\}\\}", "Ä");
+    HTML_CHARS.put("\\{\\\\\\\"\\{e\\}\\}", "ë");
+    HTML_CHARS.put("\\{\\\\\\\"\\{E\\}\\}", "Ë");
+    HTML_CHARS.put("\\{\\\\\\\"\\{i\\}\\}", "ï");
+    HTML_CHARS.put("\\{\\\\\\\"\\{I\\}\\}", "Ï");
+    HTML_CHARS.put("\\{\\\\\\\"\\{o\\}\\}", "ö");
+    HTML_CHARS.put("\\{\\\\\\\"\\{O\\}\\}", "Ö");
+    HTML_CHARS.put("\\{\\\\\\\"\\{u\\}\\}", "ü");
+    HTML_CHARS.put("\\{\\\\\\\"\\{U\\}\\}", "Ü");
+
+    HTML_CHARS.put("\\{\\\\\\`\\{e\\}\\}", "è");
+    HTML_CHARS.put("\\{\\\\\\`\\{E\\}\\}", "È");
+    HTML_CHARS.put("\\{\\\\\\`\\{i\\}\\}", "ì");
+    HTML_CHARS.put("\\{\\\\\\`\\{I\\}\\}", "Ì");
+    HTML_CHARS.put("\\{\\\\\\`\\{o\\}\\}", "ò");
+    HTML_CHARS.put("\\{\\\\\\`\\{O\\}\\}", "Ò");
+    HTML_CHARS.put("\\{\\\\\\`\\{u\\}\\}", "ù");
+    HTML_CHARS.put("\\{\\\\\\`\\{U\\}\\}", "Ù");
+
+    HTML_CHARS.put("\\{\\\\\\'\\{e\\}\\}", "é");
+    HTML_CHARS.put("\\{\\\\\\'\\{E\\}\\}", "É");
+    HTML_CHARS.put("\\{\\\\\\'\\{i\\}\\}", "í");
+    HTML_CHARS.put("\\{\\\\\\'\\{I\\}\\}", "Í");
+    HTML_CHARS.put("\\{\\\\\\'\\{o\\}\\}", "ó");
+    HTML_CHARS.put("\\{\\\\\\'\\{O\\}\\}", "Ó");
+    HTML_CHARS.put("\\{\\\\\\'\\{u\\}\\}", "ú");
+    HTML_CHARS.put("\\{\\\\\\'\\{U\\}\\}", "Ú");
+    HTML_CHARS.put("\\{\\\\\\'\\{a\\}\\}", "á");
+    HTML_CHARS.put("\\{\\\\\\'\\{A\\}\\}", "Á");
+    HTML_CHARS.put("\\{\\\\\\^\\{o\\}\\}", "ô");
+    HTML_CHARS.put("\\{\\\\\\^\\{O\\}\\}", "Ô");
+    HTML_CHARS.put("\\{\\\\\\^\\{u\\}\\}", "û");
+    HTML_CHARS.put("\\{\\\\\\^\\{U\\}\\}", "Û");
+    HTML_CHARS.put("\\{\\\\\\^\\{e\\}\\}", "ê");
+    HTML_CHARS.put("\\{\\\\\\^\\{E\\}\\}", "Ê");
+    HTML_CHARS.put("\\{\\\\\\^\\{i\\}\\}", "î");
+    HTML_CHARS.put("\\{\\\\\\^\\{I\\}\\}", "Î");
+    HTML_CHARS.put("\\{\\\\\\~\\{o\\}\\}", "õ");
+    HTML_CHARS.put("\\{\\\\\\~\\{O\\}\\}", "Õ");
+    HTML_CHARS.put("\\{\\\\\\~\\{n\\}\\}", "ñ");
+    HTML_CHARS.put("\\{\\\\\\~\\{N\\}\\}", "Ñ");
+    HTML_CHARS.put("\\{\\\\\\~\\{a\\}\\}", "ã");
+    HTML_CHARS.put("\\{\\\\\\~\\{A\\}\\}", "Ã");
+    */
+
+    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("^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", "Ç");
+    /*
+    HTML_CHARS.put("\\{\\\\\\\"a\\}", "ä");
+    HTML_CHARS.put("\\{\\\\\\\"A\\}", "Ä");
+    HTML_CHARS.put("\\{\\\\\\\"e\\}", "ë");
+    HTML_CHARS.put("\\{\\\\\\\"E\\}", "Ë");
+    HTML_CHARS.put("\\{\\\\\\\"i\\}", "ï");
+    HTML_CHARS.put("\\{\\\\\\\"I\\}", "Ï");
+    HTML_CHARS.put("\\{\\\\\\\"o\\}", "ö");
+    HTML_CHARS.put("\\{\\\\\\\"O\\}", "Ö");
+    HTML_CHARS.put("\\{\\\\\\\"u\\}", "ü");
+    HTML_CHARS.put("\\{\\\\\\\"U\\}", "Ü");
+
+    HTML_CHARS.put("\\{\\\\\\`e\\}", "è");
+    HTML_CHARS.put("\\{\\\\\\`E\\}", "È");
+    HTML_CHARS.put("\\{\\\\\\`i\\}", "ì");
+    HTML_CHARS.put("\\{\\\\\\`I\\}", "Ì");
+    HTML_CHARS.put("\\{\\\\\\`o\\}", "ò");
+    HTML_CHARS.put("\\{\\\\\\`O\\}", "Ò");
+    HTML_CHARS.put("\\{\\\\\\`u\\}", "ù");
+    HTML_CHARS.put("\\{\\\\\\`U\\}", "Ù");
+    HTML_CHARS.put("\\{\\\\\\'A\\}", "é");
+    HTML_CHARS.put("\\{\\\\\\'E\\}", "É");
+    HTML_CHARS.put("\\{\\\\\\'i\\}", "í");
+    HTML_CHARS.put("\\{\\\\\\'I\\}", "Í");
+    HTML_CHARS.put("\\{\\\\\\'o\\}", "ó");
+    HTML_CHARS.put("\\{\\\\\\'O\\}", "Ó");
+    HTML_CHARS.put("\\{\\\\\\'u\\}", "ú");
+    HTML_CHARS.put("\\{\\\\\\'U\\}", "Ú");
+    HTML_CHARS.put("\\{\\\\\\'a\\}", "á");
+    HTML_CHARS.put("\\{\\\\\\'A\\}", "Á");
+
+    HTML_CHARS.put("\\{\\\\\\^o\\}", "ô");
+    HTML_CHARS.put("\\{\\\\\\^O\\}", "Ô");
+    HTML_CHARS.put("\\{\\\\\\^u\\}", "û");
+    HTML_CHARS.put("\\{\\\\\\^U\\}", "Û");
+    HTML_CHARS.put("\\{\\\\\\^e\\}", "ê");
+    HTML_CHARS.put("\\{\\\\\\^E\\}", "Ê");
+    HTML_CHARS.put("\\{\\\\\\^i\\}", "î");
+    HTML_CHARS.put("\\{\\\\\\^I\\}", "Î");
+    HTML_CHARS.put("\\{\\\\\\~o\\}", "õ");
+    HTML_CHARS.put("\\{\\\\\\~O\\}", "Õ");
+    HTML_CHARS.put("\\{\\\\\\~n\\}", "ñ");
+    HTML_CHARS.put("\\{\\\\\\~N\\}", "Ñ");
+    HTML_CHARS.put("\\{\\\\\\~a\\}", "ã");
+    HTML_CHARS.put("\\{\\\\\\~A\\}", "Ã");
+
+    HTML_CHARS.put("\\{\\\\c c\\}", "ç");
+    HTML_CHARS.put("\\{\\\\c C\\}", "Ç");
+    */
+
+    XML_CHARS.put("\\{\\\\\\\"\\{a\\}\\}", "&#x00E4;");
+    XML_CHARS.put("\\{\\\\\\\"\\{A\\}\\}", "&#x00C4;");
+    XML_CHARS.put("\\{\\\\\\\"\\{e\\}\\}", "&#x00EB;");
+    XML_CHARS.put("\\{\\\\\\\"\\{E\\}\\}", "&#x00CB;");
+    XML_CHARS.put("\\{\\\\\\\"\\{i\\}\\}", "&#x00EF;");
+    XML_CHARS.put("\\{\\\\\\\"\\{I\\}\\}", "&#x00CF;");
+    XML_CHARS.put("\\{\\\\\\\"\\{o\\}\\}", "&#x00F6;");
+    XML_CHARS.put("\\{\\\\\\\"\\{O\\}\\}", "&#x00D6;");
+    XML_CHARS.put("\\{\\\\\\\"\\{u\\}\\}", "&#x00FC;");
+    XML_CHARS.put("\\{\\\\\\\"\\{U\\}\\}", "&#x00DC;");
+
+    XML_CHARS.put("\\{\\\\\\`\\{e\\}\\}", "&#x00E8;");
+    XML_CHARS.put("\\{\\\\\\`\\{E\\}\\}", "&#x00C8;");
+    XML_CHARS.put("\\{\\\\\\`\\{i\\}\\}", "&#x00EC;");
+    XML_CHARS.put("\\{\\\\\\`\\{I\\}\\}", "&#x00CC;");
+    XML_CHARS.put("\\{\\\\\\`\\{o\\}\\}", "&#x00F2;");
+    XML_CHARS.put("\\{\\\\\\`\\{O\\}\\}", "&#x00D2;");
+    XML_CHARS.put("\\{\\\\\\`\\{u\\}\\}", "&#x00F9;");
+    XML_CHARS.put("\\{\\\\\\`\\{U\\}\\}", "&#x00D9;");
+    XML_CHARS.put("\\{\\\\\\'\\{e\\}\\}", "&#x00E9;");
+    XML_CHARS.put("\\{\\\\\\\uFFFD\\{E\\}\\}", "&#x00C9;");
+    XML_CHARS.put("\\{\\\\\\\uFFFD\\{i\\}\\}", "&#x00ED;");
+    XML_CHARS.put("\\{\\\\\\\uFFFD\\{I\\}\\}", "&#x00CD;");
+    XML_CHARS.put("\\{\\\\\\\uFFFD\\{o\\}\\}", "&#x00F3;");
+    XML_CHARS.put("\\{\\\\\\\uFFFD\\{O\\}\\}", "&#x00D3;");
+    XML_CHARS.put("\\{\\\\\\\uFFFD\\{u\\}\\}", "&#x00FA;");
+    XML_CHARS.put("\\{\\\\\\\uFFFD\\{U\\}\\}", "&#x00DA;");
+    XML_CHARS.put("\\{\\\\\\\uFFFD\\{a\\}\\}", "&#x00E1;");
+    XML_CHARS.put("\\{\\\\\\\uFFFD\\{A\\}\\}", "&#x00C1;");
+
+    XML_CHARS.put("\\{\\\\\\^\\{o\\}\\}", "&#x00F4;");
+    XML_CHARS.put("\\{\\\\\\^\\{O\\}\\}", "&#x00D4;");
+    XML_CHARS.put("\\{\\\\\\^\\{u\\}\\}", "&#x00F9;");
+    XML_CHARS.put("\\{\\\\\\^\\{U\\}\\}", "&#x00D9;");
+    XML_CHARS.put("\\{\\\\\\^\\{e\\}\\}", "&#x00EA;");
+    XML_CHARS.put("\\{\\\\\\^\\{E\\}\\}", "&#x00CA;");
+    XML_CHARS.put("\\{\\\\\\^\\{i\\}\\}", "&#x00EE;");
+    XML_CHARS.put("\\{\\\\\\^\\{I\\}\\}", "&#x00CE;");
+    XML_CHARS.put("\\{\\\\\\~\\{o\\}\\}", "&#x00F5;");
+    XML_CHARS.put("\\{\\\\\\~\\{O\\}\\}", "&#x00D5;");
+    XML_CHARS.put("\\{\\\\\\~\\{n\\}\\}", "&#x00F1;");
+    XML_CHARS.put("\\{\\\\\\~\\{N\\}\\}", "&#x00D1;");
+    XML_CHARS.put("\\{\\\\\\~\\{a\\}\\}", "&#x00E3;");
+    XML_CHARS.put("\\{\\\\\\~\\{A\\}\\}", "&#x00C3;");
+
+
+    XML_CHARS.put("\\{\\\\\\\"a\\}", "&#x00E4;");
+    XML_CHARS.put("\\{\\\\\\\"A\\}", "&#x00C4;");
+    XML_CHARS.put("\\{\\\\\\\"e\\}", "&#x00EB;");
+    XML_CHARS.put("\\{\\\\\\\"E\\}", "&#x00CB;");
+    XML_CHARS.put("\\{\\\\\\\"i\\}", "&#x00EF;");
+    XML_CHARS.put("\\{\\\\\\\"I\\}", "&#x00CF;");
+    XML_CHARS.put("\\{\\\\\\\"o\\}", "&#x00F6;");
+    XML_CHARS.put("\\{\\\\\\\"O\\}", "&#x00D6;");
+    XML_CHARS.put("\\{\\\\\\\"u\\}", "&#x00FC;");
+    XML_CHARS.put("\\{\\\\\\\"U\\}", "&#x00DC;");
+
+    XML_CHARS.put("\\{\\\\\\`e\\}", "&#x00E8;");
+    XML_CHARS.put("\\{\\\\\\`E\\}", "&#x00C8;");
+    XML_CHARS.put("\\{\\\\\\`i\\}", "&#x00EC;");
+    XML_CHARS.put("\\{\\\\\\`I\\}", "&#x00CC;");
+    XML_CHARS.put("\\{\\\\\\`o\\}", "&#x00F2;");
+    XML_CHARS.put("\\{\\\\\\`O\\}", "&#x00D2;");
+    XML_CHARS.put("\\{\\\\\\`u\\}", "&#x00F9;");
+    XML_CHARS.put("\\{\\\\\\`U\\}", "&#x00D9;");
+    XML_CHARS.put("\\{\\\\\\'e\\}", "&#x00E9;");
+    XML_CHARS.put("\\{\\\\\\'E\\}", "&#x00C9;");
+    XML_CHARS.put("\\{\\\\\\'i\\}", "&#x00ED;");
+    XML_CHARS.put("\\{\\\\\\'I\\}", "&#x00CD;");
+    XML_CHARS.put("\\{\\\\\\'o\\}", "&#x00F3;");
+    XML_CHARS.put("\\{\\\\\\'O\\}", "&#x00D3;");
+    XML_CHARS.put("\\{\\\\\\'u\\}", "&#x00FA;");
+    XML_CHARS.put("\\{\\\\\\'U\\}", "&#x00DA;");
+    XML_CHARS.put("\\{\\\\\\'a\\}", "&#x00E1;");
+    XML_CHARS.put("\\{\\\\\\'A\\}", "&#x00C1;");
+
+    XML_CHARS.put("\\{\\\\\\^o\\}", "&#x00F4;");
+    XML_CHARS.put("\\{\\\\\\^O\\}", "&#x00D4;");
+    XML_CHARS.put("\\{\\\\\\^u\\}", "&#x00F9;");
+    XML_CHARS.put("\\{\\\\\\^U\\}", "&#x00D9;");
+    XML_CHARS.put("\\{\\\\\\^e\\}", "&#x00EA;");
+    XML_CHARS.put("\\{\\\\\\^E\\}", "&#x00CA;");
+    XML_CHARS.put("\\{\\\\\\^i\\}", "&#x00EE;");
+    XML_CHARS.put("\\{\\\\\\^I\\}", "&#x00CE;");
+    XML_CHARS.put("\\{\\\\\\~o\\}", "&#x00F5;");
+    XML_CHARS.put("\\{\\\\\\~O\\}", "&#x00D5;");
+    XML_CHARS.put("\\{\\\\\\~n\\}", "&#x00F1;");
+    XML_CHARS.put("\\{\\\\\\~N\\}", "&#x00D1;");
+    XML_CHARS.put("\\{\\\\\\~a\\}", "&#x00E3;");
+    XML_CHARS.put("\\{\\\\\\~A\\}", "&#x00C3;");
+
+    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", "\\'fc");
+    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");
+
+    //XML_CHARS.put("\\u00E1", "&#x00E1;");
+  }
+
+    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
new file mode 100644
index 0000000..4f26034
--- /dev/null
+++ b/src/java/net/sf/jabref/HelpAction.java
@@ -0,0 +1,144 @@
+/*
+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.
+
+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.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import javax.swing.event.HyperlinkListener;
+import javax.swing.event.HyperlinkEvent;
+import java.net.URL;
+
+/**
+ * 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(new ImageIcon(GUIGlobals.helpIconFile));
+	putValue(NAME, "Help");
+	this.diag = diag;
+	this.helpFile = helpFile;
+    }
+
+    public HelpAction(HelpDialog diag, String helpFile, String tooltip) {
+	super(new ImageIcon(GUIGlobals.helpIconFile));
+	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(new ImageIcon(GUIGlobals.helpIconFile));
+	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(new ImageIcon(GUIGlobals.helpIconFile));
+	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);
+    }
+
+}
diff --git a/src/java/net/sf/jabref/HelpContent.java b/src/java/net/sf/jabref/HelpContent.java
new file mode 100644
index 0000000..0bf4a62
--- /dev/null
+++ b/src/java/net/sf/jabref/HelpContent.java
@@ -0,0 +1,202 @@
+/*
+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.
+
+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.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.io.IOException;
+import java.util.Stack;
+import javax.swing.event.HyperlinkListener;
+import java.io.File;
+
+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));
+                }
+            }
+
+            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
new file mode 100644
index 0000000..a7f1a56
--- /dev/null
+++ b/src/java/net/sf/jabref/HelpDialog.java
@@ -0,0 +1,167 @@
+/*
+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.
+
+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.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import javax.swing.event.HyperlinkListener;
+import javax.swing.event.HyperlinkEvent;
+import java.net.URL;
+
+/**
+ * This is a non-modal help Dialog. The contents of the help is specified
+ * by calling
+ */
+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;
+		}
+	    });*/
+
+	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);
+	}
+	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);
+	}
+    }
+
+    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();
+	}
+    }
+
+    class BackAction extends AbstractAction {
+	public BackAction() {
+	    super("Back", new ImageIcon(GUIGlobals.backIconFile));
+	    //putValue(SHORT_DESCRIPTION, "Show the previous page");
+	}
+
+	public void actionPerformed(ActionEvent e) {
+	    setEnabled(content.back());
+	    forward.setEnabled(true);
+	}
+    }
+
+   class ForwardAction extends AbstractAction {
+       public ForwardAction() {
+	   super("Forward", new ImageIcon(GUIGlobals.forwardIconFile));
+       }
+
+       public void actionPerformed(ActionEvent e) {
+	    setEnabled(content.forward());
+	    back.setEnabled(true);
+       }
+   }
+
+   class ContentsAction extends AbstractAction {
+       public ContentsAction() {
+	   super("Contents", new ImageIcon(GUIGlobals.contentsIconFile));
+       }
+
+       public void actionPerformed(ActionEvent e) {
+	   content.setPage(GUIGlobals.helpContents);
+	   back.setEnabled(true);
+       }
+   }
+}
diff --git a/src/java/net/sf/jabref/IconStringRenderer.java b/src/java/net/sf/jabref/IconStringRenderer.java
new file mode 100644
index 0000000..03cbafb
--- /dev/null
+++ b/src/java/net/sf/jabref/IconStringRenderer.java
@@ -0,0 +1,42 @@
+/*
+ * Created on Jul 23, 2004
+ *
+ */
+package net.sf.jabref;
+
+import java.awt.Component;
+
+import javax.swing.ImageIcon;
+import javax.swing.JLabel;
+import javax.swing.JTable;
+import javax.swing.UIManager;
+import javax.swing.table.DefaultTableCellRenderer;
+
+/**
+ * @author sarahspi
+ *
+ */
+public class IconStringRenderer extends DefaultTableCellRenderer {
+
+    String toolTip;
+
+    public IconStringRenderer(String toolTip) {
+	this.toolTip = toolTip;
+    }
+
+	  /*
+	   * @see TableCellRenderer#getTableCellRendererComponent(JTable, Object, boolean, boolean, int, int)
+	   */
+	  public Component getTableCellRendererComponent(JTable table, Object value,
+	                                                 boolean isSelected, boolean hasFocus, 
+	                                                 int row, int column) {
+	  	JLabel retval = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus,row,column);	  	
+	  	if (value instanceof JLabel) {
+	  		retval.setText(((JLabel)value).getText());
+	  		retval.setIcon(((JLabel)value).getIcon());
+	  		retval.setToolTipText(toolTip);
+	  	}
+	    return retval;
+	  }
+	
+}
diff --git a/src/java/net/sf/jabref/IncrementalSearcher.java b/src/java/net/sf/jabref/IncrementalSearcher.java
new file mode 100644
index 0000000..f843d81
--- /dev/null
+++ b/src/java/net/sf/jabref/IncrementalSearcher.java
@@ -0,0 +1,83 @@
+package net.sf.jabref;
+
+import java.util.regex.Pattern;
+
+public class IncrementalSearcher {
+
+    JabRefPreferences prefs;
+    private String hitInField;
+
+    public IncrementalSearcher(JabRefPreferences prefs) {
+	this.prefs = prefs;
+    }
+
+    public String getField() {
+	return hitInField;
+    }
+
+    public boolean search(String pattern, BibtexEntry bibtexEntry) {
+	hitInField = null;
+	//if (!prefs.getBoolean("caseSensitiveSearch"))
+	//    flags = Pattern.CASE_INSENSITIVE;
+	//Pattern pattern = Pattern.compile(searchString, flags);
+	
+	if (prefs.getBoolean("searchAll")) {
+	    Object[] fields = bibtexEntry.getAllFields();
+	    return searchFields(fields, bibtexEntry, pattern);
+	} else {
+	    if (prefs.getBoolean("searchReq")) {
+		String[] requiredField = bibtexEntry.getRequiredFields() ;
+		if (searchFields(requiredField, bibtexEntry, pattern))
+		    return true;
+	    }
+	    if (prefs.getBoolean("searchOpt")) {
+		String[] optionalField = bibtexEntry.getOptionalFields() ;
+		if (searchFields(optionalField, bibtexEntry, pattern))
+		    return true;
+	    }
+	    if (prefs.getBoolean("searchGen")) {
+		String[] generalField = bibtexEntry.getGeneralFields() ;
+		if (searchFields(generalField, bibtexEntry, pattern))
+		    return true;
+	    }
+	}
+
+        return false;
+    }
+
+	protected boolean searchFields(Object[] fields, BibtexEntry bibtexEntry, 
+				       String searchString) {
+	    boolean found = false;
+	    if (fields != null) {
+		for(int i = 0 ; i < fields.length ; i++){
+		    try {
+			/*Globals.logger("Searching field '"+fields[i].toString()
+				       +"' for '"
+				       +pattern.toString()+"'.");*/
+			if (bibtexEntry.getField(fields[i].toString()) != null) {
+			    if (prefs.getBoolean("caseSensitiveSearch")) {
+				if (bibtexEntry.getField(fields[i].toString())
+				    .toString().indexOf(searchString) > -1)
+				    found = true;
+			    } else {
+				if (bibtexEntry.getField(fields[i].toString())
+				    .toString().toLowerCase()
+				    .indexOf(searchString.toLowerCase()) > -1)
+				    found = true;
+			    }
+			    
+			    if (found) {
+				hitInField = fields[i].toString();
+				return true;
+			    }
+			}
+		    }			
+		    catch(Throwable t ){
+			System.err.println("Searching error: "+t) ; 
+		    }
+		}  
+	    }
+	    return false;
+	}
+}
+
diff --git a/src/java/net/sf/jabref/JabRef.java b/src/java/net/sf/jabref/JabRef.java
new file mode 100644
index 0000000..0c758c7
--- /dev/null
+++ b/src/java/net/sf/jabref/JabRef.java
@@ -0,0 +1,784 @@
+/*
+ * 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.
+ *
+ * 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 com.jgoodies.plaf.FontSizeHints;
+import net.sf.jabref.export.*;
+import net.sf.jabref.imports.*;
+import net.sf.jabref.wizard.auximport.*;
+import net.sf.jabref.remote.RemoteListener;
+
+import gnu.dtools.ritopt.*;
+import java.awt.Font;
+import java.awt.Frame;
+
+import java.io.*;
+import java.io.File;
+
+import java.util.*;
+
+import javax.swing.*;
+
+import com.jgoodies.plaf.plastic.Plastic3DLookAndFeel;
+import com.jgoodies.plaf.windows.ExtWindowsLookAndFeel;
+
+
+
+
+//import javax.swing.UIManager;
+//import javax.swing.UIDefaults;
+//import javax.swing.UnsupportedLookAndFeelException;
+public class JabRef {
+    public static JabRef ths;
+    public static RemoteListener remoteListener = null;
+    public JabRefFrame jrf;
+    public Options options;
+    public Frame splashScreen = null;
+
+    boolean graphicFailure = false;
+
+    StringOption importFile, exportFile, exportPrefs, importPrefs, auxImExport, importToOpenBase;
+    BooleanOption helpO, disableGui, blank, loadSess;
+    /*
+    * class StringArrayOption extends ArrayOption { public public void
+    * modify(String value) { } public void modify(String[] value) { } public
+    * Object[] getObjectArray() { return null; } public String getTypeName() {
+    * return "Strings"; } public String getStringValue() { return ""; } public
+    * Object getObject() { return null; } }
+    */
+    public static void main(String[] args) {
+        new JabRef(args);
+    }
+
+    public JabRef(String[] args) {
+
+        /*
+        String aut = "{Bill and Bob Alver}, Jr., Morten Omholt and Alfredsen, Jo A. and Øie, G. and Yngvar von Olsen";
+        System.out.println("lastnameFirst: "+ImportFormatReader.fixAuthor_lastNameFirst(aut));
+        System.out.println("lastnameFirstCommas: "+ImportFormatReader.fixAuthor_lastNameFirstCommas(aut,false));
+        System.out.println("lastnameFirstCommas (abbr): "+ImportFormatReader.fixAuthor_lastNameFirstCommas(aut,true));
+        System.out.println("firstNameFirst: "+ImportFormatReader.fixAuthor_firstNameFirst(aut));
+        System.out.println("firstNameFirstCommas: "+ImportFormatReader.fixAuthor_firstNameFirstCommas(aut, false));
+        System.out.println("forAlphabetization: "+ImportFormatReader.fixAuthorForAlphabetization(aut));
+        */
+        ths = this;
+        JabRefPreferences prefs = JabRefPreferences.getInstance();
+        Globals.prefs = prefs;
+        Globals.setLanguage(prefs.get("language"), "");
+                
+        Globals.importFormatReader.resetImportFormats();
+        BibtexEntryType.loadCustomEntryTypes(prefs);
+        // Read list(s) of journal names and abbreviations:
+        //Globals.turnOnFileLogging();
+
+        Globals.initializeJournalNames();
+
+        if (Globals.prefs.getBoolean("useRemoteServer")) {
+            remoteListener = RemoteListener.openRemoteListener(this);
+            if (remoteListener != null) {
+                remoteListener.start();
+            }
+
+        // Unless we are alone, try to contact already running JabRef:
+	    if (remoteListener == null) {
+		    if (RemoteListener.sendToActiveJabRefInstance(args)) {
+                // We have successfully sent our command line options through the socket to
+                // another JabRef instance. So we assume it's all taken care of, and quit.
+                System.out.println(Globals.lang("Arguments passed on to running JabRef instance. Shutting down."));
+                System.exit(0);
+            }
+        }
+	}
+
+      /**
+       * See if the user has a personal journal list set up. If so, add these
+       * journal names and abbreviations to the list:
+       */
+      String personalJournalList = prefs.get("personalJournalList");
+      if (personalJournalList != null) {
+          try {
+              Globals.journalAbbrev.readJournalList(new File(personalJournalList));
+          } catch (FileNotFoundException e) {
+              e.printStackTrace();
+          }
+      }
+
+        
+        //System.setProperty("sun.awt.noerasebackground", "true");
+        
+        //System.out.println(java.awt.Toolkit.getDefaultToolkit().getDesktopProperty("awt.dynamicLayoutSupported"));
+        // Make sure of a proper cleanup when quitting (e.g. deleting temporary
+        // files).
+        System.runFinalizersOnExit(true);
+
+        Vector loaded = processArguments(args, true);
+        openWindow(loaded);
+        //System.out.println("1");
+    }
+
+    private void setupOptions() {
+
+        importFile = new StringOption("");
+        exportFile = new StringOption("");
+        helpO = new BooleanOption();
+        disableGui = new BooleanOption();
+        blank = new BooleanOption();
+        loadSess = new BooleanOption();
+        exportPrefs = new StringOption("jabref_prefs.xml");
+        importPrefs = new StringOption("jabref_prefs.xml");
+        auxImExport = new StringOption("");
+        importToOpenBase = new StringOption("");
+
+        options = new Options("JabRef "); // Create an options repository.
+        options.setVersion(GUIGlobals.version);
+
+        importFile.setDescription("imopoepuoeu"); //Globals.lang);
+        options.register("nogui", 'n',
+            Globals.lang("No GUI. Only process command line options."), disableGui);
+        options.register("import", 'i',
+            Globals.lang("Import file") + ": " + Globals.lang("filename")
+            + "[,import format]", importFile);
+        options.register("output", 'o',
+            Globals.lang("Output or export file") + ": " + Globals.lang("filename")
+            + "[,export format]", exportFile);
+        options.register("help", 'h',
+            Globals.lang("Display help on command line options"), helpO);
+        options.register("loads", 'l', Globals.lang("Load session"), loadSess);
+        options.register("prexp", 'x', Globals.lang("Export preferences to file"),
+            exportPrefs);
+        options.register("primp", 'p', Globals.lang("Import preferences from file"),
+            importPrefs);
+        options.register("aux", 'a',
+            Globals.lang("Subdatabase from aux") + ": " + Globals.lang("file")+"[.aux]" + ","+Globals.lang("new")+"[.bib]",
+            auxImExport);
+        options.register("blank", 'b', Globals.lang("Do not open any files at startup"), blank);
+
+        options.register("importToOpen", '\0', Globals.lang("Import to open tab"), importToOpenBase);
+
+        options.setUseMenu(false);
+    }
+
+    public Vector processArguments(String[] args, boolean initialStartup) {
+
+        setupOptions();
+        String[] leftOver = options.process(args);
+
+        //Util.pr(": Options processed");
+
+        if (initialStartup && helpO.isInvoked()) {
+            System.out.println("jabref [options] [bibtex-file]\n");
+            System.out.println(options.getHelp());
+
+            String importFormats = Globals.importFormatReader.getImportFormatList();
+            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, html, 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
+                + ".");
+            System.exit(0);
+        }
+
+        // First we quickly scan the command line parameters for any that signal
+        // that the GUI
+        // should not be opened. This is used to decide whether we should show the
+        // splash screen or not.
+        if (initialStartup && !disableGui.isInvoked()) {
+            try {
+
+                splashScreen = SplashScreen.splash();
+
+            } catch (Throwable ex) {
+                graphicFailure = true;
+                System.err.println(Globals.lang("Unable to create graphical interface")
+                    + ".");
+            }
+        }
+
+        //Util.pr("JabRef "+GUIGlobals.version);
+        // Vector to put imported/loaded database(s) in.
+        Vector loaded = new Vector();
+        Vector toImport = new Vector();
+        if (!blank.isInvoked() && (leftOver.length > 0))  {
+            for (int i = 0; i < leftOver.length; i++) {
+                // Leftover arguments are interpreted as bib files to open.
+
+                ParserResult pr = openBibFile(leftOver[i]);
+
+                if (pr != null) {
+                    if (pr == ParserResult.INVALID_FORMAT)
+                        // We will try to import this file instead:
+                        toImport.add(leftOver[i]);
+                    else
+                        loaded.add(pr);
+                } else {
+
+                }
+            }
+        }
+
+        //Util.pr(": Checked blank");
+
+        if (!blank.isInvoked() && importFile.isInvoked()) {
+            toImport.add(importFile.getStringValue());
+        }
+
+        if (toImport.size() > 0) for (int i=0; i<toImport.size(); i++) {
+            String[] data = ((String)toImport.elementAt(i)).split(",");
+
+            /*if (data.length == 1) {
+                // Load a bibtex file:
+                ParserResult pr = openBibFile(data[0]);
+
+                if (pr != null)
+                    loaded.add(pr);
+            } else if (data.length == 2) {*/
+                // Import a database in a certain format.
+                try {
+
+                    if ((data.length > 1) && !"*".equals(data[1])) {
+                        System.out.println(Globals.lang("Importing") + ": " + data[0]);
+                        List entries =
+                            Globals.importFormatReader.importFromFile(data[1],
+                                data[0].replaceAll("~", System.getProperty("user.home")));
+                        BibtexDatabase base = ImportFormatReader.createDatabase(entries);
+                        ParserResult pr = new ParserResult(base, null, new HashMap());
+                        loaded.add(pr);
+                        
+                    } else {
+                        // * means "guess the format":
+                        System.out.println(Globals.lang("Importing in unknown format")
+                            + ": " + data[0]);
+
+                        Object[] o =
+                            Globals.importFormatReader.importUnknownFormat(data[0]
+                                .replaceAll("~", System.getProperty("user.home")));
+                        String formatName = (String) o[0];
+
+                        if (formatName == null) {
+                            System.err.println(Globals.lang("Error opening file")+" '"+data[0]+"'");    
+                        }
+                        else if (formatName.equals(ImportFormatReader.BIBTEX_FORMAT)) {
+                            ParserResult pr = (ParserResult)o[1];
+                            loaded.add(pr);  
+
+                        }
+                        else {
+                            List entries = (java.util.List) o[1];
+                            if (entries != null)
+                                System.out.println(Globals.lang("Format used") + ": "
+                                    + formatName);
+                            else
+                                System.out.println(Globals.lang(
+                                        "Could not find a suitable import format."));
+
+                            if (entries != null) {
+                                BibtexDatabase base = ImportFormatReader.createDatabase(entries);
+                                ParserResult pr = new ParserResult(base, null, new HashMap());
+                        
+                                //pr.setFile(new File(data[0]));
+                                loaded.add(pr);
+                            }
+                        }
+                    }
+                } catch (IOException ex) {
+                    System.err.println(Globals.lang("Error opening file") + " '"
+                        + data[0] + "': " + ex.getMessage());
+                }
+
+
+        }
+
+
+        if (/*!initialStartup && */!blank.isInvoked() && importToOpenBase.isInvoked()) {
+            String[] data = importToOpenBase.getStringValue().split(",");
+
+            /*if (data.length == 1) {
+                // Load a bibtex file:
+                ParserResult pr = openBibFile(data[0]);
+
+                if (pr != null) {
+                    pr.setToOpenTab(true);
+                    loaded.add(pr);
+                }
+            } else if (data.length == 2) {*/
+                // Import a database in a certain format.
+                try {
+
+                    if ((data.length > 1) && !"*".equals(data[1])) {
+                        System.out.println(Globals.lang("Importing") + ": " + data[0]);
+                        List entries =
+                            Globals.importFormatReader.importFromFile(data[1],
+                                data[0].replaceAll("~", System.getProperty("user.home")));
+                        BibtexDatabase base = ImportFormatReader.createDatabase(entries);
+                        ParserResult pr = new ParserResult(base, null, new HashMap());
+                        pr.setToOpenTab(true);
+                        loaded.add(pr);
+
+                    } else {
+                        // * means "guess the format":
+                        System.out.println(Globals.lang("Importing in unknown format")
+                            + ": " + data[0]);
+
+                        Object[] o =
+                            Globals.importFormatReader.importUnknownFormat(data[0]
+                                .replaceAll("~", System.getProperty("user.home")));
+                        String formatName = (String) o[0];
+
+                        if (formatName.equals(ImportFormatReader.BIBTEX_FORMAT)) {
+                            ParserResult pr = (ParserResult)o[1];
+                            pr.setToOpenTab(true);
+                            loaded.add(pr);
+
+                        }
+                        else {
+                            List entries = (java.util.List) o[1];
+                            if (entries != null)
+                                System.out.println(Globals.lang("Format used") + ": "
+                                    + formatName);
+                            else
+                                System.out.println(Globals.lang(
+                                        "Could not find a suitable import format."));
+
+                            if (entries != null) {
+                                BibtexDatabase base = ImportFormatReader.createDatabase(entries);
+                                ParserResult pr = new ParserResult(base, null, new HashMap());
+
+                                //pr.setFile(new File(data[0]));
+                                pr.setToOpenTab(true);
+                                loaded.add(pr);
+                            }
+                        }
+                    }
+                } catch (IOException ex) {
+                    System.err.println(Globals.lang("Error opening file") + " '"
+                        + data[0] + "': " + ex.getMessage());
+                }
+
+
+        }
+        //Util.pr(": Finished import");
+
+        if (exportFile.isInvoked()) {
+            if (loaded.size() > 0) {
+                String[] data = exportFile.getStringValue().split(",");
+
+                if (data.length == 1) {
+                    // This signals that the latest import should be stored in BibTeX
+                    // format to the given file.
+                    if (loaded.size() > 0) {
+                        ParserResult pr =
+                            (ParserResult) loaded.elementAt(loaded.size() - 1);
+
+                        try {
+                            System.out.println(Globals.lang("Saving") + ": " + data[0]);
+                            SaveSession session = FileActions.saveDatabase(pr.getDatabase(),
+                                new MetaData(pr.getMetaData(),pr.getDatabase()), new File(data[0]), Globals.prefs,
+                                false, false, Globals.prefs.get("defaultEncoding"));
+                            // Show just a warning message if encoding didn't work for all characters:
+                            if (!session.getWriter().couldEncodeAll())
+                                System.err.println(Globals.lang("Warning")+": "+
+                                    Globals.lang("The chosen encoding '%0' could not encode the following characters: ",
+                                    session.getEncoding())+session.getWriter().getProblemCharacters());
+                            session.commit();
+                        } catch (SaveException ex) {
+                            System.err.println(Globals.lang("Could not save file") + " '"
+                                + data[0] + "': " + ex.getMessage());
+                        }
+                    } else
+                        System.err.println(Globals.lang(
+                                "The output option depends on a valid import option."));
+                } else if (data.length == 2) {
+                    // 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.
+                            //System.out.println(format[0]+" "+format[1]+" "+format[2]);
+                            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) {
+                        try {
+                            System.out.println(Globals.lang("Exporting") + ": " + data[0]);
+                            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]);
+                        } catch (Exception ex) {
+                            System.err.println(Globals.lang("Could not export file")
+                                + " '" + data[0] + "': " + ex.getMessage());
+                        }
+                    }
+                }
+            } else
+                System.err.println(Globals.lang(
+                        "The output option depends on a valid import option."));
+        }
+
+        //Util.pr(": Finished export");
+
+        if (exportPrefs.isInvoked()) {
+            try {
+                Globals.prefs.exportPreferences(exportPrefs.getStringValue());
+            } catch (IOException ex) {
+                Util.pr(ex.getMessage());
+            }
+        }
+
+
+	if (importPrefs.isInvoked()) {
+	    try {
+		Globals.prefs.importPreferences(importPrefs.getStringValue());
+		BibtexEntryType.loadCustomEntryTypes(Globals.prefs);
+	    }
+	    catch (IOException ex) {
+		Util.pr(ex.getMessage());
+	    }
+	}
+
+        if (!blank.isInvoked() && auxImExport.isInvoked()) {
+            boolean usageMsg = false;
+
+            if (loaded.size() > 0) // bibtex file loaded
+             {
+                String[] data = auxImExport.getStringValue().split(",");
+
+                if (data.length == 2) {
+                    ParserResult pr = (ParserResult) loaded.firstElement();
+                    AuxCommandLine acl = new AuxCommandLine(data[0], pr.getDatabase());
+                    BibtexDatabase newBase = acl.perform();
+
+                    boolean notSavedMsg = false;
+
+                    // write an output, if something could be resolved
+                    if (newBase != null) {
+                        if (newBase.getEntryCount() > 0) {
+                            String subName = Util.getCorrectFileName(data[1], "bib");
+
+                            try {
+                                System.out.println(Globals.lang("Saving") + ": "
+                                    + subName);
+                                SaveSession session = FileActions.saveDatabase(newBase, new MetaData(), // no Metadata
+                                    new File(subName), Globals.prefs, false, false,
+                                    Globals.prefs.get("defaultEncoding"));
+                                // Show just a warning message if encoding didn't work for all characters:
+                                if (!session.getWriter().couldEncodeAll())
+                                    System.err.println(Globals.lang("Warning")+": "+
+                                        Globals.lang("The chosen encoding '%0' could not encode the following characters: ",
+                                        session.getEncoding())+session.getWriter().getProblemCharacters());
+                                session.commit();
+                            } catch (SaveException ex) {
+                                System.err.println(Globals.lang("Could not save file")
+                                    + " '" + subName + "': " + ex.getMessage());
+                            }
+
+                            notSavedMsg = true;
+                        }
+                    }
+
+                    if (!notSavedMsg)
+                        System.out.println(Globals.lang("no database generated"));
+                } else
+                    usageMsg = true;
+            } else
+                usageMsg = true;
+
+            if (usageMsg) {
+                System.out.println(Globals.lang("no base-bibtex-file specified"));
+                System.out.println(Globals.lang("usage") + " :");
+                System.out.println(
+                    "jabref --aux infile[.aux],outfile[.bib] base-bibtex-file");
+            }
+        }
+
+        return loaded;
+    }
+
+    public void openWindow(Vector loaded) {
+        if (!graphicFailure && !disableGui.isInvoked()) {
+            // Call the method performCompatibilityUpdate(), which does any
+            // necessary changes for users with a preference set from an older
+            // Jabref version.
+            Util.performCompatibilityUpdate();
+
+           // This property is set to make the Mac OSX Java VM move the menu bar to
+            // the top
+            // of the screen, where Mac users expect it to be.
+            System.setProperty("apple.laf.useScreenMenuBar", "true");
+
+            // Set antialiasing on everywhere. This only works in JRE >= 1.5.
+            // Or... it doesn't work, period.
+            //System.setProperty("swing.aatext", "true");
+            // If we are not on Mac, deal with font sizes and LookAndFeels:
+            if (!Globals.ON_MAC) {
+                int fontSizes = Globals.prefs.getInt("menuFontSize");
+
+                String defaultLookAndFeel;
+
+                if (Globals.ON_WIN)
+                    defaultLookAndFeel = GUIGlobals.windowsDefaultLookAndFeel;
+                else
+                    defaultLookAndFeel = GUIGlobals.linuxDefaultLookAndFeel;
+
+                String lookAndFeel = null;
+
+                if (!Globals.prefs.getBoolean("useDefaultLookAndFeel"))
+                    lookAndFeel = Globals.prefs.get("lookAndFeel");
+                else
+                    lookAndFeel = defaultLookAndFeel;
+
+                LookAndFeel lnf = null;
+
+                //Class plastic =
+                // Class.forName("com.jgoodies.plaf.plastic.PlasticLookAndFeel");
+                //PlasticLookAndFeel lnf = new
+                // com.jgoodies.plaf.plastic.Plastic3DLookAndFeel();
+                Object objLnf = null;
+
+
+                try {
+                    //lnf2 =
+                    // Class.forName("com.jgoodies.plaf.plastic.Plastic3DLookAndFeel").newInstance();
+                    if (lookAndFeel != null)
+                        objLnf = Class.forName(lookAndFeel).newInstance();
+                    else
+                        objLnf = Class.forName(defaultLookAndFeel).newInstance();
+                } catch (Exception ex) {
+                    ex.printStackTrace();
+
+                    try {
+                        objLnf = Class.forName(defaultLookAndFeel).newInstance();
+                    } catch (Exception ex2) {
+                    }
+                }
+
+                if (objLnf != null)
+                    lnf = (LookAndFeel) objLnf;
+
+                // Set font sizes if we are using a JGoodies look and feel.
+                if ((lnf != null) && (lnf instanceof Plastic3DLookAndFeel)) {
+                    //MetalLookAndFeel.setCurrentTheme(new
+                    // com.jgoodies.plaf.plastic.theme.SkyBluer());
+                    Plastic3DLookAndFeel plLnf = (Plastic3DLookAndFeel) lnf;
+                    plLnf.setFontSizeHints(new FontSizeHints(fontSizes, fontSizes,
+                            fontSizes, fontSizes));
+                } else if ((lnf != null) && (lnf instanceof ExtWindowsLookAndFeel)) {
+                    //System.out.println("ttt");
+                    ExtWindowsLookAndFeel plLnf = (ExtWindowsLookAndFeel) lnf;
+                    plLnf.setFontSizeHints(new FontSizeHints(fontSizes, fontSizes,
+                            fontSizes, fontSizes));
+                }
+
+                if (lnf != null) {
+                    try {
+                        UIManager.setLookAndFeel(lnf);
+                        
+                        if (!Globals.ON_WIN) {
+                            UIManager.put("SimpleInternalFrame.activeTitleBackground", GUIGlobals.gradientBlue);
+                            //UIManager.put("TabbedPane.selected", Color.red);
+                        }
+                    } catch (Throwable ex) {
+                        ex.printStackTrace();
+                        System.err.println("Trying to set system default Look&Feel...");
+
+                        // if desired lnf could not be set, try system default
+                        try {
+                            UIManager.setLookAndFeel(UIManager
+                                .getSystemLookAndFeelClassName());
+                        } catch (Throwable e) {
+                            e.printStackTrace();
+                        }
+                    }
+
+                    //LookAndFeel lnf = new com.sun.java.swing.plaf.gtk.GTKLookAndFeel();
+                    //Look1AndFeel lnf = new
+                    // com.incors.plaf.kunststoff.KunststoffLookAndFeel();
+                    //com.incors.plaf.kunststoff.KunststoffLookAndFeel.setCurrentTheme(new
+                    // com.incors.plaf.kunststoff.themes.KunststoffDesktopTheme());
+                }
+            }
+
+
+            // If the option is enabled, open the last edited databases, if any.
+            if (!blank.isInvoked() && Globals.prefs.getBoolean("openLastEdited") && (Globals.prefs.get("lastEdited") != null)) {
+                // How to handle errors in the databases to open?
+                String[] names = Globals.prefs.getStringArray("lastEdited");
+lastEdLoop: 
+                for (int i = 0; i < names.length; i++) {
+                    File fileToOpen = new File(names[i]);
+
+                    for (int j = 0; j < loaded.size(); j++) {
+                        ParserResult pr = (ParserResult) loaded.elementAt(j);
+
+                        if ((pr.getFile() != null) &&pr.getFile().equals(fileToOpen))
+                            continue lastEdLoop;
+                    }
+
+                    if (fileToOpen.exists()) {
+                        ParserResult pr = openBibFile(names[i]);
+
+                        if (pr != null) {
+
+			    if (pr == ParserResult.INVALID_FORMAT) {
+				System.out.println(Globals.lang("Error opening file")+" '"+fileToOpen.getPath()+"'");
+			    }
+			    else
+				loaded.add(pr);
+
+			}
+                    }
+                }
+            }
+
+            GUIGlobals.init();
+            GUIGlobals.CURRENTFONT =
+                new Font(Globals.prefs.get("fontFamily"), Globals.prefs.getInt("fontStyle"),
+                    Globals.prefs.getInt("fontSize"));
+
+            //Util.pr(": Initializing frame");
+            jrf = new JabRefFrame();
+
+            // Add all loaded databases to the frame:
+	    boolean first = true;
+            if (loaded.size() > 0) {
+                for (Iterator i=loaded.iterator(); i.hasNext();) {
+                    ParserResult pr = (ParserResult)i.next();
+		    jrf.addTab(pr.getDatabase(), pr.getFile(), pr.getMetaData(), pr.getEncoding(), first);
+		    first = false;
+                }
+            }
+
+            if (loadSess.isInvoked())
+                jrf.loadSessionAction.actionPerformed(new java.awt.event.ActionEvent(
+                        jrf, 0, ""));
+
+            if (splashScreen != null) {// do this only if splashscreen was actually created
+                splashScreen.dispose();
+                splashScreen = null;
+            }
+
+            //Util.pr(": Showing frame");
+            jrf.setVisible(true);
+
+            for (int i = 0; i < loaded.size(); i++) {
+                ParserResult pr = (ParserResult) loaded.elementAt(i);
+                if (Globals.prefs.getBoolean("displayKeyWarningDialogAtStartup") && pr.hasWarnings()) {
+                    String[] wrns = pr.warnings();
+                    StringBuffer wrn = new StringBuffer();
+                    for (int j = 0; j<wrns.length; j++)
+                        wrn.append(j + 1).append(". ").append(wrns[j]).append("\n");
+                    if (wrn.length() > 0)
+                        wrn.deleteCharAt(wrn.length() - 1);
+                    jrf.showBaseAt(i);
+                    JOptionPane.showMessageDialog(jrf, wrn.toString(),
+                        Globals.lang("Warnings"),
+                        JOptionPane.WARNING_MESSAGE);
+                }
+            }
+
+            //Util.pr(": Finished adding panels");
+
+            if (loaded.size() > 0) {
+                jrf.tabbedPane.setSelectedIndex(0);
+                new FocusRequester(((BasePanel) jrf.tabbedPane.getComponentAt(0)).mainTable);
+            }
+        } else
+            System.exit(0);
+    }
+
+    public static ParserResult openBibFile(String name) {
+        System.out.println(Globals.lang("Opening") + ": " + name);
+
+        try {
+            File file = new File(name);
+            String encoding = Globals.prefs.get("defaultEncoding");
+            ParserResult pr = OpenDatabaseAction.loadDatabase(file, encoding);
+            if (pr == null)
+                return ParserResult.INVALID_FORMAT;
+            pr.setFile(file);
+            if (pr.hasWarnings()) {
+                String[] warn = pr.warnings();
+                for (int i=0; i<warn.length; i++)
+                    System.out.println(Globals.lang("Warning")+": "+warn[i]);
+
+            }
+            return pr;
+        } catch (Throwable ex) {
+            //System.err.println(Globals.lang("Error opening file")+" '"+ name+"':
+            // "+ex.getMessage());
+            System.err.println(Globals.lang("Error opening file") + ": "
+                + ex.getMessage());
+        }
+
+        return null;
+    }
+}
diff --git a/src/java/net/sf/jabref/JabRefFileChooser.java b/src/java/net/sf/jabref/JabRefFileChooser.java
new file mode 100644
index 0000000..04966d3
--- /dev/null
+++ b/src/java/net/sf/jabref/JabRefFileChooser.java
@@ -0,0 +1,97 @@
+/*
+Copyright (C) 2003  Morten O. Alver and 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;
+import java.io.*;
+import javax.swing.*;
+import javax.swing.plaf.*;
+import java.awt.event.*;
+import javax.swing.plaf.basic.*;
+import javax.swing.plaf.metal.*;
+
+//======================================================================
+// this class is a work around for the problem with regular filechooser:
+// single clicking will no longer put into edit mode
+//======================================================================
+public class JabRefFileChooser extends JFileChooser
+{
+    public JabRefFileChooser()
+    {
+        super();
+    }
+
+    public JabRefFileChooser(File file){
+        super(file);
+    }
+
+    //========================================================
+    //
+    //========================================================
+
+    protected void setUI(ComponentUI newUI) {
+      if (Globals.osName.equals(Globals.MAC))
+        super.setUI(newUI);
+      else
+        super.setUI(new JabRefUI(this));
+     }
+    //========================================================
+    //
+    //========================================================
+
+    public static void main(String[] args) {
+        JabRefFileChooser fc = new JabRefFileChooser();
+        int returnVal = fc.showOpenDialog(null);
+        if (returnVal == JFileChooser.APPROVE_OPTION) {
+            File file = fc.getSelectedFile();
+        }
+    }
+}
+
+class JabRefUI extends MetalFileChooserUI {
+    public JabRefUI(JFileChooser filechooser) {
+        super(filechooser);
+    }
+    protected class DoubleClickListener extends BasicFileChooserUI.DoubleClickListener {
+        JList list;
+        public DoubleClickListener(JList list) {
+            super(list);
+            this.list = list;
+        }
+        public void mouseEntered(MouseEvent e) {
+            //System.out.println("mouse entered");
+            MouseListener [] l = list.getMouseListeners();
+            for (int i = 0; i < l.length; i++) {
+                if (l[i] instanceof MetalFileChooserUI.SingleClickListener) {
+                    list.removeMouseListener(l[i]);
+                }
+            }
+            super.mouseEntered(e);
+        }
+    }
+    protected MouseListener createDoubleClickListener(JFileChooser fc, JList list) {
+        return new DoubleClickListener(list);
+    }
+}
diff --git a/src/java/net/sf/jabref/JabRefFrame.java b/src/java/net/sf/jabref/JabRefFrame.java
new file mode 100644
index 0000000..7fd6b82
--- /dev/null
+++ b/src/java/net/sf/jabref/JabRefFrame.java
@@ -0,0 +1,2663 @@
+/*
+ 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.
+
+ 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
+
+ */
+
+// 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.*;
+import net.sf.jabref.label.*;
+import net.sf.jabref.export.FileActions;
+import net.sf.jabref.export.ExpandEndnoteFilters;
+import net.sf.jabref.imports.*;
+import net.sf.jabref.wizard.auximport.gui.*;
+
+import javax.swing.*;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.SortedSet;
+import java.util.Vector;
+import java.util.List;
+import java.util.Iterator;
+import java.io.*;
+import java.net.URL;
+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 java.lang.reflect.*;
+import javax.swing.event.*;
+import net.sf.jabref.wizard.integrity.gui.*;
+import net.sf.jabref.groups.GroupSelector;
+import net.sf.jabref.journals.ManageJournalsAction;
+import com.jgoodies.uif_lite.component.UIFSplitPane;
+import com.jgoodies.plaf.HeaderStyle;
+import com.jgoodies.plaf.Options;
+
+/**
+ * The main window of the application.
+ */
+public class JabRefFrame
+    extends JFrame {
+
+  JabRefFrame ths = this;
+    UIFSplitPane contentPane = new UIFSplitPane();
+
+  JabRefPreferences prefs = Globals.prefs; //new JabRefPreferences();
+    PrefsDialog3 prefsDialog = null;
+  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);
+
+
+    class ToolBar extends JToolBar {
+      void addAction(Action a) {
+        JButton b = new JButton(a);
+        b.setText(null);
+        if (!Globals.ON_MAC)
+            b.setMargin(marg);
+        add(b);
+      }
+    }
+  ToolBar tlb = new ToolBar();
+
+  JMenuBar mb = new JMenuBar();/* {
+    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);
+
+    }
+
+  };*/
+  GridBagLayout gbl = new GridBagLayout();
+  GridBagConstraints con = new GridBagConstraints();
+
+  JLabel statusLine = new JLabel("", SwingConstants.LEFT),
+      statusLabel = new JLabel(Globals.lang("Status") + ":",
+                               SwingConstants.LEFT);
+  //SearchManager searchManager  = new SearchManager(ths, prefs);
+
+  private FileHistory fileHistory = new FileHistory(prefs, this);
+
+  LabelMaker labelMaker;
+
+  // 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.
+
+  // References to the toggle buttons in the toolbar:
+  public JToggleButton groupToggle, searchToggle, previewToggle, highlightAny,
+      highlightAll;
+
+  OpenDatabaseAction
+      open = new OpenDatabaseAction(this, true);
+  AbstractAction
+      close = new CloseDatabaseAction(),
+      quit = new CloseAction(),
+      selectKeys = new SelectKeysAction(),
+      newDatabaseAction = new NewDatabaseAction(),
+      newSubDatabaseAction = new NewSubDatabaseAction(),
+      integrityCheckAction = new IntegrityCheckAction(),
+      help = new HelpAction("JabRef help", helpDiag,
+                            GUIGlobals.baseFrameHelp, "JabRef help",
+                            prefs.getKey("Help")),
+      contents = new HelpAction("Help contents", helpDiag,
+                                GUIGlobals.helpContents, "Help contents",
+                                GUIGlobals.helpContentsIconFile),
+/* old about*/
+      about = new HelpAction("About JabRef", helpDiag,
+                             GUIGlobals.aboutPage, "About JabRef",
+                             GUIGlobals.aboutIcon),
+/**/
+  //    about2 = new NewAboutAction(),
+      editEntry = new GeneralAction("edit", "Edit entry",
+                               "Edit entry", GUIGlobals.editIconFile,
+                               prefs.getKey("Edit entry")),
+      save = new GeneralAction("save", "Save database",
+                               "Save database", GUIGlobals.saveIconFile,
+                               prefs.getKey("Save database")),
+      saveAs = new GeneralAction("saveAs", "Save database as ...",
+                                 "Save database as ...",
+                                 GUIGlobals.saveAsIconFile,
+                                 prefs.getKey("Save database as ...")),
+      saveSelectedAs = new GeneralAction("saveSelectedAs",
+                                         "Save selected as ...",
+                                         "Save selected as ...",
+                                         GUIGlobals.saveAsIconFile),
+      nextTab = new ChangeTabAction(true),
+      prevTab = new ChangeTabAction(false),
+      undo = new GeneralAction("undo", "Undo", "Undo",
+                               GUIGlobals.undoIconFile,
+                               prefs.getKey("Undo")),
+      redo = new GeneralAction("redo", "Redo", "Redo",
+                               GUIGlobals.redoIconFile,
+                               prefs.getKey("Redo")),
+      /*cut = new GeneralAction("cut", "Cut", "Cut",
+         GUIGlobals.cutIconFile,
+         prefs.getKey("Cut")),*/
+      delete = new GeneralAction("delete", "Delete", "Delete",
+                                 GUIGlobals.removeIconFile,
+                                 prefs.getKey("Delete")),
+      /*copy = new GeneralAction("copy", "Copy", "Copy",
+                               GUIGlobals.copyIconFile,
+                               prefs.getKey("Copy")),*/
+      copy = new EditAction("copy", GUIGlobals.copyIconFile),
+      paste = new EditAction("paste", GUIGlobals.pasteIconFile),
+      cut = new EditAction("cut", GUIGlobals.cutIconFile),
+      mark = new GeneralAction("markEntries", "Mark entries",
+                               "Mark entries",
+                               GUIGlobals.markIcon,
+                               prefs.getKey("Mark entries")),
+       unmark = new GeneralAction("unmarkEntries", "Unmark entries",
+                                  "Unmark entries",
+                                  GUIGlobals.unmarkIcon,
+                                  prefs.getKey("Unmark entries")),
+       unmarkAll = new GeneralAction("unmarkAll", "Unmark all"),
+      manageSelectors = new GeneralAction("manageSelectors", "Manage content selectors"),
+      saveSessionAction = new SaveSessionAction(),
+      loadSessionAction = new LoadSessionAction(),
+      incrementalSearch = new GeneralAction("incSearch", "Incremental search",
+                                            "Start incremental search",
+                                            GUIGlobals.searchIconFile,
+                                            prefs.getKey("Incremental search")),
+      normalSearch = new GeneralAction("search", "Search", "Search",
+                                       GUIGlobals.searchIconFile,
+                                       prefs.getKey("Search")),
+      toggleSearch = new GeneralAction("toggleSearch", "Search", "Toggle search panel",
+                                       GUIGlobals.searchIconFile),
+    //                                       prefs.getKey("Search")),
+      fetchCiteSeer = new FetchCiteSeerAction(),
+      importCiteSeer = new ImportCiteSeerAction(),
+      fetchMedline = new FetchMedlineAction(),
+      citeSeerPanelAction = new CiteSeerPanelAction(),
+      //fetchAuthorMedline = new FetchAuthorMedlineAction(),
+      copyKey = new GeneralAction("copyKey", "Copy BibTeX key"),
+      //"Put a BibTeX reference to the selected entries on the clipboard",
+      copyCiteKey = new GeneralAction("copyCiteKey", "Copy \\cite{BibTeX key}",
+                                      //"Put a BibTeX reference to the selected entries on the clipboard",
+                                      prefs.getKey("Copy \\cite{BibTeX key}")),
+      mergeDatabaseAction = new GeneralAction("mergeDatabase",
+                                              "Append database",
+                                              "Append contents from a BibTeX database into the currently viewed database",
+                                              GUIGlobals.openIconFile),
+      //prefs.getKey("Open")),
+      /*remove = new GeneralAction("remove", "Remove", "Remove selected entries",
+        GUIGlobals.removeIconFile),*/
+      selectAll = new GeneralAction("selectAll", "Select all",
+                                    prefs.getKey("Select all")),
+      replaceAll = new GeneralAction("replaceAll", "Replace string",
+                                     prefs.getKey("Replace string")),
+
+      editPreamble = new GeneralAction("editPreamble", "Edit preamble",
+                                       "Edit preamble",
+                                       GUIGlobals.preambleIconFile,
+                                       prefs.getKey("Edit preamble")),
+      editStrings = new GeneralAction("editStrings", "Edit strings",
+                                      "Edit strings",
+                                      GUIGlobals.stringsIconFile,
+                                      prefs.getKey("Edit strings")),
+      toggleGroups = new GeneralAction("toggleGroups",
+                                       "Toggle groups interface",
+                                       "Toggle groups interface",
+                                       GUIGlobals.groupsIconFile,
+                                       prefs.getKey("Toggle groups interface")),
+      togglePreview = new GeneralAction("togglePreview",
+                                        "Toggle entry preview",
+                                        "Toggle entry preview",
+                                        GUIGlobals.previewIconFile,
+                                        prefs.getKey("Toggle entry preview")),
+      toggleHighlightAny = new GeneralAction("toggleHighlightGroupsMatchingAny",
+                                        "Highlight groups matching any selected entry",
+                                        "Highlight groups matching any selected entry",
+                                        GUIGlobals.groupsHighlightMatchingAnyFile),
+      toggleHighlightAll = new GeneralAction("toggleHighlightGroupsMatchingAll",
+                                        "Highlight groups matching all selected entries",
+                                        "Highlight groups matching all selected entries",
+                                        GUIGlobals.groupsHighlightMatchingAllFile),
+      switchPreview = new GeneralAction("switchPreview",
+                                        "Switch preview layout",
+                                        prefs.getKey("Switch preview layout")),
+       makeKeyAction = new GeneralAction("makeKey", "Autogenerate BibTeX keys",
+                                        "Autogenerate BibTeX keys",
+                                        GUIGlobals.genKeyIconFile,
+                                        prefs.getKey("Autogenerate BibTeX keys")),
+      lyxPushAction = new GeneralAction("pushToLyX",
+                                        "Insert selected citations into LyX/Kile",
+                                        "Push selection to LyX/Kile",
+                                        GUIGlobals.lyxIconFile,
+                                        prefs.getKey("Push to LyX")),
+      winEdtPushAction = new GeneralAction("pushToWinEdt",
+                                        "Insert selected citations into WinEdt",
+                                        "Push selection to WinEdt",
+                                        GUIGlobals.winEdtIcon,
+                                        prefs.getKey("Push to WinEdt")),
+      openFile = new GeneralAction("openFile", "Open PDF or PS",
+                                   "Open PDF or PS",
+                                   GUIGlobals.pdfIcon,
+                                   prefs.getKey("Open PDF or PS")),
+      openUrl = new GeneralAction("openUrl", "Open URL or DOI",
+                                  "Open URL or DOI",
+                                  GUIGlobals.wwwIcon,
+                                  prefs.getKey("Open URL or DOI")),
+      dupliCheck = new GeneralAction("dupliCheck", "Find duplicates"),
+      strictDupliCheck = new GeneralAction("strictDupliCheck", "Find and remove exact duplicates"),
+      plainTextImport = new GeneralAction("plainTextImport",
+                                          "New entry from plain text",
+                                          prefs.getKey("New from plain text")),
+
+
+      customExpAction = new CustomizeExportsAction(),
+      customImpAction = new CustomizeImportsAction(),
+      exportCSV = new ExportCSV(),
+      exportToClipboard = new GeneralAction("exportToClipboard", "Export selected entries to clipboard"),
+      expandEndnoteZip = new ExpandEndnoteFilters(this),
+        autoSetPdf = new GeneralAction("autoSetPdf", Globals.lang("Synchronize %0 links", "PDF"), Globals.prefs.getKey("Synchronize PDF")),
+        autoSetPs = new GeneralAction("autoSetPs", Globals.lang("Synchronize %0 links", "PS"), Globals.prefs.getKey("Synchronize PS")),
+
+    abbreviateMedline = new GeneralAction("abbreviateMedline", "Abbreviate journal names (MEDLINE)",
+                "Abbreviate journal names of the selected entries (MEDLINE abbreviation)"),
+  abbreviateIso = new GeneralAction("abbreviateIso", "Abbreviate journal names (ISO)",
+                          "Abbreviate journal names of the selected entries (ISO abbreviation)",
+                          Globals.prefs.getKey("Abbreviate")),
+
+
+    unabbreviate = new GeneralAction("unabbreviate", "Unabbreviate journal names",
+                    "Unabbreviate journal names of the selected entries",
+            Globals.prefs.getKey("Unabbreviate")),
+    manageJournals = new ManageJournalsAction(this),
+    databaseProperties = new DatabasePropertiesAction(),
+    emacsPushAction = new GeneralAction("pushToEmacs", "Insert selected citations into Emacs",
+            "Push selection to Emacs", GUIGlobals.emacsIcon,
+            Globals.prefs.getKey("Push to Emacs"));
+    //test = new GeneralAction("test", "Test");
+
+  /*setupSelector = new GeneralAction("setupSelector", "", "",
+          GUIGlobals.pasteIconFile,
+          prefs.getKey(")),*/
+
+
+    MedlineFetcher medlineFetcher;
+    CiteSeerFetcher citeSeerFetcher;
+    CiteSeerFetcherPanel citeSeerFetcherPanel;
+    SearchManager2 searchManager;
+    public GroupSelector groupSelector;
+
+  // The menus for importing/appending other formats
+  JMenu importMenu = subMenu("Import and append"),
+      importNewMenu = subMenu("Import"),
+      exportMenu = subMenu("Export"),
+      customExportMenu = subMenu("Custom export"),
+      newDatabaseMenu = subMenu("New database" );
+
+
+  // The action for adding a new entry of unspecified type.
+  NewEntryAction newEntryAction = new NewEntryAction(prefs.getKey("New entry"));
+  NewEntryAction[] newSpecificEntryAction = new NewEntryAction[]
+  {
+      new NewEntryAction("article", prefs.getKey("New article")),
+      new NewEntryAction("book", prefs.getKey("New book")),
+      new NewEntryAction("phdthesis", prefs.getKey("New phdthesis")),
+      new NewEntryAction("inbook", prefs.getKey("New inbook")),
+      new NewEntryAction("mastersthesis", prefs.getKey("New mastersthesis")),
+      new NewEntryAction("proceedings", prefs.getKey("New proceedings")),
+      new NewEntryAction("inproceedings"),
+      new NewEntryAction("conference"),
+      new NewEntryAction("incollection"),
+      new NewEntryAction("booklet"),
+      new NewEntryAction("manual"),
+      new NewEntryAction("techreport"),
+      new NewEntryAction("unpublished",
+                         prefs.getKey("New unpublished")),
+      new NewEntryAction("misc")
+  };
+
+  public JabRefFrame() {
+    init();
+    setEmptyState();
+  }
+
+  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(new ImageIcon(GUIGlobals.jabreflogo).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);
+    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();
+  class AboutAction
+      extends AbstractAction {
+    public AboutAction() {
+      super(Globals.lang("About JabRef"));
+
+    }
+
+    public void actionPerformed(ActionEvent e) {
+      about();
+    }
+  }
+
+  // -------------------- !!!! NECESSARY ???? OBSOLETE ??? ----------------------
+  // General info dialog.  The OSXAdapter calls this method when "About OSXAdapter"
+  // is selected from the application menu.
+  public void about() {
+    JDialog about = new JDialog(ths, Globals.lang("About JabRef"),
+                                true);
+    JEditorPane jp = new JEditorPane();
+    JScrollPane sp = new JScrollPane
+        (jp, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
+         JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
+    jp.setEditable(false);
+    try {
+      jp.setPage(GUIGlobals.class.getResource("/help/About.html"));//GUIGlobals.aboutPage);
+      // We need a hyperlink listener to be able to switch to the license
+      // terms and back.
+      jp.addHyperlinkListener(new javax.swing.event.HyperlinkListener() {
+        public void hyperlinkUpdate(javax.swing.event.HyperlinkEvent e) {
+          if (e.getEventType()
+              == javax.swing.event.HyperlinkEvent.EventType.ACTIVATED) {
+            try {
+              ( (JEditorPane) e.getSource()).setPage(e.getURL());
+            }
+            catch (IOException ex) {}
+          }
+        }
+      });
+      about.getContentPane().add(sp);
+      about.setSize(GUIGlobals.aboutSize);
+      Util.placeDialog(about, ths);
+      about.setVisible(true);
+    }
+    catch (IOException ex) {
+      ex.printStackTrace();
+      JOptionPane.showMessageDialog(ths, "Could not load file 'About.html'",
+                                    "Error", JOptionPane.ERROR_MESSAGE);
+    }
+
+  }
+
+  // General preferences dialog.  The OSXAdapter calls this method when "Preferences..."
+  // is selected from the application menu.
+  public void preferences() {
+    //PrefsDialog.showPrefsDialog(ths, prefs);
+      AbstractWorker worker = new AbstractWorker() {
+              public void run() {
+                  output(Globals.lang("Opening preferences..."));
+                  if (prefsDialog == null) {
+                      prefsDialog = new PrefsDialog3(ths, prefs);
+                      Util.placeDialog(prefsDialog, ths);
+                  }
+                  else
+                      prefsDialog.setValues();
+
+              }
+              public void update() {
+                  prefsDialog.setVisible(true);
+                  output("");
+              }
+          };
+      worker.getWorker().run();
+      worker.getCallBack().update();
+  }
+
+public JabRefPreferences prefs() {
+  return prefs;
+}
+
+  // General info dialog.  The OSXAdapter calls this method when "Quit OSXAdapter"
+  // is selected from the application menu, Cmd-Q is pressed, or "Quit" is selected from the Dock.
+  public void quit() {
+    // Ask here if the user really wants to close, if the base
+    // has not been saved since last save.
+    boolean close = true;
+    Vector filenames = new Vector();
+    if (tabbedPane.getTabCount() > 0) {
+      loop: for (int i = 0; i < tabbedPane.getTabCount(); i++) {
+        if (baseAt(i).baseChanged) {
+          tabbedPane.setSelectedIndex(i);
+          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.
+              return;
+          }
+          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;
+              break;
+            }
+          }
+        }
+        if (baseAt(i).file != null) {
+          filenames.add(baseAt(i).file.getPath());
+        }
+      }
+    }
+    if (close) {
+      dispose();
+
+      prefs.putInt("posX", ths.getLocation().x);
+      prefs.putInt("posY", ths.getLocation().y);
+      prefs.putInt("sizeX", ths.getSize().width);
+      prefs.putInt("sizeY", ths.getSize().height);
+      prefs.putBoolean("searchPanelVisible", sidePaneManager.isPanelVisible("search"));
+
+      if (prefs.getBoolean("openLastEdited")) {
+        // Here we store the names of allcurrent filea. If
+        // there is no current file, we remove any
+        // previously stored file name.
+        if (filenames.size() == 0) {
+          prefs.remove("lastEdited");
+        }
+        else {
+          String[] names = new String[filenames.size()];
+          for (int i = 0; i < filenames.size(); i++) {
+            names[i] = (String) filenames.elementAt(i);
+
+          }
+          prefs.putStringArray("lastEdited", names);
+        }
+
+      }
+
+      fileHistory.storeHistory();
+      prefs.customExports.store();
+      prefs.customImports.store();
+      BibtexEntryType.saveCustomEntryTypes(prefs);
+
+      // Let the search interface store changes to prefs.
+      // But which one? Let's use the one that is visible.
+      if (basePanel() != null) {
+        ((SearchManager2)searchManager).updatePrefs();
+
+      }
+      System.exit(0); // End program.
+    }
+  }
+
+  private void macOSXRegistration() {
+    if (Globals.osName.equals(Globals.MAC)) {
+      try {
+        Class osxAdapter = Class.forName("osxadapter.OSXAdapter");
+
+        Class[] defArgs = {
+            JabRefFrame.class};
+        Method registerMethod = osxAdapter.getDeclaredMethod(
+            "registerMacOSXApplication", defArgs);
+        if (registerMethod != null) {
+          Object[] args = {
+              this};
+          registerMethod.invoke(osxAdapter, args);
+        }
+        // This is slightly gross.  to reflectively access methods with boolean args,
+        // use "boolean.class", then pass a Boolean object in as the arg, which apparently
+
+        defArgs[0] = boolean.class;
+        Method prefsEnableMethod = osxAdapter.getDeclaredMethod("enablePrefs",
+            defArgs);
+        if (prefsEnableMethod != null) {
+          Object args[] = {
+              Boolean.TRUE};
+          prefsEnableMethod.invoke(osxAdapter, args);
+        }
+      }
+      catch (NoClassDefFoundError e) {
+        // This will be thrown first if the OSXAdapter is loaded on a system without the EAWT
+        // because OSXAdapter extends ApplicationAdapter in its def
+        System.err.println("This version of Mac OS X does not support the Apple EAWT.  Application Menu handling has been disabled (" +
+                           e + ")");
+      }
+      catch (ClassNotFoundException e) {
+        // This shouldn't be reached; if there's a problem with the OSXAdapter we should get the
+        // above NoClassDefFoundError first.
+        System.err.println("This version of Mac OS X does not support the Apple EAWT.  Application Menu handling has been disabled (" +
+                           e + ")");
+      }
+      catch (Exception e) {
+        System.err.println("Exception while loading the OSXAdapter:");
+        e.printStackTrace();
+      }
+    }
+  }
+
+  private void setupLayout() {
+    fillMenu();
+    createToolBar();
+    getContentPane().setLayout(gbl);
+      contentPane.setDividerSize(2);
+      contentPane.setBorder(null);
+    //getContentPane().setBackground(GUIGlobals.lightGray);
+    con.fill = GridBagConstraints.HORIZONTAL;
+    con.anchor = GridBagConstraints.WEST;
+    con.weightx = 1;
+    con.weighty = 0;
+    con.gridwidth = GridBagConstraints.REMAINDER;
+    mb.setMinimumSize(mb.getPreferredSize());
+    //gbl.setConstraints(mb, con);
+    //getContentPane().add(mb);
+    setJMenuBar(mb);
+    con.anchor = GridBagConstraints.NORTH;
+    //con.gridwidth = 1;//GridBagConstraints.REMAINDER;;
+    gbl.setConstraints(tlb, con);
+    getContentPane().add(tlb);
+
+    Component lim = Box.createGlue();
+    gbl.setConstraints(lim, con);
+    //getContentPane().add(lim);
+    /*
+      JPanel empt = new JPanel();
+      empt.setBackground(GUIGlobals.lightGray);
+      gbl.setConstraints(empt, con);
+           getContentPane().add(empt);
+
+      con.insets = new Insets(1,0,1,1);
+      con.anchor = GridBagConstraints.EAST;
+      con.weightx = 0;
+      gbl.setConstraints(searchManager, con);
+      getContentPane().add(searchManager);*/
+    con.gridwidth = GridBagConstraints.REMAINDER;
+    con.weightx = 1;
+    con.weighty = 0;
+    con.fill = GridBagConstraints.BOTH;
+    con.anchor = GridBagConstraints.WEST;
+    con.insets = new Insets(0, 0, 0, 0);
+    lim = Box.createGlue();
+    gbl.setConstraints(lim, con);
+    getContentPane().add(lim);
+    //tabbedPane.setVisible(false);
+    //tabbedPane.setForeground(GUIGlobals.lightGray);
+    con.weighty = 1;
+    gbl.setConstraints(contentPane, con);
+    getContentPane().add(contentPane);
+    contentPane.setRightComponent(tabbedPane);
+    contentPane.setLeftComponent(sidePaneManager.getPanel());
+    sidePaneManager.updateView();
+
+    JPanel status = new JPanel();
+    status.setLayout(gbl);
+    con.weighty = 0;
+    con.weightx = 0;
+    con.gridwidth = 1;
+    con.insets = new Insets(0, 2, 0, 0);
+    gbl.setConstraints(statusLabel, con);
+    status.add(statusLabel);
+    con.weightx = 1;
+    con.insets = new Insets(0, 4, 0, 0);
+    con.gridwidth = GridBagConstraints.REMAINDER;
+    gbl.setConstraints(statusLine, con);
+    status.add(statusLine);
+    con.gridwidth = GridBagConstraints.REMAINDER;
+    statusLabel.setForeground(GUIGlobals.validFieldColor.darker());
+    con.insets = new Insets(0, 0, 0, 0);
+    gbl.setConstraints(status, con);
+    getContentPane().add(status);
+
+
+
+  }
+
+  private void initLabelMaker() {
+    // initialize the labelMaker
+    labelMaker = new LabelMaker();
+    labelMaker.addRule(new ArticleLabelRule(),
+                       BibtexEntryType.ARTICLE);
+    labelMaker.addRule(new BookLabelRule(),
+                       BibtexEntryType.BOOK);
+    labelMaker.addRule(new IncollectionLabelRule(),
+                       BibtexEntryType.INCOLLECTION);
+    labelMaker.addRule(new InproceedingsLabelRule(),
+                       BibtexEntryType.INPROCEEDINGS);
+  }
+
+  /**
+   * Returns the indexed BasePanel.
+   * @param i Index of base
+   */
+  BasePanel baseAt(int i) {
+    return (BasePanel) tabbedPane.getComponentAt(i);
+  }
+
+  public void showBaseAt(int i) {
+      tabbedPane.setSelectedIndex(i);
+  }
+
+  /**
+   * Returns the currently viewed BasePanel.
+   */
+  public BasePanel basePanel() {
+    return (BasePanel) tabbedPane.getSelectedComponent();
+  }
+
+  /**
+   * handle the color of active and inactive JTabbedPane tabs
+   */
+  private void markActiveBasePanel()
+  {
+    int now = tabbedPane.getSelectedIndex() ;
+    int len = tabbedPane.getTabCount() ;
+    if ((lastTabbedPanelSelectionIndex > -1) && (lastTabbedPanelSelectionIndex < len))
+      tabbedPane.setForegroundAt(lastTabbedPanelSelectionIndex, GUIGlobals.inActiveTabbed);
+    if ( (now > -1) &&  (now < len))
+      tabbedPane.setForegroundAt(now, GUIGlobals.activeTabbed);
+    lastTabbedPanelSelectionIndex = now ;
+  }
+
+  private int getTabIndex(JComponent comp) {
+    for (int i = 0; i < tabbedPane.getTabCount(); i++) {
+      if (tabbedPane.getComponentAt(i) == comp) {
+        return i;
+      }
+    }
+    return -1;
+  }
+
+  public JTabbedPane getTabbedPane() { return tabbedPane; }
+
+  public String getTabTitle(JComponent comp) {
+    return tabbedPane.getTitleAt(getTabIndex(comp));
+  }
+
+  public void setTabTitle(JComponent comp, String s) {
+    tabbedPane.setTitleAt(getTabIndex(comp), s);
+  }
+
+  class GeneralAction
+      extends MnemonicAwareAction {
+    private String command;
+    public GeneralAction(String command, String text,
+                         String description, URL icon) {
+      super(new ImageIcon(icon));
+      this.command = command;
+      putValue(NAME, text);
+      putValue(SHORT_DESCRIPTION, Globals.lang(description));
+    }
+
+    public GeneralAction(String command, String text,
+                         String description, URL icon,
+                         KeyStroke key) {
+      super(new ImageIcon(icon));
+      this.command = command;
+      putValue(NAME, text);
+      putValue(ACCELERATOR_KEY, key);
+      putValue(SHORT_DESCRIPTION, Globals.lang(description));
+    }
+
+    public GeneralAction(String command, String text) {
+      putValue(NAME, text);
+      this.command = command;
+    }
+
+    public GeneralAction(String command, String text, KeyStroke key) {
+      this.command = command;
+      putValue(NAME, text);
+      putValue(ACCELERATOR_KEY, key);
+    }
+
+    public GeneralAction(String command, String text, String description) {
+      this.command = command;
+      putValue(NAME, text);
+      putValue(SHORT_DESCRIPTION, Globals.lang(description));
+    }
+    public GeneralAction(String command, String text, String description, KeyStroke key) {
+      this.command = command;
+      putValue(NAME, text);
+      putValue(SHORT_DESCRIPTION, Globals.lang(description));
+        putValue(ACCELERATOR_KEY, key);
+    }
+
+    public void actionPerformed(ActionEvent e) {
+      if (tabbedPane.getTabCount() > 0) {
+        try {
+          ( (BasePanel) (tabbedPane.getSelectedComponent()))
+              .runCommand(command);
+        }
+        catch (Throwable ex) {
+          ex.printStackTrace();
+        }
+      }
+      else {
+        Util.pr("Action '" + command + "' must be disabled when no "
+                + "database is open.");
+      }
+    }
+  }
+
+  /** This got removed when we introduced SearchManager2.
+       class IncrementalSearchAction extends AbstractAction {
+    public IncrementalSearchAction() {
+   super("Incremental search", new ImageIcon(GUIGlobals.searchIconFile));
+   putValue(SHORT_DESCRIPTION, Globals.lang("Start incremental search"));
+   putValue(ACCELERATOR_KEY, prefs.getKey("Incremental search"));
+    }
+    public void actionPerformed(ActionEvent e) {
+   if (tabbedPane.getTabCount() > 0)
+     searchManager.startIncrementalSearch();
+    }
+       }
+
+       class SearchAction extends AbstractAction {
+    public SearchAction() {
+   super("Search", new ImageIcon(GUIGlobals.searchIconFile));
+   putValue(SHORT_DESCRIPTION, Globals.lang("Start search"));
+   putValue(ACCELERATOR_KEY, prefs.getKey("Search"));
+    }
+    public void actionPerformed(ActionEvent e) {
+   if (tabbedPane.getTabCount() > 0)
+     searchManager.startSearch();
+    }
+       }
+   */
+
+  class NewEntryAction
+      extends MnemonicAwareAction {
+
+    String type = null; // The type of item to create.
+    KeyStroke keyStroke = null; // Used for the specific instances.
+
+    public NewEntryAction(KeyStroke key) {
+      // This action leads to a dialog asking for entry type.
+      super(new ImageIcon(GUIGlobals.addIconFile));
+      putValue(NAME, "New entry");
+      putValue(ACCELERATOR_KEY, key);
+      putValue(SHORT_DESCRIPTION, Globals.lang("New BibTeX entry"));
+    }
+
+    public NewEntryAction(String type_) {
+      // This action leads to the creation of a specific entry.
+      putValue(NAME, Util.nCase(type_));
+      type = type_;
+    }
+
+    public NewEntryAction(String type_, KeyStroke key) {
+        // This action leads to the creation of a specific entry.
+        putValue(NAME, Util.nCase(type_));
+        putValue(ACCELERATOR_KEY, key);
+        type = type_;
+    }
+
+    public void actionPerformed(ActionEvent e) {
+      String thisType = type;
+      if (thisType == null) {
+        EntryTypeDialog etd = new EntryTypeDialog(ths);
+        Util.placeDialog(etd, ths);
+        etd.setVisible(true);
+        BibtexEntryType tp = etd.getChoice();
+        if (tp == null) {
+          return;
+        }
+        thisType = tp.getName();
+      }
+
+      if (tabbedPane.getTabCount() > 0) {
+        ( (BasePanel) (tabbedPane.getSelectedComponent()))
+            .newEntry(BibtexEntryType.getType(thisType));
+      }
+      else {
+        Util.pr("Action 'New entry' must be disabled when no "
+                + "database is open.");
+      }
+    }
+  }
+
+  /*
+       private void setupDatabaseLayout() {
+    // This method is called whenever this frame has been provided
+    // with a database, and completes the layout.
+
+
+    if (file != null)
+   setTitle(GUIGlobals.baseTitle+file.getName());
+    else
+    setTitle(GUIGlobals.untitledTitle);
+
+    //DragNDropManager dndm = new DragNDropManager(this);
+
+    //setNonEmptyState();
+    Util.pr("JabRefFrame: Must set non-empty state.");
+    }*/
+
+  /**
+   * Refresh import menus.
+   */
+  public void setUpImportMenus() {
+    setUpImportMenu(importMenu, false);
+    setUpImportMenu(importNewMenu, true);
+  }
+  
+  private void fillMenu() {
+    //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"),
+        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);
+      file.addSeparator();
+
+      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);
+    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(dupliCheck);
+    tools.add(strictDupliCheck);
+    tools.addSeparator();
+    tools.add(manageSelectors);
+    tools.add(makeKeyAction);
+    tools.add(emacsPushAction);
+    tools.add(lyxPushAction);
+    tools.add(winEdtPushAction);
+    tools.add(fetchMedline);
+    tools.add(citeSeerPanelAction);
+    tools.add(fetchCiteSeer);
+    //tools.add(fetchAuthorMedline);
+    tools.addSeparator();
+    tools.add(openFile);
+    tools.add(openUrl);
+    tools.addSeparator();
+    tools.add(newSubDatabaseAction);
+    tools.add(integrityCheckAction) ;
+
+      tools.addSeparator();
+      tools.add(autoSetPdf);
+      tools.add(autoSetPs);
+      tools.add(abbreviateIso);
+      tools.add(abbreviateMedline);
+      tools.add(unabbreviate);
+
+    mb.add(tools);
+
+    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);
+
+    helpMenu.add(help);
+    helpMenu.add(contents);
+    helpMenu.addSeparator();
+//old about    helpMenu.add(about);
+    helpMenu.add(about);
+    mb.add(helpMenu);
+  }
+
+    private JMenu subMenu(String name) {
+        name = Globals.menuTitle(name);
+        int i = name.indexOf('&');
+        JMenu res;
+        if (i >= 0) {
+            res = new JMenu(name.substring(0, i)+name.substring(i+1));
+            char mnemonic = Character.toUpperCase(name.charAt(i+1));
+            res.setMnemonic((int)mnemonic);
+        }
+        else res = new JMenu(name);
+
+        return res;
+    }
+
+  private void createToolBar() {
+    tlb.putClientProperty(Options.HEADER_STYLE_KEY, HeaderStyle.BOTH);
+    tlb.setBorder(null);
+    tlb.setRollover(true);
+
+    //tlb.setBorderPainted(true);
+    //tlb.setBackground(GUIGlobals.lightGray);
+    //tlb.setForeground(GUIGlobals.lightGray);
+    tlb.setFloatable(false);
+    tlb.addAction(newDatabaseAction);
+    tlb.addAction(open);
+    tlb.addAction(save);
+
+    tlb.addSeparator();
+    tlb.addAction(cut);
+    tlb.addAction(copy);
+    tlb.addAction(paste);
+    tlb.addAction(undo);
+    tlb.addAction(redo);
+
+    tlb.addSeparator();
+    tlb.addAction(newEntryAction);
+    tlb.addAction(editEntry);
+    tlb.addAction(editPreamble);
+    tlb.addAction(editStrings);
+    tlb.addAction(makeKeyAction);
+
+
+    tlb.addSeparator();
+    tlb.addAction(mark);
+    tlb.addAction(unmark);
+
+    tlb.addSeparator();
+    searchToggle = new JToggleButton(toggleSearch);
+    searchToggle.setText(null);
+    if (!Globals.ON_MAC)
+        searchToggle.setMargin(marg);
+    tlb.add(searchToggle);
+
+    previewToggle = new JToggleButton(togglePreview);
+    previewToggle.setText(null);
+    if (!Globals.ON_MAC)
+        previewToggle.setMargin(marg);
+    tlb.add(previewToggle);
+    tlb.addSeparator();
+
+    groupToggle = new JToggleButton(toggleGroups);
+    groupToggle.setText(null);
+    if (!Globals.ON_MAC)
+        groupToggle.setMargin(marg);
+    tlb.add(groupToggle);
+
+
+    highlightAny = new JToggleButton(toggleHighlightAny);
+    highlightAny.setText(null);
+    if (!Globals.ON_MAC)
+        highlightAny.setMargin(marg);
+    tlb.add(highlightAny);
+    highlightAll = new JToggleButton(toggleHighlightAll);
+    highlightAll.setText(null);
+    if (!Globals.ON_MAC)
+        highlightAll.setMargin(marg);
+    tlb.add(highlightAll);
+
+    tlb.addSeparator();
+    tlb.addAction(emacsPushAction);
+    tlb.addAction(lyxPushAction);
+    tlb.addAction(winEdtPushAction);
+    tlb.addAction(openFile);
+    tlb.addAction(openUrl);
+
+    //tlb.addSeparator();
+    //tlb.addAction(showPrefs);
+    tlb.add(Box.createHorizontalGlue());
+    //tlb.add(new JabRefLabel(GUIGlobals.frameTitle+" "+GUIGlobals.version));
+
+    tlb.addAction(closeDatabaseAction);
+    //Insets margin = new Insets(0, 0, 0, 0);
+    //for (int i=0; i<tlb.getComponentCount(); i++)
+    //  ((JButton)tlb.getComponentAtIndex(i)).setMargin(margin);
+
+  }
+
+  private class JabRefLabel
+      extends JPanel {
+    private String label;
+    public JabRefLabel(String name) {
+      label = name;
+    }
+
+    public void paint(Graphics g) {
+      Graphics2D g2 = (Graphics2D) g;
+      g2.setColor(GUIGlobals.nullFieldColor);
+      g2.setFont(GUIGlobals.jabRefFont);
+      FontMetrics fm = g2.getFontMetrics();
+      int width = fm.stringWidth(label);
+      g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
+                          RenderingHints.VALUE_ANTIALIAS_ON);
+      g2.drawString(label, getWidth() - width - 7, getHeight() - 10);
+
+     
+    }
+  }
+
+  private JMenuItem mItem(AbstractAction a, KeyStroke ks) {
+    // Set up a menu item with action and accelerator key.
+    JMenuItem mi = new JMenuItem();
+    mi.setAction(a);
+    if (ks != null) {
+      mi.setAccelerator(ks);
+    }
+    return mi;
+  }
+
+  //private void setupMainPanel() {
+
+
+  /*public Completer getAutoCompleter(String field) {
+    return (Completer)autoCompleters.get(field);
+    }
+
+
+       public void assignAutoCompleters() {
+    // Set up which fields should have autocompletion. This should
+    // probably be made customizable. Existing Completer objects are
+    // forgotten. The completers must be updated towards the database.
+    byte[] fields = prefs.getByteArray("autoCompFields");
+    autoCompleters = new Hashtable();
+    for (int i=0; i<fields.length; i++) {
+   autoCompleters.put(GUIGlobals.ALL_FIELDS[fields[i]], new Completer());
+    }
+
+       }
+
+       public void updateAutoCompleters() {
+    if (database != null)
+   database.setCompleters(autoCompleters);
+   }*/
+
+ public void output(final String s) {
+
+      SwingUtilities.invokeLater(new Runnable() {
+          public void run() {
+              statusLine.setText(s);
+              statusLine.repaint();
+          }
+      });
+  }
+
+  public void stopShowingSearchResults() {
+    for (int i = 0; i < tabbedPane.getTabCount(); i++) {
+      baseAt(i).stopShowingSearchResults();
+    }
+  }
+
+    /**
+     * 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);
+    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);
+    }
+
+    /**
+     * Disable actions that need more than one database open.
+     */
+    private void setMultiple() {
+        nextTab.setEnabled(true);
+        prevTab.setEnabled(true);
+    }
+
+  /**
+   * This method causes all open BasePanels to set up their tables
+   * anew. When called from PrefsDialog2, this updates to the new
+   * settings.
+   */
+  public void setupAllTables() {
+    // This action can be invoked without an open database, so
+    // we have to check if we have one before trying to invoke
+    // methods to execute changes in the preferences.
+
+    // We want to notify all tabs about the changes to
+    // avoid problems when changing the column set.
+    for (int i = 0; i < tabbedPane.getTabCount(); i++) {
+      BasePanel bf = baseAt(i);
+
+      // Update tables:
+      if (bf.database != null) {
+        bf.setupMainPanel();
+
+      }
+
+    }
+  }
+
+  public BasePanel addTab(BibtexDatabase db, File file, HashMap meta, String encoding, boolean raisePanel) {
+      BasePanel bp = new BasePanel(ths, db, file, meta, encoding);
+      addTab(bp, file, raisePanel);
+      return bp;
+  }
+
+    public void addTab(BasePanel bp, File file, boolean raisePanel) {
+        tabbedPane.add((file != null ? file.getName(): Globals.lang(GUIGlobals.untitledTitle)),
+                       bp);
+        if (raisePanel) {
+            tabbedPane.setSelectedComponent(bp);
+        }
+        if (tabbedPane.getTabCount() == 1) {
+            setNonEmptyState();
+        } else if (tabbedPane.getTabCount() == 2) {
+            setMultiple();
+        }
+    }
+
+  class SelectKeysAction
+      extends AbstractAction {
+    public SelectKeysAction() {
+      super(Globals.lang("Customize key bindings"));
+    }
+
+    public void actionPerformed(ActionEvent e) {
+      KeyBindingsDialog d = new KeyBindingsDialog
+          ( (HashMap) prefs.getKeyBindings().clone(),
+           prefs.getDefaultKeys());
+      d.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+      d.pack(); //setSize(300,500);
+      Util.placeDialog(d, ths);
+      d.setVisible(true);
+      if (d.getAction()) {
+        prefs.setNewKeyBindings(d.getNewKeyBindings());
+        JOptionPane.showMessageDialog
+            (ths,
+             Globals.lang("Your new key bindings have been stored.") + "\n"
+             + Globals.lang("You must restart JabRef for the new key "
+                            + "bindings to work properly."),
+             Globals.lang("Key bindings changed"),
+             JOptionPane.INFORMATION_MESSAGE);
+      }
+    }
+  }
+
+  /**
+   * The action concerned with closing the window.
+   */
+  class CloseAction
+      extends MnemonicAwareAction {
+    public CloseAction() {
+      putValue(NAME, "Quit");
+      putValue(SHORT_DESCRIPTION, Globals.lang("Quit JabRef"));
+      putValue(ACCELERATOR_KEY, prefs.getKey("Quit JabRef"));
+      //putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_Q,
+      //    Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
+
+    }
+
+    public void actionPerformed(ActionEvent e) {
+      quit();
+    }
+  }
+
+  // The action for closing the current database and leaving the window open.
+  CloseDatabaseAction closeDatabaseAction = new CloseDatabaseAction();
+  class CloseDatabaseAction
+      extends MnemonicAwareAction {
+    public CloseDatabaseAction() {
+        super(new ImageIcon(GUIGlobals.closeIconFile));
+        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
+      }
+    }
+  }
+
+
+  // The action concerned with opening a new database.
+  class NewDatabaseAction
+      extends MnemonicAwareAction {
+    public NewDatabaseAction() {
+        super(new ImageIcon(GUIGlobals.newIconFile));
+        putValue(NAME, "New database");
+        putValue(SHORT_DESCRIPTION, Globals.lang("New BibTeX database"));
+        //putValue(MNEMONIC_KEY, GUIGlobals.newKeyCode);
+    }
+
+    public void actionPerformed(ActionEvent e) {
+        // Create a new, empty, database.
+        BibtexDatabase database = new BibtexDatabase();
+        addTab(database, null, new HashMap(), Globals.prefs.get("defaultEncoding"), true);
+        output(Globals.lang("New database created."));
+    }
+  }
+
+class ImportCiteSeerAction
+        extends MnemonicAwareAction {
+
+    public ImportCiteSeerAction() {
+        super(new ImageIcon(GUIGlobals.wwwCiteSeerIcon));
+        putValue(NAME, "Import Fields from CiteSeer");
+        putValue(SHORT_DESCRIPTION, Globals.lang("Import Fields from CiteSeer Database"));
+        putValue(ACCELERATOR_KEY, prefs.getKey("Import Fields from CiteSeer")); // Key defined in MenuTitles!
+        }
+
+        public void actionPerformed(ActionEvent e) {
+
+                if(citeSeerFetcher.activateImportFetcher()) {
+
+
+                        (new Thread() {
+
+                                BasePanel currentBp;
+                                BibtexEntry toShow;
+                                //String id;
+                                int[] clickedOn = null;
+
+                                class UpdateComponent implements Runnable {
+                                        boolean changesMade;
+
+                                        UpdateComponent(boolean changesMade) {
+                                                this.changesMade = changesMade;
+                                        }
+
+                                        public void run() {
+                                            citeSeerFetcher.endImportCiteSeerProgress();
+                                            if (changesMade)
+                                                    currentBp.markBaseChanged();
+                                                //for(int i=0; i < clickedOn.length; i++)
+                                                //        currentBp.entryTable.addRowSelectionInterval(i,i);
+                                                //currentBp.showEntry(toShow);
+                                                output(Globals.lang("Completed Import Fields from CiteSeer."));
+                                        }
+                                }
+
+                            public void run() {
+                                currentBp = (BasePanel) tabbedPane.getSelectedComponent();
+                                        // We demand that at least one row is selected.
+
+                                        int rowCount = currentBp.mainTable.getSelectedRowCount();
+                                        if (rowCount >= 1) {
+                                                clickedOn = currentBp.mainTable.getSelectedRows();
+                                        } else {
+                                                JOptionPane.showMessageDialog(currentBp.frame(),
+                                                Globals.lang("You must select at least one row to perform this operation."),
+                                                Globals.lang("CiteSeer Import Error"),
+                                                JOptionPane.WARNING_MESSAGE);
+                                        }
+                                        toShow = (BibtexEntry)currentBp.mainTable.getSelected().get(0);
+                                        if (clickedOn != null) {
+                                                citeSeerFetcher.beginImportCiteSeerProgress();
+                                                NamedCompound citeseerNamedCompound =
+                                                        new NamedCompound(Globals.lang("CiteSeer Import Fields"));
+                                                boolean newValues = citeSeerFetcher.importCiteSeerEntries(clickedOn, citeseerNamedCompound);
+                                                if (newValues) {
+                                                        citeseerNamedCompound.end();
+                                                        currentBp.undoManager.addEdit(citeseerNamedCompound);
+                                                }
+                                                UpdateComponent updateComponent = new UpdateComponent(newValues);
+                                                SwingUtilities.invokeLater(updateComponent);
+                                        }
+                                        citeSeerFetcher.deactivateImportFetcher();
+                            }
+                        }).start();
+                } else {
+                        JOptionPane.showMessageDialog(tabbedPane.getSelectedComponent(),
+                                        Globals.lang("A CiteSeer import operation is currently in progress.") + "  " +
+                                        Globals.lang("Please wait until it has finished."),
+                                        Globals.lang("CiteSeer Import Error"),
+                                        JOptionPane.WARNING_MESSAGE);
+                }
+        }
+}
+
+class FetchCiteSeerAction
+        extends MnemonicAwareAction {
+
+                public FetchCiteSeerAction() {
+                    super(new ImageIcon(GUIGlobals.wwwCiteSeerIcon));
+                    putValue(NAME, "Fetch citations from CiteSeer");
+
+                    putValue(SHORT_DESCRIPTION, Globals.lang("Fetch Articles Citing your Database"));
+                    putValue(ACCELERATOR_KEY, prefs.getKey("Fetch citations from CiteSeer"));
+                }
+
+                public void actionPerformed(ActionEvent e) {
+
+                        if(citeSeerFetcher.activateCitationFetcher()) {
+                                sidePaneManager.ensureVisible("CiteSeerProgress");
+                                (new Thread() {
+                                        BasePanel newBp;
+                                        BasePanel targetBp;
+                                        BibtexDatabase newDatabase;
+                                        BibtexDatabase targetDatabase;
+
+                                        Runnable updateComponent = new Runnable() {
+
+                                                /* TODO: This should probably be selectable on/off
+                                                 * in the preferences window, but for now all
+                                                 * Citation fetcher operations will sort by citation count.
+                                                 */
+                                                private void setSortingByCitationCount() {
+                                                        newBp.sortingByCiteSeerResults = true;
+                                                }
+
+                                                public void run() {
+                                                        setSortingByCitationCount();
+                                                        tabbedPane.add(Globals.lang(GUIGlobals.untitledTitle), newBp);
+                                                        tabbedPane.setSelectedComponent(newBp);
+                                                        output(Globals.lang("Fetched all citations from target database."));
+                                                        citeSeerFetcher.deactivateCitationFetcher();
+                                                }
+                                        };
+
+                                  public void run() {
+                                        try {
+                                                newBp = new BasePanel(ths);
+                                                int errorCode;
+                                                targetBp = (BasePanel) tabbedPane.getSelectedComponent();
+                                                newDatabase = newBp.getDatabase();
+                                                targetDatabase = targetBp.getDatabase();
+                                                errorCode = citeSeerFetcher.populate(newDatabase, targetDatabase);
+                                                if (newDatabase.getEntryCount() > 0) {
+                                                        SwingUtilities.invokeLater(updateComponent);
+                                                } else if(errorCode == 0) {
+                                                        SwingUtilities.invokeLater(citeSeerFetcher.getEmptyFetchSetDialog());
+                                            } else {
+                                                    citeSeerFetcher.deactivateCitationFetcher();
+                                            }
+                                        }
+                                        catch (Exception ex) {
+                                          ex.printStackTrace();
+                                        }
+                                  }
+                                }).start();
+                        } else {
+                            JOptionPane.showMessageDialog(tabbedPane.getSelectedComponent(),
+                                                Globals.lang("A CiteSeer fetch operation is currently in progress.") + "  " +
+                                                Globals.lang("Please wait until it has finished."),
+                                                Globals.lang("CiteSeer Fetch Error"),
+                                                JOptionPane.WARNING_MESSAGE);
+                        }
+                }
+        }
+
+
+
+    // The action concerned with generate a new (sub-)database from latex aux file.
+    class NewSubDatabaseAction extends MnemonicAwareAction
+    {
+      public NewSubDatabaseAction()
+      {
+        super(new ImageIcon( GUIGlobals.newBibFile));
+        putValue(NAME, "New subdatabase based on AUX file" );
+        putValue( SHORT_DESCRIPTION, Globals.lang( "New BibTeX subdatabase" ) ) ;
+            //putValue(MNEMONIC_KEY, GUIGlobals.newKeyCode);
+      }
+
+      public void actionPerformed( ActionEvent e )
+      {
+        // Create a new, empty, database.
+
+        FromAuxDialog dialog = new FromAuxDialog(ths, "", true, ths.tabbedPane) ;
+
+        Util.placeDialog(dialog, ths);
+        dialog.setVisible(true) ;
+
+        if (dialog.okPressed())
+        {
+          BasePanel bp = new BasePanel( ths,
+                                        dialog.getGenerateDB(),   // database
+                                        null,                     // file
+                                        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." ) ) ;
+        }
+      }
+    }
+
+
+    // The action should test the database and report errors/warnings
+    class IntegrityCheckAction extends AbstractAction
+    {
+      public IntegrityCheckAction()
+      {
+        super(Globals.menuTitle("Integrity check"), //Globals.lang( "" ),
+               new ImageIcon( GUIGlobals.integrityCheck ) ) ;
+               //putValue( SHORT_DESCRIPTION, "integrity" ) ;  //Globals.lang( "integrity" ) ) ;
+            //putValue(MNEMONIC_KEY, GUIGlobals.newKeyCode);
+      }
+
+      public void actionPerformed( ActionEvent e )
+      {
+       Object selComp = tabbedPane.getSelectedComponent() ;
+       if (selComp != null)
+       {
+         BasePanel bp = ( BasePanel ) selComp ;
+         BibtexDatabase refBase = bp.getDatabase() ;
+         if (refBase != null)
+         {
+
+             IntegrityWizard wizard = new IntegrityWizard(ths, basePanel()) ;
+             Util.placeDialog(wizard, ths);
+             wizard.setVisible(true) ;
+
+         }
+       }
+      }
+    }
+
+  class FetchMedlineAction
+      extends MnemonicAwareAction {
+    public FetchMedlineAction() {
+      super(new ImageIcon(GUIGlobals.fetchMedlineIcon));
+      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(new ImageIcon(GUIGlobals.fetchMedlineIcon));
+      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 FetchAuthorMedlineAction
+      extends AbstractAction {
+    public FetchAuthorMedlineAction() {
+      super(Globals.lang("Fetch Medline by author"),
+            new ImageIcon(GUIGlobals.fetchMedlineIcon));
+      putValue(SHORT_DESCRIPTION, Globals.lang("Fetch Medline by author"));
+    }
+
+    public void actionPerformed(ActionEvent e) {
+      if (tabbedPane.getTabCount() > 0) {
+        for (int i = 0; i < tabbedPane.getTabCount(); i++) {
+          ( (BasePanel) tabbedPane.getComponentAt(i)).sidePaneManager.
+              ensureVisible("fetchAuthorMedline");
+          new FocusRequester(basePanel().medlineFetcher);
+        }
+      }
+    }
+
+    }*/
+
+  // The action for opening the preferences dialog.
+
+  AbstractAction showPrefs = new ShowPrefsAction();
+
+  class ShowPrefsAction
+      extends MnemonicAwareAction {
+    public ShowPrefsAction() {
+      super(new ImageIcon(GUIGlobals.prefsIconFile));
+      putValue(NAME, "Preferences");
+      putValue(SHORT_DESCRIPTION, Globals.lang("Preferences"));
+    }
+
+    public void actionPerformed(ActionEvent e) {
+      preferences();
+    }
+  }
+
+  /**
+   * This method does the job of adding imported entries into the active database, or into a new one.
+   * It shows the ImportInspectionDialog if preferences indicate it should be used. Otherwise it imports
+   * directly.
+   * @param panel The BasePanel to add to.
+   * @param entries The entries to add.
+   * @param filename Name of the file where the import came from.
+   * @param openInNew Should the entries be imported into a new database?
+   * @param callBack The callback for the ImportInspectionDialog to use.
+   */
+  public void addImportedEntries(final BasePanel panel, final List entries, String filename, boolean openInNew,
+                                  ImportInspectionDialog.CallBack callBack) {
+      // Use the import inspection dialog if it is enabled in preferences, and (there are more than
+      // one entry or the inspection dialog is also enabled for single entries):
+      if (Globals.prefs.getBoolean("useImportInspectionDialog") &&
+              (Globals.prefs.getBoolean("useImportInspectionDialogForSingle") || (entries.size() > 1))) {
+                String[] fields = new String[] {"author", "title", "year" };
+                ImportInspectionDialog diag = new ImportInspectionDialog(ths, panel, fields,
+                        Globals.lang("Import"), openInNew);
+                diag.addEntries(entries);
+                diag.addCallBack(callBack);
+                diag.entryListComplete();
+                Util.placeDialog(diag, ths);
+                diag.setVisible(true);
+		diag.toFront();
+        } else {
+            ths.addBibEntries(entries, filename, openInNew);
+          if ((panel != null) && (entries.size() == 1)) {
+              SwingUtilities.invokeLater(new Runnable() {
+                  public void run() {
+                      panel.highlightEntry((BibtexEntry)entries.get(0));
+                  }
+              });
+
+
+          }
+       }
+  }
+
+    /**
+     * Adds the entries to the database, possibly checking for duplicates first.
+     * @param filename If non-null, a message is printed to the status line describing
+     * how many entries were imported, and from which file. If null, the message will not
+     * be printed.
+     * @param intoNew Determines if the entries will be put in a new database or in the current
+     * one.
+     */
+  public int addBibEntries(java.util.List bibentries, String filename,
+                             boolean intoNew) {
+          if (bibentries == null || bibentries.size() == 0) {
+
+      // No entries found. We need a message for this.
+      JOptionPane.showMessageDialog(ths, Globals.lang("No entries found. Please make sure you are "
+                                                      +"using the correct import filter."), Globals.lang("Import failed"),
+                                    JOptionPane.ERROR_MESSAGE);
+      return 0;
+    }
+
+      int addedEntries = 0;
+
+    // Set owner and timestamp fields:
+    Util.setAutomaticFields(bibentries);
+
+    if (intoNew || (tabbedPane.getTabCount() == 0)) {
+      // Import into new database.
+      BibtexDatabase database = new BibtexDatabase();
+      Iterator it = bibentries.iterator();
+      while (it.hasNext()) {
+        BibtexEntry entry = (BibtexEntry) it.next();
+
+        try {
+          entry.setId(Util.createNeutralId());
+          database.insertEntry(entry);
+        }
+        catch (KeyCollisionException ex) {
+          //ignore
+          System.err.println("KeyCollisionException [ addBibEntries(...) ]");
+        }
+      }
+      HashMap meta = new HashMap();
+      // Metadata are only put in bibtex files, so we will not find it
+      // in imported files. Instead we pass an empty HashMap.
+      BasePanel bp = new BasePanel(ths, database, null, meta, Globals.prefs.get("defaultEncoding"));
+      /*
+            if (prefs.getBoolean("autoComplete")) {
+            db.setCompleters(autoCompleters);
+            }
+       */
+      addedEntries = database.getEntryCount();
+      tabbedPane.add(Globals.lang("untitled"), bp);
+      bp.markBaseChanged();
+      tabbedPane.setSelectedComponent(bp);
+      if (tabbedPane.getTabCount() == 1) {
+        setNonEmptyState();
+      }
+      if (filename != null)
+          output(Globals.lang("Imported database") + " '" + filename + "' " +
+                 Globals.lang("with") + " " +
+                 database.getEntryCount() + " " +
+                 Globals.lang("entries into new database") + ".");
+    }
+    else {
+      // Import into current database.
+      boolean checkForDuplicates = true;
+      BasePanel basePanel = basePanel();
+      BibtexDatabase database = basePanel.database;
+      int oldCount = database.getEntryCount();
+      NamedCompound ce = new NamedCompound(Globals.lang("Import entries"));
+      Iterator it = bibentries.iterator();
+
+      mainLoop: while (it.hasNext()) {
+        BibtexEntry entry = (BibtexEntry) it.next();
+        boolean dupli = false;
+        // Check for duplicates among the current entries:
+        if (checkForDuplicates) {
+            loop: for (Iterator i2=database.getKeySet().iterator();
+                 i2.hasNext();) {
+                BibtexEntry existingEntry = database.getEntryById((String)i2.next());
+                if (Util.isDuplicate(entry, existingEntry,
+                                     Globals.duplicateThreshold)) {
+                    DuplicateResolverDialog drd = new DuplicateResolverDialog
+                        (ths, existingEntry, entry, DuplicateResolverDialog.IMPORT_CHECK);
+                    drd.setVisible(true);
+                    int res = drd.getSelected();
+                    if (res == DuplicateResolverDialog.KEEP_LOWER)   {
+                        dupli = true;
+                    }
+                    else if (res == DuplicateResolverDialog.KEEP_UPPER) {
+                        database.removeEntry(existingEntry.getId());
+                        ce.addEdit(new UndoableRemoveEntry
+                                   (database, existingEntry, basePanel));
+                    } else if (res == DuplicateResolverDialog.BREAK) {
+                        break mainLoop;
+                    }
+                    break loop;
+                }
+            }
+        }
+
+        if (!dupli) {
+            try {
+                entry.setId(Util.createNeutralId());
+                database.insertEntry(entry);
+                ce.addEdit(new UndoableInsertEntry
+                           (database, entry, basePanel));
+                addedEntries++;
+            }
+            catch (KeyCollisionException ex) {
+                //ignore
+                System.err.println("KeyCollisionException [ addBibEntries(...) ]");
+            }
+        }
+      }
+        if (addedEntries > 0) {
+            ce.end();
+            basePanel.undoManager.addEdit(ce);
+            basePanel.markBaseChanged();
+            if (filename != null)
+                output(Globals.lang("Imported database") + " '" + filename + "' " +
+                     Globals.lang("with") + " " +
+                     (database.getEntryCount() - oldCount) + " " +
+                     Globals.lang("entries into new database") + ".");
+        }
+
+    }
+
+    return addedEntries;
+  }
+
+  private void setUpImportMenu(JMenu importMenu, boolean intoNew_) {
+      final boolean intoNew = intoNew_;
+      importMenu.removeAll();
+
+      // Add a menu item for autodetecting import format:
+      importMenu.add(new ImportUnknownMenuItem(ths, intoNew));
+
+      // Add custom importers
+      importMenu.addSeparator();
+      
+      SortedSet customImporters = Globals.importFormatReader.getCustomImportFormats();
+      JMenu submenu = new JMenu(Globals.lang("Custom importers"));
+      submenu.setMnemonic(KeyEvent.VK_S);
+      if (customImporters.size() == 0) {
+        submenu.setEnabled(false);
+        submenu.setToolTipText(Globals.lang("No custom imports registered yet."));
+      } 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, imFo, intoNew));
+        }        
+      }
+      
+      importMenu.add(submenu);
+      importMenu.addSeparator();
+      
+      // Put in all formatters registered in ImportFormatReader:
+      for (Iterator i=Globals.importFormatReader.getBuiltInInputFormats().iterator(); i.hasNext();) {
+          ImportFormat imFo = (ImportFormat)i.next();
+          importMenu.add(new ImportMenuItem(ths, imFo, intoNew));
+      }
+  }
+
+
+  //
+  // simply opens up a jfilechooser dialog and gets a filename
+  // returns null if user selects cancel
+  // it should also do a check perhaps to see if
+  // file exists and is readable?
+  //
+
+  public String getNewFile() {
+
+    return Globals.getNewFile(ths, prefs, new File(prefs.get("workingDirectory")),
+                              null, JFileChooser.OPEN_DIALOG, false);
+
+    /*JFileChooser fc;
+    if (prefs.get("workingDirectory") == null) {
+      fc = new JabRefFileChooser(new File(System.getProperty("user.home"))); //cwd));
+    }
+    else {
+      fc = new JabRefFileChooser(new File(prefs.get("workingDirectory"))); //cwd));
+    }
+
+    fc.addChoosableFileFilter(new OpenFileFilter());
+    fc.setDialogType(JFileChooser.OPEN_DIALOG);
+    fc.showOpenDialog(null);
+    File selectedFile = fc.getSelectedFile();
+    if (selectedFile == null) { // cancel
+      return null;
+    }
+    prefs.put("workingDirectory", selectedFile.getPath());
+    return selectedFile.getAbsolutePath();*/
+  }
+
+    public FileHistory getFileHistory() {
+        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, directory = null;
+        if (source == htmlItem) {
+          lfFileName = "html";
+          extension = ".html";
+        }
+        if (source == simpleHtmlItem) {
+          lfFileName = "simplehtml";
+          extension = ".html";
+        }
+        //else if (source == plainTextItem)
+        //lfFileName = "text";
+        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";
+          directory = "harvard";
+          extension = ".rtf";
+        }
+       else if (source == endnoteItem) {
+          lfFileName = "EndNote";
+          directory = "endnote";
+          extension = ".txt";
+        }
+        /*    else if (source == openofficeItem) {
+                  lfFileName = "openoffice-csv";
+                  directory = "openoffice";
+                  extension = ".csv";
+                }*/
+       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.
+        File outFile;
+        String chosenFile = Globals.getNewFile(ths, prefs, new File(prefs.get("workingDirectory")),
+                                               extension, JFileChooser.SAVE_DIALOG, false);
+        final String dir = (directory == null ? Globals.LAYOUT_PREFIX :
+                         Globals.LAYOUT_PREFIX+directory+"/");
+
+         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, dir, lfName, oFile, basePanel().getEncoding());
+              output(Globals.lang("Exported database to file") + " '" +
+                     oFile.getPath() + "'.");
+            }
+            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.
+     * @param enabled
+     */
+    public void setPreviewActive(boolean enabled) {
+        for (int i=0; i<tabbedPane.getTabCount(); i++) {
+            baseAt(i).setPreviewActive(enabled);
+        }
+    }
+
+
+   public void removeCachedEntryEditors() {
+       for (int j=0; j<tabbedPane.getTabCount(); j++) {
+	        BasePanel bp = (BasePanel)tabbedPane.getComponentAt(j);
+	        bp.entryEditors.clear();
+       }
+   }
+
+
+    /**
+     * This method shows a wait cursor and blocks all input to the JFrame's contents.
+     */
+    public void block() {
+        getGlassPane().setVisible(true);
+        //getGlassPane().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
+    }
+
+    /**
+     * This method reverts the cursor to normal, and stops blocking input to the JFrame's contents.
+     */
+    public void unblock() {
+        getGlassPane().setVisible(false);
+        //	getGlassPane().setCursor(Cursor.WAIT_CURSOR);
+    }
+
+
+
+class SaveSessionAction
+      extends MnemonicAwareAction {
+    public SaveSessionAction() {
+      super(new ImageIcon(GUIGlobals.saveIconFile));
+      putValue(NAME, "Save session");
+      putValue(ACCELERATOR_KEY, prefs.getKey("Save session"));
+    }
+
+    public void actionPerformed(ActionEvent e) {
+      // Here we store the names of allcurrent filea. If
+      // there is no current file, we remove any
+      // previously stored file name.
+      Vector filenames = new Vector();
+      if (tabbedPane.getTabCount() > 0) {
+        for (int i = 0; i < tabbedPane.getTabCount(); i++) {
+          if (tabbedPane.getTitleAt(i).equals(GUIGlobals.untitledTitle)) {
+            tabbedPane.setSelectedIndex(i);
+            int answer = JOptionPane.showConfirmDialog
+                (ths, Globals.lang
+                 ("This untitled database must be saved first to be "
+                  + "included in the saved session. Save now?"),
+                 Globals.lang("Save database"),
+                 JOptionPane.YES_NO_OPTION);
+            if (answer == JOptionPane.YES_OPTION) {
+              // The user wants to save.
+              try {
+                basePanel().runCommand("save");
+              }
+              catch (Throwable ex) {}
+            }
+          }
+          if (baseAt(i).file != null) {
+            filenames.add(baseAt(i).file.getPath());
+          }
+        }
+      }
+
+      if (filenames.size() == 0) {
+        output(Globals.lang("Not saved (empty session)") + ".");
+        return;
+      }
+      else {
+        String[] names = new String[filenames.size()];
+        for (int i = 0; i < filenames.size(); i++) {
+          names[i] = (String) filenames.elementAt(i);
+        }
+        prefs.putStringArray("savedSession", names);
+        output(Globals.lang("Saved session") + ".");
+      }
+
+    }
+  }
+
+  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, prefs,
+                                             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;
+    public LoadSessionAction() {
+      super(new ImageIcon(GUIGlobals.openIconFile));
+      putValue(NAME, "Load session");
+      putValue(ACCELERATOR_KEY, prefs.getKey("Load session"));
+    }
+
+    public void actionPerformed(ActionEvent e) {
+      if (prefs.get("savedSession") == null) {
+        output(Globals.lang("No saved session found."));
+        return;
+      }
+      if (running)
+          return;
+      else running = true;
+      output(Globals.lang("Loading session..."));
+      (new Thread() {
+        public void run() {
+          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());
+            }
+          }
+          int i0 = tabbedPane.getTabCount();
+          String[] names = prefs.getStringArray("savedSession");
+          for (int i = 0; i < names.length; i++) {
+            if (!currentFiles.contains(names[i])) {
+              File file = new File(names[i]);
+              if (file.exists()) {
+                //Util.pr("Opening last edited file:"
+                //+fileToOpen.getName());
+                open.openIt(file, i == 0);
+              }
+            }
+          }
+          output(Globals.lang("Files opened") + ": " +
+                 (tabbedPane.getTabCount() - i0));
+          running = false;
+        }
+      }).start();
+
+    }
+  }
+
+  class ChangeTabAction
+      extends MnemonicAwareAction {
+    private boolean next;
+    public ChangeTabAction(boolean next) {
+      putValue(NAME, next ? "Next tab" : "Previous tab");
+      this.next = next;
+      //Util.pr(""+prefs.getKey("Next tab"));
+      putValue(ACCELERATOR_KEY,
+               (next ? prefs.getKey("Next tab") : prefs.getKey("Previous tab")));
+    }
+
+    public void actionPerformed(ActionEvent e) {
+      int i = tabbedPane.getSelectedIndex();
+      int newI = (next ? i + 1 : i - 1);
+      if (newI < 0) {
+        newI = tabbedPane.getTabCount() - 1;
+      }
+      if (newI == tabbedPane.getTabCount()) {
+        newI = 0;
+      }
+      tabbedPane.setSelectedIndex(newI);
+    }
+  }
+
+  /**
+   * Class for handling general actions; cut, copy and paste. The focused component is
+   * kept track of by Globals.focusListener, and we call the action stored under the
+   * relevant name in its action map.
+   */
+  class EditAction
+      extends MnemonicAwareAction {
+    private String command;
+    public EditAction(String command, URL icon) {
+      super(new ImageIcon(icon));
+      this.command = command;
+      String nName = Util.nCase(command);
+      putValue(NAME, nName);
+      putValue(ACCELERATOR_KEY, prefs.getKey(nName));
+      putValue(SHORT_DESCRIPTION, Globals.lang(nName));
+      //putValue(ACCELERATOR_KEY,
+      //         (next?prefs.getKey("Next tab"):prefs.getKey("Previous tab")));
+    }
+
+    public void actionPerformed(ActionEvent e) {
+
+      //Util.pr(Globals.focusListener.getFocused().toString());
+      JComponent source = Globals.focusListener.getFocused();
+      try {
+        source.getActionMap().get(command).actionPerformed
+            (new ActionEvent(source, 0, command));
+      } catch (NullPointerException ex) {
+        // No component is focused, so we do nothing.
+      }
+    }
+  }
+
+  class CustomizeExportsAction extends MnemonicAwareAction {
+    public CustomizeExportsAction() {
+      putValue(NAME, "Manage custom exports");
+    }
+
+    public void actionPerformed(ActionEvent e) {
+      ExportCustomizationDialog ecd = new ExportCustomizationDialog(ths);
+      ecd.setVisible(true);
+    }
+  }
+
+  class CustomizeImportsAction extends MnemonicAwareAction {
+    public CustomizeImportsAction() {
+      putValue(NAME, "Manage custom imports");
+    }
+
+    public void actionPerformed(ActionEvent e) {
+      ImportCustomizationDialog ecd = new ImportCustomizationDialog(ths);
+      ecd.setVisible(true);
+    }
+  }
+
+    class ExportCSV extends MnemonicAwareAction {
+        public ExportCSV() {
+            putValue(NAME, "Tab-separated file");
+        }
+        public void actionPerformed(ActionEvent e) {
+            String chosenFile = Globals.getNewFile(ths, prefs, new File(prefs.get("workingDirectory")), ".csv",
+                                                   JFileChooser.SAVE_DIALOG, true);
+            if (chosenFile == null)
+                return;
+            try {
+                FileActions.exportToCSV(basePanel().database(), new File(chosenFile),
+                                        prefs);
+            } catch (Exception ex) {
+                ex.printStackTrace();
+            }
+
+        }
+    }
+
+    class CustomizeEntryTypeAction extends MnemonicAwareAction {
+        public CustomizeEntryTypeAction() {
+            putValue(NAME, "Customize entry types");
+        }
+        public void actionPerformed(ActionEvent e) {
+            JDialog dl = new EntryCustomizationDialog2(ths);
+            Util.placeDialog(dl, ths);
+            dl.setVisible(true);
+        }
+    }
+
+    class GenFieldsCustomizationAction extends MnemonicAwareAction {
+        public GenFieldsCustomizationAction() {
+            putValue(NAME, "Set up general fields");
+        }
+        public void actionPerformed(ActionEvent e) {
+            GenFieldsCustomizer gf = new GenFieldsCustomizer(ths);
+            Util.placeDialog(gf, ths);
+            gf.setVisible(true);
+
+        }
+    }
+
+    class DatabasePropertiesAction extends MnemonicAwareAction {
+        DatabasePropertiesDialog propertiesDialog = null;
+        public DatabasePropertiesAction() {
+            putValue(NAME, "Database properties");
+        }
+
+        public void actionPerformed(ActionEvent e) {
+            if (propertiesDialog == null)
+                propertiesDialog = new DatabasePropertiesDialog(JabRefFrame.this);
+            propertiesDialog.setPanel(basePanel());
+            Util.placeDialog(propertiesDialog, JabRefFrame.this);
+            propertiesDialog.setVisible(true);
+        }
+    }
+
+    /*private class ForegroundLabel extends JLabel {
+         public ForegroundLabel(String s) {
+             super(s);
+             setFont(new Font("plain", Font.BOLD, 70));
+             setHorizontalAlignment(JLabel.CENTER);
+         }
+
+        public void paint(Graphics g) {
+            Graphics2D g2 = (Graphics2D)g;
+            g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+            super.paint(g2);    //To change body of overridden methods use File | Settings | File Templates.
+        }
+    }       */
+
+  private class MyGlassPane extends JPanel {
+    //ForegroundLabel infoLabel = new ForegroundLabel("Showing search");
+    public MyGlassPane() {
+      addKeyListener(new KeyAdapter() { });
+      addMouseListener(new MouseAdapter() { });
+      /*  infoLabel.setForeground(new Color(255, 100, 100, 124));
+
+        setLayout(new BorderLayout());
+        add(infoLabel, BorderLayout.CENTER);*/
+      super.setCursor(
+        Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
+    }
+      // Override isOpaque() to prevent the glasspane from hiding the window contents:
+      public boolean isOpaque() { return false; }
+  }
+}
diff --git a/src/java/net/sf/jabref/JabRefPreferences.java b/src/java/net/sf/jabref/JabRefPreferences.java
new file mode 100644
index 0000000..fd8b323
--- /dev/null
+++ b/src/java/net/sf/jabref/JabRefPreferences.java
@@ -0,0 +1,862 @@
+/*
+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.
+
+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 javax.swing.*;
+
+import net.sf.jabref.labelPattern.DefaultLabelPatterns;
+import net.sf.jabref.labelPattern.LabelPattern;
+import net.sf.jabref.export.CustomExportList;
+import net.sf.jabref.imports.CustomImportList;
+import java.awt.*;
+import java.util.prefs.*;
+import java.util.*;
+import java.awt.event.*;
+import net.sf.jabref.export.ExportComparator;
+
+public class JabRefPreferences {
+
+    public final String
+        CUSTOM_TYPE_NAME = "customTypeName_",
+        CUSTOM_TYPE_REQ = "customTypeReq_",
+        CUSTOM_TYPE_OPT = "customTypeOpt_",
+	CUSTOM_TAB_NAME = "customTabName_",
+	CUSTOM_TAB_FIELDS = "customTabFields_";
+
+    public String WRAPPED_USERNAME;
+
+
+    Preferences prefs;
+    public HashMap defaults = new HashMap(),
+        keyBinds = new HashMap(),
+        defKeyBinds = new HashMap();
+    private HashSet putBracesAroundCapitalsFields = new HashSet(4);
+    private HashSet nonWrappableFields = new HashSet(4);
+    private static final LabelPattern KEY_PATTERN = new DefaultLabelPatterns();
+    private static LabelPattern keyPattern;
+
+    // Object containing custom export formats:
+    public CustomExportList customExports;
+
+    /** Set with all custom {@link ImportFormat}s */
+    public CustomImportList customImports;
+    
+    // Object containing info about customized entry editor tabs.
+    private EntryEditorTabList tabList = null;
+
+    // The only instance of this class:
+    private static JabRefPreferences INSTANCE = null;
+
+    public static JabRefPreferences getInstance() {
+	if (INSTANCE == null)
+	    INSTANCE = new JabRefPreferences();
+	return INSTANCE;
+    }
+
+    // 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("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("autoResizeMode", new Integer(JTable.AUTO_RESIZE_OFF));
+        defaults.put("tableColorCodesOn", Boolean.TRUE);
+        defaults.put("namesAsIs", Boolean.FALSE);
+        defaults.put("namesFf", Boolean.FALSE);
+	    defaults.put("namesLf", Boolean.FALSE);
+        defaults.put("namesNatbib", Boolean.TRUE);
+        defaults.put("abbrAuthorNames", Boolean.TRUE);
+	    defaults.put("namesLastOnly", Boolean.TRUE);
+        defaults.put("language", "en");
+        defaults.put("showShort", Boolean.TRUE);
+        defaults.put("priSort", "author");
+        defaults.put("priDescending", Boolean.FALSE);
+        defaults.put("priBinary", Boolean.FALSE);
+        defaults.put("secSort", "year");
+        defaults.put("secDescending", Boolean.TRUE);
+        defaults.put("terSort", "author");
+        defaults.put("terDescending", Boolean.FALSE);
+        defaults.put("columnNames", "entrytype;author;title;year;journal;owner;timestamp;bibtexkey");
+        defaults.put("columnWidths","75;280;400;60;100;100;100;100");
+        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("autoOpenForm", Boolean.TRUE);
+        defaults.put("entryTypeFormHeightFactor", new Integer(1));
+        defaults.put("entryTypeFormWidth", new Integer(1));
+        defaults.put("backup", Boolean.TRUE);
+        defaults.put("openLastEdited", Boolean.TRUE);
+        defaults.put("lastEdited", (String)null);
+        defaults.put("stringsPosX", new Integer(0));
+        defaults.put("stringsPosY", new Integer(0));
+        defaults.put("stringsSizeX", new Integer(600));
+        defaults.put("stringsSizeY", new Integer(400));
+        defaults.put("defaultShowSource", Boolean.FALSE);
+        defaults.put("showSource", Boolean.TRUE);
+        defaults.put("defaultAutoSort", Boolean.FALSE);
+        defaults.put("enableSourceEditing", Boolean.TRUE);
+        defaults.put("caseSensitiveSearch", Boolean.FALSE);
+        defaults.put("searchReq", Boolean.TRUE);
+        defaults.put("searchOpt", Boolean.TRUE);
+        defaults.put("searchGen", Boolean.TRUE);
+        defaults.put("searchAll", Boolean.FALSE);
+        defaults.put("incrementS", Boolean.FALSE);
+        defaults.put("saveInStandardOrder", Boolean.TRUE);
+        defaults.put("selectS", Boolean.FALSE);
+        defaults.put("regExpSearch", Boolean.TRUE);
+        defaults.put("searchPanePosX", new Integer(0));
+        defaults.put("searchPanePosY", new Integer(0));
+        defaults.put("autoComplete", Boolean.TRUE);
+        defaults.put("autoCompFields", new byte[] {0, 1, 28});
+        defaults.put("groupSelectorVisible", Boolean.TRUE);
+        defaults.put("groupFloatSelections", Boolean.TRUE);
+        defaults.put("groupIntersectSelections", Boolean.TRUE);
+        defaults.put("groupInvertSelections", Boolean.FALSE);
+        defaults.put("groupShowOverlapping", Boolean.FALSE);
+        defaults.put("groupSelectMatches", Boolean.FALSE);
+        defaults.put("groupsDefaultField", "keywords");
+        defaults.put("groupShowIcons", Boolean.TRUE);
+        defaults.put("groupShowDynamic", Boolean.TRUE);
+        defaults.put("groupExpandTree", Boolean.TRUE);
+        defaults.put("groupAutoShow", Boolean.TRUE);
+        defaults.put("groupAutoHide", Boolean.TRUE);
+        defaults.put("groupKeywordSeparator", ", ");
+        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("groupsVisibleRows", new Integer(8));
+        defaults.put("defaultOwner", System.getProperty("user.name"));
+        defaults.put("preserveFieldFormatting", Boolean.FALSE);
+	// The general fields stuff is made obsolete by the CUSTOM_TAB_... entries.
+        defaults.put("generalFields", "crossref;keywords;doi;url;citeseerurl;"+
+                     "pdf;comment;owner");
+
+	// Entry editor tab 0:
+	defaults.put(CUSTOM_TAB_NAME+"0", Globals.lang("General"));
+        defaults.put(CUSTOM_TAB_FIELDS+"0", "crossref;keywords;doi;url;citeseerurl;"+
+                     "pdf;comment;owner;timestamp");
+
+	// Entry editor tab 1:
+        defaults.put(CUSTOM_TAB_FIELDS+"1", "abstract");
+	defaults.put(CUSTOM_TAB_NAME+"1", Globals.lang("Abstract"));
+
+  // Entry editor tab 2: Review Field - used for research comments, etc.
+        defaults.put(CUSTOM_TAB_FIELDS+"2", "review");
+	defaults.put(CUSTOM_TAB_NAME+"2", Globals.lang("Review"));
+
+        //defaults.put("recentFiles", "/home/alver/Documents/bibk_dok/hovedbase.bib");
+        defaults.put("historySize", new Integer(8));
+        defaults.put("fontFamily", "Times");
+        defaults.put("fontStyle", new Integer(java.awt.Font.PLAIN));
+        defaults.put("fontSize", new Integer(12));
+        defaults.put("menuFontFamily", "Times");
+        defaults.put("menuFontStyle", new Integer(java.awt.Font.PLAIN));
+        defaults.put("menuFontSize", new Integer(11));
+        // Main table color settings:
+        defaults.put("tableBackground", "255:255:255");
+        defaults.put("tableReqFieldBackground", "230:235:255");
+        defaults.put("tableOptFieldBackground", "230:255:230");
+        defaults.put("tableText", "0:0:0");
+        defaults.put("gridColor", "210:210:210");
+        defaults.put("grayedOutBackground", "210:210:210");
+        defaults.put("grayedOutText", "40:40:40");
+        defaults.put("veryGrayedOutBackground", "180:180:180");
+        defaults.put("veryGrayedOutText", "40:40:40");
+        defaults.put("markedEntryBackground", "255:255:180");
+        defaults.put("incompleteEntryBackground", "250:175:175");
+
+        defaults.put("antialias", Boolean.FALSE);
+        defaults.put("ctrlClick", Boolean.FALSE);
+        defaults.put("disableOnMultipleSelection", Boolean.FALSE);
+        defaults.put("pdfColumn", Boolean.TRUE);
+        defaults.put("urlColumn", Boolean.TRUE);
+        defaults.put("citeseerColumn", Boolean.FALSE);
+        defaults.put("useOwner", Boolean.TRUE);
+        defaults.put("allowTableEditing", Boolean.FALSE);
+        defaults.put("dialogWarningForDuplicateKey", Boolean.TRUE);
+        defaults.put("dialogWarningForEmptyKey", Boolean.TRUE);
+        defaults.put("displayKeyWarningDialogAtStartup", Boolean.TRUE);
+        defaults.put("avoidOverwritingKey", Boolean.FALSE);
+        defaults.put("warnBeforeOverwritingKey", Boolean.TRUE);
+        defaults.put("confirmDelete", Boolean.TRUE);
+        defaults.put("grayOutNonHits", Boolean.TRUE);
+        defaults.put("defaultLabelPattern", "[auth][year]");
+        defaults.put("previewEnabled", Boolean.TRUE);
+        defaults.put("preview0", "<font face=\"arial\">"
+                     +"<b><i>\\bibtextype</i><a name=\"\\bibtexkey\">\\begin{bibtexkey} (\\bibtexkey)</a>"
+                     +"\\end{bibtexkey}</b><br>__NEWLINE__"
+                     +"\\begin{author} \\format[AuthorLastFirst,HTMLChars,AuthorAbbreviator,AuthorAndsReplacer]{\\author}<BR>\\end{author}__NEWLINE__"
+                     +"\\begin{editor} \\format[AuthorLastFirst,HTMLChars,AuthorAbbreviator,AuthorAndsReplacer]{\\editor} <i>(ed.)</i><BR>\\end{editor}__NEWLINE__"
+                     +"\\begin{title} \\format[HTMLChars]{\\title} \\end{title}<BR>__NEWLINE__"
+                     +"\\begin{chapter} \\format[HTMLChars]{\\chapter}<BR>\\end{chapter}__NEWLINE__"
+                     +"\\begin{journal} <em>\\format[HTMLChars]{\\journal}, </em>\\end{journal}__NEWLINE__"
+                     // Include the booktitle field for @inproceedings, @proceedings, etc.
+                     +"\\begin{booktitle} <em>\\format[HTMLChars]{\\booktitle}, </em>\\end{booktitle}__NEWLINE__"
+                     +"\\begin{school} <em>\\format[HTMLChars]{\\school}, </em>\\end{school}__NEWLINE__"
+                     +"\\begin{institution} <em>\\format[HTMLChars]{\\institution}, </em>\\end{institution}__NEWLINE__"
+                     +"\\begin{publisher} <em>\\format[HTMLChars]{\\publisher}, </em>\\end{publisher}__NEWLINE__"
+                     +"\\begin{year}<b>\\year</b>\\end{year}\\begin{volume}<i>, \\volume</i>\\end{volume}"
+                     +"\\begin{pages}, \\format[FormatPagesForHTML]{\\pages} \\end{pages}"
+                     +"</dd>__NEWLINE__<p></p></font>");
+
+        defaults.put("preview1", "<font face=\"arial\">"
+                     +"<b><i>\\bibtextype</i><a name=\"\\bibtexkey\">\\begin{bibtexkey} (\\bibtexkey)</a>"
+                     +"\\end{bibtexkey}</b><br>__NEWLINE__"
+                     +"\\begin{author} \\format[AuthorLastFirst,HTMLChars,AuthorAbbreviator,AuthorAndsReplacer]{\\author}<BR>\\end{author}__NEWLINE__"
+                     +"\\begin{editor} \\format[AuthorLastFirst,HTMLChars,AuthorAbbreviator,AuthorAndsReplacer]{\\editor} <i>(ed.)</i><BR>\\end{editor}__NEWLINE__"
+                     +"\\begin{title} \\format[HTMLChars]{\\title} \\end{title}<BR>__NEWLINE__"
+                     +"\\begin{chapter} \\format[HTMLChars]{\\chapter}<BR>\\end{chapter}__NEWLINE__"
+                     +"\\begin{journal} <em>\\format[HTMLChars]{\\journal}, </em>\\end{journal}__NEWLINE__"
+                     // Include the booktitle field for @inproceedings, @proceedings, etc.
+                     +"\\begin{booktitle} <em>\\format[HTMLChars]{\\booktitle}, </em>\\end{booktitle}__NEWLINE__"
+                     +"\\begin{school} <em>\\format[HTMLChars]{\\school}, </em>\\end{school}__NEWLINE__"
+                     +"\\begin{institution} <em>\\format[HTMLChars]{\\institution}, </em>\\end{institution}__NEWLINE__"
+                     +"\\begin{publisher} <em>\\format[HTMLChars]{\\publisher}, </em>\\end{publisher}__NEWLINE__"
+                     +"\\begin{year}<b>\\year</b>\\end{year}\\begin{volume}<i>, \\volume</i>\\end{volume}"
+                     +"\\begin{pages}, \\format[FormatPagesForHTML]{\\pages} \\end{pages}__NEWLINE__"
+                     +"\\begin{abstract}<BR><BR><b>Abstract: </b> \\format[HTMLChars]{\\abstract} \\end{abstract}__NEWLINE__"
+                     +"\\begin{review}<BR><BR><b>Review: </b> \\format[HTMLChars]{\\review} \\end{review}"
+                     +"</dd>__NEWLINE__<p></p></font>");
+        defaults.put("autoDoubleBraces", Boolean.FALSE);
+        defaults.put("putBracesAroundCapitals","");//"title;journal;booktitle;review;abstract");
+        defaults.put("nonWrappableFields", "pdf;ps;url;doi");
+        defaults.put("useImportInspectionDialog", Boolean.TRUE);
+        defaults.put("useImportInspectionDialogForSingle", Boolean.FALSE);
+        defaults.put("generateKeysAfterInspection", Boolean.TRUE);
+        defaults.put("warnAboutDuplicatesInInspection", Boolean.TRUE);
+        defaults.put("useTimeStamp", Boolean.TRUE);
+        defaults.put("timeStampFormat", "yyyy.MM.dd");
+        defaults.put("timeStampField", "timestamp");
+
+        defaults.put("useRemoteServer", Boolean.FALSE);
+        defaults.put("remoteServerPort", new Integer(6050));
+
+        defaults.put("personalJournalList", null);
+        defaults.put("externalJournalLists", null);
+
+        defaults.put("citeCommand", "cite");
+        //defaults.put("tempDir", System.getProperty("java.io.tmpdir"));
+        //Util.pr(System.getProperty("java.io.tempdir"));
+
+        //defaults.put("keyPattern", new LabelPattern(KEY_PATTERN));
+
+        restoreKeyBindings();
+
+        customExports = new CustomExportList(this, new ExportComparator());
+        customImports = new CustomImportList(this);
+
+        //defaults.put("oooWarning", Boolean.TRUE);
+        updateSpecialFieldHandling();
+        WRAPPED_USERNAME = "["+get("defaultOwner")+"]";
+    }
+
+    public boolean putBracesAroundCapitals(String fieldName) {
+        return putBracesAroundCapitalsFields.contains(fieldName);
+    }
+
+    public void updateSpecialFieldHandling() {
+        putBracesAroundCapitalsFields.clear();
+        String fieldString = get("putBracesAroundCapitals");
+        if (fieldString.length() > 0) {
+            String[] fields = fieldString.split(";");
+            for (int i=0; i<fields.length; i++)
+                putBracesAroundCapitalsFields.add(fields[i]);
+        }
+        nonWrappableFields.clear();
+        fieldString = get("nonWrappableFields");
+        if (fieldString.length() > 0) {
+            String[] fields = fieldString.split(";");
+            for (int i=0; i<fields.length; i++)
+                nonWrappableFields.add(fields[i]);
+        }
+
+    }
+
+    public String get(String key) {
+        return prefs.get(key, (String)defaults.get(key));
+    }
+
+    public String get(String key, String def) {
+        return prefs.get(key, def);
+    }
+
+    public boolean getBoolean(String key) {
+        return prefs.getBoolean(key, ((Boolean)defaults.get(key)).booleanValue());
+    }
+
+    public double getDouble(String key) {
+        return prefs.getDouble(key, ((Double)defaults.get(key)).doubleValue());
+    }
+
+    public int getInt(String key) {
+        return prefs.getInt(key, ((Integer)defaults.get(key)).intValue());
+    }
+
+    public byte[] getByteArray(String key) {
+        return prefs.getByteArray(key, (byte[])defaults.get(key));
+    }
+
+    public void put(String key, String value) {
+        prefs.put(key, value);
+    }
+
+    public void putBoolean(String key, boolean value) {
+        prefs.putBoolean(key, value);
+    }
+
+    public void putDouble(String key, double value) {
+        prefs.putDouble(key, value);
+    }
+
+    public void putInt(String key, int value) {
+        prefs.putInt(key, value);
+    }
+
+    public void putByteArray(String key, byte[] value) {
+        prefs.putByteArray(key, value);
+    }
+
+    public void remove(String key) {
+        prefs.remove(key);
+    }
+
+    /**
+     * Puts a string array into the Preferences, by linking its elements
+     * with ';' into a single string. Escape characters make the process
+     * transparent even if strings contain ';'.
+     */
+    public void putStringArray(String key, String[] value) {
+        if (value == null) {
+            remove(key);
+            return;
+        }
+
+        if (value.length > 0) {
+            StringBuffer linked = new StringBuffer();
+            for (int i=0; i<value.length-1; i++) {
+                linked.append(makeEscape(value[i]));
+                linked.append(";");
+            }
+            linked.append(makeEscape(value[value.length-1]));
+            put(key, linked.toString());
+        } else {
+            put(key, "");
+        }
+    }
+
+    /**
+     * Returns a String[] containing the chosen columns.
+     */
+    public String[] getStringArray(String key) {
+        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;
+        try {
+            while ((rs = getNextUnit(rd)) != null) {
+                arr.add(rs);
+            }
+        } catch (IOException ex) {}
+        String[] res = new String[arr.size()];
+        for (int i=0; i<res.length; i++)
+            res[i] = (String)arr.elementAt(i);
+
+        return res;
+    }
+
+    /**
+     * Looks up a color definition in preferences, and returns the Color object.
+     * @param key The key for this setting.
+     * @return The color corresponding to the setting.
+     */
+    public Color getColor(String key) {
+        String value = get(key);
+        int[] rgb = getRgb(value);
+        return new Color(rgb[0], rgb[1], rgb[2]);
+    }
+
+    public Color getDefaultColor(String key) {
+        String value = (String)defaults.get(key);
+        int[] rgb = getRgb(value);
+        return new Color(rgb[0], rgb[1], rgb[2]);
+    }
+
+    /**
+     * Stores a color in preferences.
+     * @param key The key for this setting.
+     * @param color The Color to store.
+     */
+    public void putColor(String key, Color color) {
+        StringBuffer sb = new StringBuffer();
+        sb.append(String.valueOf(color.getRed()));
+        sb.append(':');
+        sb.append(String.valueOf(color.getGreen()));
+        sb.append(':');
+        sb.append(String.valueOf(color.getBlue()));
+        put(key, sb.toString());
+    }
+
+    /**
+     * Looks up a color definition in preferences, and returns an array containing the RGB values.
+     * @param key The key for this setting.
+     * @return The RGB values corresponding to this color setting.
+     */
+    public int[] getRgb(String value) {
+        String[] elements = value.split(":");
+        int[] values = new int[3];
+        values[0] = Integer.parseInt(elements[0]);
+        values[1] = Integer.parseInt(elements[1]);
+        values[2] = Integer.parseInt(elements[2]);
+        return values;
+    }
+
+    /**
+     * Returns the KeyStroke for this binding, as defined by the
+     * defaults, or in the Preferences.
+     */
+    public KeyStroke getKey(String bindName) {
+
+        String s = (String)keyBinds.get(bindName);
+        // If the current key bindings don't contain the one asked for,
+        // we fall back on the default. This should only happen when a
+        // user has his own set in Preferences, and has upgraded to a
+        // new version where new bindings have been introduced.
+        if (s == null) {
+            s = (String)defKeyBinds.get(bindName);
+            // So, if this happens, we add the default value to the current
+            // hashmap, so this doesn't happen again, and so this binding
+            // will appear in the KeyBindingsDialog.
+            keyBinds.put(bindName, s);
+        }
+        if (s == null) {
+          Globals.logger("Could not get key binding for \"" + bindName + "\"");
+          //throw new RuntimeException("");
+        }
+
+        if (Globals.ON_MAC)
+          return getKeyForMac(KeyStroke.getKeyStroke(s));
+        else
+          return KeyStroke.getKeyStroke(s);
+    }
+
+    /**
+     * Returns the KeyStroke for this binding, as defined by the
+     * defaults, or in the Preferences, but adapted for Mac users,
+     * with the Command key preferred instead of Control.
+     */
+    private KeyStroke getKeyForMac(KeyStroke ks) {
+      if (ks == null) return null;
+      int keyCode = ks.getKeyCode();
+      if ((ks.getModifiers() & KeyEvent.CTRL_MASK) == 0) {
+        return ks;
+      }
+      else {
+        if ((ks.getModifiers() & KeyEvent.SHIFT_MASK) != 0) {
+          return KeyStroke.getKeyStroke(keyCode, Globals.SHORTCUT_MASK+KeyEvent.SHIFT_MASK);
+        }
+        return KeyStroke.getKeyStroke(keyCode, Globals.SHORTCUT_MASK);
+      }
+    }
+
+    /**
+     * Returns the HashMap containing all key bindings.
+     */
+    public HashMap getKeyBindings() {
+        return keyBinds;
+    }
+
+    /**
+     * Returns the HashMap containing default key bindings.
+     */
+    public HashMap getDefaultKeys() {
+        return defKeyBinds;
+    }
+
+    public void flush() {
+	try {
+	    prefs.flush();
+	} catch (BackingStoreException ex) {
+	    ex.printStackTrace();
+	}
+    }
+
+    /**
+     * Stores new key bindings into Preferences, provided they
+     * actually differ from the old ones.
+     */
+    public void setNewKeyBindings(HashMap newBindings) {
+        if (!newBindings.equals(keyBinds)) {
+            // This confirms that the bindings have actually changed.
+            String[] bindNames = new String[newBindings.size()],
+                bindings = new String[newBindings.size()];
+            int index = 0;
+            for (Iterator i=newBindings.keySet().iterator();
+                 i.hasNext();) {
+                String nm = (String)i.next();
+                String bnd = (String)newBindings.get(nm);
+                bindNames[index] = nm;
+                bindings[index] = bnd;
+                index++;
+            }
+            putStringArray("bindNames", bindNames);
+            putStringArray("bindings", bindings);
+            keyBinds = newBindings;
+        }
+    }
+
+
+        public LabelPattern getKeyPattern(){
+            
+            keyPattern = new LabelPattern(KEY_PATTERN);
+            Preferences pre = Preferences.userNodeForPackage
+                (net.sf.jabref.labelPattern.LabelPattern.class);
+            try {
+                String[] keys = pre.keys();
+            if (keys.length > 0) for (int i=0; i<keys.length; i++)
+                keyPattern.addLabelPattern(keys[i], pre.get(keys[i], null));
+            } catch (BackingStoreException ex) {
+                Globals.logger("BackingStoreException in JabRefPreferences.getKeyPattern");
+            }
+
+            ///
+            //keyPattern.addLabelPattern("article", "[author][year]");
+            //putKeyPattern(keyPattern);
+            ///
+
+            return keyPattern;
+        }
+
+        public void putKeyPattern(LabelPattern pattern){
+            keyPattern = pattern;
+            LabelPattern parent = pattern.getParent();
+            if (parent == null)
+                return;
+
+            // Store overridden definitions to Preferences.
+            Preferences pre = Preferences.userNodeForPackage
+                (net.sf.jabref.labelPattern.LabelPattern.class);
+            try {
+                pre.clear(); // We remove all old entries.
+            } catch (BackingStoreException ex) {
+                Globals.logger("BackingStoreException in JabRefPreferences.putKeyPattern");
+            }
+
+            Iterator i = pattern.keySet().iterator();
+            while (i.hasNext()) {
+                String s = (String)i.next();
+                if (!(pattern.get(s)).equals(parent.get(s)))
+                    pre.put(s, pattern.getValue(s).get(0).toString());
+            }
+        }
+
+    private void restoreKeyBindings() {
+        // Define default keybindings.
+        defineDefaultKeyBindings();
+
+        // First read the bindings, and their names.
+        String[] bindNames = getStringArray("bindNames"),
+            bindings = getStringArray("bindings");
+
+        // Then set up the key bindings HashMap.
+        if ((bindNames == null) || (bindings == null)
+            || (bindNames.length != bindings.length)) {
+            // Nothing defined in Preferences, or something is wrong.
+            setDefaultKeyBindings();
+            return;
+        }
+
+        for (int i=0; i<bindNames.length; i++)
+            keyBinds.put(bindNames[i], bindings[i]);
+    }
+
+    private void setDefaultKeyBindings() {
+        keyBinds = defKeyBinds;
+    }
+
+    private void defineDefaultKeyBindings() {
+      defKeyBinds.put("Push to LyX","ctrl L");
+      defKeyBinds.put("Push to WinEdt","ctrl shift W");
+      defKeyBinds.put("Push to Emacs","ctrl shift E");
+        defKeyBinds.put("Quit JabRef", "ctrl Q");
+        defKeyBinds.put("Open database", "ctrl O");
+        defKeyBinds.put("Save database", "ctrl S");
+        defKeyBinds.put("Save database as ...", "ctrl shift S");
+        defKeyBinds.put("Close database", "ctrl W");
+        defKeyBinds.put("New entry", "ctrl N");
+        defKeyBinds.put("Cut", "ctrl X");
+        defKeyBinds.put("Copy", "ctrl C");
+        defKeyBinds.put("Paste", "ctrl V");
+        defKeyBinds.put("Undo", "ctrl Z");
+        defKeyBinds.put("Redo", "ctrl Y");
+        defKeyBinds.put("Help", "F1");
+        defKeyBinds.put("New article", "ctrl shift A");
+        defKeyBinds.put("New book", "ctrl shift B");
+        defKeyBinds.put("New phdthesis", "ctrl shift T");
+        defKeyBinds.put("New inbook", "ctrl shift I");
+        defKeyBinds.put("New mastersthesis", "ctrl shift M");
+        defKeyBinds.put("New proceedings", "ctrl shift P");
+        defKeyBinds.put("New unpublished", "ctrl shift U");
+        defKeyBinds.put("Edit strings", "ctrl T");
+        defKeyBinds.put("Edit preamble", "ctrl P");
+        defKeyBinds.put("Select all", "ctrl A");
+        defKeyBinds.put("Toggle groups interface", "ctrl shift G");
+        defKeyBinds.put("Autogenerate BibTeX keys", "ctrl G");
+        defKeyBinds.put("Search", "ctrl F");
+        defKeyBinds.put("Incremental search", "ctrl shift F");
+        defKeyBinds.put("Repeat incremental search", "ctrl shift F");
+        defKeyBinds.put("Close dialog", "ESCAPE");
+        defKeyBinds.put("Close entry editor", "ESCAPE");
+        defKeyBinds.put("Close preamble editor", "ESCAPE");
+        defKeyBinds.put("Back, help dialog", "LEFT");
+        defKeyBinds.put("Forward, help dialog", "RIGHT");
+        defKeyBinds.put("Preamble editor, store changes", "alt S");
+        defKeyBinds.put("Clear search", "ESCAPE");
+        defKeyBinds.put("Entry editor, next panel", "ctrl TAB");//"ctrl PLUS");//"shift Right");
+        defKeyBinds.put("Entry editor, previous panel", "ctrl shift TAB");//"ctrl MINUS");
+        defKeyBinds.put("Entry editor, next panel 2", "ctrl PLUS");//"ctrl PLUS");//"shift Right");
+        defKeyBinds.put("Entry editor, previous panel 2", "ctrl MINUS");//"ctrl MINUS");
+        defKeyBinds.put("Entry editor, next entry", "ctrl shift DOWN");
+        defKeyBinds.put("Entry editor, previous entry", "ctrl shift UP");
+        defKeyBinds.put("Entry editor, store field", "alt S");
+        defKeyBinds.put("String dialog, add string", "ctrl N");
+        defKeyBinds.put("String dialog, remove string", "shift DELETE");
+        defKeyBinds.put("String dialog, move string up", "ctrl UP");
+        defKeyBinds.put("String dialog, move string down", "ctrl DOWN");
+        defKeyBinds.put("Save session", "F11");
+        defKeyBinds.put("Load session", "F12");
+        defKeyBinds.put("Copy \\cite{BibTeX key}", "ctrl K");
+        defKeyBinds.put("Next tab", "ctrl PAGE_DOWN");
+        defKeyBinds.put("Previous tab", "ctrl PAGE_UP");
+        defKeyBinds.put("Replace string", "ctrl R");
+        defKeyBinds.put("Delete", "DELETE");
+        defKeyBinds.put("Open PDF or PS", "F4");
+        defKeyBinds.put("Open URL or DOI", "F3");
+        defKeyBinds.put("Toggle entry preview", "ctrl F9");
+        defKeyBinds.put("Switch preview layout", "F9");
+        defKeyBinds.put("Edit entry", "ctrl E");
+        defKeyBinds.put("Mark entries", "ctrl M");
+        defKeyBinds.put("Unmark entries", "ctrl shift M");
+        defKeyBinds.put("Fetch Medline", "F5");
+        defKeyBinds.put("Fetch CiteSeer", "F6");
+        defKeyBinds.put("New from plain text", "ctrl shift N");
+        defKeyBinds.put("Import Fields from CiteSeer", "ctrl shift C");
+        defKeyBinds.put("Fetch citations from CiteSeer", "F7");
+        defKeyBinds.put("Synchronize PDF", "shift F4");
+        defKeyBinds.put("Synchronize PS", "ctrl F4");
+        defKeyBinds.put("Abbreviate", "ctrl alt A");
+        defKeyBinds.put("Unabbreviate", "ctrl alt shift A");
+
+        //defKeyBinds.put("Select value", "ctrl B");
+    }
+
+    private String getNextUnit(Reader data) throws IOException {
+        int c;
+        boolean escape = false, done = false;
+        StringBuffer res = new StringBuffer();
+        while (!done && ((c = data.read()) != -1)) {
+            if (c == '\\') {
+                if (!escape)
+                    escape = true;
+                else {
+                    escape = false;
+                    res.append('\\');
+                }
+            } else {
+                if (c == ';') {
+                    if (!escape)
+                        done = true;
+                    else
+                        res.append(';');
+                } else {
+                    res.append((char)c);
+                }
+                escape = false;
+            }
+        }
+        if (res.length() > 0)
+            return res.toString();
+        else
+            return null;
+    }
+
+    private String makeEscape(String s) {
+        StringBuffer sb = new StringBuffer();
+        int c;
+        for (int i=0; i<s.length(); i++) {
+            c = s.charAt(i);
+            if ((c == '\\') || (c == ';'))
+                sb.append('\\');
+            sb.append((char)c);
+        }
+        return sb.toString();
+    }
+
+    /**
+     * Stores all information about the entry type in preferences, with
+     * the tag given by number.
+     */
+    public void storeCustomEntryType(CustomEntryType tp, int number) {
+        String nr = ""+number;
+        put(CUSTOM_TYPE_NAME+nr, tp.getName());
+        putStringArray(CUSTOM_TYPE_REQ+nr, tp.getRequiredFields());
+        putStringArray(CUSTOM_TYPE_OPT+nr, tp.getOptionalFields());
+
+    }
+
+    /**
+     * Retrieves all information about the entry type in preferences,
+     * with the tag given by number.
+     */
+    public CustomEntryType getCustomEntryType(int number) {
+        String nr = ""+number;
+        String
+            name = get(CUSTOM_TYPE_NAME+nr);
+        String[]
+            req = getStringArray(CUSTOM_TYPE_REQ+nr),
+            opt = getStringArray(CUSTOM_TYPE_OPT+nr);
+        if (name == null)
+            return null;
+        else return new CustomEntryType
+            (Util.nCase(name), req, opt);
+
+
+    }
+
+    /**
+     * Removes all information about custom entry types with tags of
+     * @param number or higher.
+     */
+    public void purgeCustomEntryTypes(int number) {
+	purgeSeries(CUSTOM_TYPE_NAME, number);
+	purgeSeries(CUSTOM_TYPE_REQ, number);
+	purgeSeries(CUSTOM_TYPE_OPT, number);
+
+        /*while (get(CUSTOM_TYPE_NAME+number) != null) {
+            remove(CUSTOM_TYPE_NAME+number);
+            remove(CUSTOM_TYPE_REQ+number);
+            remove(CUSTOM_TYPE_OPT+number);
+            number++;
+	    }*/
+    }
+
+    /**
+     * Removes all entries keyed by prefix+number, where number
+     * is equal to or higher than the given number.
+     * @param number or higher.
+     */
+    public void purgeSeries(String prefix, int number) {
+        while (get(prefix+number) != null) {
+            remove(prefix+number);
+            number++;
+        }
+    }
+
+    public EntryEditorTabList getEntryEditorTabList() {
+	if (tabList == null)
+	    updateEntryEditorTabList();
+	return tabList;
+    }
+
+    public void updateEntryEditorTabList() {
+	tabList = new EntryEditorTabList();
+    }
+
+    /**
+     * Exports Preferences to an XML file.
+     *
+     * @param filename String File to export to
+     */
+    public void exportPreferences(String filename) throws IOException {
+      File f = new File(filename);
+      OutputStream os = new FileOutputStream(f);
+      try {
+        prefs.exportSubtree(os);
+      } catch (BackingStoreException ex) {
+        throw new IOException(ex.getMessage());
+      }
+    }
+
+      /**
+       * Imports Preferences from an XML file.
+       *
+       * @param filename String File to import from
+       */
+      public void importPreferences(String filename) throws IOException {
+        File f = new File(filename);
+        InputStream is = new FileInputStream(f);
+        try {
+          Preferences.importPreferences(is);
+        } catch (InvalidPreferencesFormatException ex) {
+          throw new IOException(ex.getMessage());
+        }
+      }
+
+    /**
+     * Determines whether the given field should be written without any sort of wrapping.
+     * @param fieldName The field name.
+     * @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/KeyBindingsDialog.java b/src/java/net/sf/jabref/KeyBindingsDialog.java
new file mode 100644
index 0000000..2d3da7c
--- /dev/null
+++ b/src/java/net/sf/jabref/KeyBindingsDialog.java
@@ -0,0 +1,362 @@
+/*
+ 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.
+
+ 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.util.*;
+import javax.swing.*;
+import javax.swing.table.AbstractTableModel;
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.event.*;
+import javax.swing.table.TableColumnModel;
+
+//
+class KeyBindingsDialog
+    extends JDialog {
+  KeystrokeTable table;
+  KeystrokeTableModel tableModel;
+  //JList list = new JList();
+  JTextField keyTF = new JTextField();
+  JButton ok, cancel, grabB, defB;
+  HashMap bindHM, defBinds;
+  boolean clickedSave = false;
+  int selectedRow = -1;
+  boolean getAction() {
+    return clickedSave;
+  }
+
+  HashMap getNewKeyBindings() {
+    return bindHM;
+  }
+
+  public KeyBindingsDialog(HashMap name2binding, HashMap defBinds) {
+    super();
+    this.defBinds = defBinds;
+    setTitle(Globals.lang("Key bindings"));
+    setModal(true); //this needs to be modal so that client knows when ok or cancel was clicked
+    getContentPane().setLayout(new BorderLayout());
+    bindHM = name2binding;
+    setList();
+    //JScrollPane listScroller = new JScrollPane(list);
+    JScrollPane listScroller = new JScrollPane(table);
+    listScroller.setPreferredSize(new Dimension(250, 400));
+    getContentPane().add(listScroller, BorderLayout.CENTER);
+
+    Box buttonBox = new Box(BoxLayout.X_AXIS);
+    ok = new JButton(Globals.lang("Ok"));
+    cancel = new JButton(Globals.lang("Cancel"));
+    grabB = new JButton(Globals.lang("Grab"));
+    defB = new JButton(Globals.lang("Default"));
+    grabB.addKeyListener(new JBM_CustomKeyBindingsListener());
+    /*grabB.addActionListener(new ActionListener() {
+      public void actionPerformed(ActionEvent e) {
+        selectedRow = (table.getSelectedRows())[0];
+        Util.pr(""+selectedRow);
+      }
+    });*/
+    buttonBox.add(grabB);
+    buttonBox.add(defB);
+    buttonBox.add(ok);
+    buttonBox.add(cancel);
+
+    getContentPane().add(buttonBox, BorderLayout.SOUTH);
+    //setTop();
+    setButtons();
+    keyTF.setEditable(false);
+
+    addWindowListener(new WindowAdapter() {
+      public void windowClosing(WindowEvent e) {
+        clickedSave = false;
+        dispose();
+      }
+    });
+  }
+
+  void setTop() {
+    Box topBox = new Box(BoxLayout.X_AXIS);
+
+    topBox.add(new JLabel(Globals.lang("Binding") + ":", JLabel.RIGHT));
+    topBox.add(keyTF);
+    getContentPane().add(topBox, BorderLayout.NORTH);
+
+  }
+
+  //##################################################
+  // respond to grabKey and display the key binding
+  //##################################################
+  public class JBM_CustomKeyBindingsListener
+      extends KeyAdapter {
+    public void keyPressed(KeyEvent evt) {
+      // first check if anything is selected if not the return
+      int selRow = table.getSelectedRow();
+      if (selRow < 0)
+        return;
+      //Util.pr("dei"+selectedRow+" "+table.getSelectedRow());
+      //Object[] selected = list.getSelectedValues();
+      //if (selected.length == 0) {
+      //  return;
+      //}
+
+      String code = KeyEvent.getKeyText(evt.getKeyCode());
+      String mod = KeyEvent.getKeyModifiersText(evt.getModifiers());
+      // all key bindings must have a modifier: ctrl alt etc
+
+      if (mod.equals("")) {
+        int kc = evt.getKeyCode();
+        if ( (kc < KeyEvent.VK_F1) && (kc > KeyEvent.VK_F12) &&
+            (kc != KeyEvent.VK_ESCAPE) && (kc != KeyEvent.VK_DELETE)) {
+          return; // need a modifier except for function keys
+        }
+      }
+      // second key cannot be a modifiers
+      //if ( evt.isActionKey()) {
+      //Util.pr(code);
+      if ( //code.equals("Escape")
+          code.equals("Tab")
+          || code.equals("Backspace")
+          || code.equals("Enter")
+          //|| code.equals("Delete")
+          || code.equals("Space")
+          || code.equals("Ctrl")
+          || code.equals("Shift")
+          || code.equals("Alt")) {
+        return;
+      }
+      //}
+      String newKey;
+      if (!mod.equals("")) {
+        newKey = mod.toLowerCase().replaceAll("\\+"," ") + " " + code;
+      }
+      else {
+        newKey = code;
+      }
+      keyTF.setText(newKey);
+      //find which key is selected and set its value int the bindHM
+      String selectedFunction = (String) table.getOriginalName(selRow);
+      table.setValueAt(newKey, selRow, 1);
+      table.revalidate();
+      table.repaint();
+      //Util.pr(selectedFunction);
+      //String selectedFunction = (String) list.getSelectedValue();
+      // log print
+      // System.out.println("selectedfunction " + selectedFunction + " new key: " + newKey);
+      bindHM.put(selectedFunction, newKey);
+      //table.setValueAt(newKey, );
+    }
+  }
+
+  //##################################################
+  // put the corresponding key binding into keyTF
+  //##################################################
+  class MyListSelectionListener
+      implements ListSelectionListener {
+    // This method is called each time the user changes the set of selected items
+    public void valueChanged(ListSelectionEvent evt) {
+      // When the user release the mouse button and completes the selection,
+      // getValueIsAdjusting() becomes false
+      if (!evt.getValueIsAdjusting()) {
+        JList list = (JList) evt.getSource();
+
+        // Get all selected items
+        Object[] selected = list.getSelectedValues();
+
+        // Iterate all selected items
+        for (int i = 0; i < selected.length; i++) {
+          Object sel = selected[i];
+          keyTF.setText( (String) bindHM.get(sel));
+        }
+      }
+    }
+  }
+
+  class MyListDataListener
+      implements ListDataListener {
+    // This method is called when new items have been added to the list
+    public void intervalAdded(ListDataEvent evt) {
+      DefaultListModel model = (DefaultListModel) evt.getSource();
+
+      // Get range of new  items
+      int start = evt.getIndex0();
+      int end = evt.getIndex1();
+      int count = end - start + 1;
+
+      // Get new items
+      for (int i = start; i <= end; i++) {
+        Object item = model.getElementAt(i);
+      }
+    }
+
+    // This method is called when items have been removed from the list
+    public void intervalRemoved(ListDataEvent evt) {
+      // Get range of removed items
+      int start = evt.getIndex0();
+      int end = evt.getIndex1();
+      int count = end - start + 1;
+
+      // The removed items are not available
+    }
+
+    // This method is called when items in the list are replaced
+    public void contentsChanged(ListDataEvent evt) {
+      DefaultListModel model = (DefaultListModel) evt.getSource();
+
+      // Get range of changed items
+      int start = evt.getIndex0();
+      int end = evt.getIndex1();
+      int count = end - start + 1;
+
+      // Get changed items
+      for (int i = start; i <= end; i++) {
+        Object item = model.getElementAt(i);
+      }
+    }
+  }
+
+  //setup so that clicking on list will display the current binding
+  void setList() {
+
+    DefaultListModel listModel = new DefaultListModel();
+    Iterator it = bindHM.keySet().iterator();
+    String[][] tableData = new String[bindHM.size()][3];
+    int i=0;
+    while (it.hasNext()) {
+      String s = (String) it.next();
+      tableData[i][2] = s;
+      tableData[i][1] = (String) bindHM.get(s);
+      tableData[i][0] = Globals.lang(s);
+      i++;
+      //listModel.addElement(s + " (" + bindHM.get(s) + ")");
+   }
+   TreeMap sorted = new TreeMap();
+   for (i=0; i<tableData.length; i++)
+     sorted.put(tableData[i][0], tableData[i]);
+
+    tableModel = new KeystrokeTableModel(sorted);
+    table = new KeystrokeTable(tableModel);
+    //table.setCellSelectionEnabled(false);
+    table.setRowSelectionAllowed(true);
+    table.setColumnSelectionAllowed(false);
+    table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+
+    //list.setModel(listModel);
+    TableColumnModel cm = table.getColumnModel();
+    cm.getColumn(0).setPreferredWidth(GUIGlobals.KEYBIND_COL_0);
+    cm.getColumn(1).setPreferredWidth(GUIGlobals.KEYBIND_COL_1);
+    table.setRowSelectionInterval(0, 0); //select the first entry
+  }
+
+  class KeystrokeTable extends JTable {
+    public KeystrokeTable(KeystrokeTableModel model) { super(model); }
+     public boolean isCellEditable(int row, int col) { return false; }
+     public String getOriginalName(int row) { return ((KeystrokeTableModel)getModel()).data[row][2]; }
+   }
+
+    class KeystrokeTableModel extends AbstractTableModel {
+      String[][] data;
+      //String[] trData;
+      public KeystrokeTableModel(TreeMap sorted) {
+        data = new String[sorted.size()][3];
+        Iterator i = sorted.keySet().iterator();
+        int row = 0;
+        while (i.hasNext()) {
+          data[row++] = ((String[])sorted.get(i.next()));
+        }
+        //for (int i=0; i<trData.length; i++)
+        //  trData[i] = Globals.lang(data[i][0]);
+      }
+      public boolean isCellEditable(int row, int col) { return false; }
+      public String getColumnName(int col) {
+        return (col==0 ? Globals.lang("Action") : Globals.lang("Shortcut"));
+      }
+      public int getColumnCount() {
+        return 2;
+      }
+
+      public int getRowCount() {
+        return data.length;
+      }
+      public Object getValueAt(int rowIndex, int columnIndex) {
+        //if (columnIndex == 0)
+        return data[rowIndex][columnIndex];
+        //else
+        //return data[rowIndex][0];
+      }
+      public void setValueAt(Object o, int row, int col) {
+        data[row][col] = (String)o;
+      }
+    }
+
+  // listners
+  void setButtons() {
+    ok.addActionListener(new ActionListener() {
+      public void actionPerformed(ActionEvent e) {
+        // save all the key bindings
+        dispose();
+        clickedSave = true;
+        // message: key bindings will take into effect next time you start JBM
+      }
+    });
+    cancel.addActionListener(new ActionListener() {
+      public void actionPerformed(ActionEvent e) {
+        dispose();
+        clickedSave = false;
+        //System.exit(-1);//get rid of this
+      }
+    });
+    defB.addActionListener(new ActionListener() {
+      public void actionPerformed(ActionEvent e) {
+        /*Object[] selected = list.getSelectedValues();
+        if (selected.length == 0) {
+          return;
+        }
+        keyTF.setText(setToDefault( (String) list.getSelectedValue()));*/
+      }
+    });
+
+  }
+
+  String setToDefault(String name) {
+    String defKey = (String) defBinds.get(name);
+    bindHM.put(name, defKey);
+    return defKey;
+  }
+
+  /*
+       public static void main(String args[])
+       {
+    HashMap h=new HashMap();
+    h.put("new-bibtex","ctrl N");
+    h.put("edit-bibtex","ctrl E");
+    h.put("exit-bibtex","ctrl Q");
+    KeyBindingsDialog d= new KeyBindingsDialog(h);
+    d.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+    d.setSize(200,300);
+    d.setVisible(true);
+
+    }*/
+}
diff --git a/src/java/net/sf/jabref/KeyCollisionException.java b/src/java/net/sf/jabref/KeyCollisionException.java
new file mode 100644
index 0000000..3c2717f
--- /dev/null
+++ b/src/java/net/sf/jabref/KeyCollisionException.java
@@ -0,0 +1,49 @@
+/*
+Copyright (C) 2003 David Weitzman
+
+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;
+
+public class KeyCollisionException extends Exception
+{
+    public KeyCollisionException()
+    {
+        super();
+    }
+
+    public KeyCollisionException(String msg)
+    {
+        super(msg);
+    }
+
+    public KeyCollisionException(String msg, Throwable exception)
+    {
+        super(msg, exception);
+    }
+
+    public KeyCollisionException(Throwable exception)
+    {
+        super(exception);
+    }
+}
diff --git a/src/java/net/sf/jabref/MarkedComparator.java b/src/java/net/sf/jabref/MarkedComparator.java
new file mode 100644
index 0000000..48ae85d
--- /dev/null
+++ b/src/java/net/sf/jabref/MarkedComparator.java
@@ -0,0 +1,41 @@
+package net.sf.jabref;
+
+import java.util.Comparator;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: alver
+ * Date: Sep 1, 2005
+ * Time: 11:35:02 PM
+ * To change this template use File | Settings | File Templates.
+ */
+public class MarkedComparator implements Comparator {
+
+    Comparator next;
+
+    public MarkedComparator(Comparator next) {
+        this.next = next;
+    }
+    public int compare(Object o1, Object o2) {
+
+        BibtexEntry e1 = (BibtexEntry)o1,
+            e2 = (BibtexEntry)o2;
+
+        if (e1 == e2)
+            return 0;
+
+        boolean mrk1 = Util.isMarked(e1),
+                mrk2 = Util.isMarked(e2);
+
+        if (mrk1 == mrk2)
+            return (next != null ? next.compare(o1, o2) : idCompare(e1, e2));
+
+        else if (mrk2)
+            return 1;
+        else return -1;
+    }
+
+    private int idCompare(BibtexEntry b1, BibtexEntry b2) {
+	    return ((String)(b1.getId())).compareTo((String)(b2.getId()));
+    }
+}
diff --git a/src/java/net/sf/jabref/MergeDialog.java b/src/java/net/sf/jabref/MergeDialog.java
new file mode 100644
index 0000000..99d3fd2
--- /dev/null
+++ b/src/java/net/sf/jabref/MergeDialog.java
@@ -0,0 +1,130 @@
+package net.sf.jabref;
+
+import java.awt.*;
+import javax.swing.*;
+import javax.swing.border.*;
+import java.awt.event.*;
+
+/**
+ * <p>Title: MergeDialog</p>
+ * <p>Description: Asks for details about merge database operation.</p>
+ * <p>Copyright: Copyright (c) 2003</p>
+ * @author Morten O. Alver
+ */
+
+public class MergeDialog extends JDialog {
+  JPanel panel1 = new JPanel();
+  BorderLayout borderLayout1 = new BorderLayout();
+  JPanel jPanel1 = new JPanel();
+  JPanel jPanel2 = new JPanel();
+  JButton ok = new JButton();
+  JButton Cancel = new JButton();
+  TitledBorder titledBorder1;
+  JCheckBox entries = new JCheckBox();
+  JCheckBox strings = new JCheckBox();
+  GridBagLayout gridBagLayout1 = new GridBagLayout();
+  JCheckBox groups = new JCheckBox();
+  JCheckBox selector = new JCheckBox();
+
+  boolean okPressed = false;
+
+  public MergeDialog(JabRefFrame frame, String title, boolean modal) {
+    super(frame, title, modal);
+    try {
+      jbInit(frame);
+      pack();
+    }
+    catch(Exception ex) {
+      ex.printStackTrace();
+    }
+  }
+
+  public MergeDialog() {
+    this(null, "", false);
+  }
+
+  private void jbInit(JabRefFrame parent) {
+      titledBorder1 = new TitledBorder(BorderFactory.createLineBorder(new Color(153, 153, 153),2),Globals.lang("Options"));
+    panel1.setLayout(borderLayout1);
+    ok.setText(Globals.lang("Ok"));
+    ok.addActionListener(new MergeDialog_ok_actionAdapter(this));
+    Cancel.setText(Globals.lang("Cancel"));
+    Cancel.addActionListener(new MergeDialog_Cancel_actionAdapter(this));
+    jPanel1.setBorder(titledBorder1);
+    jPanel1.setLayout(gridBagLayout1);
+    entries.setToolTipText("");
+    entries.setSelected(true);
+    entries.setText(Globals.lang("Import entries"));
+    strings.setSelected(true);
+    strings.setText(Globals.lang("Import strings"));
+    groups.setText(Globals.lang("Import group definitions"));
+    selector.setText(Globals.lang("Import word selector definitions"));
+    this.setModal(true);
+    this.setResizable(false);
+    this.setTitle("Import database");
+    getContentPane().add(panel1);
+    panel1.add(jPanel2, BorderLayout.SOUTH);
+    jPanel2.add(ok, null);
+    jPanel2.add(Cancel, null);
+    panel1.add(jPanel1, BorderLayout.CENTER);
+    jPanel1.add(entries,     new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0
+            ,GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0));
+    jPanel1.add(strings,     new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0
+            ,GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
+    jPanel1.add(groups,  new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0
+            ,GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
+    jPanel1.add(selector,  new GridBagConstraints(0, 3, 1, 1, 0.0, 0.0
+            ,GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
+
+    // Key bindings:
+    ActionMap am = jPanel1.getActionMap();
+    InputMap im = jPanel1.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
+    im.put(parent.prefs.getKey("Close dialog"), "close");
+    am.put("close", new AbstractAction() {
+      public void actionPerformed(ActionEvent e) {
+        dispose();
+      }
+    });
+
+  }
+
+  void ok_actionPerformed(ActionEvent e) {
+    okPressed = true;
+    dispose();
+  }
+
+  void Cancel_actionPerformed(ActionEvent e) {
+    dispose();
+  }
+
+  public boolean okPressed() {
+    return okPressed;
+  }
+
+  public boolean importEntries() { return entries.isSelected(); }
+  public boolean importGroups() { return groups.isSelected(); }
+  public boolean importStrings() { return strings.isSelected(); }
+  public boolean importSelectorWords() { return selector.isSelected(); }
+}
+
+class MergeDialog_ok_actionAdapter implements java.awt.event.ActionListener {
+  MergeDialog adaptee;
+
+  MergeDialog_ok_actionAdapter(MergeDialog adaptee) {
+    this.adaptee = adaptee;
+  }
+  public void actionPerformed(ActionEvent e) {
+    adaptee.ok_actionPerformed(e);
+  }
+}
+
+class MergeDialog_Cancel_actionAdapter implements java.awt.event.ActionListener {
+  MergeDialog adaptee;
+
+  MergeDialog_Cancel_actionAdapter(MergeDialog adaptee) {
+    this.adaptee = adaptee;
+  }
+  public void actionPerformed(ActionEvent e) {
+    adaptee.Cancel_actionPerformed(e);
+  }
+}
diff --git a/src/java/net/sf/jabref/MetaData.java b/src/java/net/sf/jabref/MetaData.java
new file mode 100644
index 0000000..8b74a69
--- /dev/null
+++ b/src/java/net/sf/jabref/MetaData.java
@@ -0,0 +1,228 @@
+/*
+ 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.
+
+ 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.util.*;
+
+import net.sf.jabref.groups.*;
+
+public class MetaData {
+    private HashMap metaData = new HashMap();
+    private StringReader data;
+    private GroupTreeNode groupsRoot = null;
+
+    /**
+     * 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
+     * must simply make sure the appropriate changes are reflected in the Vector
+     * it has been passed.
+     */
+    public MetaData(HashMap inData, BibtexDatabase db) {
+        this();
+        boolean groupsTreePresent = false;
+        Vector flatGroupsData = null;
+        Vector treeGroupsData = null;
+        // The first version (0) lacked a version specification, 
+        // thus this value defaults to 0.
+        int groupsVersionOnDisk = 0;
+        
+        if (inData != null) for (Iterator i = inData.keySet().iterator(); i.hasNext();) {
+            String key = (String) i.next();
+            data = new StringReader((String) inData.get(key));
+            String unit;
+            Vector orderedData = new Vector();
+            // We must allow for ; and \ in escape sequences.
+            try {
+                while ((unit = getNextUnit(data)) != null) {
+                    orderedData.add(unit);
+                }
+            } catch (IOException ex) {
+                System.err.println("Weird error while parsing meta data.");
+            }
+            if (key.equals("groupsversion")) {
+                if (orderedData.size() >= 1)
+                    groupsVersionOnDisk = Integer.parseInt(orderedData.firstElement().toString());
+            } else if (key.equals("groupstree")) {
+                groupsTreePresent = true;
+                treeGroupsData = orderedData; // save for later user
+                // actual import operation is handled later because "groupsversion"
+                // tag might not yet have been read
+            } else if (key.equals("groups")) {
+                flatGroupsData = orderedData;
+            } else {
+                putData(key, orderedData);
+            }
+        }
+        
+        // this possibly handles import of a previous groups version
+        if (groupsTreePresent)
+            putGroups(treeGroupsData, db, groupsVersionOnDisk);
+        
+        if (!groupsTreePresent && flatGroupsData != null) {
+            groupsRoot = VersionHandling.importFlatGroups(flatGroupsData);
+        }
+    }
+
+    /**
+     * The MetaData object can be constructed with no data in it.
+     */
+    public MetaData() {
+        metaData.put(Globals.SELECTOR_META_PREFIX + "keywords", new Vector());
+        metaData.put(Globals.SELECTOR_META_PREFIX + "author", new Vector());
+        metaData.put(Globals.SELECTOR_META_PREFIX + "journal", new Vector());
+        metaData.put(Globals.SELECTOR_META_PREFIX + "publisher", new Vector());
+    }
+
+    public Iterator iterator() {
+        return metaData.keySet().iterator();
+    }
+
+    public Vector getData(String key) {
+        return (Vector) metaData.get(key);
+    }
+
+    public void remove(String key) {
+        metaData.remove(key);
+    }
+
+    /**
+     * Stores the specified data in this object, using the specified key. For
+     * certain keys (e.g. "groupstree"), the objects in orderedData are
+     * reconstructed from their textual (String) representation if they are of
+     * type String, and stored as an actual instance.
+     */
+    public void putData(String key, Vector orderedData) {
+        metaData.put(key, orderedData);
+    }
+    
+    private void putGroups(Vector orderedData, BibtexDatabase db, int version) {
+        try {
+            groupsRoot = VersionHandling.importGroups(orderedData, db, 
+                    version);
+        } catch (Exception e) {
+            // we cannot really do anything about this here
+            System.err.println(e);
+        }
+    }
+    
+    public GroupTreeNode getGroups() {
+        return groupsRoot;
+    }
+    
+    /**
+     * Sets a new group root node. <b>WARNING </b>: This invalidates everything
+     * returned by getGroups() so far!!!
+     */
+    public void setGroups(GroupTreeNode root) {
+        groupsRoot = root;
+    }
+
+    /**
+     * Writes all data to the specified writer, using each object's toString()
+     * method.
+     */
+    public void writeMetaData(Writer out) throws IOException {
+        // write all meta data except groups
+        for (Iterator i = metaData.keySet().iterator(); i.hasNext();) {
+            String key = (String) i.next();
+            StringBuffer sb = new StringBuffer();
+            Vector orderedData = (Vector) metaData.get(key);
+            if (orderedData.size() > 0) {
+                sb.append("@comment{").append(GUIGlobals.META_FLAG).append(key).append(":");
+                for (int j = 0; j < orderedData.size(); j++) {
+                    sb.append(Util.quote((String) orderedData.elementAt(j), ";", '\\')).append(";");
+                }
+                sb.append("}");
+                sb.append(Globals.NEWLINE);
+                sb.append(Globals.NEWLINE);
+            }
+            wrapStringBuffer(sb, Globals.METADATA_LINE_LENGTH);
+            out.write(sb.toString());
+        }
+        // write groups if present. skip this if only the root node exists 
+        // (which is always the AllEntriesGroup).
+        if (groupsRoot != null && groupsRoot.getChildCount() > 0) {
+            StringBuffer sb = new StringBuffer();
+            // write version first
+            sb.append("@comment{").append(GUIGlobals.META_FLAG).append("groupsversion:");
+            sb.append(""+VersionHandling.CURRENT_VERSION+";");
+            sb.append("}");
+            sb.append(Globals.NEWLINE);
+            sb.append(Globals.NEWLINE);
+            out.write(sb.toString());
+            
+            // now write actual groups
+            sb = new StringBuffer();
+            sb.append("@comment{").append(GUIGlobals.META_FLAG).append("groupstree:");
+            sb.append(Globals.NEWLINE);
+            // GroupsTreeNode.toString() uses "\n" for separation
+            StringTokenizer tok = new StringTokenizer(groupsRoot.getTreeAsString(),Globals.NEWLINE);
+            while (tok.hasMoreTokens()) {
+                StringBuffer s = 
+                    new StringBuffer(Util.quote(tok.nextToken(), ";", '\\') + ";");
+                wrapStringBuffer(s, Globals.METADATA_LINE_LENGTH);
+                sb.append(s);
+                sb.append(Globals.NEWLINE);
+            }
+            sb.append("}");
+            sb.append(Globals.NEWLINE);
+            sb.append(Globals.NEWLINE);
+            out.write(sb.toString());
+        }
+    }
+
+    private void wrapStringBuffer(StringBuffer sb, int lineLength) {
+        for (int i=lineLength; i<sb.length(); i+=lineLength+1) {
+            sb.insert(i, Globals.NEWLINE);
+        }
+    }
+    
+    /**
+     * Reads the next unit. Units are delimited by ';'. 
+     */
+    private String getNextUnit(Reader reader) throws IOException {
+        int c;
+        boolean escape = false;
+        StringBuffer res = new StringBuffer();
+        while ((c = reader.read()) != -1) {
+            if (escape) {
+                res.append((char)c);
+                escape = false;
+            } else if (c == '\\') {
+                escape = true;
+            } else if (c == ';') {
+                break;
+            } else {
+                res.append((char)c);
+            }
+        }
+        if (res.length() > 0)
+            return res.toString();
+        return null;
+    }
+}
diff --git a/src/java/net/sf/jabref/MnemonicAwareAction.java b/src/java/net/sf/jabref/MnemonicAwareAction.java
new file mode 100644
index 0000000..cdf7c58
--- /dev/null
+++ b/src/java/net/sf/jabref/MnemonicAwareAction.java
@@ -0,0 +1,64 @@
+/*
+Copyright (C) 2003 Morten O. Alver and 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;
+
+
+import javax.swing.*;
+/**
+ * This class extends {@link AbstractAction} with the ability to set
+ * the mnemonic key based on a '&' character inserted in front of
+ * the desired mnemonic letter. This is done by setting the action's
+ * name using putValue(NAME, actionname).
+ * This facilitates localized mnemonics.
+ */
+public abstract class MnemonicAwareAction extends AbstractAction {
+
+    public MnemonicAwareAction() {
+	//super("");
+    }
+
+    public MnemonicAwareAction(ImageIcon icon) {
+	//super(icon);
+        
+        putValue(SMALL_ICON, icon);
+    }
+
+    public void putValue(String key, Object value) {
+	if (key.equals(Action.NAME)) {
+	    String name = Globals.menuTitle(value.toString());
+	    int i = name.indexOf('&');
+	    if (i >= 0) {
+		char mnemonic = Character.toUpperCase(name.charAt(i+1));
+		putValue(Action.MNEMONIC_KEY, new Integer((int) mnemonic));
+		value = name.substring(0, i) + name.substring(i+1);
+	    } else
+                value = name;
+	}
+	super.putValue(key, value);
+    }
+}
diff --git a/src/java/net/sf/jabref/NameCache.java b/src/java/net/sf/jabref/NameCache.java
new file mode 100644
index 0000000..8d1d1d0
--- /dev/null
+++ b/src/java/net/sf/jabref/NameCache.java
@@ -0,0 +1,33 @@
+package net.sf.jabref;
+
+import java.util.HashMap;
+
+/**
+ * HashMap that empties itself upon reaching a maximum entry count. Used to cache
+ * name transformations for better performance. By doing this, we accomplish removing
+ * old entries that may never be used again.
+ * @author Morten O. Alver
+ */
+public class NameCache extends HashMap {
+
+  int max, toAdd;
+
+  public NameCache(int max_) {
+    max = max_;
+    toAdd = max_;
+  }
+
+  public Object put(Object key, Object o) {
+    super.put(key, o);
+    if (size() > max) {
+
+      // We have reached the maximum entry count. Thus we remove all entries, and increase the
+      // max value.
+      clear();
+      max += toAdd;
+      super.put(key, o);
+    }
+
+    return o;
+  }
+}
diff --git a/src/java/net/sf/jabref/OpenFileFilter.java b/src/java/net/sf/jabref/OpenFileFilter.java
new file mode 100644
index 0000000..35584e2
--- /dev/null
+++ b/src/java/net/sf/jabref/OpenFileFilter.java
@@ -0,0 +1,102 @@
+package net.sf.jabref;
+
+import java.util.*;
+import java.io.*;
+
+public class OpenFileFilter extends javax.swing.filechooser.FileFilter implements FilenameFilter {
+
+  HashSet extSet = new HashSet();
+  String desc;
+
+  public OpenFileFilter(String[] extensions) {
+    StringBuffer buf = new StringBuffer();
+    int numExt = extensions.length;
+
+    if (numExt>0) {
+      buf.append('*');
+      buf.append(extensions[0]);
+
+      extSet.add(extensions[0]);
+    }
+
+    for(int curExt = 1; curExt<numExt; curExt++) {
+      buf.append(", *");
+      buf.append(extensions[curExt]);
+
+      extSet.add(extensions[curExt]);
+    }
+
+    desc = buf.toString();
+  }
+
+  public OpenFileFilter() {
+    this( new String[] {
+      ".bib",
+      ".dat",  // silverplatter ending
+      ".txt",  // windows puts ".txt" extentions and for scifinder
+      ".ris",
+      ".ref",  // refer/endnote format
+      ".fcgi", // default for pubmed
+      ".bibx", // default for BibTeXML
+      ".xml"
+    });
+  }
+
+  public OpenFileFilter(String s) {
+    this(s.split("[, ]+",0));
+  }
+
+  public boolean accept(File file){
+    if (file.isDirectory())
+      return true;
+
+    return accept(file.getName());
+  }
+
+  public boolean accept(String filenm){
+
+    filenm = filenm.toLowerCase();
+    int dotPos = filenm.lastIndexOf(".");
+
+    if (dotPos==-1)
+      return false;
+
+    int dotDotPos = filenm.lastIndexOf(".", dotPos-1); // for dot.dot extensions
+
+    return extSet.contains(filenm.substring(dotPos)) ||
+      (dotDotPos>=0 && extSet.contains(filenm.substring(dotDotPos)));
+  }
+
+  public String getSuffix(String filenm) {
+
+    int dotPos;
+    String suffix;
+    
+    dotPos = filenm.lastIndexOf(".");
+    if (dotPos==-1)
+      return null;
+
+    suffix = filenm.substring(dotPos);
+    if (extSet.contains(suffix))
+      return suffix;
+
+    dotPos = filenm.lastIndexOf(".", dotPos-1); // for dot.dot extensions
+    if (dotPos==-1)
+      return null;
+
+    suffix = filenm.substring(dotPos);
+    if (extSet.contains(suffix))
+      return suffix;
+
+    return null;
+  }
+
+  public String getDescription(){
+    return desc;
+  }
+
+  public boolean accept(File dir, String name) {
+    return accept(new File(dir.getPath()+name));
+  }
+}
+
diff --git a/src/java/net/sf/jabref/PreambleEditor.java b/src/java/net/sf/jabref/PreambleEditor.java
new file mode 100644
index 0000000..807f101
--- /dev/null
+++ b/src/java/net/sf/jabref/PreambleEditor.java
@@ -0,0 +1,221 @@
+/*
+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.
+
+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.awt.event.*;
+import java.awt.*;
+import javax.swing.*;
+import net.sf.jabref.undo.UndoablePreambleChange;
+
+public class PreambleEditor extends JDialog {
+
+    // A reference to the entry this object works on.
+    BibtexDatabase base;
+    BasePanel panel;
+    JabRefFrame baseFrame;
+    JabRefPreferences prefs;
+
+    // Layout objects.
+    GridBagLayout gbl = new GridBagLayout();
+    GridBagConstraints con = new GridBagConstraints();
+    JLabel lab;
+    Container conPane = getContentPane();
+    //JToolBar tlb = new JToolBar();
+    JPanel pan = new JPanel();
+    FieldEditor ed;
+
+
+    public PreambleEditor(JabRefFrame baseFrame,
+			  BasePanel panel, BibtexDatabase base,
+			  JabRefPreferences prefs) {
+	super(baseFrame);
+	this.baseFrame = baseFrame;
+	this.panel = panel;
+	this.base = base;
+	this.prefs = prefs;
+
+	addWindowListener(new WindowAdapter() {
+		public void windowClosing(WindowEvent e) {
+		    closeAction.actionPerformed(null);
+		}
+		public void windowOpened(WindowEvent e) {
+		    ed.requestFocus();
+		}
+	    });
+	setFocusTraversalPolicy(new LayoutFocusTraversalPolicy() {
+		protected boolean accept(Component c) {
+		    return (super.accept(c) && (c instanceof FieldEditor));
+		}
+	    });
+
+	int prefHeight = (int)(GUIGlobals.PE_HEIGHT*GUIGlobals.FORM_HEIGHT[prefs.getInt("entryTypeFormHeightFactor")]);
+	setSize(GUIGlobals.FORM_WIDTH[prefs.getInt("entryTypeFormWidth")], prefHeight);
+
+	pan.setLayout(gbl);
+	con.fill = GridBagConstraints.BOTH;
+	con.weighty = 1;
+	con.insets = new Insets(10,5,10,5);
+
+	String content = base.getPreamble();
+
+	ed = new FieldTextArea(Globals.lang("Preamble"), ((content != null) ? content : ""));
+	setupJTextComponent((FieldTextArea)ed);
+
+	gbl.setConstraints(ed.getLabel(), con);
+	pan.add(ed.getLabel());
+
+	con.weightx = 1;
+
+	gbl.setConstraints(ed.getPane(), con);
+	pan.add(ed.getPane());
+
+	//tlb.add(closeAction);
+	//conPane.add(tlb, BorderLayout.NORTH);
+	conPane.add(pan, BorderLayout.CENTER);
+	setTitle(Globals.lang("Edit preamble"));
+    }
+
+    private void setupJTextComponent(javax.swing.text.JTextComponent ta) {
+	// Set up key bindings and focus listener for the FieldEditor.
+	ta.getInputMap().put(prefs.getKey("Close preamble editor"), "close");
+	ta.getActionMap().put("close", closeAction);
+	ta.getInputMap().put(prefs.getKey("Preamble editor, store changes"), "store");
+	ta.getActionMap().put("store", storeFieldAction);
+	ta.getInputMap().put(prefs.getKey("Close preamble editor"), "close");
+	ta.getActionMap().put("close", closeAction);
+
+	ta.getInputMap().put(prefs.getKey("Undo"), "undo");
+	ta.getActionMap().put("undo", undoAction);
+	ta.getInputMap().put(prefs.getKey("Redo"), "redo");
+	ta.getActionMap().put("redo", redoAction);
+
+
+	ta.addFocusListener(new FieldListener());
+    }
+
+    public void updatePreamble() {
+	ed.setText(base.getPreamble());
+    }
+
+   class FieldListener extends FocusAdapter {
+	/*
+	 * Focus listener that fires the storeFieldAction when a FieldTextArea
+	 * loses focus.
+	 */
+       public void focusLost(FocusEvent e) {
+	   if (!e.isTemporary())
+	       storeFieldAction.actionPerformed(new ActionEvent(e.getSource(), 0, ""));
+       }
+
+   }
+
+    StoreFieldAction storeFieldAction = new StoreFieldAction();
+    class StoreFieldAction extends AbstractAction {
+	public StoreFieldAction() {
+	    super("Store field value");
+	    putValue(SHORT_DESCRIPTION, "Store field value");
+	}
+	public void actionPerformed(ActionEvent e) {
+	    String toSet = null;
+	    boolean set;
+	    if (ed.getText().length() > 0)
+		toSet = ed.getText();
+	    // 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 (base.getPreamble() == null)
+		    set = false;
+		else
+		    set = true;
+	    } else {
+		if ((base.getPreamble() != null)
+		    && toSet.equals(base.getPreamble()))
+		    set = false;
+		    else
+		    set = true;
+	    }
+
+	    if (set) {
+		panel.undoManager.addEdit(new UndoablePreambleChange
+				  (base, panel, base.getPreamble(), toSet));
+		base.setPreamble(toSet);
+		if ((toSet != null) && (toSet.length() > 0)) {
+		    ed.setLabelColor(GUIGlobals.validFieldColor);
+		    ed.setBackground(GUIGlobals.validFieldBackground);
+		} else {
+		    ed.setLabelColor(GUIGlobals.nullFieldColor);
+		    ed.setBackground(GUIGlobals.validFieldBackground);
+		}
+		panel.markBaseChanged();
+	    }
+
+	}
+    }
+
+    UndoAction undoAction = new UndoAction();
+    class UndoAction extends AbstractAction {
+	public UndoAction() {
+	    super("Undo", new ImageIcon(GUIGlobals.undoIconFile));
+	    putValue(SHORT_DESCRIPTION, "Undo");
+	}
+	public void actionPerformed(ActionEvent e) {
+	    try {
+		panel.runCommand("undo");
+	    } catch (Throwable ex) {}
+	}
+    }
+
+    RedoAction redoAction = new RedoAction();
+    class RedoAction extends AbstractAction {
+	public RedoAction() {
+	    super("Undo", new ImageIcon(GUIGlobals.redoIconFile));
+	    putValue(SHORT_DESCRIPTION, "Redo");
+	}
+	public void actionPerformed(ActionEvent e) {
+	    try {
+		panel.runCommand("redo");
+	    } catch (Throwable ex) {}
+	}
+    }
+
+    // The action concerned with closing the window.
+    CloseAction closeAction = new CloseAction();
+    class CloseAction extends AbstractAction {
+	public CloseAction() {
+	    super(Globals.lang("Close window"));
+	    //, new ImageIcon(GUIGlobals.closeIconFile));
+	    //putValue(SHORT_DESCRIPTION, "Close window (Ctrl-Q)");
+	}
+	public void actionPerformed(ActionEvent e) {
+	    storeFieldAction.actionPerformed(null);
+	    panel.preambleEditorClosing();
+	    dispose();
+	}
+    }
+
+}
diff --git a/src/java/net/sf/jabref/PrefsDialog2.java b/src/java/net/sf/jabref/PrefsDialog2.java
new file mode 100644
index 0000000..bfe7eed
--- /dev/null
+++ b/src/java/net/sf/jabref/PrefsDialog2.java
@@ -0,0 +1,150 @@
+/*
+Copyright (C) 2003 JabRef project
+
+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.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import javax.swing.table.*;
+
+/**
+ * Preferences dialog. Contains a TabbedPane, and tabs will be defined
+ * in separate classes. Tabs MUST implement the PrefsTab interface,
+ * since this dialog will call the storeSettings() method of all tabs
+ * when the user presses ok.
+ *
+ * With this design, it should be very easy to add new tabs later.
+ *
+ */
+public class PrefsDialog2 extends JDialog {
+
+    private JabRefPreferences _prefs;
+    JPanel upper = new JPanel(),
+        lower = new JPanel();
+    GridBagLayout gbl = new GridBagLayout();
+    GridBagConstraints con = new GridBagConstraints();
+    JTabbedPane tabbed = new JTabbedPane();
+    JabRefFrame frame;
+
+    public PrefsDialog2(JabRefFrame parent, JabRefPreferences prefs) {
+        super(parent, Globals.lang("JabRef preferences"), false);
+        _prefs = prefs;
+        frame = parent;
+        getContentPane().setLayout(gbl);
+        con.weighty = 1;
+        con.weightx = 1;
+        con.fill = GridBagConstraints.BOTH;
+        con.gridwidth = GridBagConstraints.REMAINDER;
+        con.insets = new Insets(5, 5, 0, 5);
+        gbl.setConstraints(tabbed, con);
+        getContentPane().add(tabbed);
+        con.weighty = 0;
+        con.gridheight = GridBagConstraints.REMAINDER;
+        gbl.setConstraints(lower, con);
+        //lower.setBackground(GUIGlobals.lightGray);
+        //getContentPane().setBackground(GUIGlobals.lightGray);
+        getContentPane().add(lower);
+
+        // ----------------------------------------------------------------
+        // Add tabs to tabbed 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));
+	
+	if (!Globals.ON_MAC)
+	    tabbed.addTab(Globals.lang("Advanced"), new AdvancedTab(_prefs, parent.helpDiag));
+        JButton
+            ok = new JButton(Globals.lang("Ok")),
+            cancel = new JButton(Globals.lang("Cancel"));
+        ok.addActionListener(new OkAction());
+        CancelAction cancelAction = new CancelAction();
+        cancel.addActionListener(cancelAction);
+        lower.add(ok);
+        lower.add(cancel);
+
+        // Key bindings:
+        ActionMap am = tabbed.getActionMap();
+        InputMap im = tabbed.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
+        im.put(frame.prefs().getKey("Close dialog"), "close");
+        am.put("close", cancelAction);
+
+        pack(); //setSize(440, 500);
+    }
+
+    class OkAction extends AbstractAction {
+        public OkAction() {
+            super("Ok");
+        }
+        public void actionPerformed(ActionEvent e) {
+
+	    AbstractWorker worker = new AbstractWorker() {
+		    public void run() {
+			// First check that all tabs are ready to close:
+			for (int i = 0; i < tabbed.getTabCount(); i++) {
+			    if (!((PrefsTab)tabbed.getComponentAt(i)).readyToClose())
+				return; // If not, break off.
+			}			
+			// Then store settings and close:
+			for (int i = 0; i < tabbed.getTabCount(); i++) {
+			    ( (PrefsTab) tabbed.getComponentAt(i)).storeSettings();
+			}
+
+			//try { Thread.sleep(3000); } catch (InterruptedException ex) {}
+		    }
+		    public void update() {
+			dispose();
+			frame.setupAllTables();
+			frame.output(Globals.lang("Preferences recorded."));
+		    }
+		};
+            worker.getWorker().run();
+            worker.getCallBack().update();
+            
+        }
+    }
+
+    class CancelAction extends AbstractAction {
+        public CancelAction() {
+            super("Cancel");
+
+        }
+        public void actionPerformed(ActionEvent e) {
+	    dispose();
+            // Just close dialog without recording changes.
+            /*(new Thread() {
+              public void run() {
+
+              }
+	      }).start();*/
+        }
+    }
+
+}
diff --git a/src/java/net/sf/jabref/PrefsDialog3.java b/src/java/net/sf/jabref/PrefsDialog3.java
new file mode 100644
index 0000000..f9950b6
--- /dev/null
+++ b/src/java/net/sf/jabref/PrefsDialog3.java
@@ -0,0 +1,300 @@
+/*
+Copyright (C) 2003 JabRef project
+
+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.awt.*;
+import java.awt.event.*;
+import java.io.*;
+import java.util.*;
+
+import javax.swing.*;
+import javax.swing.event.*;
+
+import net.sf.jabref.groups.GroupsPrefsTab;
+import net.sf.jabref.gui.MainTable;
+
+/**
+ * Preferences dialog. Contains a TabbedPane, and tabs will be defined
+ * in separate classes. Tabs MUST implement the PrefsTab interface,
+ * since this dialog will call the storeSettings() method of all tabs
+ * when the user presses ok.
+ *
+ * With this design, it should be very easy to add new tabs later.
+ *
+ */
+public class PrefsDialog3 extends JDialog {
+
+    private JabRefPreferences _prefs;
+    JPanel upper = new JPanel(),
+        lower = new JPanel(),
+    main = new JPanel();/* {
+		public void add(Component c, Object o) {
+		    super.add(c, o);
+		    System.out.println(o+" "+c.getPreferredSize());
+		    }
+		    };*/
+    JList chooser;
+    JButton importPrefs = new JButton(Globals.lang("Import preferences")),
+    exportPrefs = new JButton(Globals.lang("Export preferences"));
+    CardLayout cardLayout = new CardLayout();
+    HashMap panels = new HashMap();
+    JabRefFrame frame;
+    PrefsDialog3 ths = this;
+
+    public PrefsDialog3(JabRefFrame parent, JabRefPreferences prefs) {
+        super(parent, Globals.lang("JabRef preferences"), false);
+        _prefs = prefs;
+        frame = parent;
+        getContentPane().setLayout(new BorderLayout());
+    getContentPane().add(upper, BorderLayout.CENTER);
+        getContentPane().add(lower, BorderLayout.SOUTH);
+
+        // ----------------------------------------------------------------
+        // Add tabs to tabbed here. Remember, tabs must implement PrefsTab.
+        // ----------------------------------------------------------------
+    String
+        GEN = Globals.lang("General"),
+        APP = Globals.lang("Appearance"),
+        GRP = Globals.lang("Groups"), // JZTODO lyrics
+        EXT = Globals.lang("External programs"),
+        TAB = Globals.lang("Entry table"),
+        COL = Globals.lang("Entry table columns"),
+        KEY = Globals.lang("Key pattern"),
+        PRE = Globals.lang("Entry preview"),
+        //JOU = Globals.lang("Journal names"),
+        ADV = Globals.lang("Advanced");
+
+    ArrayList al = new ArrayList();
+    al.add(GEN);
+    al.add(APP);
+    al.add(GRP);
+    al.add(EXT);
+    al.add(TAB);
+    al.add(COL);
+    al.add(KEY);
+    //al.add(JOU);
+    al.add(PRE);
+
+    main.setLayout(cardLayout);
+
+        main.add(new GeneralTab(frame, _prefs), GEN);
+    if (!Globals.ON_MAC) {
+        al.add(ADV);
+        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), 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);
+
+    upper.setBorder(BorderFactory.createEtchedBorder());
+
+    chooser = new JList(al.toArray());
+    chooser.setBorder(BorderFactory.createEtchedBorder());
+    // Set a prototype value to control the width of the list:
+    chooser.setPrototypeCellValue("This should be wide enough");
+    chooser.setSelectedIndex(0);
+    chooser.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+
+    // Add the selection listener that will show the correct panel when selection changes:
+    chooser.addListSelectionListener(new ListSelectionListener() {
+        public void valueChanged(ListSelectionEvent e) {
+            if (e.getValueIsAdjusting())
+            return;
+            String o = (String)chooser.getSelectedValue();
+            //Util.pr(o);
+            cardLayout.show(main, o);
+            //main.revalidate();
+            //main.repaint();
+        }
+        });
+
+    JPanel one = new JPanel(), two = new JPanel();
+    one.setLayout(new BorderLayout());
+    two.setLayout(new BorderLayout());
+    one.add(chooser, BorderLayout.CENTER);
+    one.add(importPrefs, BorderLayout.SOUTH);
+    two.add(one, BorderLayout.CENTER);
+    two.add(exportPrefs, BorderLayout.SOUTH);
+    upper.setLayout(new BorderLayout());
+    upper.add(two, BorderLayout.WEST);
+    upper.add(main, BorderLayout.CENTER);
+
+    // Add all panels to main panel:
+    //for (Iterator i=panels.entrySet().iterator(); i.hasNext();) {
+
+
+    //}
+
+        JButton
+            ok = new JButton(Globals.lang("Ok")),
+            cancel = new JButton(Globals.lang("Cancel"));
+        ok.addActionListener(new OkAction());
+        CancelAction cancelAction = new CancelAction();
+        cancel.addActionListener(cancelAction);
+        lower.add(ok);
+        lower.add(cancel);
+
+        // Key bindings:
+        ActionMap am = chooser.getActionMap();
+        InputMap im = chooser.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
+        im.put(frame.prefs().getKey("Close dialog"), "close");
+        am.put("close", cancelAction);
+
+    // Import and export actions:
+    exportPrefs.setToolTipText(Globals.lang("Export preferences to file"));
+    importPrefs.setToolTipText(Globals.lang("Import preferences from file"));
+    exportPrefs.addActionListener(new ActionListener() {
+        public void actionPerformed(ActionEvent e) {
+            String filename = Globals.getNewFile
+            (frame, _prefs, new File(System.getProperty("user.home")),
+             ".xml", JFileChooser.SAVE_DIALOG, false);
+            if (filename == null)
+            return;
+            File file = new File(filename);
+            if (!file.exists() ||
+            (JOptionPane.showConfirmDialog
+                         (ths, "'"+file.getName()+"' "+Globals.lang("exists. Overwrite file?"),
+                          Globals.lang("Export preferences"), JOptionPane.OK_CANCEL_OPTION)
+                         == JOptionPane.OK_OPTION)) {
+
+            try {
+                _prefs.exportPreferences(filename);
+            } catch (IOException ex) {
+                JOptionPane.showMessageDialog
+                (ths, Globals.lang("Could not export preferences")+": "+ex.getMessage(), Globals.lang("Export preferences"), JOptionPane.ERROR_MESSAGE);
+                //ex.printStackTrace();
+            }
+            }
+
+        }
+        });
+
+    importPrefs.addActionListener(new ActionListener() {
+        public void actionPerformed(ActionEvent e) {
+            String filename = Globals.getNewFile
+            (frame, _prefs, new File(System.getProperty("user.home")),
+             ".xml", JFileChooser.OPEN_DIALOG, false);
+            if (filename == null)
+            return;
+
+            try {
+            _prefs.importPreferences(filename);
+            setValues();
+                BibtexEntryType.loadCustomEntryTypes(_prefs);
+                frame.removeCachedEntryEditors();
+            } catch (IOException ex) {
+            JOptionPane.showMessageDialog
+                (ths, Globals.lang("Could not import preferences")+": "+ex.getMessage(), Globals.lang("Import preferences"), JOptionPane.ERROR_MESSAGE);
+            //ex.printStackTrace();
+            }
+        }
+
+
+        });
+
+    setValues();
+
+        pack(); //setSize(440, 500);
+    }
+
+    class OkAction extends AbstractAction {
+        public OkAction() {
+            super("Ok");
+        }
+        public void actionPerformed(ActionEvent e) {
+
+        AbstractWorker worker = new AbstractWorker() {
+            boolean ready = true;
+            public void run() {
+            // First check that all tabs are ready to close:
+            int count = main.getComponentCount();
+            Component[] comps = main.getComponents();
+            for (int i = 0; i < count; i++) {
+                if (!((PrefsTab)comps[i]).readyToClose()) {
+                ready = false;
+                return; // If not, break off.
+                }
+            }
+            // Then store settings and close:
+            for (int i = 0; i < count; i++) {
+                ( (PrefsTab)comps[i]).storeSettings();
+            }
+            Globals.prefs.flush();
+            //try { Thread.sleep(3000); } catch (InterruptedException ex) {}
+            }
+            public void update() {
+            if (!ready)
+                return;
+            setVisible(false);
+            MainTable.updateRenderers();
+            frame.setupAllTables();
+            frame.groupSelector.revalidateGroups(); // icons may have changed
+            frame.output(Globals.lang("Preferences recorded."));
+            }
+        };
+        worker.getWorker().run();
+        worker.getCallBack().update();
+
+        }
+    }
+
+    public void setValues() {
+    // Update all field values in the tabs:
+    int count = main.getComponentCount();
+    Component[] comps = main.getComponents();
+    for (int i = 0; i < count; i++) {
+        ((PrefsTab)comps[i]).setValues();
+    }
+    }
+
+    class CancelAction extends AbstractAction {
+        public CancelAction() {
+            super("Cancel");
+
+        }
+        public void actionPerformed(ActionEvent e) {
+        setVisible(false);
+            // Just close dialog without recording changes.
+            /*(new Thread() {
+              public void run() {
+
+              }
+	      }).start();*/
+        }
+    }
+
+}
diff --git a/src/java/net/sf/jabref/PrefsTab.java b/src/java/net/sf/jabref/PrefsTab.java
new file mode 100644
index 0000000..2831131
--- /dev/null
+++ b/src/java/net/sf/jabref/PrefsTab.java
@@ -0,0 +1,34 @@
+
+package net.sf.jabref;
+
+
+public interface PrefsTab {
+
+    /**
+     * This method is called when the dialog is opened, or if it is made
+     * visible after being hidden. The tab should update all its values.
+     *
+     * This is the ONLY PLACE to set values for the fields in the tab. It
+     * is ILLEGAL to set values only at construction time, because the dialog
+     * will be reused and updated.
+     */
+    public void setValues();
+
+    /**
+     * This method is called when the user presses OK in the
+     * Preferences dialog. Implementing classes must make sure all
+     * settings presented get stored in JabRefPreferences.
+     *
+     */
+    public void storeSettings();
+
+    /**
+     * This method is called before the {@ling storeSettings()} method, 
+     * to check if there are illegal settings in the tab, or if is ready
+     * to be closed.
+     * If the tab is *not* ready, it should display a message to the user 
+     * informing about the illegal setting.
+     */
+    public boolean readyToClose();
+
+}
diff --git a/src/java/net/sf/jabref/PreviewPanel.java b/src/java/net/sf/jabref/PreviewPanel.java
new file mode 100644
index 0000000..ab5354c
--- /dev/null
+++ b/src/java/net/sf/jabref/PreviewPanel.java
@@ -0,0 +1,226 @@
+package net.sf.jabref;
+
+import javax.swing.*;
+import javax.swing.event.HyperlinkListener;
+import javax.swing.event.HyperlinkEvent;
+import javax.swing.border.Border;
+import java.io.*;
+import java.net.URL;
+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;
+
+public class PreviewPanel extends JEditorPane {
+
+  public String CONTENT_TYPE = "text/html";
+      //LAYOUT_FILE = "simplehtml";
+  BibtexEntry entry;
+  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, String layoutFile) {
+        this(layoutFile);
+        this.database = db;
+    }
+
+    public PreviewPanel(BibtexDatabase db, BibtexEntry be, String layoutFile) {
+        this(be, layoutFile);
+        this.database = db;
+    }
+
+  public PreviewPanel(BibtexEntry be, 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) {
+    sp = new JScrollPane(this, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
+                         JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
+    this.layoutFile = layoutFile;
+    sp.setBorder(null);
+
+    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(address, "url", Globals.prefs);
+                  } 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);
+  }
+
+}
diff --git a/src/java/net/sf/jabref/PreviewPrefsTab.java b/src/java/net/sf/jabref/PreviewPrefsTab.java
new file mode 100644
index 0000000..03ab8ca
--- /dev/null
+++ b/src/java/net/sf/jabref/PreviewPrefsTab.java
@@ -0,0 +1,204 @@
+package net.sf.jabref;
+
+import javax.swing.*;
+import java.awt.*;
+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, 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, 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(Globals.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/RegExpRule.java b/src/java/net/sf/jabref/RegExpRule.java
new file mode 100644
index 0000000..1c56699
--- /dev/null
+++ b/src/java/net/sf/jabref/RegExpRule.java
@@ -0,0 +1,86 @@
+/*
+ Copyright (C) 2003 Nathan Dunn, 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 net.sf.jabref.export.layout.format.RemoveBrackets;
+
+import java.util.*;
+import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
+import java.util.regex.Matcher;
+
+public class RegExpRule implements SearchRule {
+
+    final boolean m_caseSensitiveSearch;
+    static RemoveBrackets removeBrackets = new RemoveBrackets();
+
+    public RegExpRule(boolean caseSensitive) {
+        m_caseSensitiveSearch = caseSensitive;
+    }
+
+    public int applyRule(Map searchStrings, BibtexEntry bibtexEntry) throws PatternSyntaxException {
+
+        int score = 0;
+        Iterator e = searchStrings.values().iterator();
+
+        String searchString = (String) e.next();
+
+        int flags = 0;
+        if (!m_caseSensitiveSearch)
+            flags = Pattern.CASE_INSENSITIVE; // testing
+        //System.out.println(searchString);
+        Pattern pattern = Pattern.compile(searchString, flags);
+
+        Object[] fields = bibtexEntry.getAllFields();
+        score += searchFields(fields, bibtexEntry, pattern);
+
+        return score;
+    }
+
+    protected int searchFields(Object[] fields, BibtexEntry bibtexEntry,
+                               Pattern pattern) {
+        int score = 0;
+        if (fields != null) {
+            for (int i = 0; i < fields.length; i++) {
+                try {
+                    Object value = bibtexEntry.getField((String)fields[i]);
+                    if (value != null) {
+                        Matcher m = pattern.matcher(removeBrackets.format((String)value));
+                        if (m.find())
+                            score++;
+                    }
+                }
+
+                catch (Throwable t) {
+                    System.err.println("Searching error: " + t);
+                }
+            }
+        }
+        return score;
+    }
+
+}
diff --git a/src/java/net/sf/jabref/ReplaceStringDialog.java b/src/java/net/sf/jabref/ReplaceStringDialog.java
new file mode 100644
index 0000000..4ea138d
--- /dev/null
+++ b/src/java/net/sf/jabref/ReplaceStringDialog.java
@@ -0,0 +1,237 @@
+/*
+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.
+
+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.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import net.sf.jabref.undo.*;
+
+/**
+ * Dialog for creating or modifying groups. Operates directly on the
+ * Vector containing group information.
+ */
+class ReplaceStringDialog extends JDialog {
+
+    JTextField
+	fields = new JTextField("", 30),
+	from = new JTextField("", 30),
+	to = new JTextField("", 30);
+    JLabel
+	fl = new JLabel(Globals.lang("Search for")+":"),
+	tl = new JLabel(Globals.lang("Replace with")+":");
+
+    JButton
+	ok = new JButton(Globals.lang("Ok")),
+	cancel = new JButton(Globals.lang("Cancel"));
+    JPanel
+	settings = new JPanel(),
+	main = new JPanel(),
+	opt = new JPanel();
+    JCheckBox
+	selOnly = new JCheckBox(Globals.lang("Limit to selected entries"), false);
+    JRadioButton
+	allFi = new JRadioButton(Globals.lang("All fields"), true),
+	field = new JRadioButton(Globals.lang("Limit to fields")+":", false);
+    ButtonGroup bg = new ButtonGroup();
+    private boolean ok_pressed = false;
+    private JabRefFrame parent;
+    String[] flds = null;
+    String s1, s2;
+
+    GridBagLayout gbl = new GridBagLayout();
+    GridBagConstraints con = new GridBagConstraints();
+
+    public ReplaceStringDialog(JabRefFrame parent_) {
+	super(parent_, Globals.lang("Replace string"), true);
+	parent = parent_;
+
+	bg.add(allFi);
+	bg.add(field);
+	ActionListener okListener = new ActionListener() {
+		public void actionPerformed(ActionEvent e) {
+		    s1 = from.getText();
+		    s2 = to.getText();
+		    if (s1.equals(""))
+			return;
+		    ok_pressed = true;
+		    flds = Util.delimToStringArray(fields.getText().toLowerCase(), ";");
+		    dispose();
+		}
+	    };
+	ok.addActionListener(okListener);
+	to.addActionListener(okListener);
+	fields.addActionListener(okListener);
+	AbstractAction cancelAction = new AbstractAction() {
+		public void actionPerformed(ActionEvent e) {
+		    dispose();
+		}
+	    };
+	cancel.addActionListener(cancelAction);
+
+	// Key bindings:
+	ActionMap am = settings.getActionMap();
+	InputMap im = settings.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
+	im.put(parent.prefs.getKey("Close dialog"), "close");
+	am.put("close", cancelAction);
+
+	// Layout starts here.
+	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:
+	/*
+	con.weightx = 0;
+	con.insets = new Insets(3, 5, 3, 5);
+	con.anchor = GridBagConstraints.EAST;
+	con.fill = GridBagConstraints.NONE;
+	con.gridx = 0;
+	con.gridy = 2;
+	gbl.setConstraints(nf, con);
+	settings.add(nf);*/
+
+	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);
+	gbl.setConstraints(selOnly, con);
+	settings.add(selOnly);
+	con.gridy = 1;
+	con.insets = new Insets(13, 5, 3, 5);
+	gbl.setConstraints(allFi, con);
+	settings.add(allFi);
+	con.gridwidth = 1;
+	con.gridy = 2;
+	con.gridx = 0;
+	con.insets = new Insets(3, 5, 3, 5);
+	gbl.setConstraints(field, con);
+	settings.add(field);
+	con.gridx = 1;
+	con.weightx = 1;
+	//con.insets = new Insets(3, 5, 3, 5);
+	gbl.setConstraints(fields, con);
+	settings.add(fields);
+
+	con.weightx = 0;
+	con.gridx = 0;
+	con.gridy = 0;
+	gbl.setConstraints(fl, con);
+	main.add(fl);
+	con.gridy = 1;
+	gbl.setConstraints(tl, con);
+	main.add(tl);
+	con.weightx = 1;
+	con.gridx = 1;
+	con.gridy = 0;
+	gbl.setConstraints(from, con);
+	main.add(from);
+	con.gridy = 1;
+	gbl.setConstraints(to, con);
+	main.add(to);
+
+       	// Option buttons:
+	con.gridx = GridBagConstraints.RELATIVE;
+	con.gridy = GridBagConstraints.RELATIVE;
+	con.weightx = 1;
+	con.gridwidth = 1;
+	con.anchor = GridBagConstraints.EAST;
+	con.fill = GridBagConstraints.NONE;
+	gbl.setConstraints(ok, con);
+	opt.add(ok);
+	con.anchor = GridBagConstraints.WEST;
+	con.gridwidth = GridBagConstraints.REMAINDER;
+	gbl.setConstraints(cancel, con);
+	opt.add(cancel);
+
+	getContentPane().add(main, BorderLayout.NORTH);
+	getContentPane().add(settings, BorderLayout.CENTER);
+	getContentPane().add(opt, BorderLayout.SOUTH);
+
+	pack();
+	//setSize(400, 170);
+
+	Util.placeDialog(this, parent);
+    }
+
+    public boolean okPressed() { return ok_pressed; }
+    public boolean allFields() { return allFi.isSelected(); }
+    public boolean selOnly() { return selOnly.isSelected(); }
+    public String[] fields() { return Util.delimToStringArray(field.getText(), ";"); }
+
+    /**
+     * Does the actual operation on a Bibtex entry based on the
+     * settings specified in this same dialog. Returns the number of
+     * occurences replaced.
+     */
+    public int replace(BibtexEntry be, NamedCompound ce) {
+	int counter = 0;
+	if (allFields()) {
+	    Object[] os = be.getAllFields();
+	    for (int i=0; i<os.length; i++) {
+		String s = (String)os[i];
+		if (!s.equals(Globals.KEY_FIELD))
+		    counter += replaceField(be, s, ce);
+	    }
+	} else {
+	    for (int i=0; i<flds.length; i++) {
+		if (!flds[i].equals(Globals.KEY_FIELD))
+		    counter += replaceField(be, flds[i], ce);
+	    }
+
+	}
+	return counter;
+    }
+
+    public int replaceField(BibtexEntry be, String field, NamedCompound ce) {
+	Object o = be.getField(field);
+	if (o == null) return 0;
+	String txt = o.toString();
+	StringBuffer sb = new StringBuffer();
+	int ind = -1, piv = 0, counter = 0, len1 = s1.length();
+	while ((ind=txt.indexOf(s1, piv)) >= 0) {
+	    counter++;
+	    sb.append(txt.substring(piv, ind)); // Text leading up to s1
+	    sb.append(s2);  // Insert s2
+	    piv = ind+len1;
+	}
+	sb.append(txt.substring(piv));
+	String newStr = sb.toString();
+	be.setField(field, newStr);
+	ce.addEdit(new UndoableFieldChange(be, field, txt, newStr));
+	return counter;
+    }
+}
diff --git a/src/java/net/sf/jabref/RightClickMenu.java b/src/java/net/sf/jabref/RightClickMenu.java
new file mode 100644
index 0000000..3a85ec0
--- /dev/null
+++ b/src/java/net/sf/jabref/RightClickMenu.java
@@ -0,0 +1,340 @@
+/*
+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.
+
+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.awt.Font;
+import java.awt.event.*;
+import java.util.*;
+
+import javax.swing.*;
+import javax.swing.event.*;
+import javax.swing.undo.AbstractUndoableEdit;
+
+import net.sf.jabref.groups.*;
+import net.sf.jabref.undo.NamedCompound;
+
+public class RightClickMenu extends JPopupMenu
+    implements PopupMenuListener {
+
+    BasePanel panel;
+    MetaData metaData;
+    JMenu groupAddMenu = new JMenu(Globals.lang("Add to group")),
+        groupRemoveMenu = new JMenu(Globals.lang("Remove from group")),
+        groupMoveMenu = new JMenu("Assign exclusively to group"), // JZTODO lyrics
+        typeMenu = new JMenu(Globals.lang("Change entry type"));
+
+    public RightClickMenu(BasePanel panel_, MetaData metaData_) {
+        panel = panel_;
+        metaData = metaData_;
+        
+        // Are multiple entries selected?
+        boolean multiple = (panel.mainTable.getSelectedRowCount() > 1);
+
+        // If only one entry is selected, get a reference to it for adapting the menu.
+        BibtexEntry be = null;
+        if (panel.mainTable.getSelectedRowCount() == 1)
+          be = (BibtexEntry)panel.mainTable.getSelected().get(0);
+
+        addPopupMenuListener(this);
+
+        add(new AbstractAction(Globals.lang("Copy"), new ImageIcon(GUIGlobals.copyIconFile)) {
+                public void actionPerformed(ActionEvent e) {
+                    try {
+                        panel.runCommand("copy");
+                    } catch (Throwable ex) {}
+                }
+            });
+        add(new AbstractAction(Globals.lang("Paste"), new ImageIcon(GUIGlobals.pasteIconFile)) {
+                public void actionPerformed(ActionEvent e) {
+                    try {
+                        panel.runCommand("paste");
+                    } catch (Throwable ex) {}
+                }
+            });
+        add(new AbstractAction(Globals.lang("Cut"), new ImageIcon(GUIGlobals.cutIconFile)) {
+                public void actionPerformed(ActionEvent e) {
+                    try {
+                        panel.runCommand("cut");
+                    } catch (Throwable ex) {}
+                }
+            });
+
+        add(new AbstractAction(Globals.lang("Delete"), new ImageIcon(GUIGlobals.removeIconFile)) {
+                public void actionPerformed(ActionEvent e) {
+                    /*SwingUtilities.invokeLater(new Runnable () {
+                        public void run() {*/
+                            try {
+                                panel.runCommand("delete");
+                            } catch (Throwable ex) {}
+                        /*}
+                    }); */
+
+                }
+            });
+            addSeparator();
+
+        add(new AbstractAction(Globals.lang("Export to clipboard")) {
+                public void actionPerformed(ActionEvent e) {
+                    try {
+                        panel.runCommand("exportToClipboard");
+                    } catch (Throwable ex) {}
+                }
+            });
+            addSeparator();
+         
+        if (multiple) {
+          add(new AbstractAction(Globals.lang("Mark entries"), new ImageIcon(GUIGlobals.markIcon)) {
+            public void actionPerformed(ActionEvent e) {
+              try {
+                panel.runCommand("markEntries");
+              } catch (Throwable ex) {}
+            }
+          });
+          add(new AbstractAction(Globals.lang("Unmark entries"), new ImageIcon(GUIGlobals.unmarkIcon)) {
+            public void actionPerformed(ActionEvent e) {
+              try {
+                panel.runCommand("unmarkEntries");
+              } catch (Throwable ex) {}
+            }
+          });
+          addSeparator();
+        } else if (be != null) {
+          if (be.getField(Globals.MARKED) == null)
+            add(new AbstractAction(Globals.lang("Mark entry"), new ImageIcon(GUIGlobals.markIcon)) {
+               public void actionPerformed(ActionEvent e) {
+                 try {
+                   panel.runCommand("markEntries");
+                 } catch (Throwable ex) {}
+               }
+             });
+           else
+             add(new AbstractAction(Globals.lang("Unmark entry"), new ImageIcon(GUIGlobals.unmarkIcon)) {
+               public void actionPerformed(ActionEvent e) {
+                 try {
+                   panel.runCommand("unmarkEntries");
+                 } catch (Throwable ex) {}
+               }
+             });
+           addSeparator();
+        }
+
+        add(new AbstractAction(Globals.lang("Open PDF or PS"), new ImageIcon(GUIGlobals.pdfIcon)) {
+                public void actionPerformed(ActionEvent e) {
+                    try {
+                        panel.runCommand("openFile");
+                    } catch (Throwable ex) {}
+                }
+            });
+
+            add(new AbstractAction(Globals.lang("Open URL or DOI"), new ImageIcon(GUIGlobals.wwwIcon)) {
+              public void actionPerformed(ActionEvent e) {
+                try {
+                  panel.runCommand("openUrl");
+                } catch (Throwable ex) {}
+              }
+            });
+
+        add(new AbstractAction(Globals.lang("Copy BibTeX key"), new ImageIcon(GUIGlobals.copyKeyIconFile)) {
+                public void actionPerformed(ActionEvent e) {
+                    try {
+                        panel.runCommand("copyKey");
+                    } catch (Throwable ex) {}
+                }
+            });
+
+        add(new AbstractAction(Globals.lang("Copy")+" \\cite{"+Globals.lang("BibTeX key")+"}", new ImageIcon(GUIGlobals.copyKeyIconFile)) {
+                public void actionPerformed(ActionEvent e) {
+                    try {
+                        panel.runCommand("copyCiteKey");
+                    } catch (Throwable ex) {}
+                }
+            });
+
+        addSeparator();
+        populateTypeMenu();
+
+        add(typeMenu);
+        add(new AbstractAction(Globals.lang("Plain text import"))
+        {
+                public void actionPerformed(ActionEvent e) {
+                    try {
+                        panel.runCommand("importPlainText");
+                    } catch (Throwable ex) {}
+                }
+            });
+        addSeparator(); // for "add/move/remove to/from group" entries (appended here)
+    }
+
+    /**
+     * Remove all types from the menu. Then cycle through all available
+     * types, and add them.
+     */
+    public void populateTypeMenu() {
+        typeMenu.removeAll();
+        for (Iterator i=BibtexEntryType.ALL_TYPES.keySet().iterator();
+             i.hasNext();) {
+            typeMenu.add(new ChangeTypeAction
+                             (BibtexEntryType.getType((String)i.next()), panel));
+        }
+    }
+
+    /**
+     * Set the dynamic contents of "Add to group ..." submenu.
+     */
+    public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
+      BibtexEntry[] bes = panel.getSelectedEntries();
+      panel.storeCurrentEdit();
+      GroupTreeNode groups = metaData.getGroups();
+      if (groups == null) {
+        groupAddMenu.setEnabled(false);
+        groupMoveMenu.setEnabled(false);
+        groupRemoveMenu.setEnabled(false);
+        return;
+      }
+      
+      groupAddMenu.setEnabled(true);
+      groupMoveMenu.setEnabled(true);
+      groupRemoveMenu.setEnabled(true);
+      groupAddMenu.removeAll();
+      groupMoveMenu.removeAll();
+      groupRemoveMenu.removeAll();
+      
+      if (bes == null)
+        return;
+      add(groupAddMenu);
+      add(groupMoveMenu);
+      add(groupRemoveMenu);
+
+      groupAddMenu.setEnabled(false);
+      groupMoveMenu.setEnabled(false);
+      groupRemoveMenu.setEnabled(false);
+      insertNodes(groupAddMenu,metaData.getGroups(),bes,true,false);
+      insertNodes(groupMoveMenu,metaData.getGroups(),bes,true,true);
+      insertNodes(groupRemoveMenu,metaData.getGroups(),bes,false,false);
+    }
+    
+    /**
+     * @param move For add: if true, remove from previous groups
+     */
+    public void insertNodes(JMenu menu, GroupTreeNode node, BibtexEntry[] selection, 
+    		boolean add, boolean move) {
+        final AbstractAction action = getAction(node,selection,add,move);
+        
+        if (node.getChildCount() == 0) {
+            JMenuItem menuItem = new JMenuItem(action);
+            setGroupFontAndIcon(menuItem, node.getGroup());
+            menu.add(menuItem);            
+            if (action.isEnabled())
+            	menu.setEnabled(true);
+            return;
+        }
+        
+        JMenu submenu = null;
+        if (node.getGroup() instanceof AllEntriesGroup) {
+            for (int i = 0; i < node.getChildCount(); ++i) {
+                insertNodes(menu,(GroupTreeNode) node.getChildAt(i), selection, add, move);
+            }
+        } else {
+            submenu = new JMenu("["+node.getGroup().getName()+"]");
+            setGroupFontAndIcon(submenu, node.getGroup());
+            // setEnabled(true) is done above/below if at least one menu 
+            // entry (item or submenu) is enabled
+            submenu.setEnabled(action.isEnabled()); 
+            JMenuItem menuItem = new JMenuItem(action);
+            setGroupFontAndIcon(menuItem, node.getGroup());
+            submenu.add(menuItem);
+            submenu.add(new Separator());
+            for (int i = 0; i < node.getChildCount(); ++i)
+                insertNodes(submenu,(GroupTreeNode) node.getChildAt(i), selection, add, move);
+            menu.add(submenu);
+            if (submenu.isEnabled())
+                menu.setEnabled(true);
+        }
+    }
+    
+    /** Sets the font and icon to be used, depending on the group */
+    private void setGroupFontAndIcon(JMenuItem menuItem, AbstractGroup group) {
+        if (Globals.prefs.getBoolean("groupShowDynamic")) {
+        	menuItem.setFont(menuItem.getFont().deriveFont(group.isDynamic() ? 
+        			Font.ITALIC : Font.PLAIN));
+        }
+    	if (Globals.prefs.getBoolean("groupShowIcons")) {
+    		switch (group.getHierarchicalContext()) {
+    		case AbstractGroup.INCLUDING:
+    			menuItem.setIcon(GUIGlobals.groupIncludingIcon);
+    			break;
+    		case AbstractGroup.REFINING:
+    			menuItem.setIcon(GUIGlobals.groupRefiningIcon);
+    			break;
+    		default:
+    			menuItem.setIcon(GUIGlobals.groupRegularIcon);
+				break;
+    		}
+    	}
+    }
+    
+    /**
+     * @param move For add: if true, remove from all previous groups
+     */
+    private AbstractAction getAction(GroupTreeNode node, BibtexEntry[] selection, 
+    		boolean add, boolean move) {
+        AbstractAction action = add ? (AbstractAction) new AddToGroupAction(node, move,
+                panel) : (AbstractAction) new RemoveFromGroupAction(node, panel);
+        AbstractGroup group = node.getGroup();
+        if (!move) {
+	        action.setEnabled(add ? group.supportsAdd() && !group.containsAll(selection)
+	                : group.supportsRemove() && group.containsAny(selection));
+        } else {
+        	action.setEnabled(group.supportsAdd());
+        }
+        return action;
+    }
+
+    public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
+      remove(groupAddMenu);
+      remove(groupMoveMenu);
+      remove(groupRemoveMenu);
+    }
+
+    public void popupMenuCanceled(PopupMenuEvent e) {
+        // nothing to do
+    }
+
+    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(type);
+      }
+    }
+}
diff --git a/src/java/net/sf/jabref/SearchManager2.java b/src/java/net/sf/jabref/SearchManager2.java
new file mode 100644
index 0000000..28a642b
--- /dev/null
+++ b/src/java/net/sf/jabref/SearchManager2.java
@@ -0,0 +1,574 @@
+/*
+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;
+
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.Collection;
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import javax.swing.event.*;
+import javax.swing.event.ChangeListener;
+import javax.swing.event.ChangeEvent;
+
+import net.sf.jabref.search.*;
+import net.sf.jabref.search.SearchExpression;
+import ca.odell.glazedlists.matchers.Matcher;
+import ca.odell.glazedlists.EventList;
+
+class SearchManager2 extends SidePaneComponent
+    implements ActionListener, KeyListener, ItemListener, CaretListener, ErrorMessageDisplay {
+
+    private JabRefFrame frame;
+
+    GridBagLayout gbl = new GridBagLayout() ;
+    GridBagConstraints con = new GridBagConstraints() ;
+
+    IncrementalSearcher incSearcher;
+
+    //private JabRefFrame frame;
+    private JTextField searchField = new JTextField("", 12);
+    private JLabel lab = //new JLabel(Globals.lang("Search")+":");
+    new JLabel(new ImageIcon(GUIGlobals.searchIconFile));
+    private JPopupMenu settings = new JPopupMenu();
+    private JButton openset = new JButton(Globals.lang("Settings"));
+    private JButton escape = new JButton(Globals.lang("Clear"));
+    private JButton help = new JButton(new ImageIcon(GUIGlobals.helpIconFile));
+    /** This button's text will be set later. */
+    private JButton search = new JButton();
+    private JCheckBoxMenuItem searchReq, searchOpt, searchGen,
+    searchAll, caseSensitive, regExpSearch;
+
+    private JRadioButton increment, floatSearch, hideSearch;
+    private JCheckBoxMenuItem select;
+    private ButtonGroup types = new ButtonGroup();
+    private boolean incSearch = false, startedFloatSearch=false, startedFilterSearch=false;
+
+    private int incSearchPos = -1; // To keep track of where we are in
+                   // an incremental search. -1 means
+                   // that the search is inactive.
+
+
+    public SearchManager2(JabRefFrame frame, SidePaneManager manager) {
+    super(manager, GUIGlobals.searchIconFile, Globals.lang("Search"));
+
+        this.frame = frame;
+    incSearcher = new IncrementalSearcher(Globals.prefs);
+
+
+
+    //setBorder(BorderFactory.createMatteBorder(1,1,1,1,Color.magenta));
+
+        searchReq = new JCheckBoxMenuItem
+        (Globals.lang("Search required fields"),
+         Globals.prefs.getBoolean("searchReq"));
+    searchOpt = new JCheckBoxMenuItem
+        (Globals.lang("Search optional fields"),
+         Globals.prefs.getBoolean("searchOpt"));
+    searchGen = new JCheckBoxMenuItem
+        (Globals.lang("Search general fields"),
+         Globals.prefs.getBoolean("searchGen"));
+        searchAll = new JCheckBoxMenuItem
+        (Globals.lang("Search all fields"),
+         Globals.prefs.getBoolean("searchAll"));
+        regExpSearch = new JCheckBoxMenuItem
+        (Globals.lang("Use regular expressions"),
+         Globals.prefs.getBoolean("regExpSearch"));
+
+
+    increment = new JRadioButton(Globals.lang("Incremental"), false);
+    floatSearch = new JRadioButton(Globals.lang("Float"), true);
+    hideSearch = new JRadioButton(Globals.lang("Filter"), true);
+    types.add(increment);
+    types.add(floatSearch);
+        types.add(hideSearch);
+
+        select = new JCheckBoxMenuItem(Globals.lang("Select matches"), false);
+        increment.setToolTipText(Globals.lang("Incremental search"));
+        floatSearch.setToolTipText(Globals.lang("Gray out non-matching entries"));
+        hideSearch.setToolTipText(Globals.lang("Hide non-matching entries"));
+
+    // Add an item listener that makes sure we only listen for key events
+    // when incremental search is turned on.
+    increment.addItemListener(this);
+        floatSearch.addItemListener(this);
+        hideSearch.addItemListener(this);
+
+        // Add the global focus listener, so a menu item can see if this field was focused when
+        // an action was called.
+        searchField.addFocusListener(Globals.focusListener);
+
+
+    if (searchAll.isSelected()) {
+        searchReq.setEnabled(false);
+        searchOpt.setEnabled(false);
+        searchGen.setEnabled(false);
+    }
+    searchAll.addChangeListener(new ChangeListener() {
+        public void stateChanged(ChangeEvent event) {
+            boolean state = !searchAll.isSelected();
+            searchReq.setEnabled(state);
+            searchOpt.setEnabled(state);
+            searchGen.setEnabled(state);
+        }
+    });
+
+        caseSensitive = new JCheckBoxMenuItem(Globals.lang("Case sensitive"),
+                      Globals.prefs.getBoolean("caseSensitiveSearch"));
+settings.add(select);
+
+    // 2005.03.29, trying to remove field category searches, to simplify
+        // search usability.
+    //settings.addSeparator();
+    //settings.add(searchReq);
+    //settings.add(searchOpt);
+    //settings.add(searchGen);
+    //settings.addSeparator();
+    //settings.add(searchAll);
+    // ---------------------------------------------------------------
+    settings.addSeparator();
+        settings.add(caseSensitive);
+    settings.add(regExpSearch);
+    //settings.addSeparator();
+
+
+    searchField.addActionListener(this);
+    searchField.addCaretListener(this);
+        search.addActionListener(this);
+    searchField.addFocusListener(new FocusAdapter() {
+          public void focusGained(FocusEvent e) {
+            if (increment.isSelected())
+              searchField.setText("");
+          }
+        public void focusLost(FocusEvent e) {
+            incSearch = false;
+            incSearchPos = -1; // Reset incremental
+                       // search. This makes the
+                       // incremental search reset
+                       // once the user moves focus to
+                       // somewhere else.
+                    if (increment.isSelected()) {
+                      //searchField.setText("");
+                      //System.out.println("focuslistener");
+                    }
+        }
+        });
+    escape.addActionListener(this);
+
+    openset.addActionListener(new ActionListener() {
+        public void actionPerformed(ActionEvent e) {
+                  if (settings.isVisible()) {
+                    //System.out.println("oee");
+                    //settings.setVisible(false);
+                  }
+                  else {
+                    JButton src = (JButton) e.getSource();
+                    settings.show(src, 0, openset.getHeight());
+                  }
+        }
+        });
+
+            Insets margin = new Insets(0, 2, 0, 2);
+            //search.setMargin(margin);
+            escape.setMargin(margin);
+            openset.setMargin(margin);
+            Dimension butDim = new Dimension(20, 20);
+            help.setPreferredSize(butDim);
+            help.setMinimumSize(butDim);
+            help.setMargin(margin);
+            help.addActionListener(new HelpAction(Globals.helpDiag, GUIGlobals.searchHelp, "Help"));
+
+    if (Globals.prefs.getBoolean("incrementS"))
+        increment.setSelected(true);
+
+    JPanel main = new JPanel();
+    main.setLayout(gbl);
+    //SidePaneHeader header = new SidePaneHeader("Search", GUIGlobals.searchIconFile, this);
+    con.gridwidth = GridBagConstraints.REMAINDER;
+    con.fill = GridBagConstraints.BOTH;
+        con.weightx = 1;
+    //con.insets = new Insets(0, 0, 2,  0);
+    //gbl.setConstraints(header, con);
+    //add(header);
+        //con.insets = new Insets(0, 0, 0,  0);
+        gbl.setConstraints(searchField,con);
+        main.add(searchField) ;
+        //con.gridwidth = 1;
+        gbl.setConstraints(search,con);
+        main.add(search) ;
+        con.gridwidth = GridBagConstraints.REMAINDER;
+        gbl.setConstraints(escape,con);
+        main.add(escape) ;
+        con.insets = new Insets(0, 2, 0,  0);
+        gbl.setConstraints(increment, con);
+        main.add(increment);
+        gbl.setConstraints(floatSearch, con);
+        main.add(floatSearch);
+        gbl.setConstraints(hideSearch, con);
+        main.add(hideSearch);
+    con.insets = new Insets(0, 0, 0,  0);
+        JPanel pan = new JPanel();
+        GridBagLayout gb = new GridBagLayout();
+        gbl.setConstraints(pan, con);
+        pan.setLayout(gb);
+        con.weightx = 1;
+        con.gridwidth = 1;
+        gb.setConstraints(openset, con);
+        pan.add(openset);
+        con.weightx = 0;
+        gb.setConstraints(help, con);
+        pan.add(help);
+        main.add(pan);
+        main.setBorder(BorderFactory.createEmptyBorder(1,1,1,1));
+        add(main, BorderLayout.CENTER);
+
+    searchField.getInputMap().put(Globals.prefs.getKey("Repeat incremental search"),
+                      "repeat");
+
+    searchField.getActionMap().put("repeat", new AbstractAction() {
+        public void actionPerformed(ActionEvent e) {
+            if (increment.isSelected())
+            repeatIncremental();
+        }
+        });
+    searchField.getInputMap().put(Globals.prefs.getKey("Clear search"), "escape");
+    searchField.getActionMap().put("escape", new AbstractAction() {
+        public void actionPerformed(ActionEvent e) {
+            hideAway();
+            //SearchManager2.this.actionPerformed(new ActionEvent(escape, 0, ""));
+        }
+        });
+    setSearchButtonSizes();
+    updateSearchButtonText();
+    }
+
+    /** force the search button to be large enough for
+     * the longer of the two texts */
+    private void setSearchButtonSizes() {
+        search.setText(Globals.lang("Search Specified Field(s)"));
+        Dimension size1 = search.getPreferredSize();
+        search.setText(Globals.lang("Search All Fields"));
+        Dimension size2 = search.getPreferredSize();
+        size2.width = Math.max(size1.width,size2.width);
+        search.setMinimumSize(size2);
+        search.setPreferredSize(size2);
+    }
+
+    public void updatePrefs() {
+    Globals.prefs.putBoolean("searchReq", searchReq.isSelected());
+    Globals.prefs.putBoolean("searchOpt", searchOpt.isSelected());
+    Globals.prefs.putBoolean("searchGen", searchGen.isSelected());
+    Globals.prefs.putBoolean("searchAll", searchAll.isSelected());
+    Globals.prefs.putBoolean("incrementS", increment.isSelected());
+    Globals.prefs.putBoolean("selectS", select.isSelected());
+    Globals.prefs.putBoolean("grayOutNonHits", floatSearch.isSelected());
+    Globals.prefs.putBoolean("caseSensitiveSearch",
+             caseSensitive.isSelected());
+    Globals.prefs.putBoolean("regExpSearch", regExpSearch.isSelected());
+
+    }
+
+    public void startIncrementalSearch() {
+    increment.setSelected(true);
+    searchField.setText("");
+        //System.out.println("startIncrementalSearch");
+    searchField.requestFocus();
+    }
+
+    /**
+     * Clears and focuses the search field if it is not
+     * focused. Otherwise, cycles to the next search type.
+     */
+    public void startSearch() {
+    if (increment.isSelected() && incSearch) {
+        repeatIncremental();
+        return;
+    }
+    if (!searchField.hasFocus()) {
+        //searchField.setText("");
+            searchField.selectAll();
+        searchField.requestFocus();
+    } else {
+        if (increment.isSelected())
+            floatSearch.setSelected(true);
+        else if (floatSearch.isSelected())
+            hideSearch.setSelected(true);
+        else {
+        increment.setSelected(true);
+        }
+        increment.revalidate();
+        increment.repaint();
+
+        searchField.requestFocus();
+
+    }
+    }
+
+    public void actionPerformed(ActionEvent e) {
+    if (e.getSource() == escape) {
+        incSearch = false;
+        if (panel != null) {
+        (new Thread() {
+            public void run() {
+                clearSearch();
+            }
+            }).start();
+
+        }
+    }
+    else if (((e.getSource() == searchField) || (e.getSource() == search))
+         && !increment.isSelected()
+         && (panel != null)) {
+        updatePrefs(); // Make sure the user's choices are recorded.
+            if (searchField.getText().equals("")) {
+              // An empty search field should cause the search to be cleared.
+              panel.stopShowingSearchResults();
+              return;
+            }
+        // Setup search parameters common to both normal and float.
+        Hashtable searchOptions = new Hashtable();
+        searchOptions.put("option",searchField.getText()) ;
+        SearchRuleSet searchRules = new SearchRuleSet() ;
+        SearchRule rule1;
+        if (Globals.prefs.getBoolean("regExpSearch"))
+            rule1 = new RegExpRule(
+                    Globals.prefs.getBoolean("caseSensitiveSearch"));
+        else
+            rule1 = new SimpleSearchRule(
+                    Globals.prefs.getBoolean("caseSensitiveSearch"));
+
+        try {
+            // this searches specified fields if specified,
+            // and all fields otherwise
+            rule1 = new SearchExpression(Globals.prefs,searchOptions);
+        } catch (Exception ex) {
+            // we'll do a search in all fields
+        }
+
+        searchRules.addRule(rule1) ;
+        SearchWorker worker = new SearchWorker(searchRules, searchOptions);
+        worker.getWorker().run();
+        worker.getCallBack().update();
+
+    }
+    }
+
+    class SearchWorker extends AbstractWorker {
+        private SearchRuleSet rules;
+        Hashtable searchTerm;
+        int hits = 0;
+        public SearchWorker(SearchRuleSet rules, Hashtable searchTerm) {
+            this.rules = rules;
+            this.searchTerm = searchTerm;
+        }
+
+        public void run() {
+            Collection entries = panel.getDatabase().getEntries();
+            for (Iterator i=entries.iterator(); i.hasNext();) {
+                BibtexEntry entry = (BibtexEntry)i.next();
+                boolean hit = rules.applyRule(searchTerm, entry) > 0;
+                entry.setSearchHit(hit);
+                if (hit) hits++;
+            }
+        }
+
+        public void update() {
+            panel.output(Globals.lang("Searched database. Number of hits")
+                    + ": " + hits);
+
+            // Show the result in the chosen way:
+            if (hideSearch.isSelected()) {
+                // Filtering search - removes non-hits from the table:
+                if (startedFloatSearch) {
+                    panel.mainTable.stopShowingFloatSearch();
+                    startedFloatSearch = false;
+                }
+                startedFilterSearch = true;
+                panel.setSearchMatcher(SearchMatcher.INSTANCE);
+
+            } else {
+                // Float search - floats hits to the top of the table:
+                if (startedFilterSearch) {
+                    panel.stopShowingSearchResults();
+                    startedFilterSearch = false;
+                }
+                startedFloatSearch = true;
+                panel.mainTable.showFloatSearch(SearchMatcher.INSTANCE);
+
+            }
+
+            // Afterwards, select all text in the search field.
+            searchField.select(0, searchField.getText().length());
+
+        }
+    }
+
+    public void clearSearch() {
+        if (startedFloatSearch) {
+            startedFloatSearch = false;
+            panel.mainTable.stopShowingFloatSearch();
+        } else if (startedFilterSearch) {
+            startedFilterSearch = false;
+            panel.stopShowingSearchResults();
+        }
+
+
+    }
+    public void itemStateChanged(ItemEvent e) {
+    if (e.getSource() == increment) {
+        if (startedFilterSearch || startedFloatSearch) {
+            clearSearch();
+        }
+        updateSearchButtonText();
+        if (increment.isSelected())
+        searchField.addKeyListener(this);
+        else
+        searchField.removeKeyListener(this);
+    } else /*if (e.getSource() == normal)*/ {
+        updateSearchButtonText();
+
+        // If this search type is disabled, remove reordering from
+        // all databases.
+        /*if ((panel != null) && increment.isSelected()) {
+            clearSearch();
+        } */
+    }
+    }
+
+    private void repeatIncremental() {
+    incSearchPos++;
+    if (panel != null)
+        goIncremental();
+    }
+
+    /**
+     * Used for incremental search. Only activated when incremental
+     * is selected.
+     *
+     * The variable incSearchPos keeps track of which entry was last
+     * checked.
+     */
+    public void keyTyped(KeyEvent e) {
+    if (e.isControlDown()) {
+        return;
+    }
+    if (panel != null)
+        goIncremental();
+    }
+
+    private void goIncremental() {
+    incSearch = true;
+    SwingUtilities.invokeLater(new Thread() {
+        public void run() {
+            String text = searchField.getText();
+
+
+            if (incSearchPos >= panel.getDatabase().getEntryCount()) {
+            panel.output("'"+text+"' : "+Globals.lang
+
+                     ("Incremental search failed. Repeat to search from top.")+".");
+            incSearchPos = -1;
+            return;
+            }
+
+            if (searchField.getText().equals("")) return;
+            if (incSearchPos < 0)
+            incSearchPos = 0;
+            BibtexEntry be = panel.mainTable.getEntryAt(incSearchPos);
+            while (!incSearcher.search(text, be)) {
+                incSearchPos++;
+                if (incSearchPos < panel.getDatabase().getEntryCount())
+                    be = panel.mainTable.getEntryAt(incSearchPos);
+            else {
+                panel.output("'"+text+"' : "+Globals.lang
+                     ("Incremental search failed. Repeat to search from top."));
+                incSearchPos = -1;
+                return;
+            }
+            }
+            if (incSearchPos >= 0) {
+
+            panel.selectSingleEntry(incSearchPos);
+            panel.output("'"+text+"' "+Globals.lang
+
+                     ("found")+".");
+
+            }
+        }
+        });
+    }
+
+    public void componentClosing() {
+    frame.searchToggle.setSelected(false);
+        if (panel != null) {
+            if (startedFilterSearch || startedFloatSearch)
+                clearSearch();
+        }
+    }
+
+
+    public void keyPressed(KeyEvent e) {}
+    public void keyReleased(KeyEvent e) {}
+
+    public void caretUpdate(CaretEvent e) {
+        if (e.getSource() == searchField) {
+            updateSearchButtonText();
+        }
+    }
+
+    /** Updates the text on the search button to reflect
+      * the type of search that will happen on click. */
+    private void updateSearchButtonText() {
+        search.setText(!increment.isSelected()
+                && SearchExpressionParser.checkSyntax(
+                searchField.getText(),
+                caseSensitive.isSelected(),
+                regExpSearch.isSelected()) != null
+                ? Globals.lang("Search Specified Field(s)")
+                : Globals.lang("Search All Fields"));
+    }
+
+    /**
+     * This method is required by the ErrorMessageDisplay interface, and lets this class
+     * serve as a callback for regular expression exceptions happening in DatabaseSearch.
+     * @param errorMessage
+     */
+    public void reportError(String errorMessage) {
+        JOptionPane.showMessageDialog(panel, errorMessage, Globals.lang("Search error"),
+                JOptionPane.ERROR_MESSAGE);
+    }
+
+    /**
+     * This method is required by the ErrorMessageDisplay interface, and lets this class
+     * serve as a callback for regular expression exceptions happening in DatabaseSearch.
+     * @param errorMessage
+     */
+    public void reportError(String errorMessage, Exception exception) {
+        reportError(errorMessage);
+    }
+}
diff --git a/src/java/net/sf/jabref/SearchRule.java b/src/java/net/sf/jabref/SearchRule.java
new file mode 100644
index 0000000..c3adb19
--- /dev/null
+++ b/src/java/net/sf/jabref/SearchRule.java
@@ -0,0 +1,37 @@
+/*
+Copyright (C) 2003  Nathan Dunn
+
+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.util.Map;
+
+public interface SearchRule{
+
+    public int applyRule(Map searchStrings,BibtexEntry bibtexEntry) ;
+
+}
+
+
diff --git a/src/java/net/sf/jabref/SearchRuleSet.java b/src/java/net/sf/jabref/SearchRuleSet.java
new file mode 100644
index 0000000..a18e768
--- /dev/null
+++ b/src/java/net/sf/jabref/SearchRuleSet.java
@@ -0,0 +1,52 @@
+/*
+ Copyright (C) 2003  Nathan Dunn
+
+ 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.util.*;
+import java.util.regex.PatternSyntaxException;
+
+public class SearchRuleSet implements SearchRule {
+    protected Vector ruleSet = new Vector();
+
+    public void addRule(SearchRule newRule) {
+        ruleSet.add(newRule);
+    }
+
+    public void clearRules() {
+        ruleSet.clear();
+    }
+
+    public int applyRule(Map searchString, BibtexEntry bibtexEntry) throws PatternSyntaxException{
+        int score = 0;
+        Enumeration e = ruleSet.elements();
+        while (e.hasMoreElements()) {
+            score += ((SearchRule) e.nextElement()).applyRule(searchString,
+                    bibtexEntry);
+        }
+        return score;
+    }
+}
diff --git a/src/java/net/sf/jabref/SidePane.java b/src/java/net/sf/jabref/SidePane.java
new file mode 100644
index 0000000..22eb060
--- /dev/null
+++ b/src/java/net/sf/jabref/SidePane.java
@@ -0,0 +1,114 @@
+/*
+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.
+
+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 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;
+
+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;
+    }
+}
diff --git a/src/java/net/sf/jabref/SidePaneComponent.java b/src/java/net/sf/jabref/SidePaneComponent.java
new file mode 100644
index 0000000..2c29ef4
--- /dev/null
+++ b/src/java/net/sf/jabref/SidePaneComponent.java
@@ -0,0 +1,115 @@
+/*
+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.
+
+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 javax.swing.*;
+import java.awt.Dimension;
+import java.awt.Insets;
+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(new ImageIcon(GUIGlobals.closeIconFile));
+    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();
+        }
+    }
+}
diff --git a/src/java/net/sf/jabref/SidePaneHeader.java b/src/java/net/sf/jabref/SidePaneHeader.java
new file mode 100644
index 0000000..b71d8a2
--- /dev/null
+++ b/src/java/net/sf/jabref/SidePaneHeader.java
@@ -0,0 +1,130 @@
+/*
+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.
+
+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 javax.swing.*;
+import java.awt.*;
+import java.awt.event.ActionListener;
+import java.awt.event.ActionEvent;
+import java.net.URL;
+
+public class SidePaneHeader extends JPanel implements ActionListener {
+
+  private JButton close = new JButton(new ImageIcon(GUIGlobals.close2IconFile));
+    private JLabel nameLabel, imageIcon;
+    private SidePaneComponent parent;
+    private GridBagLayout gbl = new GridBagLayout();
+    private GridBagConstraints con = new GridBagConstraints();
+
+    /*
+    public SidePaneHeader(String name, URL image, JButton button,
+			  JComponent parent_) {
+
+			  }*/
+
+    public SidePaneHeader(String name, URL image, SidePaneComponent parent_) {
+    addPart(name, image, parent_);
+    }
+
+    public void paintComponent(Graphics g) {
+      Graphics2D g2 = (Graphics2D)g;
+      Paint oldPaint = g2.getPaint();
+      //g2.putColor(Color.red);
+      Insets ins = getInsets();
+      int width = getWidth() - ins.left - ins.right,
+          height = getHeight() - ins.top - ins.bottom;
+      //g2.setPaint(new GradientPaint(0, 0, GUIGlobals.gradientGray,
+     //                              width, height, GUIGlobals.gradientBlue, false));
+     g2.setPaint(new GradientPaint(ins.left, ins.top, GUIGlobals.gradientGray,
+                                   width, height, GUIGlobals.gradientBlue, false));
+      g2.fillRect(ins.left, ins.top, width-1, height);
+      //g2.fillRect(0, 0, 100, 10);
+      g2.setPaint(oldPaint);
+      //super.paintComponent(g);
+    }
+
+    //public boolean isOpaque() { return true; }
+
+    private void addPart(String name, URL image, SidePaneComponent parent_) {
+    parent = parent_;
+    setLayout(gbl);
+        //setPreferredSize(new Dimension(GUIGlobals.SPLIT_PANE_DIVIDER_LOCATION, 18));
+        //setMinimumSize(new Dimension(GUIGlobals.SPLIT_PANE_DIVIDER_LOCATION, 18));
+    //imageIcon = new JLabel(new ImageIcon(image));
+    nameLabel = new JLabel(Globals.lang(name), new ImageIcon(image),
+                   SwingConstants.LEFT);
+//        setBackground(new Color(0, 0, 175)); //SystemColor.activeCaption);
+
+        //close.setOpaque(false);
+        nameLabel.setForeground(new Color(230, 230, 230));
+    //nameLabel.setPreferredSize(new Dimension(70, 24));
+        /*AbstractAction close = new AbstractAction("Close", new ImageIcon(GUIGlobals.closeIconFile)) {
+          public void actionPerformed(ActionEvent e) {
+            parent.hideAway();
+          }
+        };
+	close.putValue(close.SHORT_DESCRIPTION, "Close");
+        JToolBar tlb = new JToolBar();
+        tlb.setFloatable(false);
+        tlb.setMargin(new Insets(0,0,0,0));
+        tlb.setSize(20, 20);
+        tlb.add(close);*/
+  //close.setMargin(new Insets(0,0,0,0));
+  //close.setRolloverEnabled(true);
+  close.setBorder(null);
+  close.setOpaque(false);
+  close.setPreferredSize(new Dimension(15, 15));
+  close.setMaximumSize(new Dimension(15, 15));
+  close.setMinimumSize(new Dimension(15, 15));
+  close.addActionListener(this);
+
+  //setBorder(BorderFactory.createEtchedBorder());
+  //setBorder(BorderFactory.createMatteBorder(1,1,1,2,new Color(150,150,150)));
+    //add(imageIcon, BorderLayout.WEST);
+    con.insets = new Insets(1, 1, 1, 1);
+    con.gridwidth = 1;
+    con.anchor = GridBagConstraints.WEST;
+    con.fill = GridBagConstraints.NONE;
+    gbl.setConstraints(nameLabel, con);
+    add(nameLabel);
+    JPanel pan = new JPanel();
+        pan.setOpaque(false);
+    con.fill = GridBagConstraints.HORIZONTAL;
+    con.weightx = 1;
+    gbl.setConstraints(pan, con);
+    add(pan);
+    con.weightx = 0;
+    con.fill = GridBagConstraints.NONE;
+    con.gridwidth = GridBagConstraints.REMAINDER;
+        gbl.setConstraints(close, con);
+    add(close);
+    }
+
+    public void actionPerformed(ActionEvent e) {
+    parent.hideAway(); //setVisible(false);
+    }
+}
diff --git a/src/java/net/sf/jabref/SidePaneManager.java b/src/java/net/sf/jabref/SidePaneManager.java
new file mode 100644
index 0000000..7502ae1
--- /dev/null
+++ b/src/java/net/sf/jabref/SidePaneManager.java
@@ -0,0 +1,227 @@
+/*
+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.
+
+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.util.*;
+
+import net.sf.jabref.groups.*;
+
+import javax.swing.event.ChangeListener;
+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());
+            }
+        });
+
+    }
+}
diff --git a/src/java/net/sf/jabref/SimpleSearchRule.java b/src/java/net/sf/jabref/SimpleSearchRule.java
new file mode 100644
index 0000000..24d1194
--- /dev/null
+++ b/src/java/net/sf/jabref/SimpleSearchRule.java
@@ -0,0 +1,72 @@
+/*
+ Copyright (C) 2003 Nathan Dunn, 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 net.sf.jabref.export.layout.format.RemoveBrackets;
+
+import java.util.*;
+
+public class SimpleSearchRule implements SearchRule {
+
+    final boolean m_caseSensitiveSearch;
+    static RemoveBrackets removeBrackets = new RemoveBrackets();
+
+    public SimpleSearchRule(boolean caseSensitive) {
+        m_caseSensitiveSearch = caseSensitive;
+    }
+
+    public int applyRule(Map searchStrings, BibtexEntry bibtexEntry) {
+        String searchString = (String) searchStrings.values().iterator().next();
+
+        if (!m_caseSensitiveSearch)
+            searchString = searchString.toLowerCase();
+        int score = 0;
+        int counter = 0;
+        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)
+                try {
+                    fieldContent = removeBrackets.format(fieldContentAsObject.toString());
+                    if (!m_caseSensitiveSearch)
+                        fieldContent = fieldContent.toLowerCase();
+                    counter = fieldContent.indexOf(searchString, counter);
+                    while (counter >= 0) {
+                        ++score;
+                        counter = fieldContent.indexOf(searchString, counter + 1);
+                    }
+                } catch (Throwable t) {
+                    System.err.println("sorting error: " + t);
+                }
+            counter = 0;
+        }
+        return score;
+    }
+
+}
diff --git a/src/java/net/sf/jabref/SimpleUrlDragDrop.java b/src/java/net/sf/jabref/SimpleUrlDragDrop.java
new file mode 100644
index 0000000..cfdac3c
--- /dev/null
+++ b/src/java/net/sf/jabref/SimpleUrlDragDrop.java
@@ -0,0 +1,153 @@
+/*
+Copyright (C) 2004 E. Putrycz
+
+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.awt.Component;
+import java.awt.datatransfer.DataFlavor;
+import java.awt.datatransfer.Transferable;
+import java.awt.datatransfer.UnsupportedFlavorException;
+import java.awt.dnd.DnDConstants;
+import java.awt.dnd.DropTargetDragEvent;
+import java.awt.dnd.DropTargetDropEvent;
+import java.awt.dnd.DropTargetEvent;
+import java.awt.dnd.DropTargetListener;
+import java.awt.event.ActionEvent;
+import java.io.IOException;
+import java.net.URL;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.swing.JOptionPane;
+
+import net.sf.jabref.EntryEditor.StoreFieldAction;
+
+/**
+ * @author Erik Putrycz erik.putrycz-at-nrc-cnrc.gc.ca
+ */
+
+public class SimpleUrlDragDrop implements DropTargetListener {
+
+    private static Logger logger = Logger.getLogger(SimpleUrlDragDrop.class
+            .getName());
+
+    private FieldEditor editor;
+
+    private StoreFieldAction storeFieldAction;
+
+    public SimpleUrlDragDrop(FieldEditor _editor,
+            StoreFieldAction _storeFieldAction) {
+        editor = _editor;
+        storeFieldAction = _storeFieldAction;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see java.awt.dnd.DropTargetListener#dragEnter(java.awt.dnd.DropTargetDragEvent)
+     */
+    public void dragEnter(DropTargetDragEvent dtde) {
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see java.awt.dnd.DropTargetListener#dragOver(java.awt.dnd.DropTargetDragEvent)
+     */
+    public void dragOver(DropTargetDragEvent dtde) {
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see java.awt.dnd.DropTargetListener#dropActionChanged(java.awt.dnd.DropTargetDragEvent)
+     */
+    public void dropActionChanged(DropTargetDragEvent dtde) {
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see java.awt.dnd.DropTargetListener#dragExit(java.awt.dnd.DropTargetEvent)
+     */
+    public void dragExit(DropTargetEvent dte) {
+    }
+
+    private static class JOptionChoice {
+
+        private String label;
+
+        private int id;
+
+        public JOptionChoice(String _label, int _id) {
+            label = _label;
+            id = _id;
+        }
+
+        public String toString() {
+            return label;
+        }
+
+        public int getId() {
+            return id;
+        }
+
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see java.awt.dnd.DropTargetListener#drop(java.awt.dnd.DropTargetDropEvent)
+     */
+    public void drop(DropTargetDropEvent dtde) {
+        Transferable tsf = dtde.getTransferable();
+        dtde.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
+        //try with an URL
+        DataFlavor dtURL = null;
+        try{
+            dtURL = new DataFlavor("application/x-java-url; class=java.net.URL");
+        }catch (ClassNotFoundException e){
+            logger.log(Level.WARNING,
+                    "Class not found for DnD... should not happen", e);
+        }
+        try{
+            URL url = (URL) tsf.getTransferData(dtURL);
+            //insert URL
+            editor.setText(url.toString());
+            storeFieldAction.actionPerformed(new ActionEvent(editor, 0, ""));
+            return;
+        }catch (UnsupportedFlavorException nfe){
+            // if not an URL
+            JOptionPane.showMessageDialog((Component) editor, Globals
+                    .lang("Operation not supported"), Globals
+                    .lang("Drag and Drop Error"), JOptionPane.ERROR_MESSAGE);
+            logger.log(Level.WARNING, "Transfer exception", nfe);
+        }catch (IOException ioex){
+            logger.log(Level.WARNING, "!should not happen!", ioex);
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/src/java/net/sf/jabref/SplashScreen.java b/src/java/net/sf/jabref/SplashScreen.java
new file mode 100644
index 0000000..af7fc4b
--- /dev/null
+++ b/src/java/net/sf/jabref/SplashScreen.java
@@ -0,0 +1,110 @@
+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/jabref-2.0-splash.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/StrictDuplicateSearch.java b/src/java/net/sf/jabref/StrictDuplicateSearch.java
new file mode 100644
index 0000000..c9da2f9
--- /dev/null
+++ b/src/java/net/sf/jabref/StrictDuplicateSearch.java
@@ -0,0 +1,86 @@
+/*  
+ * StrictDuplicateSearch.java
+ *
+ * Created on November 4, 2004, 11:59 PM
+ */
+
+package net.sf.jabref;
+
+import javax.swing.*;
+import net.sf.jabref.undo.NamedCompound;
+import net.sf.jabref.undo.UndoableRemoveEntry;
+import java.util.HashSet;
+import java.util.Iterator;
+
+/**
+ *
+ * @author  alver
+ */
+public class StrictDuplicateSearch extends Thread {
+    
+    BasePanel panel;
+    
+    /** Creates a new instance of StrictDuplicateSearch */
+    public StrictDuplicateSearch(BasePanel bp) {
+        this.panel = bp;
+        
+    }
+    
+    public void run() {
+        HashSet toRemove = new HashSet();
+        NamedCompound ce = new NamedCompound(Globals.lang("Remove duplicates"));
+        int duplicateCounter = 0;
+        panel.output(Globals.lang("Searching for duplicates..."));
+        Object[] keys = panel.database.getKeySet().toArray();
+        if ((keys == null) || (keys.length < 2))
+            return;
+        BibtexEntry[] bes = new BibtexEntry[keys.length];
+        for (int i=0; i<keys.length; i++)
+            bes[i] = panel.database.getEntryById((String)keys[i]);
+        
+        for (int i = 0; i<bes.length-1; i++) {
+            for (int j = i + 1; j<bes.length; j++) {
+                // We only check the entries if none of the two are already marked for removal.
+                if (!toRemove.contains(bes[i]) && !toRemove.contains(bes[j]) && 
+                    Util.compareEntriesStrictly(bes[i], bes[j]) > 1) {
+                    // These two entries are exactly the same, so we can remove one.                    
+                    if (!toRemove.contains(bes[i]) && !toRemove.contains(bes[j])) {
+                        toRemove.add(bes[j]);
+                    }
+                }
+            }
+         }
+    
+        if (toRemove.size() == 0) {
+            panel.output(Globals.lang("No duplicates found")+".");
+            return;
+        }
+               
+        // Finished searching. Now, remove all entries scheduled for removal:
+        int answer = JOptionPane.showConfirmDialog(panel.frame(), Globals.lang("Duplicates found")+": "+
+            toRemove.size()+". "+Globals.lang("Remove all?"), Globals.lang("Remove duplicates"),
+            JOptionPane.OK_CANCEL_OPTION);
+        if (answer == JOptionPane.CANCEL_OPTION)
+            return;
+        
+        panel.output(Globals.lang("Duplicates removed")+": "+toRemove.size());
+        
+        for (Iterator i=toRemove.iterator(); i.hasNext();) {
+            BibtexEntry entry = (BibtexEntry)i.next();
+            panel.database.removeEntry(entry.getId());        
+            ce.addEdit(new UndoableRemoveEntry(panel.database, entry, panel));
+        }
+     
+        ce.end();
+        panel.undoManager.addEdit(ce);
+        
+        SwingUtilities.invokeLater(new Runnable() {
+            public void run() {                
+                panel.markBaseChanged();
+            }
+        });
+
+        
+    }
+}
+
diff --git a/src/java/net/sf/jabref/StringDialog.java b/src/java/net/sf/jabref/StringDialog.java
new file mode 100644
index 0000000..20fd942
--- /dev/null
+++ b/src/java/net/sf/jabref/StringDialog.java
@@ -0,0 +1,550 @@
+/*
+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.
+
+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.awt.event.*;
+import java.awt.*;
+import javax.swing.*;
+import javax.swing.table.*;
+import java.util.*;
+import net.sf.jabref.undo.*;
+import net.sf.jabref.export.LatexFieldFormatter;
+import javax.swing.undo.CompoundEdit;
+
+public class StringDialog extends JDialog {
+
+    // A reference to the entry this object works on.
+    BibtexDatabase base;
+    JabRefFrame frame;
+    BasePanel panel;
+    JabRefPreferences prefs;
+    TreeSet stringsSet; // Our locally sorted set of strings.
+    Object[] strings;
+
+    // Layout objects.
+    GridBagLayout gbl = new GridBagLayout();
+    GridBagConstraints con = new GridBagConstraints();
+    JLabel lab;
+    Container conPane = getContentPane();
+    JToolBar tlb = new JToolBar();
+    JPanel pan = new JPanel();
+    StringTable table;
+    HelpAction helpAction;
+
+    public StringDialog(JabRefFrame frame, BasePanel panel,
+			BibtexDatabase base, JabRefPreferences prefs) {
+	super(frame);
+	this.frame = frame;
+	this.panel = panel;
+	this.base = base;
+	this.prefs = prefs;
+
+	sortStrings();
+
+	helpAction = new HelpAction
+	    (frame.helpDiag, GUIGlobals.stringEditorHelp, "Help");
+
+
+	addWindowListener(new WindowAdapter() {
+		public void windowClosing(WindowEvent e) {
+		    closeAction.actionPerformed(null);
+		}
+	    });
+
+	// We replace the default FocusTraversalPolicy with a subclass
+	// that only allows the StringTable to gain keyboard focus.
+	setFocusTraversalPolicy(new LayoutFocusTraversalPolicy() {
+		protected boolean accept(Component c) {
+		    return (super.accept(c) && (c instanceof StringTable));
+		}
+	    });
+
+	setLocation(prefs.getInt("stringsPosX"), prefs.getInt("stringsPosY"));
+	setSize(prefs.getInt("stringsSizeX"), prefs.getInt("stringsSizeY"));
+
+	pan.setLayout(gbl);
+	con.fill = GridBagConstraints.BOTH;
+	con.weighty = 1;
+	con.weightx = 1;
+
+	StringTableModel stm = new StringTableModel(this, base);
+	table = new StringTable(stm);
+	if (base.getStringCount() > 0)
+	    table.setRowSelectionInterval(0,0);
+
+	gbl.setConstraints(table.getPane(), con);
+	pan.add(table.getPane());
+
+	InputMap im = tlb.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
+	ActionMap am = tlb.getActionMap();
+	im.put(prefs.getKey("String dialog, add string"), "add");
+	am.put("add", newStringAction);
+	im.put(prefs.getKey("String dialog, remove string"), "remove");
+	am.put("remove", removeStringAction);
+	//im.put(prefs.getKey("String dialog, move string up"), "up");
+	//am.put("up", stringUpAction);
+	//im.put(prefs.getKey("String dialog, move string down"), "down");
+	//am.put("down", stringDownAction);
+	im.put(prefs.getKey("Close dialog"), "close");
+	am.put("close", closeAction);
+	im.put(prefs.getKey("Help"), "help");
+	am.put("help", helpAction);
+	im.put(prefs.getKey("Undo"), "undo");
+	am.put("undo", undoAction);
+	im.put(prefs.getKey("Redo"), "redo");
+	am.put("redo", redoAction);
+
+	//tlb.add(closeAction);
+	//tlb.addSeparator();
+	tlb.add(newStringAction);
+	tlb.add(removeStringAction);
+	tlb.addSeparator();
+	//tlb.add(stringUpAction);
+	//tlb.add(stringDownAction);
+	tlb.addSeparator();
+	tlb.add(helpAction);
+	conPane.add(tlb, BorderLayout.NORTH);
+	conPane.add(pan, BorderLayout.CENTER);
+
+	if (panel.file != null)
+	    setTitle(Globals.lang(GUIGlobals.stringsTitle)+": "+panel.file.getName());
+	else
+	    setTitle(Globals.lang(GUIGlobals.stringsTitle)+": "+Globals.lang(GUIGlobals.untitledTitle));
+
+    }
+
+    class StringTable extends JTable {
+	JScrollPane sp = new JScrollPane((JTable)this);
+	public StringTable(StringTableModel stm) {
+	    super(stm);
+	    setShowVerticalLines(true);
+	    setShowHorizontalLines(true);
+	    setColumnSelectionAllowed(true);
+	    DefaultCellEditor dce = new DefaultCellEditor(new JTextField());
+	    dce.setClickCountToStart(2);
+	    setDefaultEditor(String.class, dce);
+	    TableColumnModel cm = getColumnModel();
+	    cm.getColumn(0).setPreferredWidth(800);
+	    cm.getColumn(1).setPreferredWidth(2000);
+	    sp.getViewport().setBackground(Globals.prefs.getColor("tableBackground"));
+	    // getInputMap().remove(GUIGlobals.exitDialog);
+	    getInputMap().put(frame.prefs.getKey("Close dialog"), "close");
+	    getActionMap().put("close", closeAction);
+	    getInputMap().put(frame.prefs.getKey("Help"), "help");
+	    getActionMap().put("help", helpAction);
+
+	}
+
+	public JComponent getPane() {
+	    return sp;
+	}
+
+    }
+
+    private void sortStrings() {
+	// Rebuild our sorted set of strings:
+	stringsSet = new TreeSet(new BibtexStringComparator(false));
+	Iterator i = base.getStringKeySet().iterator();
+	for (;i.hasNext();) {
+	    stringsSet.add(base.getString(i.next()));
+	}
+	strings = stringsSet.toArray();
+    }
+
+    public void refreshTable() {
+	sortStrings();
+	table.revalidate();
+	table.clearSelection();
+	table.repaint();
+    }
+
+    class StringTableModel extends AbstractTableModel {
+
+	BibtexDatabase base;
+	StringDialog parent;
+
+	public StringTableModel(StringDialog parent, BibtexDatabase base) {
+	    this.parent = parent;
+	    this.base = base;
+	}
+
+	public Object getValueAt(int row, int col) {
+	    return ((col == 0) ?
+		    ((BibtexString)strings[row]).getName() :
+		    ((BibtexString)strings[row]).getContent());
+	}
+
+	public void setValueAt(Object value, int row, int col) {
+	    //	    if (row >= base.getStringCount())
+	    //	return; // After a Remove operation the program somehow
+	                // thinks the user is still editing an entry,
+	                // which might now be outside
+	    if (col == 0) {
+		// Change name of string.
+		if (!((String)value).equals(((BibtexString)strings[row]).getName())) {
+		    if (base.hasStringLabel((String)value))
+			JOptionPane.showMessageDialog(parent,
+						      Globals.lang("A string with that label "
+								   +"already exists"),
+						      Globals.lang("Label"),
+						      JOptionPane.ERROR_MESSAGE);
+                      else if (((String)value).indexOf(" ") >= 0) {
+                        JOptionPane.showMessageDialog
+                            (parent,
+                             Globals.lang("The label of the string can not contain spaces."),
+                             Globals.lang("Label"),
+                             JOptionPane.ERROR_MESSAGE);
+                      }
+                      else if (((String)value).indexOf("#") >= 0) {
+                        JOptionPane.showMessageDialog
+                            (parent,
+                            Globals.lang("The label of the string can not contain the '#' character."),
+                            Globals.lang("Label"),
+                            JOptionPane.ERROR_MESSAGE);
+                      }   
+                      else if ((value != null) && isNumber((String)value)) {
+                          JOptionPane.showMessageDialog
+                              (parent,
+                               Globals.lang("The label of the string can not be a number."),
+                               Globals.lang("Label"),
+                               JOptionPane.ERROR_MESSAGE);
+		    }
+		    else {
+			// Store undo information.
+			BibtexString subject = (BibtexString)strings[row];
+			panel.undoManager.addEdit
+			    (new UndoableStringChange
+			     (panel, subject, true,
+			      subject.getName(), (String)value));
+			subject.setName((String)value);
+			panel.markBaseChanged();
+			refreshTable();
+		    }
+		}
+	    } else {
+		// Change content of string.
+		BibtexString subject = (BibtexString)strings[row];
+
+		if (!((String)value).equals(subject.getContent())) {
+                    try {
+                        (new LatexFieldFormatter()).format((String)value, "__dummy");
+                    } catch (IllegalArgumentException ex) {
+                        return;
+                    }
+		    // Store undo information.
+		    panel.undoManager.addEdit
+			(new UndoableStringChange
+			 (panel, subject, false,
+			  subject.getContent(), (String)value));
+
+		    subject.setContent((String)value);
+		    panel.markBaseChanged();
+		}
+	    }
+	}
+
+	public int getColumnCount() {
+	    return 2;
+	}
+
+	public int getRowCount() {
+	    return strings.length; //base.getStringCount();
+	}
+
+	public String getColumnName(int col) {
+	    return ((col == 0) ?
+		    Globals.lang("Name") : Globals.lang("Content"));
+	}
+
+	public boolean isCellEditable(int row, int col) {
+	    return true;
+	}
+    }
+
+    protected boolean isNumber(String name) {
+	// A pure integer number can not be used as a string label,
+	// since Bibtex will read it as a number.
+	try {
+	    Integer.parseInt(name);
+	    return true;
+	} catch (NumberFormatException ex) {
+	    return false;
+	}
+
+    }
+
+    protected void assureNotEditing() {
+	if (table.isEditing()) {
+	    int col = table.getEditingColumn(),
+		row = table.getEditingRow();
+	    table.getCellEditor(row, col).stopCellEditing();
+	}
+    }
+
+    // The action concerned with closing the window.
+    CloseAction closeAction = new CloseAction(this);
+    class CloseAction extends AbstractAction {
+	StringDialog parent;
+	public CloseAction(StringDialog parent) {
+	    super("Close window");
+	    //, new ImageIcon(GUIGlobals.closeIconFile));
+	    putValue(SHORT_DESCRIPTION, Globals.lang("Close dialog"));
+	    this.parent = parent;
+	}
+	public void actionPerformed(ActionEvent e) {
+	    panel.stringsClosing();
+	    dispose();
+	    Point p = getLocation();
+	    Dimension d = getSize();
+	    prefs.putInt("stringsPosX", p.x);
+	    prefs.putInt("stringsPosY", p.y);
+	    prefs.putInt("stringsSizeX", d.width);
+	    prefs.putInt("stringsSizeY", d.height);
+	}
+    }
+
+    NewStringAction newStringAction = new NewStringAction(this);
+    class NewStringAction extends AbstractAction {
+	StringDialog parent;
+	public NewStringAction(StringDialog parent) {
+	    super("New string",
+		  new ImageIcon(GUIGlobals.addIconFile));
+	    putValue(SHORT_DESCRIPTION, Globals.lang("New string"));
+	    this.parent = parent;
+	}
+	public void actionPerformed(ActionEvent e) {
+	    String name =
+		JOptionPane.showInputDialog(parent,
+					    Globals.lang("Please enter the string's label"));
+	    if (name == null)
+		return;
+	    if (isNumber(name)) {
+		JOptionPane.showMessageDialog
+		    (parent,
+		     Globals.lang("The label of the string can not be a number."),
+		     Globals.lang("Label"),
+		     JOptionPane.ERROR_MESSAGE);
+		return;
+	    }
+            if (name.indexOf("#") >= 0) {
+             JOptionPane.showMessageDialog
+                 (parent,
+                  Globals.lang("The label of the string can not contain the '#' character."),
+                  Globals.lang("Label"),
+                  JOptionPane.ERROR_MESSAGE);
+             return;
+           }           
+           if (name.indexOf(" ") >= 0) {
+             JOptionPane.showMessageDialog
+                 (parent,
+                  Globals.lang("The label of the string can not contain spaces."),
+                  Globals.lang("Label"),
+                  JOptionPane.ERROR_MESSAGE);
+             return;
+           }
+	    try {
+		String newId = Util.createNeutralId();
+		BibtexString bs = new BibtexString(newId, name, "");
+
+		// Store undo information:
+		panel.undoManager.addEdit
+		    (new UndoableInsertString
+		     (panel, panel.database, bs));
+
+		base.addString(bs);
+		refreshTable();
+		//		table.revalidate();
+		panel.markBaseChanged();
+	    } catch (KeyCollisionException ex) {
+		JOptionPane.showMessageDialog(parent,
+					      Globals.lang("A string with that label "
+							   +"already exists"),
+					      Globals.lang("Label"),
+					      JOptionPane.ERROR_MESSAGE);
+	    }
+	}
+    }
+
+    StoreContentAction storeContentAction = new StoreContentAction(this);
+    class StoreContentAction extends AbstractAction {
+	StringDialog parent;
+	public StoreContentAction(StringDialog parent) {
+	    super("Store string",
+		  new ImageIcon(GUIGlobals.addIconFile));
+	    putValue(SHORT_DESCRIPTION, Globals.lang("Store string"));
+	    this.parent = parent;
+	}
+	public void actionPerformed(ActionEvent e) {
+	}
+    }
+
+    RemoveStringAction removeStringAction = new RemoveStringAction(this);
+    class RemoveStringAction extends AbstractAction {
+	StringDialog parent;
+	public RemoveStringAction(StringDialog parent) {
+	    super("Remove selected strings",
+		  new ImageIcon(GUIGlobals.removeIconFile));
+	    putValue(SHORT_DESCRIPTION, Globals.lang("Remove selected strings"));
+	    this.parent = parent;
+	}
+	public void actionPerformed(ActionEvent e) {
+	    int[] sel = table.getSelectedRows();
+	    if (sel.length > 0) {
+
+		// Make sure no cell is being edited, as caused by the
+		// keystroke. This makes the content hang on the screen.
+		assureNotEditing();
+
+		String msg = Globals.lang("Really delete the selected")+" "+
+		    ((sel.length>1) ? sel.length+" "+Globals.lang("entries")
+		     : Globals.lang("entry"))+"?";
+		int answer = JOptionPane.showConfirmDialog(parent, msg, Globals.lang("Delete strings"),
+							   JOptionPane.YES_NO_OPTION,
+							   JOptionPane.QUESTION_MESSAGE);
+		if (answer == JOptionPane.YES_OPTION) {
+		    CompoundEdit ce = new CompoundEdit();
+		    for (int i=sel.length-1; i>=0; i--) {
+			// Delete the strings backwards to avoid moving indexes.
+
+			BibtexString subject = (BibtexString)strings[sel[i]];
+
+			// Store undo information:
+			ce.addEdit(new UndoableRemoveString
+				   (panel, base,
+				    subject));
+
+			base.removeString(subject.getId());
+		    }
+		    ce.end();
+		    panel.undoManager.addEdit(ce);
+
+		    //table.revalidate();
+		    refreshTable();
+		    if (base.getStringCount() > 0)
+			table.setRowSelectionInterval(0,0);
+		    //table.repaint();
+		    //panel.markBaseChanged();
+		}
+	    }
+	}
+    }
+
+    /*    StringUpAction stringUpAction = new StringUpAction();
+    class StringUpAction extends AbstractAction {
+	public StringUpAction() {
+	    super("Move string up",
+		  new ImageIcon(GUIGlobals.upIconFile));
+	    putValue(SHORT_DESCRIPTION, Globals.lang("Move string up"));
+	}
+	public void actionPerformed(ActionEvent e) {
+	    int[] sel = table.getSelectedRows();
+	    if ((sel.length == 1) && (sel[0] > 0)) {
+
+		// Make sure no cell is being edited, as caused by the
+		// keystroke. This makes the content hang on the screen.
+		assureNotEditing();
+		// Store undo information:
+		panel.undoManager.addEdit(new UndoableMoveString
+					      (panel, base, sel[0], true));
+
+		BibtexString bs = base.getString(sel[0]);
+		base.removeString(sel[0]);
+		try {
+		    base.addString(bs, sel[0]-1);
+		} catch (KeyCollisionException ex) {}
+		table.revalidate();
+		table.setRowSelectionInterval(sel[0]-1, sel[0]-1);
+		table.repaint();
+		panel.markBaseChanged();
+	    }
+	}
+    }
+
+    StringDownAction stringDownAction = new StringDownAction();
+    class StringDownAction extends AbstractAction {
+	public StringDownAction() {
+	    super("Move string down",
+		  new ImageIcon(GUIGlobals.downIconFile));
+	    putValue(SHORT_DESCRIPTION, Globals.lang("Move string down"));
+	}
+	public void actionPerformed(ActionEvent e) {
+	    int[] sel = table.getSelectedRows();
+	    if ((sel.length == 1) && (sel[0]+1 < base.getStringCount())) {
+
+		// Make sure no cell is being edited, as caused by the
+		// keystroke. This makes the content hang on the screen.
+		assureNotEditing();
+
+
+		// Store undo information:
+		panel.undoManager.addEdit(new UndoableMoveString
+					      (panel, base, sel[0], false));
+
+
+		BibtexString bs = base.getString(sel[0]);
+		base.removeString(sel[0]);
+		try {
+		    base.addString(bs, sel[0]+1);
+		} catch (KeyCollisionException ex) {}
+		table.revalidate();
+		table.setRowSelectionInterval(sel[0]+1, sel[0]+1);
+		table.repaint();
+		panel.markBaseChanged();
+	    }
+
+	}
+    }*/
+
+    UndoAction undoAction = new UndoAction();
+    class UndoAction extends AbstractAction {
+	public UndoAction() {
+	    super("Undo", new ImageIcon(GUIGlobals.undoIconFile));
+	    putValue(SHORT_DESCRIPTION, Globals.lang("Undo"));
+	}
+	public void actionPerformed(ActionEvent e) {
+	    try {
+		panel.runCommand("undo");
+	    } catch (Throwable ex) {}
+	}
+    }
+
+    RedoAction redoAction = new RedoAction();
+    class RedoAction extends AbstractAction {
+	public RedoAction() {
+	    super("Undo", new ImageIcon(GUIGlobals.redoIconFile));
+	    putValue(SHORT_DESCRIPTION, Globals.lang("Redo"));
+	}
+	public void actionPerformed(ActionEvent e) {
+	    try {
+		panel.runCommand("redo");
+	    } catch (Throwable ex) {}
+	}
+    }
+
+
+}
diff --git a/src/java/net/sf/jabref/TabLabelPattern.java b/src/java/net/sf/jabref/TabLabelPattern.java
new file mode 100644
index 0000000..be2a635
--- /dev/null
+++ b/src/java/net/sf/jabref/TabLabelPattern.java
@@ -0,0 +1,409 @@
+/*
+ * Created on 09-Dec-2003
+ */
+package net.sf.jabref;
+
+import java.util.Iterator;
+import java.util.HashMap;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+import java.awt.Font;
+import java.awt.Container;
+import java.awt.BorderLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+import javax.swing.*;
+import javax.swing.event.ChangeListener;
+import javax.swing.event.ChangeEvent;
+
+import net.sf.jabref.labelPattern.LabelPattern;
+import net.sf.jabref.labelPattern.LabelPatternUtil;
+import com.jgoodies.forms.layout.FormLayout;
+import com.jgoodies.forms.builder.DefaultFormBuilder;
+
+/**
+ * This is the panel for the key pattern definition tab in 'Preferences'. So far
+ * it is only possible to edit default entry types.
+ * 
+ * Labels and buttons does not yet draw from a resource file.
+ *   
+ * @author Ulrik Stervbo (ulriks AT ruc.dk)
+ */
+public class TabLabelPattern extends JPanel implements PrefsTab{
+	
+    private String def = Globals.lang("Default");
+    private GridBagLayout gbl = new GridBagLayout();
+    private GridBagConstraints con = new GridBagConstraints();
+    private HashMap textFields = new HashMap();
+
+	private JabRefPreferences _prefs;
+	private LabelPattern _keypatterns = null;
+	
+    private JCheckBox dontOverwrite = new JCheckBox(Globals.lang("Do not overwrite existing keys")),
+        warnBeforeOverwriting = new JCheckBox(Globals.lang("Warn before overwriting existing keys"));
+
+    
+	private JLabel lblEntryType, lblKeyPattern;
+
+    private JTextField defaultPat = new JTextField();
+
+    //private JTextField basenamePatternRegex = new JTextField(20);
+    //private JTextField basenamePatternReplacement = new JTextField(20);
+    private JTextField KeyPatternRegex = new JTextField(20);
+    private JTextField KeyPatternReplacement = new JTextField(20);
+
+	private JButton btnDefaultAll, btnDefault;
+
+
+    private HelpAction help;
+	
+	/**
+	 * The constructor
+	 */
+	public TabLabelPattern(JabRefPreferences prefs, HelpDialog helpDiag) {
+		_prefs = prefs;
+		//_keypatterns = _prefs.getKeyPattern();
+		help = new HelpAction(helpDiag, GUIGlobals.labelPatternHelp,
+				      "Help on key patterns");
+		buildGUI();
+        //fillTextfields();
+	}
+
+	/**
+	 * Store changes to table preferences. This method is called when
+	 * the user clicks Ok.
+	 *
+	 */
+	public void storeSettings() {
+
+         // Set the default value:
+         Globals.prefs.put("defaultLabelPattern", defaultPat.getText());
+
+         Globals.prefs.putBoolean("warnBeforeOverwritingKey", warnBeforeOverwriting.isSelected());
+         Globals.prefs.putBoolean("avoidOverwritingKey", dontOverwrite.isSelected());
+
+         //Globals.prefs.put("basenamePatternRegex", basenamePatternRegex.getText());
+         //Globals.prefs.put("basenamePatternReplacement", basenamePatternReplacement.getText());
+         Globals.prefs.put("KeyPatternRegex", KeyPatternRegex.getText());
+         Globals.prefs.put("KeyPatternReplacement", KeyPatternReplacement.getText());
+
+         LabelPatternUtil.updateDefaultPattern();
+
+
+	    LabelPattern defKeyPattern = _keypatterns.getParent();
+	    _keypatterns = new LabelPattern(defKeyPattern);
+	    
+	    // then we rebuild... 
+	    Iterator i=textFields.keySet().iterator();
+	    //String defa = (String)LabelPatternUtil.DEFAULT_LABELPATTERN.get(0);
+	    while (i.hasNext()) {
+		String s = (String)i.next(),
+		    text = ((JTextField)textFields.get(s)).getText();
+		if (!"".equals(text.trim())) //(!defa.equals(text))
+		    _keypatterns.addLabelPattern(s, text);
+	    }
+
+	    _prefs.putKeyPattern(_keypatterns);
+
+	}
+	
+    private  JTextField addEntryType(Container c, String name, int y) { 
+
+	JLabel lab = new JLabel(Util.nCase(name));
+	name = name.toLowerCase();
+	con.gridx = 0;
+	con.gridy = y;
+	con.fill = GridBagConstraints.BOTH;
+	con.weightx = 0;
+	con.weighty = 0;
+	con.anchor = GridBagConstraints.WEST;
+	con.insets = new Insets( 0,5,0,5 );
+	gbl.setConstraints( lab, con );
+	c.add( lab );
+	
+	JTextField tf = new JTextField();//_keypatterns.getValue(name).get(0).toString());
+	tf.setColumns( 15 );
+	con.gridx = 1;
+	con.fill = GridBagConstraints.HORIZONTAL;
+	con.weightx = 1;
+	con.weighty = 0;
+	con.anchor = GridBagConstraints.CENTER;
+	con.insets = new Insets( 0,5,0,5 );
+	gbl.setConstraints( tf, con );
+	c.add( tf );	
+	
+	JButton but = new JButton( def );
+	con.gridx = 2;
+	con.fill = GridBagConstraints.BOTH;
+	con.weightx = 0;
+	con.weighty = 0;
+	con.anchor = GridBagConstraints.CENTER;
+	con.insets = new Insets( 0,5,0,5 );
+	gbl.setConstraints( but, con );
+	but.setActionCommand(name);
+        but.addActionListener(new buttonHandler());
+	c.add( but );		
+
+	return tf;
+    }
+
+    private void setValue(JTextField tf, String fieldName) {
+        if (_keypatterns.isDefaultValue(fieldName))
+            tf.setText("");
+        else {
+            //System.out.println(":: "+_keypatterns.getValue(fieldName).get(0).toString());
+            tf.setText(_keypatterns.getValue(fieldName).get(0).toString());
+        }
+    }
+
+	/**
+	 * Method to build GUI
+	 *
+	 */
+	private void buildGUI(){
+
+	    JPanel pan = new JPanel();
+	    JScrollPane sp = new JScrollPane(pan);	
+	    sp.setBorder(BorderFactory.createEmptyBorder());
+	    pan.setLayout(gbl);
+	    setLayout(gbl);	    
+	    // The header - can be removed
+	    lblEntryType = new JLabel(Globals.lang("Entry type"));
+	    Font f = new Font("plain", Font.BOLD, 12);
+	    lblEntryType.setFont(f);
+	    con.gridx = 0;
+	    con.gridy = 0;
+	    con.gridwidth = 1;
+	    con.gridheight = 1;
+	    con.fill = GridBagConstraints.VERTICAL;
+	    con.anchor = GridBagConstraints.WEST;
+	    con.insets = new Insets( 5,5,10,0 );
+	    gbl.setConstraints( lblEntryType, con );
+	    pan. add( lblEntryType );
+	    
+	    lblKeyPattern = new JLabel(Globals.lang("Key pattern"));
+	    lblKeyPattern.setFont(f);
+	    con.gridx = 1;
+	    con.gridy = 0;
+	    //con.gridwidth = 2;
+	    con.gridheight = 1;
+	    con.fill = GridBagConstraints.HORIZONTAL;
+	    con.anchor = GridBagConstraints.WEST;
+	    con.insets = new Insets( 5,5,10,5 );
+	    gbl.setConstraints( lblKeyPattern, con );
+	    pan.add( lblKeyPattern );
+
+
+            con.gridy = 1;
+            con.gridx = 0;
+            JLabel lab = new JLabel(Globals.lang("Default pattern"));
+            gbl.setConstraints(lab, con);
+            pan.add(lab);
+            con.gridx = 1;
+            gbl.setConstraints(defaultPat, con);
+            pan.add(defaultPat);
+        con.insets = new Insets( 5,5,10,5 );
+        btnDefault = new JButton(Globals.lang("Default"));
+        btnDefault.addActionListener(new ActionListener() {
+            public void actionPerformed(ActionEvent event) {
+                defaultPat.setText((String)Globals.prefs.defaults.get("defaultLabelPattern"));
+            }
+        });
+        con.gridx = 2;
+	    int y = 2;
+        gbl.setConstraints(btnDefault, con);
+        pan.add(btnDefault);
+
+	    Iterator i=BibtexEntryType.ALL_TYPES.keySet().iterator();
+	    while (i.hasNext()) {
+		String s = (String)i.next();
+		textFields.put(s, addEntryType(pan, s, y));
+		y++;
+	    }
+
+	    con.fill = GridBagConstraints.BOTH;
+	    con.gridx = 0;
+	    con.gridy = 1;
+	    con.gridwidth = 3;
+	    con.weightx = 1;
+	    con.weighty = 1;
+	    gbl.setConstraints(sp, con );
+	    add(sp);
+
+	    // A help button
+	    con.gridwidth = 1;
+	    con.gridx = 1;
+	    con.gridy = 2;
+	    con.fill = GridBagConstraints.HORIZONTAL;
+	    //
+	    con.weightx = 0;
+	    con.weighty = 0;
+	    con.anchor = GridBagConstraints.SOUTHEAST;
+	    con.insets = new Insets( 0,5,0,5 );
+	    JButton hlb = new JButton(new ImageIcon(GUIGlobals.helpSmallIconFile));
+	    hlb.setToolTipText(Globals.lang("Help on key patterns"));
+	    gbl.setConstraints( hlb, con );
+	    add(hlb);
+	    hlb.addActionListener(help);
+	    
+	    // And finally a button to reset everything
+	    btnDefaultAll = new JButton(Globals.lang("Reset all"));
+	    con.gridx = 2;
+	    con.gridy = 2;
+
+	    //con.fill = GridBagConstraints.BOTH;
+	    con.weightx = 1;
+	    con.weighty = 0;
+	    con.anchor = GridBagConstraints.SOUTHEAST;
+	    con.insets = new Insets( 20,5,0,5 );
+	    gbl.setConstraints( btnDefaultAll, con );
+	    btnDefaultAll.addActionListener(new buttonHandler());
+	    add( btnDefaultAll );
+
+
+        // Build a panel for checkbox settings:
+        FormLayout layout = new FormLayout
+	        ("1dlu, 8dlu, left:pref, 8dlu, left:pref", "");//, 8dlu, 20dlu, 8dlu, fill:pref", "");
+        pan = new JPanel();
+	    DefaultFormBuilder builder = new DefaultFormBuilder(layout);
+        builder.appendSeparator(Globals.lang("Key generator settings"));
+
+        builder.nextLine();
+        builder.append(pan);
+        builder.append(warnBeforeOverwriting);
+        builder.nextLine();
+        builder.append(pan);
+        builder.append(dontOverwrite);
+
+        builder.nextLine();
+        builder.append(pan);
+        builder.append(Globals.lang("Replace (regular expression)")+":");
+        builder.append(Globals.lang("by")+":");
+
+        builder.nextLine();
+        builder.append(pan);
+        builder.append(KeyPatternRegex);
+        builder.append(KeyPatternReplacement);
+
+        builder.getPanel().setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+        con.gridx = 1;
+	    con.gridy = 3;
+        con.gridwidth = GridBagConstraints.REMAINDER;
+        con.weightx = 1;
+        con.fill = GridBagConstraints.BOTH;
+        gbl.setConstraints(builder.getPanel(), con);
+        add(builder.getPanel());
+
+        dontOverwrite.addChangeListener(new ChangeListener() {
+            public void stateChanged(ChangeEvent event) {
+                // Warning before overwriting is only relevant if overwriting can happen:
+                warnBeforeOverwriting.setEnabled(!dontOverwrite.isSelected());
+            }
+        });
+
+      /*
+       Simon Fischer's patch for replacing a regexp in keys before converting to filename:
+
+	layout = new FormLayout
+	        ("left:pref, 8dlu, left:pref, left:pref", "");
+	builder = new DefaultFormBuilder(layout);
+        builder.appendSeparator(Globals.lang("Bibkey to filename conversion"));
+        builder.nextLine();
+	builder.append(Globals.lang("Replace"), basenamePatternRegex);
+        builder.nextLine();
+	builder.append(Globals.lang("by"), basenamePatternReplacement);
+        builder.nextLine();
+
+        builder.getPanel().setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+        con.gridx = 2;
+ 	con.gridy = 3;
+	con.gridwidth = GridBagConstraints.REMAINDER;
+	con.weightx = 1;
+	con.fill = GridBagConstraints.BOTH;
+	gbl.setConstraints(builder.getPanel(), con);
+        add(builder.getPanel());
+        */
+	}
+	
+	/**
+	 * Method for filling the text fields with user defined key patterns or default.
+	 * The method used (<code>getValue(key)</code>) to get the ArrayList 
+	 * corrosponding to an entry type throws a <code>NullPointerException</code>
+	 * and <code>?</code> if an entry cannot be found. It really shouln't be
+	 * nessesary to catch those exceptions here... 
+	 */
+    /*	private void fillTextfields(){
+		txtArticle.setText(_keypatterns.getValue("article").get(0).toString());
+		txtBook.setText(_keypatterns.getValue("book").get(0).toString());
+		txtBooklet.setText(_keypatterns.getValue("booklet").get(0).toString());
+		txtConference.setText(_keypatterns.getValue("conference").get(0).toString());
+		txtInbook.setText(_keypatterns.getValue("inbook").get(0).toString());
+		txtIncollection.setText(_keypatterns.getValue("incollection").get(0).toString());
+		txtInproceedings.setText(_keypatterns.getValue("inproceedings").get(0).toString());
+		txtManual.setText(_keypatterns.getValue("manual").get(0).toString());
+		txtMastersthesis.setText(_keypatterns.getValue("mastersthesis").get(0).toString());
+		txtMisc.setText(_keypatterns.getValue("misc").get(0).toString());
+		txtPhdthesis.setText(_keypatterns.getValue("phdthesis").get(0).toString());
+		txtProceedings.setText(_keypatterns.getValue("proceedings").get(0).toString());
+		txtTechreport.setText(_keypatterns.getValue("techreport").get(0).toString());
+		txtUnpublished.setText(_keypatterns.getValue("unpublished").get(0).toString());
+	}
+
+    */
+	/**
+	 * An inner class to handle button actions
+	 * @author Ulrik Stervbo (ulriks AT ruc.dk)
+	 */
+	class buttonHandler implements ActionListener{
+		public void actionPerformed(ActionEvent evt){
+
+		    if (evt.getSource() == btnDefaultAll) {
+			// All to default
+			Iterator i=textFields.keySet().iterator();
+			while (i.hasNext()) {
+			    String s = (String)i.next();
+			    //_keypatterns.removeLabelPattern(s);
+			    JTextField tf = (JTextField)textFields.get(s);
+                            tf.setText("");
+    			    /*tf.setText(_keypatterns.getParent()
+				       .getValue(s).get(0).toString());*/
+			}
+
+			return;
+		    }
+
+		    //_keypatterns.removeLabelPattern(evt.getActionCommand());
+		    JTextField tf = (JTextField)textFields.get(evt.getActionCommand());
+                    tf.setText("");
+		    /*tf.setText(_keypatterns.getParent()
+			       .getValue(evt.getActionCommand()).get(0).toString());*/
+		}
+	    
+	}
+
+    public boolean readyToClose() {
+	return true;
+    }
+
+    public void setValues() {
+        _keypatterns = _prefs.getKeyPattern();
+        defaultPat.setText(Globals.prefs.get("defaultLabelPattern"));
+        dontOverwrite.setSelected(Globals.prefs.getBoolean("avoidOverwritingKey"));
+        warnBeforeOverwriting.setSelected(Globals.prefs.getBoolean("warnBeforeOverwritingKey"));
+        // Warning before overwriting is only relevant if overwriting can happen:
+        warnBeforeOverwriting.setEnabled(!dontOverwrite.isSelected());
+	    for (Iterator i=textFields.keySet().iterator(); i.hasNext();) {
+            String name = (String)i.next();
+            JTextField tf = (JTextField)textFields.get(name);
+    	    setValue(tf, name);
+    	}
+
+        KeyPatternRegex.setText(Globals.prefs.get("KeyPatternRegex"));
+        KeyPatternReplacement.setText(Globals.prefs.get("KeyPatternReplacement"));
+
+	    //basenamePatternRegex.setText(Globals.prefs.get("basenamePatternRegex"));
+	    //basenamePatternReplacement.setText(Globals.prefs.get("basenamePatternReplacement"));
+    }
+}
diff --git a/src/java/net/sf/jabref/TableColumnsTab.java b/src/java/net/sf/jabref/TableColumnsTab.java
new file mode 100644
index 0000000..12b8055
--- /dev/null
+++ b/src/java/net/sf/jabref/TableColumnsTab.java
@@ -0,0 +1,397 @@
+package net.sf.jabref;
+
+import java.util.Vector;
+import javax.swing.*;
+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.*;
+
+class TableColumnsTab extends JPanel implements PrefsTab {
+
+    JabRefPreferences _prefs;
+    private String[] _choices;
+    private boolean tableChanged = false;
+    private JTable colSetup;
+    private int rowCount = -1, ncWidth = -1;
+    private Vector tableRows = new Vector(10);
+    private Font font = GUIGlobals.CURRENTFONT,	menuFont;
+    private JabRefFrame frame;
+    private int oldMenuFontSize;
+
+    class TableRow {
+        String name;
+        int length;
+        public TableRow(String name) {
+            this.name = name;
+            length = GUIGlobals.DEFAULT_FIELD_LENGTH;
+        }
+        public TableRow(int length) {
+            this.length = length;
+            name = "";
+        }
+        public TableRow(String name, int length) {
+            this.name = name;
+            this.length = length;
+        }
+    }
+
+
+    /**
+     * Customization of external program paths.
+     *
+     * @param prefs a <code>JabRefPreferences</code> value
+     */
+    public TableColumnsTab(JabRefPreferences prefs, JabRefFrame frame) {
+        _prefs = prefs;
+        this.frame = frame;
+        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 == 0)
+                    return (column==0 ? GUIGlobals.NUMBER_COL : ""+ncWidth);
+                  row--;
+                  if (row >= tableRows.size())
+                    return "";
+                  Object rowContent = tableRows.elementAt(row);
+                  if (rowContent == null)
+                    return "";
+                  TableRow tr = (TableRow)rowContent;
+                  switch (column) {
+                    case 0:
+                      return tr.name;
+                    case 1:
+                      return ((tr.length > 0) ? Integer.toString(tr.length) : "");
+                  }
+                  return null; // Unreachable.
+                }
+
+                public String getColumnName(int col) {
+                    return (col == 0 ? Globals.lang("Field name") : Globals.lang("Column width"));
+                }
+                public Class getColumnClass(int column) {
+                    if (column == 0) return String.class;
+                    else return Integer.class;
+                }
+                public boolean isCellEditable(int row, int col) {
+                    return !((row == 0) && (col == 0));
+                }
+                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("", -1));
+
+                        if ((row == 0) && (col == 1)) {
+                          ncWidth = Integer.parseInt(value.toString());
+                          return;
+                        }
+
+                    TableRow rowContent = (TableRow)tableRows.elementAt(row-1);
+
+                    if (col == 0) {
+                        rowContent.name = value.toString();
+                        if (((String)getValueAt(row, 1)).equals(""))
+                            setValueAt(""+GUIGlobals.DEFAULT_FIELD_LENGTH, row, 1);
+                    }
+                    else {
+                        if (value == null) rowContent.length = -1;
+                        else rowContent.length = Integer.parseInt(value.toString());
+                    }
+                }
+
+            };
+
+        colSetup = new JTable(tm);
+        TableColumnModel cm = colSetup.getColumnModel();
+        cm.getColumn(0).setPreferredWidth(140);
+        cm.getColumn(1).setPreferredWidth(80);
+
+        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();
+
+
+        JPanel tabPanel = new JPanel();
+        tabPanel.setLayout(new BorderLayout());
+        JScrollPane sp = new JScrollPane
+            (colSetup, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
+             JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
+        colSetup.setPreferredScrollableViewportSize(new Dimension(250,200));
+        sp.setMinimumSize(new Dimension(250,300));
+        tabPanel.add(sp, BorderLayout.CENTER);
+        JToolBar tlb = new JToolBar(SwingConstants.VERTICAL);
+        tlb.setFloatable(false);
+        //tlb.setRollover(true);
+        //tlb.setLayout(gbl);
+        AddRowAction ara = new AddRowAction();
+        DeleteRowAction dra = new DeleteRowAction();
+        tlb.setBorder(null);
+        tlb.add(ara);
+        tlb.add(dra);
+        //tlb.addSeparator();
+        //tlb.add(new UpdateWidthsAction());
+        tabPanel.add(tlb, BorderLayout.EAST);
+
+        builder.appendSeparator(Globals.lang("Entry table columns"));
+        builder.nextLine();
+        builder.append(pan); builder.append(tabPanel); builder.nextLine();
+//	lab = new JLabel("<HTML>("+Globals.lang("this button will update the column width settings<BR>"
+//						+"to match the current widths in your table")+")</HTML>");
+//        lab = new JLabel("<HTML>("+Globals.lang("this_button_will_update") +")</HTML>") ;
+        builder.append(pan);
+        JButton button = new JButton(new UpdateWidthsAction());
+        builder.append(button); builder.nextLine();
+        builder.append(pan); 
+        //builder.append(lab);
+        builder.nextLine();
+        pan = builder.getPanel();
+        pan.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+        add(pan, BorderLayout.CENTER);
+    }
+
+    public void setValues() {
+	tableRows.clear();
+	String[] names = _prefs.getStringArray("columnNames"),
+            lengths = _prefs.getStringArray("columnWidths");
+        for (int i=0; i<names.length; i++) {
+            if (i<lengths.length)
+                tableRows.add(new TableRow(names[i], Integer.parseInt(lengths[i])));
+            else
+                tableRows.add(new TableRow(names[i]));
+        }
+        rowCount = tableRows.size()+5;
+        ncWidth = _prefs.getInt("numberColWidth");
+
+    }
+
+
+    class DeleteRowAction extends AbstractAction {
+        public DeleteRowAction() {
+          //super(Globals.lang("Delete rows"));
+          super("Delete row", new ImageIcon(GUIGlobals.delRowIconFile));
+          putValue(SHORT_DESCRIPTION, Globals.lang("Delete rows"));
+        }
+        public void actionPerformed(ActionEvent e) {
+          int[] rows = colSetup.getSelectedRows();
+          if (rows.length == 0)
+            return;
+          int offs = 0;
+          for (int i=0; i<rows.length; i++) {
+            if ((rows[i]-i < tableRows.size()) && (rows[i] != 0)) {
+              tableRows.remove(rows[i] -1 - offs);
+              offs++;
+            }
+          }
+          rowCount -= offs; //rows.length;
+          if (rows.length > 1) colSetup.clearSelection();
+          colSetup.revalidate();
+          colSetup.repaint();
+          tableChanged = true;
+        }
+      }
+
+    class AddRowAction extends AbstractAction {
+        public AddRowAction() {
+          //super(Globals.lang("Insert rows"));
+          super("Add row", new ImageIcon(GUIGlobals.addIconFile));
+          putValue(SHORT_DESCRIPTION, Globals.lang("Insert rows"));
+        }
+        public void actionPerformed(ActionEvent e) {
+            int[] rows = colSetup.getSelectedRows();
+            if (rows.length == 0) {
+                // No rows selected, so we just add one at the end.
+                rowCount++;
+                colSetup.revalidate();
+                colSetup.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(GUIGlobals.DEFAULT_FIELD_LENGTH));
+            }
+            rowCount += rows.length;
+            if (rows.length > 1) colSetup.clearSelection();
+            colSetup.revalidate();
+            colSetup.repaint();
+            tableChanged = true;
+        }
+    }
+
+    class UpdateWidthsAction extends AbstractAction {
+        public UpdateWidthsAction() {
+          //super(Globals.lang("Update to current column widths"));
+          super(Globals.lang("Update to current column widths"), new ImageIcon(GUIGlobals.sheetIcon));
+          //putValue(SHORT_DESCRIPTION, Globals.lang("Update to current column widths"));
+        }
+        public void actionPerformed(ActionEvent e) {
+            BasePanel panel = frame.basePanel();
+            if (panel == null) return;
+            TableColumnModel colMod = panel.mainTable.getColumnModel();
+            colSetup.setValueAt(""+colMod.getColumn(0).getWidth(), 0, 1);
+            for (int i=1; i<colMod.getColumnCount(); i++) {
+            try {
+                String name = panel.mainTable.getColumnName(i).toLowerCase();
+                int width = colMod.getColumn(i).getWidth();
+                //Util.pr(":"+((String)colSetup.getValueAt(i-1, 0)).toLowerCase());
+                //Util.pr("-"+name);
+                if ((i <= tableRows.size()) && (((String)colSetup.getValueAt(i, 0)).toLowerCase()).equals(name))
+                    colSetup.setValueAt(""+width, i, 1);
+                else { // Doesn't match; search for a matching col in our table
+                    for (int j=0; j<colSetup.getRowCount(); j++) {
+                        if ((j < tableRows.size()) &&
+                            (((String)colSetup.getValueAt(j, 0)).toLowerCase()).equals(name)) {
+                            colSetup.setValueAt(""+width, j, 1);
+                            break;
+                        }
+                    }
+                }
+            } catch (Throwable ex) {
+                ex.printStackTrace();
+            }
+            colSetup.revalidate();
+            colSetup.repaint();
+        }
+
+        }
+    }
+
+ 
+    /**
+     * Store changes to table preferences. This method is called when
+     * the user clicks Ok.
+     *
+     */
+    public void storeSettings() {
+
+        if (colSetup.isEditing()) {
+            int col = colSetup.getEditingColumn(),
+                row = colSetup.getEditingRow();
+            colSetup.getCellEditor(row, col).stopCellEditing();
+        }
+
+
+        //_prefs.putStringArray("columnNames", getChoices());
+        /*String[] cols = tableFields.getText().replaceAll("\\s+","")
+            .replaceAll("\\n+","").toLowerCase().split(";");
+        if (cols.length > 0) for (int i=0; i<cols.length; i++)
+            cols[i] = cols[i].trim();
+            else cols = null;*/
+
+        // 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()],
+                widths = new String[tableRows.size()];
+            int[] nWidths = new int[tableRows.size()];
+
+            _prefs.putInt("numberColWidth", ncWidth);
+            for (i=0; i<tableRows.size(); i++) {
+                TableRow tr = (TableRow)tableRows.elementAt(i);
+                names[i] = tr.name;
+                nWidths[i] = tr.length;
+                widths[i] = ""+tr.length;
+                //Util.pr(names[i]+"   "+widths[i]);
+            }
+
+            // Finally, we store the new preferences.
+            _prefs.putStringArray("columnNames", names);
+            _prefs.putStringArray("columnWidths", widths);
+        }
+
+    }
+
+    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);
+        */
diff --git a/src/java/net/sf/jabref/TablePrefsTab.java b/src/java/net/sf/jabref/TablePrefsTab.java
new file mode 100644
index 0000000..62a1780
--- /dev/null
+++ b/src/java/net/sf/jabref/TablePrefsTab.java
@@ -0,0 +1,312 @@
+package net.sf.jabref;
+
+import java.util.Vector;
+import javax.swing.*;
+import javax.swing.event.ChangeListener;
+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;
+
+class TablePrefsTab extends JPanel implements PrefsTab {
+
+    JabRefPreferences _prefs;
+    private JCheckBox autoResizeMode, priDesc, secDesc, terDesc,
+    pdfColumn, urlColumn, citeseerColumn;
+    private JRadioButton namesAsIs, namesFf, namesFl, namesNatbib, abbrNames, noAbbrNames, lastNamesOnly;
+    private JComboBox
+    priSort = new JComboBox(GUIGlobals.ALL_FIELDS),
+    secSort = new JComboBox(GUIGlobals.ALL_FIELDS),
+    terSort = new JComboBox(GUIGlobals.ALL_FIELDS);
+    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"));
+
+        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(GUIGlobals.ALL_FIELDS[priSort.getSelectedIndex() - 1]);
+              priSort.setSelectedIndex(0);
+            }
+          }
+        });
+        secSort.addActionListener(new ActionListener() {
+          public void actionPerformed(ActionEvent e) {
+            if (secSort.getSelectedIndex() > 0) {
+              secField.setText(GUIGlobals.ALL_FIELDS[secSort.getSelectedIndex() - 1]);
+              secSort.setSelectedIndex(0);
+            }
+          }
+        });
+        terSort.addActionListener(new ActionListener() {
+          public void actionPerformed(ActionEvent e) {
+            if (terSort.getSelectedIndex() > 0) {
+              terField.setText(GUIGlobals.ALL_FIELDS[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.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"));
+
+        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());
+    // 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);
+	*/
diff --git a/src/java/net/sf/jabref/TitleLabel.java b/src/java/net/sf/jabref/TitleLabel.java
new file mode 100644
index 0000000..f5c2fd6
--- /dev/null
+++ b/src/java/net/sf/jabref/TitleLabel.java
@@ -0,0 +1,17 @@
+package net.sf.jabref;
+
+import javax.swing.*;
+import java.awt.*;
+
+public class TitleLabel extends JLabel {
+
+    public TitleLabel(String txt, int orientation) {
+	super(txt, orientation);
+	setFont((java.awt.Font)UIManager.get("TitledBorder.font"));
+	setForeground((java.awt.Color)UIManager.get("TitledBorder.titleColor"));
+    }
+
+    public TitleLabel(String txt) {
+	this(txt, SwingConstants.CENTER);
+    }
+}
diff --git a/src/java/net/sf/jabref/TransferableBibtexEntry.java b/src/java/net/sf/jabref/TransferableBibtexEntry.java
new file mode 100644
index 0000000..5cb1870
--- /dev/null
+++ b/src/java/net/sf/jabref/TransferableBibtexEntry.java
@@ -0,0 +1,79 @@
+/*
+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.
+
+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 net.sf.jabref.export.LatexFieldFormatter;
+import java.awt.datatransfer.*;
+import java.io.*;
+import javax.swing.JOptionPane;
+
+/*
+ * A transferable object containing an array of BibtexEntry objects. Used
+ * for copy-paste operations.
+ */
+public class TransferableBibtexEntry implements Transferable {
+
+    private BibtexEntry[] data;
+    public static DataFlavor entryFlavor = new DataFlavor(BibtexEntry.class, "JabRef entry");
+
+    public TransferableBibtexEntry(BibtexEntry[] data) {
+	this.data = data;
+    }
+
+    public DataFlavor[] getTransferDataFlavors() {
+	return new DataFlavor[] {TransferableBibtexEntry.entryFlavor,
+	                         DataFlavor.stringFlavor};
+    }
+
+    public boolean isDataFlavorSupported(DataFlavor flavor) {
+	return (flavor.equals(entryFlavor) ||
+		flavor.equals(DataFlavor.stringFlavor));
+    }
+
+    public Object getTransferData(DataFlavor flavor)
+	throws UnsupportedFlavorException {
+	if (flavor.equals(entryFlavor))
+	    return data;
+	else if (flavor.equals(DataFlavor.stringFlavor)) {
+	    try {
+		StringWriter sw = new StringWriter();
+		LatexFieldFormatter ff = new LatexFieldFormatter();
+		for (int i=0; i<data.length; i++)
+		    data[i].write(sw, ff, false);
+		return sw.toString();
+	    } catch (IOException ex) {
+		JOptionPane.showMessageDialog
+		    (null, "Could not paste entry as text:\n"+ex.getMessage(),
+		     "Clipboard", JOptionPane.ERROR_MESSAGE);
+		return "";
+	    }
+	} else
+	    throw new UnsupportedFlavorException(flavor);
+    }
+}
+
diff --git a/src/java/net/sf/jabref/UnknownEntryType.java b/src/java/net/sf/jabref/UnknownEntryType.java
new file mode 100644
index 0000000..e8a77e4
--- /dev/null
+++ b/src/java/net/sf/jabref/UnknownEntryType.java
@@ -0,0 +1,49 @@
+package net.sf.jabref;
+
+import java.io.*;
+
+/**
+ * This class is used to represent an unknown entry type, e.g. encountered
+ * during bibtex parsing. The only known information is the type name.
+ * This is useful if the bibtex file contains type definitions that are used
+ * in the file - because the entries will be parsed before the type definitions
+ * are found. In the meantime, the entries will be assigned an 
+ * UnknownEntryType giving the name.
+ */
+public class UnknownEntryType extends BibtexEntryType {
+
+    private String name;
+    private String[] fields = new String[0];
+
+    public UnknownEntryType(String name_) {
+	name = name_;
+    }
+
+    public String getName() {
+	return name;
+    }
+
+    public String[] getOptionalFields() {
+	return fields;
+    }
+    public String[] getRequiredFields() {
+	return fields;
+    }
+
+
+    public String describeRequiredFields() {
+	return "unknown";
+    }
+
+    public String describeOptionalFields() {
+	return "unknown";
+    }
+
+    public boolean hasAllRequiredFields(BibtexEntry entry) {
+	return true;
+    }
+
+    public void save(Writer out) {
+    }
+
+}
diff --git a/src/java/net/sf/jabref/UrlDragDrop.java b/src/java/net/sf/jabref/UrlDragDrop.java
new file mode 100644
index 0000000..4cb05a3
--- /dev/null
+++ b/src/java/net/sf/jabref/UrlDragDrop.java
@@ -0,0 +1,219 @@
+/*
+ Copyright (C) 2004 E. Putrycz
+
+ 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.awt.Component;
+import java.awt.datatransfer.DataFlavor;
+import java.awt.datatransfer.Transferable;
+import java.awt.datatransfer.UnsupportedFlavorException;
+import java.awt.dnd.DnDConstants;
+import java.awt.dnd.DropTargetDragEvent;
+import java.awt.dnd.DropTargetDropEvent;
+import java.awt.dnd.DropTargetEvent;
+import java.awt.dnd.DropTargetListener;
+import java.io.File;
+import java.io.IOException;
+import java.net.URL;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.swing.JOptionPane;
+
+import net.sf.jabref.net.URLDownload;
+
+/**
+ * @author Erik Putrycz erik.putrycz-at-nrc-cnrc.gc.ca
+ */
+
+public class UrlDragDrop implements DropTargetListener {
+
+    private static Logger logger = Logger
+            .getLogger(UrlDragDrop.class.getName());
+
+    private FieldEditor feditor;
+
+    private EntryEditor editor;
+
+    private JabRefFrame frame;
+
+    public UrlDragDrop(EntryEditor _editor, JabRefFrame _frame,
+            FieldEditor _feditor) {
+        editor = _editor;
+        feditor = _feditor;
+        frame = _frame;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see java.awt.dnd.DropTargetListener#dragEnter(java.awt.dnd.DropTargetDragEvent)
+     */
+    public void dragEnter(DropTargetDragEvent dtde) {
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see java.awt.dnd.DropTargetListener#dragOver(java.awt.dnd.DropTargetDragEvent)
+     */
+    public void dragOver(DropTargetDragEvent dtde) {
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see java.awt.dnd.DropTargetListener#dropActionChanged(java.awt.dnd.DropTargetDragEvent)
+     */
+    public void dropActionChanged(DropTargetDragEvent dtde) {
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see java.awt.dnd.DropTargetListener#dragExit(java.awt.dnd.DropTargetEvent)
+     */
+    public void dragExit(DropTargetEvent dte) {
+    }
+
+    private static class JOptionChoice {
+
+        private String label;
+
+        private int id;
+
+        public JOptionChoice(String _label, int _id) {
+            label = _label;
+            id = _id;
+        }
+
+        public String toString() {
+            return label;
+        }
+
+        public int getId() {
+            return id;
+        }
+
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see java.awt.dnd.DropTargetListener#drop(java.awt.dnd.DropTargetDropEvent)
+     */
+    public void drop(DropTargetDropEvent dtde) {
+        Transferable tsf = dtde.getTransferable();
+        dtde.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
+        //try with an URL
+        DataFlavor dtURL = null;
+        try{
+            dtURL = new DataFlavor("application/x-java-url; class=java.net.URL");
+        }catch (ClassNotFoundException e){
+            logger.log(Level.WARNING,
+                    "Class not found for DnD... should not happen", e);
+        }
+        try{
+            URL url = (URL) tsf.getTransferData(dtURL);
+            JOptionChoice res = (JOptionChoice) JOptionPane
+                    .showInputDialog((Component) editor, "", Globals
+                            .lang("Select action"),
+                            JOptionPane.QUESTION_MESSAGE, null,
+                            new JOptionChoice[] {
+                                    new JOptionChoice(Globals
+                                            .lang("Insert URL"), 0),
+                                    new JOptionChoice(Globals
+                                            .lang("Download file"), 1) },
+                            new JOptionChoice(Globals.lang("Insert URL"), 0));
+            switch (res.getId()) {
+            //insert URL
+            case 0:
+                feditor.setText(url.toString());
+                editor.updateField(feditor);
+                break;
+            //download file
+            case 1:
+                try{
+                    //auto file name:
+                    File file = new File(new File(Globals.prefs
+                            .get("pdfDirectory")), editor.getEntry()
+                            .getField(Globals.KEY_FIELD)
+                            + ".pdf");
+                    URLDownload udl = new URLDownload((Component) editor, url,
+                            file);
+                    frame.output(Globals.lang("Downloading..."));
+                    udl.download();
+                    frame.output(Globals.lang("Download completed"));
+                    feditor.setText(file.toURL().toString());
+                    editor.updateField(feditor);
+
+                }catch (IOException ioex){
+                    logger.log(Level.SEVERE, "Error while downloading file",
+                            ioex);
+                    JOptionPane.showMessageDialog((Component) editor, Globals
+                            .lang("File download"), Globals
+                            .lang("Error while downloading file:"
+                                    + ioex.getMessage()),
+                            JOptionPane.ERROR_MESSAGE);
+                }
+                break;
+            }
+            return;
+        }catch (UnsupportedFlavorException nfe){
+            // not an URL then...
+        }catch (IOException ioex){
+            logger.log(Level.WARNING, "!should not happen!", ioex);
+        }
+
+        try{
+            //try with a File List
+            List filelist = (List) tsf
+                    .getTransferData(DataFlavor.javaFileListFlavor);
+            if (filelist.size() > 1){
+                JOptionPane
+                        .showMessageDialog((Component) editor, Globals
+                                .lang("Only one item is supported"), Globals
+                                .lang("Drag and Drop Error"),
+                                JOptionPane.ERROR_MESSAGE);
+                return;
+            }
+            File fl = (File) filelist.get(0);
+            feditor.setText(fl.toURI().toURL().toString());
+            editor.updateField(feditor);
+
+        }catch (UnsupportedFlavorException nfe){
+            JOptionPane.showMessageDialog((Component) editor, Globals
+                    .lang("Operation not supported"), Globals
+                    .lang("Drag and Drop Error"), JOptionPane.ERROR_MESSAGE);
+            logger.log(Level.WARNING, "Transfer exception", nfe);
+        }catch (IOException ioex){
+            logger.log(Level.WARNING, "Transfer exception", ioex);
+        }
+
+    }
+
+}
\ No newline at end of file
diff --git a/src/java/net/sf/jabref/Util.java b/src/java/net/sf/jabref/Util.java
new file mode 100644
index 0000000..11b9e5b
--- /dev/null
+++ b/src/java/net/sf/jabref/Util.java
@@ -0,0 +1,1365 @@
+/*
+ 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;
+
+import java.awt.*;
+import java.awt.event.ActionListener;
+import java.awt.event.ActionEvent;
+import java.io.*;
+import java.util.*;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.text.SimpleDateFormat;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetEncoder;
+
+import javax.swing.*;
+
+import com.jgoodies.forms.layout.FormLayout;
+import com.jgoodies.forms.builder.DefaultFormBuilder;
+
+import net.sf.jabref.export.LatexFieldFormatter;
+import net.sf.jabref.groups.*;
+import net.sf.jabref.imports.*;
+import net.sf.jabref.undo.NamedCompound;
+import net.sf.jabref.undo.UndoableFieldChange;
+
+/**
+ * Describe class <code>Util</code> here.
+ *
+ * @author <a href="mailto:"> </a>
+ * @version 1.0
+ */
+public class Util {
+
+    // 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;
+
+    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 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(String link, String fieldName,
+                                          JabRefPreferences prefs) throws IOException {
+
+        if (fieldName.equals("ps") || fieldName.equals("pdf")) {
+            //System.out.println(expandFilename(link, prefs.get(fieldName+"Directory")));
+            File file = expandFilename(link, prefs.get(fieldName + "Directory"));
+
+            // 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);
+
+                //System.err.println("Starting HTML browser: "
+                //                   + prefs.get("htmlviewer") + " " + link);
+                if (Globals.ON_MAC) {
+                    String[] cmd = {"/usr/bin/open", "-a",
+                            prefs.get("htmlviewer"), link};
+                    Process child = Runtime.getRuntime().exec(cmd);
+                } else if (Globals.ON_WIN) {
+                    openFileOnWindows(link, false);
+                    /*cmdArray[0] = prefs.get("htmlviewer");
+                    cmdArray[1] = link;
+                    Process child = Runtime.getRuntime().exec(
+                    cmdArray[0] + " " + cmdArray[1]);
+                    */
+                } else {
+                    cmdArray[0] = prefs.get("htmlviewer");
+                    cmdArray[1] = link;
+                    Process child = Runtime.getRuntime().exec(cmdArray);
+                }
+
+            } catch (IOException e) {
+                System.err.println("An error occured on the command: "
+                        + prefs.get("htmlviewer") + " " + link);
+            }
+        } else if (fieldName.equals("ps")) {
+            try {
+                if (Globals.ON_MAC) {
+                    String[] cmd = {"/usr/bin/open", "-a",
+                            prefs.get("psviewer"), link};
+                    Process child = Runtime.getRuntime().exec(cmd);
+                } else if (Globals.ON_WIN) {
+                    openFileOnWindows(link, true);
+                    /*
+                    cmdArray[0] = prefs.get("psviewer");
+                    cmdArray[1] = link;
+                    Process child = Runtime.getRuntime().exec(
+                            cmdArray[0] + " " + cmdArray[1]);
+                    */
+                } else {
+                    cmdArray[0] = prefs.get("psviewer");
+                    cmdArray[1] = link;
+                    Process child = Runtime.getRuntime().exec(cmdArray);
+                }
+            } catch (IOException e) {
+                System.err.println("An error occured on the command: "
+                        + prefs.get("psviewer") + " " + link);
+            }
+        } else if (fieldName.equals("pdf")) {
+            try {
+                if (Globals.ON_MAC) {
+                    String[] cmd = {"/usr/bin/open", "-a",
+                            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] = 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: "
+                        + 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);
+    }
+
+    /**
+     * 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 = new File(name);
+        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) name = name.replaceAll("/", "\\");
+            else name = name.replaceAll("\\\\", "/");
+            //System.out.println("expandFilename: "+name);
+            file = new File(name);
+            return (file.exists() ? file : null);
+        } else 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 an array
+     * 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();
+        // Iterate through all entries
+        for (int i = 0; i < bibs.size(); i++) {
+            // Get current entry
+            BibtexEntry curEntry = (BibtexEntry) bibs.get(i);
+
+            // Set owner field if this option is enabled:
+            if (Globals.prefs.getBoolean("useOwner")) {
+                // No or empty owner field?
+                if (curEntry.getField(Globals.OWNER) == null
+                        || ((String) curEntry.getField(Globals.OWNER)).length() == 0) {
+                    // Set owner field to default value
+                    curEntry.setField(Globals.OWNER, defaultOwner);
+                }
+            }
+
+            if (Globals.prefs.getBoolean("useTimeStamp"))
+                curEntry.setField(Globals.prefs.get("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; i < GUIGlobals.ALL_FIELDS.length; ++i) {
+                    if (field.equals(GUIGlobals.ALL_FIELDS[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 = (String) GUIGlobals.FIELD_EXTRAS.get(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() {
+        String format = Globals.prefs.get("timeStampFormat");
+        Date today = new Date();
+        SimpleDateFormat formatter = new SimpleDateFormat(format);
+        return formatter.format(today);
+    }
+
+
+    public static void markEntry(BibtexEntry be, NamedCompound ce) {
+        Object o = be.getField(Globals.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, Globals.MARKED,
+                                          be.getField(Globals.MARKED), newValue));
+        be.setField(Globals.MARKED, newValue);
+    }
+
+    public static void unmarkEntry(BibtexEntry be, BibtexDatabase database, NamedCompound ce) {
+        Object o = be.getField(Globals.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, Globals.MARKED,
+                be.getField(Globals.MARKED), newVal));
+            be.setField(Globals.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(Globals.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, Globals.MARKED, be.getField(Globals.MARKED), newVal));
+        be.setField(Globals.MARKED, newVal);
+
+    }
+
+    public static boolean isMarked(BibtexEntry be) {
+        Object fieldVal = be.getField(Globals.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;
+    }
+
+}
diff --git a/src/java/net/sf/jabref/Worker.java b/src/java/net/sf/jabref/Worker.java
new file mode 100644
index 0000000..f4e8eee
--- /dev/null
+++ b/src/java/net/sf/jabref/Worker.java
@@ -0,0 +1,13 @@
+
+
+package net.sf.jabref;
+
+
+/**
+ * ...
+ */
+public interface Worker {
+
+    public void run();
+
+}
diff --git a/src/java/net/sf/jabref/about/About2.java b/src/java/net/sf/jabref/about/About2.java
new file mode 100644
index 0000000..de7891c
--- /dev/null
+++ b/src/java/net/sf/jabref/about/About2.java
@@ -0,0 +1,102 @@
+/*
+ animated about dialog
+
+Copyright (C) 2005 Raik Nagel <kiar at users.sourceforge.net>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice,
+  this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright notice,
+  this list of conditions and the following disclaimer in the documentation
+  and/or other materials provided with the distribution.
+* Neither the name of the author nor the names of its contributors may be
+  used to endorse or promote products derived from this software without
+  specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+// created by : r.nagel 05.05.2005
+//
+// function : new about dialog
+//
+// todo     :
+//
+// modified :
+
+
+package net.sf.jabref.about ;
+
+import java.awt.* ;
+import java.awt.event.* ;
+import javax.swing.* ;
+
+import net.sf.jabref.* ;
+
+public class About2 extends JDialog implements ActionListener
+{
+  private static final long serialVersionUID = 1L ;
+
+  // AboutDialog constructor
+  public About2( JFrame parent )
+  {
+    super( parent, Globals.lang("About JabRef"), true ) ;
+
+//    setDefaultCloseOperation( EXIT_ON_CLOSE ) ;
+
+    JPanel contentPanel = new JPanel( new BorderLayout() ) ;
+    contentPanel.setBackground( Color.white);
+//    content.setBorder( new EmptyBorder( 12, 12, 12, 12 ) ) ;
+    setContentPane( contentPanel ) ;
+
+    contentPanel.add( BorderLayout.CENTER, new ExtendedInfoPanel(this) ) ;
+
+    this.setBackground( Color.white);
+
+    pack() ;
+    setResizable( false ) ;
+    setLocationRelativeTo( parent ) ;
+    setVisible( true ) ;
+  }
+
+  protected void processWindowEvent( WindowEvent e )
+  {
+    super.processWindowEvent( e ) ;
+    if ( e.getID() == WindowEvent.WINDOW_CLOSING )
+    {
+      System.exit( 0 ) ;
+    }
+  }
+
+  public void actionPerformed( ActionEvent e )
+  {
+    String cmd = e.getActionCommand() ;
+    if ( cmd.equals( "close" ) )
+    {
+
+      setVisible( false ) ;
+      dispose() ;
+//      System.exit( 0 ) ;
+    }
+    else if ( cmd.equals( "license" ) )
+    {
+//      showLicense() ;
+    }
+  }
+
+// ----------------------------------------------------------------------------
+
+}
diff --git a/src/java/net/sf/jabref/about/AboutPanel.java b/src/java/net/sf/jabref/about/AboutPanel.java
new file mode 100644
index 0000000..f4f3c4b
--- /dev/null
+++ b/src/java/net/sf/jabref/about/AboutPanel.java
@@ -0,0 +1,487 @@
+/*
+ animated about dialog
+
+Copyright (C) 2005 Raik Nagel <kiar at users.sourceforge.net>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice,
+  this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright notice,
+  this list of conditions and the following disclaimer in the documentation
+  and/or other materials provided with the distribution.
+* Neither the name of the author nor the names of its contributors may be
+  used to endorse or promote products derived from this software without
+  specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+// created by : r.nagel 05.05.2005
+//
+// todo     :
+//
+// modified :
+
+
+package net.sf.jabref.about ;
+
+import java.io.* ;
+import java.util.* ;
+
+import java.awt.* ;
+import java.awt.image.* ;
+import javax.swing.* ;
+import javax.swing.border.* ;
+
+import net.sf.jabref.* ;
+
+// AboutPanel class
+public class AboutPanel extends JComponent
+{
+  private Vector textBlocks ;
+  private String versionStr ;
+  private String buildStr ;
+  private AnimationThread thread;
+  private ImageIcon image;
+
+
+  // animated text positions
+  public int TOP = 300 ; // offset from top - hide
+  public int BOTTOM = 0 ; // show
+
+  public int HEIGHT = 500 ;
+  public int WIDTH = 500 ;
+
+  private int borders[] ;  // Border-Coordinates of paintarea (xLeft, xRight, yTop, yBottom)
+  private int paintWidth ;
+
+  private Font font1 ;
+  private Font font2 ;
+  private Font font3 ;
+
+  private AnimationListener aniListener ;
+  private ImageProducer iProducer ;
+  private HighlightFilter filter ;
+
+  AboutPanel()
+  {
+    Font font = loadFont("ASTROLYT.TTF") ;
+    font1 = font.deriveFont(Font.BOLD, (float) 14.0) ;
+    font2 = font.deriveFont(Font.BOLD, (float) 20.0) ;
+
+    font = loadFont("AUGIE.TTF") ;
+    font3 = font.deriveFont(Font.BOLD, (float) 14.0) ;
+
+    versionStr = "Version " + Globals.VERSION ;
+    buildStr = " build " + Globals.BUILD ;
+
+    image = new ImageIcon(getClass().getResource("/images/autumn.png"));
+
+    filter = new HighlightFilter(false, 5) ;
+    filter.setMiddle(image.getIconWidth(), image.getIconHeight());
+    iProducer = new FilteredImageSource( image.getImage().getSource(), filter) ;
+
+    HEIGHT = image.getIconHeight() ;
+    WIDTH = image.getIconWidth() ;
+
+    FontMetrics fm = getFontMetrics( font2 ) ;
+    TOP = 2*fm.getHeight() ;
+    fm = getFontMetrics( font1 ) ;
+    BOTTOM = 2*fm.getHeight() ;
+
+    borders = new int[4] ;
+    borders[0] = 0 ;
+    borders[1] = WIDTH ;
+    borders[2] = TOP ;
+    borders[3] = HEIGHT - TOP - BOTTOM ;
+
+
+    paintWidth = borders[1] - borders[0] ;
+
+    setForeground( Color.black) ;
+    setBackground( Color.white) ;
+
+    setBorder ( BorderFactory.createBevelBorder( BevelBorder.RAISED)) ;
+
+    textBlocks = new Vector( 50 ) ;
+
+    loadAboutText() ;
+
+    this.setDoubleBuffered(true);
+
+    thread = new AnimationThread();
+  }
+// ----------------------------------------------------------------------------
+
+  public void addAnimationListener(AnimationListener listener)
+  {
+    aniListener = listener ;
+  }
+
+// ----------------------------------------------------------------------------
+
+  // returns
+  private int getMiddleX(String text, Font font)
+  {
+    FontMetrics fm = getFontMetrics(font);
+    return ( paintWidth/2 - ((fm.stringWidth(text) + 10) / 2)) ;
+  }
+
+// ----------------------------------------------------------------------------
+
+  private Font loadFont(String fontName)
+  {
+    Font back = UIManager.getFont("Label.font") ;
+    try
+    {
+      InputStream myStream = getClass().getResourceAsStream(GUIGlobals.fontPath + fontName) ;
+      back = Font.createFont(Font.TRUETYPE_FONT, myStream) ;
+    }
+    catch (Exception e) { System.out.println(e) ; }
+
+    return back ;
+  }
+
+// ----------------------------------------------------------------------------
+
+  private final void loadAboutText()
+  {
+    TextBlock block = null ;
+    AboutTextLine aLine = null ;
+
+    int index = -3 ;
+    FontMetrics fm = getFontMetrics(font3);
+    try
+    {
+      InputStream stream = getClass().getResourceAsStream(GUIGlobals.getLocaleHelpPath() + "credits.txt" ) ;
+      if (stream == null)
+      {
+        stream = getClass().getResourceAsStream( GUIGlobals.helpPre +
+                                                 "credits.txt" ) ;
+      }
+      InputStreamReader reader = new InputStreamReader( stream ) ;
+//          getClass().getResourceAsStream(GUIGlobals.getLocaleHelpPath() + "credits.txt" ) ) ;
+//          getClass().getResourceAsStream( "/help/credits.txt" ) ) ;
+      BufferedReader input = new BufferedReader(reader, 1000) ;
+
+//      System.out.println("encoding :" +reader.getEncoding() ) ;
+
+      while ( input.ready() )
+      {
+        String line = input.readLine() ;
+
+        if (line != null)
+        {
+          line = line.trim() ;
+
+          if (line.length() > 0)
+          {
+            if (line.charAt(0) == '#')  // new Block....
+            {
+              if (block != null)  //insert previous block
+              {
+                textBlocks.add(block) ;
+                index+=2 ;
+              }
+
+              aLine = new AboutTextLine( line.substring(1).trim()) ;
+              aLine.setTag(2);
+              aLine.setPos(getMiddleX(aLine.getText(), font2), borders[0] -fm.getHeight()*(index+3)*1.5);
+              aLine.setDirection(0.0, 1.0);
+              aLine.setFont(font2);
+
+              block = new TextBlock() ;
+              block.setHeading(aLine);
+              block.setVisible(true);
+
+            }
+            else  // Blocklines
+            {
+              aLine = new AboutTextLine( line.trim() ) ;
+              aLine.setPos( getMiddleX( line, font3 ),
+                            borders[3] + ( index * fm.getHeight() * 1.5 ) ) ;
+              aLine.setTag( 10 ) ;
+              aLine.setDirection( 0.0, -1.0 ) ;
+              aLine.setFont( font3 ) ;
+
+//              System.out.println( "line " +aLine.getText() +"<" +(borders[3] + ( index * fm.getHeight() * 1.5 )) +">" ) ;
+
+              block.add( aLine ) ;
+              index++ ;
+            }
+          }
+        }
+      }
+      input.close() ;
+    }
+
+    catch ( Exception e )
+    {
+      block = new TextBlock() ;
+      block.setHeading( new AboutTextLine("failure") );
+      String line = "no infos available" ;
+      aLine = new AboutTextLine( line ) ;
+      block.add( aLine ) ;
+    }
+
+    textBlocks.add(block);  // insert last block
+  }
+
+// ----------------------------------------------------------------------------
+
+  public void paintComponent( Graphics g )
+  {
+    if (thread.mode == 0)
+    {
+      thread.start();
+//      thread.setEnabled(true);
+    }
+    else
+    if (thread.mode == 1)
+    {
+      image.paintIcon(this, g, 0, 0);
+
+      FontMetrics fm = g.getFontMetrics( font1 ) ;
+
+      int x1 = ( getWidth() - fm.stringWidth( versionStr ) ) / 2 ;
+      int y1 = getHeight() - fm.getHeight() - 4 ;
+      int y2 = getHeight() - 5 ;
+/*
+      int x1 = ( getWidth() - fm.stringWidth( versionStr ) ) / 2 ;
+      int y1 = 4 ;
+      int y2 = fm.getHeight() +4 ;
+*/
+      g.setFont( font1 ) ;
+
+      g.setColor( Color.black ) ;
+      g.drawString( versionStr, x1, y1 ) ;
+      g.drawString( buildStr, x1, y2 ) ;
+
+      g.setFont( font2) ;
+      fm = g.getFontMetrics( font2 ) ;
+      g.drawString( "JabRef", (getWidth() - fm.stringWidth("JabRef")) /2, fm.getHeight()+10) ;
+
+
+      for ( Enumeration myE = textBlocks.elements() ; myE.hasMoreElements() ; )
+      {
+        TextBlock block = (TextBlock) myE.nextElement() ;
+
+        if (block.isVisible()) // only if Block is marked as visible
+        {
+          // print Heading
+          AboutTextLine head = block.getHeading() ;
+          drawLine(head, g) ;
+
+          for ( Enumeration myEnum = block.getEnumeration() ; myEnum.hasMoreElements() ; )
+          {
+            AboutTextLine line = ( AboutTextLine ) myEnum.nextElement() ;
+            drawLine(line, g) ;
+          }
+        }
+      }
+    }
+    else
+    {
+      image.paintIcon(this, g, 0, 0);
+      if (filter.isReady())
+      {
+        skipAnimation() ;
+      }
+    }
+  }
+// ----------------------------------------------------------------------------
+
+  private void drawLine(AboutTextLine line, Graphics g)
+  {
+    int x = line.getPosX() ;
+    int y = line.getPosY() ;
+    if ( ( x > borders[0] - 10 ) && ( x < borders[1] + 10 ) &&
+         ( y > borders[2] - 10 ) && ( y < borders[3] + 10 ) )
+    {
+      if ( line.getVisible() )
+      {
+        g.setFont( line.getFont() ) ;
+        g.setColor( line.getColor() ) ;
+        g.drawString( line.getText(), line.getPosX(), line.getPosY() ) ;
+      }
+    }
+  }
+// ----------------------------------------------------------------------------
+// ----------------------------------------------------------------------------
+
+  public Dimension getPreferredSize()
+  {
+    return new Dimension( WIDTH, HEIGHT ) ;
+  }
+
+  public void removeNotify()
+  {
+    super.removeNotify();
+    thread.kill();
+  }
+
+  public void skipAnimation()
+  {
+    thread.kill() ;
+    if (aniListener != null) aniListener.animationReady();
+  }
+
+// ---------------------------------------------------------------------------
+// ---------------------------------------------------------------------------
+
+  class AnimationThread extends Thread
+  {
+    private boolean running = true ;
+    private double help01 = 1.0 ;
+    private int mode = 0 ;
+    public int sleepTime = 50 ;
+    private int zone2Counter = 0 ;
+    private boolean runMode = true ;
+
+    AnimationThread()
+    {
+      super( "About box animation thread" ) ;
+      setPriority( Thread.MIN_PRIORITY ) ;
+    }
+
+    public void kill()
+    {
+      running = false ;
+    }
+
+    public void setEnabled(boolean onOff) { runMode = onOff ; }
+
+    public synchronized void setMode(int newMode) { mode = newMode ; }
+
+    public void run()
+    {
+      Object mutex = new Object() ;
+
+      mode = 1 ;
+      runMode = true ;
+      while ( running )
+      {
+
+        synchronized(mutex)
+        {
+          try
+          {
+            do
+            {
+              mutex.wait( sleepTime ) ;
+            } while (!runMode) ;
+          }
+          catch ( Exception e )
+          {
+          }
+        }
+        if (mode == 1)  // Textanimation
+        {
+          int counter = 0 ;
+
+          for ( Enumeration myE = textBlocks.elements() ; myE.hasMoreElements() ; )
+          {
+            TextBlock block = ( TextBlock ) myE.nextElement() ;
+            AboutTextLine head = block.getHeading() ;
+            counter = performStep(head) ;
+
+            for ( Enumeration myEnum = block.getEnumeration() ; myEnum.hasMoreElements() ; )
+            {
+              AboutTextLine line = ( AboutTextLine ) myEnum.nextElement() ;
+              counter += performStep( line ) ;
+            }
+          }
+          if (counter < 1)
+          {
+            mode = 2 ;
+          }
+          repaint(borders[0]-10, borders[2]-10, borders[1]+10, borders[3]+10) ;
+        }
+        else if (mode == 2)  // Picture animation
+        {
+          if (sleepTime < 2)
+            sleepTime = 5 ;
+          else
+            sleepTime -= sleepTime / 3 ;
+
+          image.setImage( createImage( iProducer) );
+          filter.nextStep();
+          repaint(0, 0, WIDTH, HEIGHT) ;
+        }
+      }
+    }
+
+    private int performStep(AboutTextLine line)
+    {
+      int back = 0 ;
+
+      line.performTimeStep( 1.0 ) ;
+
+      if ( line.getTag() == 2 )  // Heading
+      {
+        int zone = (int) (HEIGHT / 3.5) ;
+        if ( line.getPosY() > zone )
+        {
+          line.setSpeed( 0.0 ) ;
+          line.setTag( 4 ) ;
+          zone2Counter = 0 ;
+        } else
+        if ( line.getPosY() > ( zone - 10) )
+        {
+          zone2Counter=1 ;
+        }
+        back++ ;
+      }
+      else if ( line.getTag() == 4) // Heading Blender
+      {
+        if (zone2Counter < 1)
+        {
+          Color col = line.getColor() ;
+          int rgb = col.getRGB() + 1023 ;
+          line.setColor( new Color( rgb ) ) ;
+        }
+        else
+        {
+          line.setVisible(false);
+          line.setTag(5);
+        }
+      }
+      else if ( line.getTag() == 10 )  // scrolling text
+      {
+        if ( line.getPosY() < ( HEIGHT / 3 ) )
+        {
+          line.setDirection( help01, 0.0 ) ;
+          line.setAccel( 0.5 ) ;
+          line.setTag( 11 ) ;
+          help01 = help01 * -1.0 ;
+        }
+        back = 1 ;
+      }
+      else if (line.getTag() == 11) // text line out
+      {
+         if ((line.getPosX() < -100) || (line.getPosX() > WIDTH+100))
+         {
+           line.setTag(12);
+           line.setVisible(false);
+         }
+         back = 1 ;
+      }
+
+      return back ;
+    }
+  }
+
+}
+
diff --git a/src/java/net/sf/jabref/about/AboutTextLine.java b/src/java/net/sf/jabref/about/AboutTextLine.java
new file mode 100644
index 0000000..7119f76
--- /dev/null
+++ b/src/java/net/sf/jabref/about/AboutTextLine.java
@@ -0,0 +1,226 @@
+/*
+ animated about dialog
+
+Copyright (C) 2005 Raik Nagel <kiar at users.sourceforge.net>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice,
+  this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright notice,
+  this list of conditions and the following disclaimer in the documentation
+  and/or other materials provided with the distribution.
+* Neither the name of the author nor the names of its contributors may be
+  used to endorse or promote products derived from this software without
+  specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+// created by : r.nagel 05.05.2005
+//
+// function : a animated line for about dialog
+//
+// todo     :
+//
+// modified :
+
+package net.sf.jabref.about ;
+
+import java.util.*;
+import java.awt.*;
+import javax.swing.UIManager;
+
+// a single About Line
+public class AboutTextLine
+{
+  private String text ;
+  private double direction[] ;
+  private double pos[] ;
+  private double speed ;
+  private double accel ;
+  private int tag ;  // additional user information
+  private Font font ;
+  private Color color ;
+
+  private boolean visible ;
+
+  public AboutTextLine(String txt)
+  {
+    Random rand = new Random(System.currentTimeMillis()* this.hashCode()) ;
+
+    text = txt ;
+
+    pos = new double[2] ;
+    pos[0] = rand.nextDouble() *100.0 ;
+    pos[1] = rand.nextDouble() *100.0 ;
+
+    direction = new double [2] ;
+    direction[0] = rand.nextDouble() ;
+    direction[1] = rand.nextDouble() ;
+
+    accel = 0.0 ;
+    speed = 1.0 ;
+
+    tag = 0 ;
+
+    color = Color.black ;
+
+    visible = true ;
+
+    font = UIManager.getFont("Label.font") ;
+  }
+
+// ------------------------------------------------------------------------
+
+  public void performTimeStep(double time)
+  {
+    accel = accel * time ;
+    speed += accel ;
+
+    double move = speed * time ;  //
+
+    pos[0] += (move * direction[0]) ;
+    pos[1] += (move * direction[1]) ;
+  }
+
+// ------------------------------------------------------------------------
+
+  public String toString()
+  {
+    return (text + "<" +pos[0] +", " +pos[1] +">"
+                 + "<" +direction[0] +", " +direction[1] +">" ) ;
+  }
+
+// ------------------------------------------------------------------------
+
+  public int getPosX()
+  {
+    return (int) pos[0] ;
+  }
+
+  public int getPosY()
+  {
+    return (int) pos[1] ;
+  }
+
+  public double[] getPos()
+  {
+    return pos;
+  }
+
+  public void setPos(double posX, double posY)
+  {
+    this.pos[0] = posX ;
+    this.pos[1] = posY ;
+  }
+
+ // ------------------------------------------------------------------------
+
+  public String getText()
+  {
+    return text;
+  }
+
+  public void setText(String pText)
+  {
+    this.text = pText;
+  }
+
+// ------------------------------------------------------------------------
+
+  public double[] getDirection()
+  {
+    return direction;
+  }
+
+  public void setDirection(double dirX, double dirY)
+  {
+    this.direction[0] = dirX ;
+    this.direction[1] = dirY ;
+  }
+
+// ------------------------------------------------------------------------
+
+  public double getSpeed()
+  {
+    return speed;
+  }
+
+  public void setSpeed(double pSpeed)
+  {
+    this.speed = pSpeed;
+  }
+
+// ------------------------------------------------------------------------
+
+  public double getAccel()
+  {
+    return accel;
+  }
+
+  public void setAccel(double pAccel)
+  {
+    this.accel = pAccel;
+  }
+
+// ------------------------------------------------------------------------
+
+  public int getTag()
+  {
+    return tag;
+  }
+
+  public void setTag(int pTag)
+  {
+    this.tag = pTag;
+  }
+
+// ------------------------------------------------------------------------
+
+  public Font getFont()
+  {
+    return font;
+  }
+  public void setFont(Font pFont)
+  {
+    this.font = pFont;
+  }
+
+// ------------------------------------------------------------------------
+
+  public Color getColor()
+  {
+    return color;
+  }
+  public void setColor(Color pColor)
+  {
+    this.color = pColor;
+  }
+
+// ------------------------------------------------------------------------
+
+  public boolean getVisible()
+  {
+    return visible;
+  }
+  public void setVisible(boolean pVisible)
+  {
+    this.visible = pVisible;
+  }
+// ------------------------------------------------------------------------
+// ------------------------------------------------------------------------
+
+}
diff --git a/src/java/net/sf/jabref/about/AnimationListener.java b/src/java/net/sf/jabref/about/AnimationListener.java
new file mode 100644
index 0000000..4abe446
--- /dev/null
+++ b/src/java/net/sf/jabref/about/AnimationListener.java
@@ -0,0 +1,44 @@
+/*
+ animated about dialog
+
+Copyright (C) 2005 Raik Nagel <kiar at users.sourceforge.net>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice,
+  this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright notice,
+  this list of conditions and the following disclaimer in the documentation
+  and/or other materials provided with the distribution.
+* Neither the name of the author nor the names of its contributors may be
+  used to endorse or promote products derived from this software without
+  specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+// created by : r.nagel 05.05.2005
+//
+// function : listener for animation actions
+//
+// todo     :
+//
+// modified :
+
+package net.sf.jabref.about ;
+
+public interface AnimationListener
+{
+  public void animationReady() ;
+}
diff --git a/src/java/net/sf/jabref/about/ExtendedInfoPanel.java b/src/java/net/sf/jabref/about/ExtendedInfoPanel.java
new file mode 100644
index 0000000..538ca0b
--- /dev/null
+++ b/src/java/net/sf/jabref/about/ExtendedInfoPanel.java
@@ -0,0 +1,179 @@
+/*
+ animated about dialog
+
+Copyright (C) 2005 Raik Nagel <kiar at users.sourceforge.net>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice,
+  this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright notice,
+  this list of conditions and the following disclaimer in the documentation
+  and/or other materials provided with the distribution.
+* Neither the name of the author nor the names of its contributors may be
+  used to endorse or promote products derived from this software without
+  specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+// created by : r.nagel 05.05.2005
+//
+// function : content for the about dialog
+//
+// todo     :
+//
+// modified :
+//            28.07.2005
+//            - hide license button
+
+package net.sf.jabref.about ;
+
+import javax.swing.* ;
+import java.net.* ;
+import java.io.*;
+import java.awt.*;
+import javax.swing.border.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.*;
+import net.sf.jabref.Globals;
+import net.sf.jabref.*;
+
+public class ExtendedInfoPanel extends JPanel implements AnimationListener, ActionListener
+{
+  private JEditorPane textPane ;
+  private JScrollPane scroller ;
+  private CardLayout cards ;
+
+  private JButton close ;
+  private JButton license ;
+
+  private AboutPanel about ;
+  private JPanel infoPanel ;
+
+  private boolean animationIsRunning = true ;
+
+  private ActionListener mainListener ;
+
+  public ExtendedInfoPanel(ActionListener mainFrame)
+  {
+    mainListener = mainFrame ;
+
+    // animated area
+    about = new AboutPanel();
+    about.addAnimationListener(this);
+
+    // scrallable html infos
+    textPane = new JEditorPane() ;
+
+    textPane.setEditable( false ) ;
+//    URL helpURL = getClass().getResource( "/help/About.html" ) ;
+    // try to load about.html for the locale language
+    URL helpURL = getClass().getResource( GUIGlobals.getLocaleHelpPath() + GUIGlobals.aboutPage) ;
+    // about.html could not detected => try to load the default version
+    if (helpURL == null)
+    {
+      helpURL = getClass().getResource( GUIGlobals.helpPre + GUIGlobals.aboutPage) ;
+    }
+
+    if ( helpURL != null )
+    {
+      try
+      {
+        textPane.setPage( helpURL ) ;
+      }
+      catch ( IOException e )
+      {
+        System.err.println( "Attempted to read a bad URL: " + helpURL ) ;
+      }
+    }
+    else
+    {
+      System.err.println( "Couldn't find file: About.html" ) ;
+    }
+
+    scroller = new JScrollPane(textPane) ; //, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS) ;
+    scroller.setPreferredSize( about.getSize());
+
+    // overlapped animated/scrollable area
+    infoPanel = new JPanel() ;
+    cards = new CardLayout() ;
+    infoPanel.setLayout( cards);
+
+    infoPanel.add(about, "ani") ;
+    infoPanel.add(scroller, "inf") ;
+
+     // Buttons
+    JPanel buttonPanel = new JPanel() ;
+    buttonPanel.setBackground( Color.white);
+    buttonPanel.setLayout( new GridLayout(1, 2, 10, 20) );
+    buttonPanel.setBorder( BorderFactory.createBevelBorder( BevelBorder.RAISED));
+
+    buttonPanel.add( Box.createGlue() ) ;
+    close = new JButton( Globals.lang("Skip") ) ;
+    close.addActionListener( this ) ;
+    close.setActionCommand( "close" ) ;
+    close.setFocusable( false ) ;
+
+    license = new JButton( Globals.lang("License") ) ;
+    license.addActionListener( this ) ;
+    license.setActionCommand( "license" ) ;
+    license.setFocusable( false ) ;
+
+    buttonPanel.add( close ) ;
+//    buttonPanel.add( license ) ;
+    buttonPanel.add( Box.createGlue() ) ;
+
+
+    // main panel
+    this.setLayout( new BorderLayout(0, 0));
+
+    this.add(infoPanel, BorderLayout.CENTER) ;
+    this.add(buttonPanel, BorderLayout.SOUTH) ;
+
+//    about.startAnimation();
+  }
+
+  public void animationReady()
+  {
+    animationIsRunning = false ;
+    cards.show(infoPanel, "inf");
+    close.setText(Globals.lang("Close"));
+  }
+
+  public void actionPerformed( ActionEvent e )
+  {
+    String cmd = e.getActionCommand() ;
+    if ( cmd.equals( "close" ) )
+    {
+      if (animationIsRunning)
+      {
+         about.skipAnimation(); // implicit call of AnimationListener.animationReady()
+      }
+      else
+      {
+        setVisible( false ) ;
+        mainListener.actionPerformed(e);
+      }
+    }
+    else if ( cmd.equals( "license" ) )
+    {
+//      showLicense() ;
+      mainListener.actionPerformed(e);
+    }
+  }
+
+}
diff --git a/src/java/net/sf/jabref/about/HighlightFilter.java b/src/java/net/sf/jabref/about/HighlightFilter.java
new file mode 100644
index 0000000..d64efaa
--- /dev/null
+++ b/src/java/net/sf/jabref/about/HighlightFilter.java
@@ -0,0 +1,104 @@
+/*
+ * @(#)HighlightFilter.java	1.6 98/03/18
+ *
+ * Copyright (c) 1995-1997 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * Sun grants you ("Licensee") a non-exclusive, royalty free, license to use,
+ * modify and redistribute this software in source and binary code form,
+ * provided that i) this copyright notice and license appear on all copies of
+ * the software; and ii) Licensee does not utilize the software in a manner
+ * which is disparaging to Sun.
+ *
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY
+ * IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+ * NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE
+ * LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
+ * OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS
+ * LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT,
+ * INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
+ * CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF
+ * OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ *
+ * This software is not designed or intended for use in on-line control of
+ * aircraft, air traffic, aircraft navigation or aircraft communications; or in
+ * the design, construction, operation or maintenance of any nuclear
+ * facility. Licensee represents and warrants that it will not use or
+ * redistribute the Software for such purposes.
+ */
+
+package net.sf.jabref.about ;
+
+import java.awt.* ;
+import java.awt.image.* ;
+
+/**
+ * An image filter to highlight an image by brightening or darkening
+ * the pixels in the images.
+ *
+ * @author 	Jim Graham
+ * @version 	1.6, 03/18/98
+ */
+class HighlightFilter extends RGBImageFilter
+{
+  boolean brighter ;
+  int percent ;
+  private int middleX ;
+  private int middleY ;
+  private int dimX ;
+  private int dimY ;
+  private int distance = 0 ;
+  private int startSize = 10 ;
+
+  private int white = Color.white.getRGB() ;
+  private int black = Color.black.getRGB() ;
+
+  public HighlightFilter( boolean b, int p )
+  {
+    brighter = b ;
+    percent = p ;
+    canFilterIndexColorModel = true ;
+  }
+
+  public void setMiddle(int x, int y)
+  {
+    middleX = x/2 ;
+    middleY = y/2 ;
+    dimX = x ;
+    dimY = y ;
+    distance = startSize ;
+  }
+
+  public final void nextStep() { distance+= distance/1.5 +1; }
+
+  public boolean isReady()
+  {
+    boolean back = false ;
+    if ((dimX < distance) && (dimY < distance))
+      back = true ;
+
+    return back ;
+  }
+
+  public final int filterRGB( int x, int y, int rgb )
+  {
+    int back = rgb ;
+
+    int x1 = x - middleX ;
+    int y1 = y - middleY ;
+
+    int dist = (int) Math.sqrt( Math.abs(2*x1*y1) ) ;
+
+    if ( ((dist < distance) && (x != middleX) && (y != middleY)) ||
+         (((x == middleX) || (y == middleY)) && (distance > 30)) )
+    {
+       back = white ;
+    } else if ((dist == distance) && (dist > 20)) // Black border
+    {
+      back = black ;
+    }
+
+    return back ;
+  }
+}
diff --git a/src/java/net/sf/jabref/about/NewAboutAction.java b/src/java/net/sf/jabref/about/NewAboutAction.java
new file mode 100644
index 0000000..c57d4b5
--- /dev/null
+++ b/src/java/net/sf/jabref/about/NewAboutAction.java
@@ -0,0 +1,67 @@
+/*
+ animated about dialog
+
+Copyright (C) 2005 Raik Nagel <kiar at users.sourceforge.net>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice,
+  this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright notice,
+  this list of conditions and the following disclaimer in the documentation
+  and/or other materials provided with the distribution.
+* Neither the name of the author nor the names of its contributors may be
+  used to endorse or promote products derived from this software without
+  specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+// created by : r.nagel 05.05.2005
+//
+// function : about action, used in JabrefFrame
+//
+// todo     :
+//
+// modified :
+
+package net.sf.jabref.about ;
+
+import java.awt.event.* ;
+import javax.swing.* ;
+
+import net.sf.jabref.* ;
+
+public class NewAboutAction
+    extends MnemonicAwareAction
+{
+
+  private String type = null ; // The type of item to create.
+  private KeyStroke keyStroke = null ; // Used for the specific instances.
+
+  public NewAboutAction()
+  {
+    // This action leads to a dialog asking for entry type.
+    super( new ImageIcon( GUIGlobals.helpIconFile ) ) ;
+    putValue( NAME, "About JabRef" ) ;
+//    putValue( ACCELERATOR_KEY, key ) ;
+    putValue( SHORT_DESCRIPTION, Globals.lang( "About JabRef" ) ) ;
+  }
+
+  public void actionPerformed( ActionEvent e )
+  {
+    About2 dialog = new About2((JFrame) null) ;
+  }
+}
diff --git a/src/java/net/sf/jabref/about/TextBlock.java b/src/java/net/sf/jabref/about/TextBlock.java
new file mode 100644
index 0000000..d2206dd
--- /dev/null
+++ b/src/java/net/sf/jabref/about/TextBlock.java
@@ -0,0 +1,85 @@
+/*
+ animated about dialog
+
+Copyright (C) 2005 Raik Nagel <kiar at users.sourceforge.net>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice,
+  this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright notice,
+  this list of conditions and the following disclaimer in the documentation
+  and/or other materials provided with the distribution.
+* Neither the name of the author nor the names of its contributors may be
+  used to endorse or promote products derived from this software without
+  specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+// created by : r.nagel 05.05.2005
+//
+// function : set of animated lines
+//
+// todo     :
+//
+// modified :
+
+package net.sf.jabref.about ;
+
+import java.util.*;
+
+public class TextBlock
+{
+  private Vector textLines ;
+  private AboutTextLine headLine ;
+  private boolean visible ;
+
+  public TextBlock()
+  {
+    textLines = new Vector() ;
+    visible = false ;
+  }
+
+// ---------------------------------------------------------------------------
+
+  public void add(AboutTextLine line)
+  {
+    textLines.add(line);
+  }
+
+  public Enumeration getEnumeration() { return textLines.elements() ; }
+
+// ---------------------------------------------------------------------------
+  public void setHeading(AboutTextLine head)
+  {
+    headLine = head ;
+  }
+
+  public AboutTextLine getHeading() { return headLine ; }
+
+// ---------------------------------------------------------------------------
+  public boolean isVisible()
+  {
+    return visible;
+  }
+
+  public void setVisible(boolean pVisible)
+  {
+    this.visible = pVisible;
+  }
+
+
+}
diff --git a/src/java/net/sf/jabref/aspects/violations/DetectSwingSingleThreadRuleViolations.aj b/src/java/net/sf/jabref/aspects/violations/DetectSwingSingleThreadRuleViolations.aj
new file mode 100644
index 0000000..17dcdfd
--- /dev/null
+++ b/src/java/net/sf/jabref/aspects/violations/DetectSwingSingleThreadRuleViolations.aj
@@ -0,0 +1,41 @@
+/*
+ * Package package net.sf.jabref.aspects.violations;
+ * Created on Nov 6, 2004
+ * Author mspiegel
+ *
+ */
+package net.sf.jabref.aspects.violations;
+
+import java.awt.Component;
+import java.awt.EventQueue;
+
+public aspect DetectSwingSingleThreadRuleViolations {
+
+	pointcut guiUpdates(Component component)
+		:	call(* java..Component+.*(..)) && 
+		    !call(* net..jabref+.*(..)) && target(component);			
+    
+	pointcut safeGuiCalls()
+		: call (* javax..JComponent.repaint(..))
+			|| call(* javax..JComponent.revalidate(..))
+		    || call(* javax..JComponent.invalidate(..))
+		    || call(* javax..*.add*Listener(..))
+		    || call(* javax..*.remove*Listener(..));
+		        
+	pointcut unsafeGuiCalls(Component component)
+		: guiUpdates(component) && !safeGuiCalls();
+    
+    before(Component component) : unsafeGuiCalls(component) 
+    	&& if (!EventQueue.isDispatchThread() && (component != null) &&
+    	        	component.isDisplayable() && !Thread.currentThread().getName().equals("main")) {
+            System.err.println(	
+                    "Violation: Swing component method called from nonAWT thread"
+                    + "\nCalled method: " + thisJoinPointStaticPart.getSignature()
+                    + "\nCaller:" + thisEnclosingJoinPointStaticPart.getSignature()
+                    + "\nSource Location:" + thisJoinPointStaticPart.getSourceLocation()
+                    + "\nThread:" + Thread.currentThread() 
+                    + "\nChange code to use EventQueue.invokeLater() or EventQueue.invokeAndWait()"
+                    + "\n");
+    	}
+    
+}
diff --git a/src/java/net/sf/jabref/collab/Change.java b/src/java/net/sf/jabref/collab/Change.java
new file mode 100644
index 0000000..342fd8f
--- /dev/null
+++ b/src/java/net/sf/jabref/collab/Change.java
@@ -0,0 +1,64 @@
+package net.sf.jabref.collab;
+
+import net.sf.jabref.Globals;
+import net.sf.jabref.BasePanel;
+import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.JComponent;
+import net.sf.jabref.undo.NamedCompound;
+
+public abstract class Change extends DefaultMutableTreeNode {
+
+  String name;
+  boolean accepted = true;
+
+  public Change() {
+    name = "";
+  }
+
+  public Change(String name) {
+    this.name = Globals.lang(name);
+  }
+
+  public String getName() {
+    return name;
+  }
+
+  public String toString() {
+    return getName();
+  }
+
+  public boolean isAccepted() {
+    return accepted;
+  }
+
+  public void setAccepted(boolean a) {
+    accepted = a;
+  }
+
+  /**
+   * This method is used to disable the "accept" box if the parent has been set to "not accepted".
+   * Thus the user can disable e.g. an entry change without having to disable all field changes.
+   * @return boolean false if the parent overrides by not being accepted.
+   */
+  public boolean isAcceptable() {
+    if ((getParent() != null) && (getParent() instanceof Change))
+      return ((Change)getParent()).isAccepted();
+    else
+      return true;
+  }
+
+  /**
+   * This method returns a JComponent detailing the nature of the change.
+   * @return JComponent
+   */
+  abstract JComponent description();
+
+  /**
+  * Perform the change. This method is responsible for adding a proper undo edit to
+  * the NamedCompound, so the change can be undone.
+  * @param panel BasePanel The tab where the database lives.
+  * @param undoEdit NamedCompound The compound to hold the undo edits.
+  */
+  abstract void makeChange(BasePanel panel, NamedCompound undoEdit);
+
+}
diff --git a/src/java/net/sf/jabref/collab/ChangeDisplayDialog.java b/src/java/net/sf/jabref/collab/ChangeDisplayDialog.java
new file mode 100644
index 0000000..cf49d7b
--- /dev/null
+++ b/src/java/net/sf/jabref/collab/ChangeDisplayDialog.java
@@ -0,0 +1,117 @@
+package net.sf.jabref.collab;
+
+import javax.swing.*;
+import javax.swing.tree.DefaultMutableTreeNode;
+import java.awt.BorderLayout;
+import net.sf.jabref.Globals;
+import java.awt.Insets;
+import javax.swing.event.TreeSelectionListener;
+import javax.swing.event.TreeSelectionEvent;
+import javax.swing.event.ChangeListener;
+import javax.swing.event.ChangeEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.ActionEvent;
+import java.util.Enumeration;
+import net.sf.jabref.BasePanel;
+import net.sf.jabref.undo.NamedCompound;
+
+public class ChangeDisplayDialog extends JDialog implements TreeSelectionListener {
+
+  DefaultMutableTreeNode root;
+  JTree tree;
+  JPanel infoPanel = new JPanel(),
+      buttonPanel = new JPanel(),
+      infoBorder = new JPanel();
+  JButton ok = new JButton(Globals.lang("Ok")),
+      cancel = new JButton(Globals.lang("Cancel"));
+  JCheckBox cb = new JCheckBox(Globals.lang("Accept change"));
+  JLabel rootInfo = new JLabel(Globals.lang("Select the tree nodes to view and accept or reject changes")+".");
+  Change selected = null;
+  JComponent infoShown = null;
+
+  public ChangeDisplayDialog(JFrame owner, final BasePanel panel, final DefaultMutableTreeNode root) {
+    super(owner, Globals.lang("External changes"), true);
+    this.root = root;
+    tree = new JTree(root);
+    tree.addTreeSelectionListener(this);
+    JSplitPane pane = new JSplitPane();
+    pane.setLeftComponent(new JScrollPane(tree));
+    pane.setRightComponent(infoBorder);
+
+    cb.setMargin(new Insets(2, 2, 2, 2));
+    cb.setEnabled(false);
+    infoPanel.setLayout(new BorderLayout());
+    infoBorder.setLayout(new BorderLayout());
+    infoBorder.setBorder(BorderFactory.createEtchedBorder());
+    infoBorder.add(infoPanel, BorderLayout.CENTER);
+    setInfo(rootInfo);
+    infoPanel.add(cb, BorderLayout.SOUTH);
+
+    buttonPanel.add(ok);
+    buttonPanel.add(cancel);
+
+    getContentPane().add(pane, BorderLayout.CENTER);
+    getContentPane().add(buttonPanel, BorderLayout.SOUTH);
+
+    cb.addChangeListener(new ChangeListener() {
+      public void stateChanged(ChangeEvent e) {
+        if (selected != null)
+          selected.setAccepted(cb.isSelected());
+      }
+    });
+    cancel.addActionListener(new ActionListener() {
+      public void actionPerformed(ActionEvent e) {
+        dispose();
+      }
+    });
+    ok.addActionListener(new ActionListener() {
+      public void actionPerformed(ActionEvent e) {
+
+        // Perform all accepted changes:
+        // Store all edits in an Undoable object:
+        NamedCompound ce = new NamedCompound(Globals.lang("Merged external changes"));
+        Enumeration enumer = root.children();
+        for (; enumer.hasMoreElements();) {
+          Change c = (Change)enumer.nextElement();
+          if (c.isAcceptable() && c.isAccepted())
+            c.makeChange(panel, ce);
+        }
+        ce.end();
+        panel.undoManager.addEdit(ce);
+        panel.markBaseChanged();
+        panel.setUpdatedExternally(false);
+        dispose();
+      }
+    });
+
+    pack();
+  }
+
+  private void setInfo(JComponent comp) {
+    if (infoShown != null)
+      infoPanel.remove(infoShown);
+    infoShown = comp;
+    infoPanel.add(infoShown, BorderLayout.CENTER);
+    infoPanel.revalidate();
+    infoPanel.repaint();
+  }
+
+  /**
+   * valueChanged
+   *
+   * @param e TreeSelectionEvent
+   */
+  public void valueChanged(TreeSelectionEvent e) {
+    Object o = tree.getLastSelectedPathComponent();
+    if (o instanceof Change) {
+      selected = (Change)o;
+      setInfo(selected.description());
+      cb.setSelected(selected.isAccepted());
+      cb.setEnabled(selected.isAcceptable());
+    } else {
+      setInfo(rootInfo);
+      selected = null;
+      cb.setEnabled(false);
+    }
+  }
+}
diff --git a/src/java/net/sf/jabref/collab/ChangeScanner.java b/src/java/net/sf/jabref/collab/ChangeScanner.java
new file mode 100644
index 0000000..abdc7dc
--- /dev/null
+++ b/src/java/net/sf/jabref/collab/ChangeScanner.java
@@ -0,0 +1,502 @@
+package net.sf.jabref.collab;
+
+import java.io.*;
+import java.util.*;
+import javax.swing.*;
+import javax.swing.tree.DefaultMutableTreeNode;
+import net.sf.jabref.*;
+import net.sf.jabref.groups.*;
+import net.sf.jabref.imports.*;
+
+
+public class ChangeScanner extends Thread {
+
+    final double MATCH_THRESHOLD = 0.4;
+    final String[] sortBy = new String[] {"year", "author", "title" };
+    File f;
+    BibtexDatabase inMem;
+    MetaData mdInMem;
+    BasePanel panel;
+    JabRefFrame frame;
+
+    /**
+     * We create an ArrayList to hold the changes we find. These will be added in the form
+     * of UndoEdit objects. We instantiate these so that the changes found in the file on disk
+     * can be reproduced in memory by calling redo() on them. REDO, not UNDO!
+     */
+    //ArrayList changes = new ArrayList();
+    DefaultMutableTreeNode changes = new DefaultMutableTreeNode(Globals.lang("External changes"));
+    
+    //  NamedCompound edit = new NamedCompound("Merged external changes")
+    
+    public ChangeScanner(JabRefFrame frame, BasePanel bp) { //, BibtexDatabase inMem, MetaData mdInMem) {
+        panel = bp;
+        this.frame = frame;
+        this.inMem = bp.database();
+        this.mdInMem = bp.metaData();
+        // Set low priority:
+        setPriority(Thread.MIN_PRIORITY);
+
+    }
+
+    public void changeScan(File f) {
+        this.f = f;
+        start();
+    }
+
+    public void run() {
+        try {
+            //long startTime = System.currentTimeMillis();
+            
+            // Parse the temporary file.
+            File tempFile = Globals.fileUpdateMonitor.getTempFile(panel.fileMonitorHandle());
+            ParserResult pr = OpenDatabaseAction.loadDatabase(tempFile,
+            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);
+            comp = new EntryComparator(false, true, sortBy[0], comp);
+            EntrySorter sInTemp = inTemp.getSorter(comp);
+            comp = new EntryComparator(false, true, sortBy[2]);
+            comp = new EntryComparator(false, true, sortBy[1], comp);
+            comp = new EntryComparator(false, true, sortBy[0], comp);
+            EntrySorter sOnDisk = onDisk.getSorter(comp);
+            comp = new EntryComparator(false, true, sortBy[2]);
+            comp = new EntryComparator(false, true, sortBy[1], comp);
+            comp = new EntryComparator(false, true, sortBy[0], comp);
+            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();
+        }
+    }
+
+    public boolean changesFound() {
+        return changes.getChildCount() > 0;
+    }
+
+    public void displayResult() {
+        if (changes.getChildCount() > 0) {
+            SwingUtilities.invokeLater(new Runnable() {
+                public void run() {
+                    ChangeDisplayDialog dial = new ChangeDisplayDialog(frame, panel, changes);
+                    Util.placeDialog(dial, frame);
+                    dial.show();
+                }
+            });
+
+        } else {
+            JOptionPane.showMessageDialog(frame, Globals.lang("No actual changes found."),
+            Globals.lang("External changes"), JOptionPane.INFORMATION_MESSAGE);
+        }
+    }
+
+    private void scanEntries(EntrySorter mem, EntrySorter tmp, EntrySorter disk) {
+
+        // Create pointers that are incremented as the entries of each base are used in
+        // successive order from the beginning. Entries "further down" in the "disk" base
+        // can also be matched.
+        int piv1 = 0, piv2 = 0;
+        
+        // Create a HashSet where we can put references to entry numbers in the "disk"
+        // database that we have matched. This is to avoid matching them twice.
+        HashSet used = new HashSet(disk.getEntryCount());
+        HashSet notMatched = new HashSet(tmp.getEntryCount());
+        
+        // Loop through the entries of the "mem" database, looking for exact matches in the "disk" one.
+        // 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;
+            // (if there are not any entries left in the "disk" database, comp will stay at -1,
+            // and this entry will be marked as nonmatched).
+            if (!used.contains(""+piv2) && (piv2<disk.getEntryCount())) {
+                comp = Util.compareEntriesStrictly(tmp.getEntryAt(piv1), disk.getEntryAt(piv2));
+            }
+            if (comp > 1) {
+                used.add(""+piv2);
+                piv2++;
+                continue mainLoop;
+            }
+            
+            // No? Then check if another entry matches exactly.
+            if (piv2 < disk.getEntryCount()-1) {
+                for (int i = piv2+1; i < disk.getEntryCount(); i++) {
+                    if (!used.contains(""+i))
+                        comp = Util.compareEntriesStrictly(tmp.getEntryAt(piv1), disk.getEntryAt(i));
+                    else
+                        comp = -1;
+
+                    if (comp > 1) {
+                        used.add("" + i);
+                        continue mainLoop;
+                    }
+                }
+            }
+            
+            // No? Add this entry to the list of nonmatched entries.
+            notMatched.add(new Integer(piv1));
+        }
+        
+        
+        // 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.
+                int bestMatchI = -1;
+                double bestMatch = 0;
+                double comp = -1;
+
+                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));
+                        }
+                        else
+                            comp = -1;
+
+                        if (comp > bestMatch) {
+                            bestMatch = comp;
+                            bestMatchI = i;
+                        }
+                    }
+                }
+
+                if (bestMatch > MATCH_THRESHOLD) {
+                    used.add(""+bestMatchI);
+                    it.remove();
+
+                    EntryChange ec = new EntryChange(bestFit(tmp, mem, piv1), tmp.getEntryAt(piv1),
+                    disk.getEntryAt(bestMatchI));
+                    changes.add(ec);
+                    
+                    // Create an undo edit to represent this change:
+                    //NamedCompound ce = new NamedCompound("Modified entry");
+                    //ce.addEdit(new UndoableRemoveEntry(inMem, disk.getEntryAt(bestMatchI), panel));
+                    //ce.addEdit(new UndoableInsertEntry(inMem, tmp.getEntryAt(piv1), panel));
+                    //ce.end();
+                    //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));
+                    changes.add(ec);
+          /*NamedCompound ce = new NamedCompound("Removed entry");
+          ce.addEdit(new UndoableInsertEntry(inMem, tmp.getEntryAt(piv1), panel));
+          ce.end();
+          changes.add(ce);*/
+
+                }
+
+            }
+
+        }
+
+        // Finally, look if there are still untouched entries in the disk database. These
+        // mayhave been added.
+        if (used.size() < disk.getEntryCount()) {
+            for (int i=0; i<disk.getEntryCount(); i++) {
+                if (!used.contains(""+i)) {
+
+                    // See if there is an identical dupe in the mem database:
+                    boolean hasAlready = false;
+                    for (int j = 0; j < mem.getEntryCount(); j++) {
+                        if (Util.compareEntriesStrictly(mem.getEntryAt(j),
+                            disk.getEntryAt(i)) >= 1) {
+                            hasAlready = true;
+                            break;
+                        }
+                    }
+                    if (!hasAlready) {
+                        EntryAddChange ec = new EntryAddChange(disk.getEntryAt(i));
+                        changes.add(ec);
+                    }
+          /*NamedCompound ce = new NamedCompound("Added entry");
+          ce.addEdit(new UndoableRemoveEntry(inMem, disk.getEntryAt(i), panel));
+          ce.end();
+          changes.add(ce);*/
+                }
+            }
+            //System.out.println("Suspected new entries in file: "+(disk.getEntryCount()-used.size()));
+        }
+    }
+
+    /**
+     * Finds the entry in neu best fitting the specified entry in old. If no entries get a score
+     * above zero, an entry is still returned.
+     * @param old EntrySorter
+     * @param neu EntrySorter
+     * @param index int
+     * @return BibtexEntry
+     */
+    private BibtexEntry bestFit(EntrySorter old, EntrySorter neu, int index) {
+        double comp = -1;
+        int found = 0;
+        loop: for (int i=0; i<neu.getEntryCount(); i++) {
+            double res = Util.compareEntriesStrictly(old.getEntryAt(index),
+            neu.getEntryAt(i));
+            if (res > comp) {
+                comp = res;
+                found = i;
+            }
+            if (comp > 1)
+                break loop;
+        }
+        return neu.getEntryAt(found);
+    }
+
+    private void scanPreamble(BibtexDatabase inMem, BibtexDatabase onTmp, BibtexDatabase onDisk) {
+        String mem = inMem.getPreamble(),
+        tmp = onTmp.getPreamble(),
+        disk = onDisk.getPreamble();
+        if (tmp != null) {
+            if ((disk == null) || !tmp.equals(disk))
+                changes.add(new PreambleChange(tmp, mem, disk));
+        }
+        else if ((disk != null) && !disk.equals("")) {
+            changes.add(new PreambleChange(tmp, mem, disk));
+        }
+    }
+
+    private void scanStrings(BibtexDatabase inMem, BibtexDatabase onTmp, BibtexDatabase onDisk) {
+        int nTmp = onTmp.getStringCount(),
+        nDisk = onDisk.getStringCount();
+        if ((nTmp == 0) && (nDisk == 0))
+            return;
+
+        HashSet used = new HashSet();
+        HashSet usedInMem = new HashSet();
+        HashSet notMatched = new HashSet(onTmp.getStringCount());
+        
+        // First try to match by string names.
+        //int piv2 = -1;
+        mainLoop: for (Iterator i=onTmp.getStringKeySet().iterator(); i.hasNext();) {
+            Object tmpId = i.next();
+            BibtexString tmp = onTmp.getString(tmpId);
+            
+            //      for (int j=piv2+1; j<nDisk; j++)
+            for (Iterator j=onDisk.getStringKeySet().iterator(); j.hasNext();) {
+                Object diskId = j.next();
+                if (!used.contains(diskId)) {
+                    BibtexString disk = onDisk.getString(diskId);
+                    if (disk.getName().equals(tmp.getName())) {
+                        // We have found a string with a matching name.
+                        if ((tmp.getContent() != null) && !tmp.getContent().equals(disk.getContent())) {
+                            // But they have nonmatching contents, so we've found a change.
+                            BibtexString mem = findString(inMem, tmp.getName(), usedInMem);
+                            if (mem != null)
+                                changes.add(new StringChange(mem, tmp.getName(),
+                                mem.getContent(),
+                                tmp.getContent(), disk.getContent()));
+                            else
+                                changes.add(new StringChange(null, tmp.getName(), null, tmp.getContent(), disk.getContent()));
+                        }
+                        used.add(diskId);
+                        //if (j==piv2)
+                        //  piv2++;
+                        continue mainLoop;
+                    }
+
+                }
+            }
+            // If we get here, there was no match for this string.
+            notMatched.add(tmp.getId());
+        }
+        
+        // See if we can detect a name change for those entries that we couldn't match.
+        if (notMatched.size() > 0) {
+            for (Iterator i = notMatched.iterator(); i.hasNext(); ) {
+                Object nmId = i.next();
+                BibtexString tmp = onTmp.getString(nmId);
+                
+                // If we get to this point, we found no string with matching name. See if we
+                // can find one with matching content.
+                String tmpContent = tmp.getContent();
+                //for (Iterator i=onTmp.getStringKeySet().iterator(); i.hasNext();) {
+                for (Iterator j=onDisk.getStringKeySet().iterator(); j.hasNext();) {
+                    Object diskId = j.next();
+                    //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.
+                            
+                            // Try to find the matching one in memory:
+                            BibtexString bsMem = null;
+                            findInMem: for (Iterator k=inMem.getStringKeySet().iterator(); k.hasNext();) {
+                                Object memId = k.next();
+                                //for (int k = 0; k < inMem.getStringCount(); k++) {
+                                BibtexString bsMem_cand = inMem.getString(memId);
+                                if (bsMem_cand.getContent().equals(disk.getContent()) &&
+                                !usedInMem.contains(memId)) {
+                                    usedInMem.add(memId);
+                                    bsMem = bsMem_cand;
+                                    break findInMem;
+                                }
+                            }
+
+                            changes.add(new StringNameChange(bsMem, bsMem.getName(),
+                            tmp.getName(), disk.getName(),
+                            tmp.getContent()));
+                            i.remove();
+                            used.add(diskId);
+                            //System.out.println(onDisk.getString(diskId).getName());
+                        }
+                    }
+                }
+            }
+        }
+
+        if (notMatched.size() > 0) {
+            // Still one or more non-matched strings. So they must have been removed.
+            for (Iterator i = notMatched.iterator(); i.hasNext(); ) {
+                Object nmId = i.next();
+                BibtexString tmp = onTmp.getString(nmId);
+                BibtexString mem = findString(inMem, tmp.getName(), usedInMem);
+                if (mem != null) { // The removed string is not removed from the mem version.
+                    changes.add(new StringRemoveChange(tmp, mem));
+                }
+            }
+        }
+
+        //System.out.println(used.size());
+        
+        // Finally, see if there are remaining strings in the disk database. They
+        // must have been added.
+        for (Iterator i=onDisk.getStringKeySet().iterator(); i.hasNext();) {
+            Object diskId = i.next();
+            if (!used.contains(diskId)) {
+                BibtexString disk = onDisk.getString(diskId);
+                //System.out.println(disk.getName());
+                used.add(diskId);
+                changes.add(new StringAddChange(disk));
+            }
+        }
+    }
+
+    private BibtexString findString(BibtexDatabase base, String name, HashSet used) {
+        if (!base.hasStringLabel(name))
+            return null;
+        for (Iterator i=base.getStringKeySet().iterator(); i.hasNext();) {
+            Object key = i.next();
+            BibtexString bs = base.getString(key);
+            if (bs.getName().equals(name) && !used.contains(key)) {
+                used.add(key);
+                return bs;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * This method only detects wheter a change took place or not. It does not
+     * determine the type of change. This would be possible, but difficult to do
+     * properly, so I rather only report the change.
+     */
+    public void scanGroups(MetaData inMem, MetaData onTmp, MetaData onDisk) {
+        final GroupTreeNode groupsMem = inMem.getGroups();
+        final GroupTreeNode groupsTmp = onTmp.getGroups();
+        final GroupTreeNode groupsDisk = onDisk.getGroups();
+        if (groupsTmp == null && groupsDisk == null)
+            return;
+        if ((groupsTmp != null && groupsDisk == null)
+                || (groupsTmp == null && groupsDisk != null)) {
+            changes.add(new GroupChange(groupsDisk));
+            return;
+        }
+        if (groupsTmp.equals(groupsDisk))
+            return;
+        changes.add(new GroupChange(groupsDisk));
+        return;
+        
+//        
+//        if (((vOnTmp == null) || (vOnTmp.size()==0)) && ((vOnDisk == null) || (vOnDisk.size()==0))) {
+//            // No groups defined in either the tmp or disk version.
+//            return;
+//        }
+//        
+//        // To avoid checking for null all the time, make empty vectors to replace null refs. We clone
+//        // non-null vectors so we can remove the elements as we finish with them.
+//        if (vOnDisk == null)
+//            vOnDisk = new Vector(0);
+//        else
+//            vOnDisk = (Vector)vOnDisk.clone();
+//        if (vOnTmp == null)
+//            vOnTmp = new Vector(0);
+//        else
+//            vOnTmp = (Vector)vOnTmp.clone();
+//        if (vInMem == null)
+//            vInMem = new Vector(0);
+//        else
+//            vInMem = (Vector)vInMem.clone();
+//        
+//        // If the tmp version has groups, iterate through these and compare with disk version:
+//        while (vOnTmp.size() >= 1) {
+//            AbstractGroup group = (AbstractGroup)vOnTmp.firstElement();
+//            vOnTmp.removeElementAt(0);
+//            int pos = GroupSelector.findGroupByName(vOnDisk,group.getName());
+//            if (pos == -1) {
+//                // Couldn't find the group.
+//                changes.add(new GroupAddOrRemove(group, false));
+//            } else {
+//                AbstractGroup diskGroup = (AbstractGroup)vOnDisk.elementAt(pos);
+//                
+//                if (!diskGroup.equals(group)) {
+//                    // Group has changed.
+//                    changes.add(new GroupChange(inMem, group, diskGroup));
+//                }
+//                
+//                // Remove this group, since it's been accounted for.
+//                vOnDisk.remove(pos);
+//            }
+//        }
+//        
+//        // If there are entries left in the disk version, these must have been added.
+//        while (vOnDisk.size() >= 1) {
+//            AbstractGroup group = (AbstractGroup)vOnDisk.firstElement();
+//            vOnDisk.removeElementAt(0);
+//            changes.add(new GroupAddOrRemove(group, true));
+//        }
+    }
+
+}
diff --git a/src/java/net/sf/jabref/collab/EntryAddChange.java b/src/java/net/sf/jabref/collab/EntryAddChange.java
new file mode 100644
index 0000000..e62d608
--- /dev/null
+++ b/src/java/net/sf/jabref/collab/EntryAddChange.java
@@ -0,0 +1,44 @@
+package net.sf.jabref.collab;
+
+import net.sf.jabref.Globals;
+import net.sf.jabref.BibtexEntry;
+import net.sf.jabref.BasePanel;
+import net.sf.jabref.Util;
+import net.sf.jabref.undo.NamedCompound;
+import net.sf.jabref.undo.UndoableInsertEntry;
+import net.sf.jabref.KeyCollisionException;
+import javax.swing.JComponent;
+import javax.swing.JLabel;
+import net.sf.jabref.PreviewPanel;
+import javax.swing.JScrollPane;
+
+public class EntryAddChange extends Change {
+
+  BibtexEntry diskEntry;
+//  boolean isModifiedLocally, modificationsAgree;[[[[[[
+  PreviewPanel pp;
+  JScrollPane sp;
+
+  public EntryAddChange(BibtexEntry diskEntry) {
+    super("Added entry");
+    this.diskEntry = diskEntry;
+
+    pp = new PreviewPanel(diskEntry, Globals.prefs.get("preview0"));
+    sp = new JScrollPane(pp);
+  }
+
+  public void makeChange(BasePanel panel, NamedCompound undoEdit) {
+    try {
+      diskEntry.setId(Util.createNeutralId());
+      panel.database().insertEntry(diskEntry);
+      undoEdit.addEdit(new UndoableInsertEntry(panel.database(), diskEntry, panel));
+    } catch (KeyCollisionException ex) {
+
+    }
+
+  }
+
+  JComponent description() {
+    return sp;
+  }
+}
diff --git a/src/java/net/sf/jabref/collab/EntryChange.java b/src/java/net/sf/jabref/collab/EntryChange.java
new file mode 100644
index 0000000..ec00b7f
--- /dev/null
+++ b/src/java/net/sf/jabref/collab/EntryChange.java
@@ -0,0 +1,151 @@
+package net.sf.jabref.collab;
+
+import net.sf.jabref.BibtexEntry;
+import net.sf.jabref.BasePanel;
+import net.sf.jabref.Util;
+import net.sf.jabref.KeyCollisionException;
+import javax.swing.JComponent;
+import javax.swing.JLabel;
+import java.util.TreeSet;
+import java.util.Iterator;
+import javax.swing.JTextPane;
+import net.sf.jabref.Globals;
+import java.util.Enumeration;
+import javax.swing.JScrollPane;
+import net.sf.jabref.undo.NamedCompound;
+import net.sf.jabref.undo.UndoableFieldChange;
+
+public class EntryChange extends Change {
+
+  BibtexEntry memEntry, tmpEntry, diskEntry;
+  boolean isModifiedLocally, modificationsAgree;
+
+  public EntryChange(BibtexEntry memEntry, BibtexEntry tmpEntry, BibtexEntry diskEntry) {
+    super();
+    String key = tmpEntry.getCiteKey();
+    if (key == null)
+      name = "Modified entry";
+    else
+      name = "Modified entry: '"+key+"'";
+    this.memEntry = memEntry;
+    this.tmpEntry = tmpEntry;
+    this.diskEntry = diskEntry;
+
+    // We know that tmpEntry is not equal to diskEntry. Check if it has been modified
+    // locally as well, since last tempfile was saved.
+    isModifiedLocally = ! (Util.compareEntriesStrictly(memEntry, tmpEntry) > 1);
+
+    // Another (unlikely?) possibility is that both disk and mem version has been modified
+    // in the same way. Check for this, too.
+    modificationsAgree = (Util.compareEntriesStrictly(memEntry, diskEntry) > 1);
+
+    //Util.pr("Modified entry: "+memEntry.getCiteKey()+"\n Modified locally: "+isModifiedLocally
+    //        +" Modifications agree: "+modificationsAgree);
+
+    TreeSet allFields = new TreeSet(); //one.getAllFields());
+    Object[] o = memEntry.getAllFields();
+    for (int i = 0; i < o.length; i++)
+      allFields.add(o[i]);
+    o = tmpEntry.getAllFields();
+    for (int i = 0; i < o.length; i++)
+      allFields.add(o[i]);
+    o = diskEntry.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();
+      String mem = (String)memEntry.getField(field),
+          tmp = (String)tmpEntry.getField(field),
+          disk = (String)diskEntry.getField(field);
+
+      if ((tmp != null) && (disk != null)) {
+        if (!tmp.equals(disk)) {
+          // Modified externally.
+          add(new FieldChange(field, memEntry, mem, tmp, disk));
+        }
+      } else if ((tmp == null) && (disk != null) && !disk.equals("")) {
+        // Added externally.
+        add(new FieldChange(field, memEntry, mem, tmp, disk));
+      } else if ((disk == null) && (tmp != null) && !tmp.equals("")
+                 && (mem != null) && !mem.equals("")) {
+        // Deleted externally and not locally.
+        add(new FieldChange(field, memEntry, mem, tmp, disk));
+      }
+
+      //Util.pr("Field: "+fld.next());
+    }
+  }
+
+  public void makeChange(BasePanel panel, NamedCompound undoEdit) {
+
+    Enumeration e = children();
+    for (; e.hasMoreElements();) {
+      Change c = (Change)e.nextElement();
+      if (c.isAcceptable() && c.isAccepted())
+        c.makeChange(panel, undoEdit);
+    }
+
+    /*panel.database().removeEntry(memEntry.getId());
+    try {
+      diskEntry.setId(Util.createNeutralId());
+    } catch (KeyCollisionException ex) {}
+    panel.database().removeEntry(memEntry.getId());*/
+  }
+
+  JComponent description() {
+    return new JLabel(name);
+  }
+
+
+
+
+  class FieldChange extends Change {
+
+    BibtexEntry entry;
+    String field, inMem, onTmp, onDisk;
+    InfoPane tp = new InfoPane();
+    JScrollPane sp = new JScrollPane(tp);
+
+    public FieldChange(String field, BibtexEntry memEntry, String inMem, String onTmp, String onDisk) {
+      entry = memEntry;
+      name = field;
+      this.field = field;
+      this.inMem = inMem;
+      this.onTmp = onTmp;
+      this.onDisk = onDisk;
+
+      StringBuffer text = new StringBuffer();
+      text.append("<FONT SIZE=10>");
+        text.append("<H2>").append(Globals.lang("Modification of field")).append(" <I>").append(field).append("</I></H2>");
+
+      if ((onDisk != null) && !onDisk.equals(""))
+          text.append("<H3>").append(Globals.lang("Value set externally")).append(":</H3>" + " ").append(onDisk);
+      else
+          text.append("<H3>").append(Globals.lang("Value cleared externally")).append("</H3>");
+
+      if ((inMem != null) && !inMem.equals(""))
+          text.append("<H3>").append(Globals.lang("Current value")).append(":</H3>" + " ").append(inMem);
+      else {
+        // No value in memory.
+        /*if ((onTmp != null) && !onTmp.equals(inMem))
+          text.append("<H2>"+Globals.lang("You have cleared this field. Original value")+":</H2>"
+                      +" "+onTmp);*/
+      }
+      tp.setContentType("text/html");
+      tp.setText(text.toString());
+    }
+
+    public void makeChange(BasePanel panel, NamedCompound undoEdit) {
+      //System.out.println(field+" "+onDisk);
+      entry.setField(field, onDisk);
+      undoEdit.addEdit(new UndoableFieldChange(entry, field, inMem, onDisk));
+    }
+
+    JComponent description() {
+      return sp;
+    }
+
+  }
+}
diff --git a/src/java/net/sf/jabref/collab/EntryDeleteChange.java b/src/java/net/sf/jabref/collab/EntryDeleteChange.java
new file mode 100644
index 0000000..1ae2841
--- /dev/null
+++ b/src/java/net/sf/jabref/collab/EntryDeleteChange.java
@@ -0,0 +1,50 @@
+package net.sf.jabref.collab;
+
+import net.sf.jabref.Globals;
+import net.sf.jabref.BibtexEntry;
+import net.sf.jabref.BasePanel;
+import net.sf.jabref.Util;
+import net.sf.jabref.KeyCollisionException;
+import javax.swing.JComponent;
+import javax.swing.JLabel;
+import net.sf.jabref.PreviewPanel;
+import javax.swing.JScrollPane;
+import net.sf.jabref.undo.NamedCompound;
+import net.sf.jabref.undo.UndoableRemoveEntry;
+
+public class EntryDeleteChange extends Change {
+
+  BibtexEntry memEntry, tmpEntry, diskEntry;
+  boolean isModifiedLocally;
+  double matchWithTmp;
+  PreviewPanel pp;
+  JScrollPane sp;
+
+  public EntryDeleteChange(BibtexEntry memEntry, BibtexEntry tmpEntry) {
+    super("Deleted entry");
+    this.memEntry = memEntry;
+    this.tmpEntry = tmpEntry;
+
+    // Compare the deleted entry in memory with the one in the tmpfile. The
+    // entry could have been removed in memory.
+    matchWithTmp = Util.compareEntriesStrictly(memEntry, tmpEntry);
+
+    // Check if it has been modified locally, since last tempfile was saved.
+    isModifiedLocally = !(matchWithTmp > 1);
+
+    //Util.pr("Modified entry: "+memEntry.getCiteKey()+"\n Modified locally: "+isModifiedLocally
+    //        +" Modifications agree: "+modificationsAgree);
+
+    pp = new PreviewPanel(memEntry, Globals.prefs.get("preview0"));
+    sp = new JScrollPane(pp);
+  }
+
+  public void makeChange(BasePanel panel, NamedCompound undoEdit) {
+    panel.database().removeEntry(memEntry.getId());
+    undoEdit.addEdit(new UndoableRemoveEntry(panel.database(), memEntry, panel));
+  }
+
+  JComponent description() {
+    return sp;
+  }
+}
diff --git a/src/java/net/sf/jabref/collab/FileUpdateListener.java b/src/java/net/sf/jabref/collab/FileUpdateListener.java
new file mode 100644
index 0000000..8f072c7
--- /dev/null
+++ b/src/java/net/sf/jabref/collab/FileUpdateListener.java
@@ -0,0 +1,15 @@
+package net.sf.jabref.collab;
+
+public interface FileUpdateListener {
+
+  /**
+   * The file has been updated. A new call will not result until the file has been modified again.
+   */
+  public void fileUpdated();
+
+  /**
+   * The file does no longer exist.
+   */
+  public void fileRemoved();
+
+}
diff --git a/src/java/net/sf/jabref/collab/FileUpdateMonitor.java b/src/java/net/sf/jabref/collab/FileUpdateMonitor.java
new file mode 100644
index 0000000..e684f47
--- /dev/null
+++ b/src/java/net/sf/jabref/collab/FileUpdateMonitor.java
@@ -0,0 +1,223 @@
+package net.sf.jabref.collab;
+
+import net.sf.jabref.Globals;
+import net.sf.jabref.Util;
+import java.util.HashMap;
+import java.io.File;
+import java.io.IOException;
+import java.util.Iterator;
+
+/**
+ * This thread monitors a set of files, each associated with a FileUpdateListener, for changes
+* in the file's last modification time stamp. The
+ */
+public class FileUpdateMonitor extends Thread {
+
+  final int WAIT = 4000;
+  static int tmpNum = 0;
+  int no = 0;
+  HashMap entries = new HashMap();
+  boolean running;
+
+  public FileUpdateMonitor() {
+    setPriority(MIN_PRIORITY);
+  }
+
+  public void run() {
+    running = true;
+
+    // The running variable is used to make the thread stop when needed.
+    while (running) {
+      //System.out.println("Polling...");
+      Iterator i = entries.keySet().iterator();
+      for (;i.hasNext();) {
+        Entry e = (Entry)entries.get(i.next());
+        try {
+          if (e.hasBeenUpdated())
+            e.notifyListener();
+
+          //else
+          //System.out.println("File '"+e.file.getPath()+"' not modified.");
+        } catch (IOException ex) {
+          e.notifyFileRemoved();
+        }
+      }
+
+      // Sleep for a while before starting a new polling round.
+      try {
+        sleep(WAIT);
+      } catch (InterruptedException ex) {
+      }
+    }
+  }
+
+  /**
+   * Cause the thread to stop monitoring. It will finish the current round before stopping.
+   */
+  public void stopMonitoring() {
+    running = false;
+  }
+
+  /**
+   * Add a new file to monitor. Returns a handle for accessing the entry.
+   * @param ul FileUpdateListener The listener to notify when the file changes.
+   * @param file File The file to monitor.
+   * @throws IOException if the file does not exist.
+   */
+  public String addUpdateListener(FileUpdateListener ul, File file) throws IOException {
+     // System.out.println(file.getPath());
+    if (!file.exists())
+      throw new IOException("File not found");
+    no++;
+    String key = ""+no;
+    entries.put(key, new Entry(ul, file));
+    return key;
+  }
+
+    /**
+     * Forces a check on the file, and returns the result. Does not
+     * force a report to all listeners before the next routine check.
+     */
+    public boolean hasBeenModified(String handle) throws IllegalArgumentException {
+	Object o = entries.get(handle);
+	if (o == null)
+            return false;
+        //	    throw new IllegalArgumentException("Entry not found");
+	try {
+	    return ((Entry)o).hasBeenUpdated();
+	} catch (IOException ex) {
+	    // Thrown if file has been removed. We return false.
+	    return false;
+	}
+    }
+
+  /**
+   * Removes a listener from the monitor.
+   * @param handle String The handle for the listener to remove.
+   */
+  public void removeUpdateListener(String handle) {
+    entries.remove(handle);
+  }
+
+  public void updateTimeStamp(String key) throws IllegalArgumentException {
+    Object o = entries.get(key);
+    if (o == null)
+      throw new IllegalArgumentException("Entry not found");
+    Entry entry = (Entry)o;
+    entry.updateTimeStamp();
+
+  }
+
+  public void changeFile(String key, File file) throws IOException, IllegalArgumentException {
+    if (!file.exists())
+      throw new IOException("File not found");
+    Object o = entries.get(key);
+    if (o == null)
+      throw new IllegalArgumentException("Entry not found");
+    ((Entry)o).file = file;
+  }
+
+  /**
+   * Method for getting the temporary file used for this database. The tempfile
+   * is used for comparison with the changed on-disk version.
+   * @param key String The handle for this monitor.
+   * @throws IllegalArgumentException If the handle doesn't correspond to an entry.
+   * @return File The temporary file.
+   */
+  public File getTempFile(String key) throws IllegalArgumentException {
+    Object o = entries.get(key);
+    if (o == null)
+      throw new IllegalArgumentException("Entry not found");
+    return ((Entry)o).tmpFile;
+  }
+
+  /**
+   * A class containing the File, the FileUpdateListener and the current time stamp for one file.
+   */
+  class Entry {
+    FileUpdateListener listener;
+    File file;
+    File tmpFile;
+    long timeStamp;
+
+    public Entry(FileUpdateListener ul, File f) {
+      listener = ul;
+      file = f;
+      timeStamp = file.lastModified();
+      tmpFile = getTempFile();
+      copy();
+    }
+
+    /**
+     * Check if time stamp has changed.
+     * @throws IOException if the file does no longer exist.
+     * @return boolean true if the file has changed.
+     */
+    public boolean hasBeenUpdated() throws IOException {
+      long modified = file.lastModified();
+      if (modified == 0L)
+        throw new IOException("File deleted");
+      return timeStamp != modified;
+    }
+
+    public void updateTimeStamp() {
+      timeStamp = file.lastModified();
+      if (timeStamp == 0L)
+        notifyFileRemoved();
+
+      copy();
+    }
+
+    public boolean copy() {
+	
+	//Util.pr("<copy file=\""+tmpFile.getPath()+"\">");
+      boolean res = false;
+      try {
+        res = Util.copyFile(file, tmpFile, true);
+      } catch (IOException ex) {
+        Globals.logger("Cannot copy to temporary file '"+tmpFile.getPath()+"'");
+      }
+      //Util.pr("</copy>");
+      return res;
+	
+      //return true;
+    }
+
+    /**
+     * Call the listener method to signal that the file has changed.
+     */
+    public void notifyListener() {
+      // Update time stamp.
+      timeStamp = file.lastModified();
+      listener.fileUpdated();
+    }
+
+    /**
+     * Call the listener method to signal that the file has been removed.
+     */
+    public void notifyFileRemoved() {
+      listener.fileRemoved();
+    }
+
+    public void finalize() {
+      try {
+        tmpFile.delete();
+      } catch (Throwable e) {
+        Globals.logger("Cannot delete temporary file '"+tmpFile.getPath()+"'");
+      }
+    }
+  }
+
+  static synchronized File getTempFile() {
+    File f = null;
+    // Globals.prefs.get("tempDir")
+    //while ((f = File.createTempFile("jabref"+(tmpNum++), null)).exists());
+    try {
+	f = File.createTempFile("jabref", null);
+	//System.out.println(f.getPath());
+    } catch (IOException ex) {
+	ex.printStackTrace();
+    }
+    return f;
+  }
+}
diff --git a/src/java/net/sf/jabref/collab/FileUpdatePanel.java b/src/java/net/sf/jabref/collab/FileUpdatePanel.java
new file mode 100644
index 0000000..e35d384
--- /dev/null
+++ b/src/java/net/sf/jabref/collab/FileUpdatePanel.java
@@ -0,0 +1,59 @@
+package net.sf.jabref.collab;
+
+import net.sf.jabref.*;
+import java.awt.BorderLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import javax.swing.*;
+import java.io.IOException;
+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.saveIconFile, 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();
+    //}
+  }
+}
diff --git a/src/java/net/sf/jabref/collab/GroupChange.java b/src/java/net/sf/jabref/collab/GroupChange.java
new file mode 100644
index 0000000..dea681e
--- /dev/null
+++ b/src/java/net/sf/jabref/collab/GroupChange.java
@@ -0,0 +1,43 @@
+package net.sf.jabref.collab;
+
+import javax.swing.*;
+
+import net.sf.jabref.*;
+import net.sf.jabref.groups.*;
+import net.sf.jabref.undo.NamedCompound;
+
+public class GroupChange extends Change {
+    private final GroupTreeNode m_changedGroups;
+    public GroupChange(GroupTreeNode changedGroups) {
+        super(changedGroups != null ? 
+                "Modified groups tree"
+                : "Removed all groups"); // JZTODO lyrics
+        m_changedGroups = changedGroups;
+    }
+
+    public void makeChange(BasePanel panel, NamedCompound undoEdit) {
+        final GroupTreeNode root = panel.getGroupSelector().getGroupTreeRoot();
+        final UndoableModifySubtree undo = new UndoableModifySubtree(
+                panel.getGroupSelector(), root, Globals.lang("Modified groups")); // JZTODO lyrics
+        root.removeAllChildren();
+        if (m_changedGroups == null) {
+            // I think setting root to null is not possible
+            root.setGroup(new AllEntriesGroup());
+        } else {
+            // change root group, even though it'll be AllEntries anyway
+            root.setGroup(m_changedGroups.getGroup());
+            for (int i = 0; i < m_changedGroups.getChildCount(); ++i)        
+                root.add(((GroupTreeNode) m_changedGroups.getChildAt(i)).deepCopy());
+        }
+        panel.getGroupSelector().revalidateGroups();
+        undoEdit.addEdit(undo);
+    }
+
+    JComponent description() {
+        return new JLabel("<html>" + name + "." + (m_changedGroups != null ? " " 
+                + "Accepting the change replaces the complete " +
+                "groups tree with the externally modified groups tree." : "") 
+                + "</html>"); 
+        // JZTODO lyrics
+    }
+}
diff --git a/src/java/net/sf/jabref/collab/InfoPane.java b/src/java/net/sf/jabref/collab/InfoPane.java
new file mode 100644
index 0000000..b8ee526
--- /dev/null
+++ b/src/java/net/sf/jabref/collab/InfoPane.java
@@ -0,0 +1,19 @@
+package net.sf.jabref.collab;
+
+import javax.swing.JEditorPane;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.RenderingHints;
+
+public class InfoPane extends JEditorPane {
+  public InfoPane() {
+    setEditable(false);
+    setContentType("text/html");
+  }
+  public void paint(Graphics g) {
+    Graphics2D g2 = (Graphics2D)g;
+    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
+                        RenderingHints.VALUE_ANTIALIAS_ON);
+    super.paint(g2);
+  }
+}
diff --git a/src/java/net/sf/jabref/collab/PreambleChange.java b/src/java/net/sf/jabref/collab/PreambleChange.java
new file mode 100644
index 0000000..3a8f592
--- /dev/null
+++ b/src/java/net/sf/jabref/collab/PreambleChange.java
@@ -0,0 +1,51 @@
+package net.sf.jabref.collab;
+
+import net.sf.jabref.BibtexEntry;
+import net.sf.jabref.BasePanel;
+import net.sf.jabref.Util;
+import net.sf.jabref.undo.NamedCompound;
+import net.sf.jabref.undo.UndoablePreambleChange;
+import net.sf.jabref.KeyCollisionException;
+import javax.swing.JComponent;
+import javax.swing.JLabel;
+import javax.swing.JEditorPane;
+import javax.swing.JScrollPane;
+import net.sf.jabref.Globals;
+
+public class PreambleChange extends Change {
+
+  String tmp, mem, disk;
+  InfoPane tp = new InfoPane();
+  JScrollPane sp = new JScrollPane(tp);
+
+  public PreambleChange(String tmp, String mem, String disk) {
+    super("Changed preamble");
+    this.disk = disk;
+    this.mem = mem;
+    this.tmp = tmp;
+
+    StringBuffer text = new StringBuffer();
+    text.append("<FONT SIZE=3>");
+      text.append("<H2>").append(Globals.lang("Changed preamble")).append("</H2>");
+
+    if ((disk != null) && !disk.equals(""))
+        text.append("<H3>").append(Globals.lang("Value set externally")).append(":</H3>" + "<CODE>").append(disk).append("</CODE>");
+    else
+        text.append("<H3>").append(Globals.lang("Value cleared externally")).append("</H3>");
+
+    if ((mem != null) && !mem.equals(""))
+        text.append("<H3>").append(Globals.lang("Current value")).append(":</H3>" + "<CODE>").append(mem).append("</CODE>");
+
+      //tp.setContentType("text/html");
+      tp.setText(text.toString());
+  }
+
+  public void makeChange(BasePanel panel, NamedCompound undoEdit) {
+    panel.database().setPreamble(disk);
+    undoEdit.addEdit(new UndoablePreambleChange(panel.database(), panel, mem, disk));
+  }
+
+  JComponent description() {
+    return sp;
+  }
+}
diff --git a/src/java/net/sf/jabref/collab/StringAddChange.java b/src/java/net/sf/jabref/collab/StringAddChange.java
new file mode 100644
index 0000000..9ae6b8d
--- /dev/null
+++ b/src/java/net/sf/jabref/collab/StringAddChange.java
@@ -0,0 +1,57 @@
+package net.sf.jabref.collab;
+
+import javax.swing.*;
+
+import net.sf.jabref.*;
+import net.sf.jabref.undo.*;
+import net.sf.jabref.undo.UndoableStringChange;
+
+public class StringAddChange extends Change {
+
+  BibtexString string;
+
+  InfoPane tp = new InfoPane();
+  JScrollPane sp = new JScrollPane(tp);
+
+  public StringAddChange(BibtexString string) {
+    name = Globals.lang("Added string")+": '"+string.getName()+"'";
+    this.string = string;
+
+    StringBuffer sb = new StringBuffer();
+    sb.append("<HTML><H2>");
+    sb.append(Globals.lang("Added string"));
+    sb.append("</H2><H3>");
+      sb.append(Globals.lang("Label")).append(":</H3>");
+    sb.append(string.getName());
+    sb.append("<H3>");
+      sb.append(Globals.lang("Content")).append(":</H3>");
+    sb.append(string.getContent());
+    sb.append("</HTML>");
+    tp.setText(sb.toString());
+
+  }
+
+  public void makeChange(BasePanel panel, NamedCompound undoEdit) {
+
+    if (panel.database().hasStringLabel(string.getName())) {
+      // The name to change to is already in the database, so we can't comply.
+      Globals.logger("Cannot add string '"+string.getName()+"' because the name "
+                     +"is already in use.");
+    }
+
+    try {
+      panel.database().addString(string);
+      undoEdit.addEdit(new UndoableInsertString(panel, panel.database(), string));
+    } catch (KeyCollisionException ex) {
+      Globals.logger("Error: could not add string '"+string.getName()+"': "+ex.getMessage());
+    }
+
+  }
+
+
+  JComponent description() {
+    return sp;
+  }
+
+
+}
diff --git a/src/java/net/sf/jabref/collab/StringChange.java b/src/java/net/sf/jabref/collab/StringChange.java
new file mode 100644
index 0000000..2e98895
--- /dev/null
+++ b/src/java/net/sf/jabref/collab/StringChange.java
@@ -0,0 +1,70 @@
+package net.sf.jabref.collab;
+
+import javax.swing.*;
+
+import net.sf.jabref.*;
+import net.sf.jabref.undo.*;
+import net.sf.jabref.undo.UndoableStringChange;
+
+public class StringChange extends Change {
+
+  BibtexString string;
+  String mem, tmp, disk, label;
+
+  InfoPane tp = new InfoPane();
+  JScrollPane sp = new JScrollPane(tp);
+
+  public StringChange(BibtexString string, String label, String mem, String tmp, String disk) {
+    name = Globals.lang("Modified string")+": '"+label+"'";
+    this.string = string;
+    this.label = label;
+    this.mem = mem;
+    this.tmp = tmp;
+    this.disk = disk;
+
+    StringBuffer sb = new StringBuffer();
+    sb.append("<HTML><H2>");
+    sb.append(Globals.lang("Modified string"));
+    sb.append("</H2><H3>");
+      sb.append(Globals.lang("Label")).append(":</H3>");
+    sb.append(label);
+    sb.append("<H3>");
+      sb.append(Globals.lang("New content")).append(":</H3>");
+    sb.append(disk);
+    if (string != null) {
+      sb.append("<H3>");
+        sb.append(Globals.lang("Current content")).append(":</H3>");
+      sb.append(string.getContent());
+    } else {
+      sb.append("<P><I>");
+        sb.append(Globals.lang("Cannot merge this change")).append(": ");
+        sb.append(Globals.lang("The string has been removed locally")).append("</I>");
+    }
+    sb.append("</HTML>");
+    tp.setText(sb.toString());
+  }
+
+  public void makeChange(BasePanel panel, NamedCompound undoEdit) {
+    if (string != null) {
+      string.setContent(disk);
+      undoEdit.addEdit(new UndoableStringChange(panel, string, false, mem, disk));
+    } else {
+      // The string was removed or renamed locally. We guess that it was removed.
+	String newId = Util.createNeutralId();
+	BibtexString bs = new BibtexString(newId, label, disk);
+	try {
+	    panel.database().addString(bs);
+	    undoEdit.addEdit(new UndoableInsertString(panel, panel.database(), bs));
+	} catch (KeyCollisionException ex) {
+	    Globals.logger("Error: could not add string '"+string.getName()+"': "+ex.getMessage());
+	}
+    }
+  }
+
+
+  JComponent description() {
+    return sp;
+  }
+
+
+}
diff --git a/src/java/net/sf/jabref/collab/StringNameChange.java b/src/java/net/sf/jabref/collab/StringNameChange.java
new file mode 100644
index 0000000..0490c1a
--- /dev/null
+++ b/src/java/net/sf/jabref/collab/StringNameChange.java
@@ -0,0 +1,55 @@
+package net.sf.jabref.collab;
+
+import javax.swing.*;
+
+import net.sf.jabref.*;
+import net.sf.jabref.undo.*;
+import net.sf.jabref.undo.UndoableStringChange;
+
+public class StringNameChange extends Change {
+
+  BibtexString string;
+  String mem, tmp, disk, content;
+
+  public StringNameChange(BibtexString string, String mem, String tmp, String disk, String content) {
+    name = Globals.lang("Renamed string")+": '"+tmp+"'";
+    this.string = string;
+    this.content = content;
+    this.mem = mem;
+    this.tmp = tmp;
+    this.disk = disk;
+
+  }
+
+  public void makeChange(BasePanel panel, NamedCompound undoEdit) {
+
+    if (panel.database().hasStringLabel(disk)) {
+      // The name to change to is already in the database, so we can't comply.
+      Globals.logger("Cannot rename string '"+mem+"' to '"+disk+"' because the name "
+                     +"is already in use.");
+    }
+
+    if (string != null) {
+      string.setName(disk);
+      undoEdit.addEdit(new UndoableStringChange(panel, string, true, mem,
+                                                disk));
+    } else {
+      // The string was removed or renamed locally. We guess that it was removed.
+	String newId = Util.createNeutralId();
+	BibtexString bs = new BibtexString(newId, disk, content);
+      try {
+        panel.database().addString(bs);
+        undoEdit.addEdit(new UndoableInsertString(panel, panel.database(), bs));
+      } catch (KeyCollisionException ex) {
+        Globals.logger("Error: could not add string '"+bs.getName()+"': "+ex.getMessage());
+      }
+    }
+  }
+
+
+  JComponent description() {
+    return new JLabel(disk+" : "+content);
+  }
+
+
+}
diff --git a/src/java/net/sf/jabref/collab/StringRemoveChange.java b/src/java/net/sf/jabref/collab/StringRemoveChange.java
new file mode 100644
index 0000000..35db1a2
--- /dev/null
+++ b/src/java/net/sf/jabref/collab/StringRemoveChange.java
@@ -0,0 +1,53 @@
+package net.sf.jabref.collab;
+
+import javax.swing.*;
+
+import net.sf.jabref.*;
+import net.sf.jabref.undo.*;
+import net.sf.jabref.undo.UndoableStringChange;
+
+public class StringRemoveChange extends Change {
+
+  BibtexString string, inMem;
+
+  InfoPane tp = new InfoPane();
+  JScrollPane sp = new JScrollPane(tp);
+
+
+  public StringRemoveChange(BibtexString string, BibtexString inMem) {
+    name = Globals.lang("Removed string")+": '"+string.getName()+"'";
+    this.string = string;
+    this.inMem = inMem; // Holds the version in memory. Check if it has been modified...?
+
+    StringBuffer sb = new StringBuffer();
+    sb.append("<HTML><H2>");
+    sb.append(Globals.lang("Removed string"));
+    sb.append("</H2><H3>");
+      sb.append(Globals.lang("Label")).append(":</H3>");
+    sb.append(string.getName());
+    sb.append("<H3>");
+      sb.append(Globals.lang("Content")).append(":</H3>");
+    sb.append(string.getContent());
+    sb.append("</HTML>");
+    tp.setText(sb.toString());
+
+  }
+
+  public void makeChange(BasePanel panel, NamedCompound undoEdit) {
+
+    try {
+      panel.database().removeString(inMem.getId());
+      undoEdit.addEdit(new UndoableRemoveString(panel, panel.database(), string));
+    } catch (Exception ex) {
+      Globals.logger("Error: could not add string '"+string.getName()+"': "+ex.getMessage());
+    }
+
+  }
+
+
+  JComponent description() {
+    return sp;
+  }
+
+
+}
diff --git a/src/java/net/sf/jabref/export/CustomExportDialog.java b/src/java/net/sf/jabref/export/CustomExportDialog.java
new file mode 100644
index 0000000..a54f8bd
--- /dev/null
+++ b/src/java/net/sf/jabref/export/CustomExportDialog.java
@@ -0,0 +1,250 @@
+/*
+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.
+
+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;
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import java.util.Vector;
+import java.io.File;
+import net.sf.jabref.JabRefFrame;
+import net.sf.jabref.Util;
+import net.sf.jabref.Globals;
+import net.sf.jabref.GUIGlobals;
+
+/**
+ * Dialog for creating or modifying custom exports.
+ */
+class CustomExportDialog extends JDialog {
+
+    JTextField
+	name = new JTextField(60),
+	layoutFile = new JTextField(60),
+	extension = new JTextField(60);
+    JLabel
+	nl = new JLabel(Globals.lang("Export name")+":"),
+	nr = new JLabel(Globals.lang("Main layout file")+":"),
+	nf = new JLabel(Globals.lang("File extension")+":");
+    JButton
+        ok = new JButton(Globals.lang("Ok")),
+        cancel = new JButton(Globals.lang("Cancel")),
+        browse = new JButton(Globals.lang("Browse"));
+    JPanel
+	main = new JPanel(),
+	opt = new JPanel();
+    private boolean ok_pressed = false;
+    private Vector groups;
+    private int index;
+    private JabRefFrame parent;
+
+    private String /*name, regexp, field,*/ oldName, oldRegexp, oldField;
+
+    GridBagLayout gbl = new GridBagLayout();
+    GridBagConstraints con = new GridBagConstraints();
+
+
+    public CustomExportDialog(JabRefFrame parent_, String name_, String layoutFile_, String extension_) {
+      this(parent_);
+      name.setText(name_);
+      layoutFile.setText(layoutFile_);
+      extension.setText(extension_);
+    }
+
+
+    public CustomExportDialog(JabRefFrame parent_) {
+	super(parent_, Globals.lang("Edit custom export"), true);
+	parent = parent_;
+	//groups = groups_;
+	//index = index_;
+	/*if (index >= 0) {
+	    // Group entry already exists.
+	    try {
+		oldField = (String)groups.elementAt(index);
+		field.setText(oldField);
+		oldName = (String)groups.elementAt(index+1);
+		name.setText(oldName);
+		oldRegexp = (String)groups.elementAt(index+2);
+		regexp.setText(oldRegexp);
+
+		// We disable these text fields, since changing field
+		// or regexp would leave the entries added to the
+		// group hanging.
+		field.setEnabled(false);
+		regexp.setEnabled(false);
+	    } catch (ArrayIndexOutOfBoundsException ex) {
+	    }
+	} else
+	    field.setText(defaultField);
+*/
+	ActionListener okListener = new ActionListener() {
+		public void actionPerformed(ActionEvent e) {
+
+		    // Check that there are no empty strings.
+		    if ((layoutFile.getText().equals("")) ||
+			(name.getText().equals("")) ||
+			(extension.getText().equals("")) ||
+                        (!layoutFile.getText().endsWith(".layout"))) {
+			//JOptionPane.showMessageDialog
+			//    (parent, Globals.lang("You must provide a name, a search "
+			//			  +"string and a field name for this group."),
+			//			  Globals.lang("Create group"),
+			//     JOptionPane.ERROR_MESSAGE);
+			return;
+		    }
+
+		    // Handling of : and ; must also be done.
+
+		    ok_pressed = true;
+		    dispose();
+		}
+	    };
+	ok.addActionListener(okListener);
+	name.addActionListener(okListener);
+	layoutFile.addActionListener(okListener);
+	extension.addActionListener(okListener);
+
+	AbstractAction cancelAction = new AbstractAction() {
+          public void actionPerformed(ActionEvent e) {
+              dispose();
+		}
+	    };
+
+	cancel.addActionListener(cancelAction);
+
+        browse.addActionListener(new ActionListener() {
+          public void actionPerformed(ActionEvent e) {
+            File directory = new File(Globals.prefs.get("exportWorkingDirectory"));
+            String chosenStr = Globals.getNewFile(parent, Globals.prefs, directory, ".layout",
+                                             JFileChooser.OPEN_DIALOG, false);
+            if (chosenStr == null) return;
+            File chosen = new File(chosenStr);
+
+            // Update working directory for layout files.
+            Globals.prefs.put("exportWorkingDirectory", chosen.getParent());
+
+            layoutFile.setText(chosen.getPath());
+          }
+        });
+
+        // Key bindings:
+        ActionMap am = main.getActionMap();
+        InputMap im = main.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
+        im.put(parent.prefs().getKey("Close dialog"), "close");
+	am.put("close", cancelAction);
+
+
+	// Layout starts here.
+	main.setLayout(gbl);
+	//opt.setLayout(gbl);
+	main.setBorder(BorderFactory.createTitledBorder
+		       (BorderFactory.createEtchedBorder(),
+			Globals.lang("Export properties")));
+
+	// Main panel:
+	con.weightx = 0;
+	con.gridwidth = 1;
+	con.insets = new Insets(3, 5, 3, 5);
+	con.anchor = GridBagConstraints.EAST;
+	con.fill = GridBagConstraints.NONE;
+	con.gridx = 0;
+	con.gridy = 0;
+	gbl.setConstraints(nl, con);
+	main.add(nl);
+	con.gridy = 1;
+	gbl.setConstraints(nr, con);
+	main.add(nr);
+	con.gridy = 2;
+	gbl.setConstraints(nf, con);
+	main.add(nf);
+
+        con.gridwidth = 2;
+        con.weightx = 1;
+	con.anchor = GridBagConstraints.WEST;
+	con.fill = GridBagConstraints.HORIZONTAL;
+	con.gridy = 0;
+	con.gridx = 1;
+	gbl.setConstraints(name, con);
+	main.add(name);
+	con.gridy = 1;
+        con.gridwidth = 1;
+        gbl.setConstraints(layoutFile, con);
+	main.add(layoutFile);
+        con.gridx = 2;
+        con.weightx = 0;
+        gbl.setConstraints(browse, con);
+        main.add(browse);
+        con.weightx = 1;
+        con.gridwidth = 2;
+        con.gridx = 1;
+	con.gridy = 2;
+	gbl.setConstraints(extension, con);
+	main.add(extension);
+
+       	// Option buttons:
+	con.gridx = GridBagConstraints.RELATIVE;
+	con.gridy = GridBagConstraints.RELATIVE;
+	con.weightx = 1;
+	con.gridwidth = 1;
+	con.anchor = GridBagConstraints.EAST;
+	con.fill = GridBagConstraints.NONE;
+	//gbl.setConstraints(ok, con);
+	opt.add(ok);
+	con.anchor = GridBagConstraints.WEST;
+	con.gridwidth = GridBagConstraints.REMAINDER;
+	//gbl.setConstraints(cancel, con);
+	opt.add(cancel);
+
+	getContentPane().add(main, BorderLayout.CENTER);
+	getContentPane().add(opt, BorderLayout.SOUTH);
+
+	//pack();
+	setSize(600, 170);
+
+        Util.placeDialog(this, parent);
+    }
+
+    public boolean okPressed() {
+	return ok_pressed;
+    }
+
+    public int index() { return index; }
+    public String oldField() { return oldField; }
+    public String oldName() { return oldName; }
+    public String oldRegexp() { return oldRegexp; }
+    public String layoutFile() { return layoutFile.getText(); }
+    public String name() { return name.getText(); }
+    public String extension() {
+      String ext = extension.getText();
+      if (ext.startsWith("."))
+        return ext;
+      else if (ext.startsWith("*."))
+        return ext.substring(1);
+      else
+        return "."+ext;
+    }
+
+}
diff --git a/src/java/net/sf/jabref/export/CustomExportList.java b/src/java/net/sf/jabref/export/CustomExportList.java
new file mode 100644
index 0000000..193e784
--- /dev/null
+++ b/src/java/net/sf/jabref/export/CustomExportList.java
@@ -0,0 +1,80 @@
+package net.sf.jabref.export;
+
+import java.util.TreeSet;
+import java.util.Comparator;
+import net.sf.jabref.Globals;
+import net.sf.jabref.JabRefPreferences;
+
+/**
+* This class handles user defined custom export formats. They are initially read from Preferences,
+* and kept alphabetically (sorted by name). Formats can be added or removed. When modified, the
+* sort() method must be called to make sure the formats stay properly sorted.
+* When the method store() is called, export formats are written to Preferences.
+*/
+
+public class CustomExportList extends TreeSet {
+
+  private Object[] array;
+  JabRefPreferences prefs;
+//  ExportComparator comp = new ExportComparator();
+
+  public CustomExportList(JabRefPreferences prefs_, Comparator comp) {
+    super(comp);
+    //super(new ExportComparator());
+    prefs = prefs_;
+    readPrefs();
+    sort();
+  }
+
+
+
+  private void readPrefs() {
+    int i=0;
+    String[] s = null;
+    while ((s = prefs.getStringArray("customExportFormat"+i)) != null) {
+      super.add(s);
+      i++;
+    }
+  }
+
+  public String[] getElementAt(int pos) {
+    return (String[])(array[pos]);
+  }
+
+  public void addFormat(String[] s) {
+    super.add(s);
+    sort();
+  }
+
+  public void remove(int pos) {
+    super.remove(array[pos]);
+    sort();
+  }
+
+  public void sort() {
+    array = toArray();
+  }
+
+  public void store() {
+
+    if (array.length == 0)
+      purge(0);
+    else {
+      for (int i=0; i<array.length; i++) {
+        //System.out.println(i+"..");
+        Globals.prefs.putStringArray("customExportFormat"+i, (String[])(array[i]));
+      }
+      purge(array.length);
+    }
+  }
+
+  private void purge(int from) {
+    String[] s = null;
+    int i = from;
+    while ((s = Globals.prefs.getStringArray("customExportFormat"+i)) != null) {
+      Globals.prefs.remove("customExportFormat"+i);
+      i++;
+    }
+  }
+
+}
diff --git a/src/java/net/sf/jabref/export/ExpandEndnoteFilters.java b/src/java/net/sf/jabref/export/ExpandEndnoteFilters.java
new file mode 100644
index 0000000..1efc72a
--- /dev/null
+++ b/src/java/net/sf/jabref/export/ExpandEndnoteFilters.java
@@ -0,0 +1,67 @@
+/*
+ * ExpandEndnoteFilters.java
+ *
+ * Created on January 22, 2005, 6:31 PM
+ */
+
+package net.sf.jabref.export;
+
+import java.awt.event.*;
+import javax.swing.*;
+import java.io.File;
+import net.sf.jabref.*;
+import net.sf.jabref.util.ResourceExtractor;
+import spin.Spin;
+
+/**
+ *
+ * @author alver
+ */
+public class ExpandEndnoteFilters extends MnemonicAwareAction implements Worker {
+    
+    JabRefFrame frame;
+    File file = null;
+    final String FILENAME = "/EndNote.zip";
+    
+    /** Creates a new instance of ExpandEndnoteFilters */
+    public ExpandEndnoteFilters(JabRefFrame frame) {
+        this.frame = frame;
+        putValue(NAME, "Unpack EndNote filter set");
+        putValue(SHORT_DESCRIPTION, Globals.lang("<HTML>Unpack the zip file containing import/export filters for Endnote,<BR>"
+                +"for optimal interoperability with JabRef</HTML>"));
+    }
+    
+    public void actionPerformed(ActionEvent e) {
+        
+        String filename = Globals.getNewFile(frame, Globals.prefs, new File(System.getProperty("user.home")), ".zip", 
+                JFileChooser.SAVE_DIALOG, false); 
+        
+        if (filename == null)
+            return;
+        
+        //if (!filename.substring(4).equalsIgnoreCase(".zip"))
+        //    filename += ".zip";
+        file = new File(filename);
+        if (file.exists()) {
+            int confirm = JOptionPane.showConfirmDialog(frame, "'"+file.getName()+"' "+
+                          Globals.lang("exists. Overwrite file?"),
+                          Globals.lang("Unpack EndNote filter set"), JOptionPane.OK_CANCEL_OPTION);
+            if (confirm != JOptionPane.OK_OPTION)
+                return;
+        }
+        
+        // Spin off the GUI thread, and run the run() method.
+       ((Worker)Spin.off(this)).run(); 
+       
+       file = null;
+    }
+    
+    /**
+     * Worker method.
+     */
+    public void run() {
+        ResourceExtractor re = new ResourceExtractor(frame, FILENAME, file);
+        re.run();
+        frame.output(Globals.lang("Unpacked file."));
+    }
+}
diff --git a/src/java/net/sf/jabref/export/ExportComparator.java b/src/java/net/sf/jabref/export/ExportComparator.java
new file mode 100644
index 0000000..fc7293a
--- /dev/null
+++ b/src/java/net/sf/jabref/export/ExportComparator.java
@@ -0,0 +1,13 @@
+package net.sf.jabref.export;
+
+import java.util.Comparator;
+
+public class ExportComparator implements Comparator {
+  public ExportComparator() {}// super(); }
+  public int compare(Object o1, Object o2) {
+    String[] s1 = (String[])o1,
+        s2 = (String[])o2;
+    return s1[0].compareTo(s2[0]);
+  }
+
+}
diff --git a/src/java/net/sf/jabref/export/ExportCustomizationDialog.java b/src/java/net/sf/jabref/export/ExportCustomizationDialog.java
new file mode 100644
index 0000000..3d68767
--- /dev/null
+++ b/src/java/net/sf/jabref/export/ExportCustomizationDialog.java
@@ -0,0 +1,159 @@
+package net.sf.jabref.export;
+
+import javax.swing.JDialog;
+import java.awt.*;
+import net.sf.jabref.*;
+import javax.swing.*;
+import java.awt.event.ActionListener;
+import java.awt.event.ActionEvent;
+import javax.swing.table.AbstractTableModel;
+import javax.swing.table.TableColumnModel;
+
+/**
+ * <p>Title: </p>
+ * <p>Description: </p>
+ * <p>Copyright: Copyright (c) 2003</p>
+ * <p>Company: </p>
+ * @author not attributable
+ * @version 1.0
+ */
+
+public class ExportCustomizationDialog extends JDialog {
+
+  JabRefFrame frame;
+  JButton addExport = new JButton(Globals.lang("Add new")),
+      modify = new JButton(Globals.lang("Modify")),
+      remove = new JButton(Globals.lang("Remove")),
+      close = new JButton(Globals.lang("Close")),
+      help = new JButton(Globals.lang("Help"));
+
+  JPanel options = new JPanel(),
+      main = new JPanel();
+  JTable table;
+
+
+  public ExportCustomizationDialog(JabRefFrame frame_) throws HeadlessException {
+
+    super(frame_, Globals.lang("Manage custom exports"), false);
+    frame = frame_;
+    addExport.addActionListener(new ActionListener() {
+     public void actionPerformed(ActionEvent e) {
+       CustomExportDialog ecd = new CustomExportDialog(frame);
+       ecd.show();
+       if (ecd.okPressed()) {
+         String[] newFormat = new String[] {ecd.name(), ecd.layoutFile(), ecd.extension() };
+         Globals.prefs.customExports.addFormat(newFormat);
+         table.revalidate();
+         table.repaint();
+         frame.setUpCustomExportMenu();
+       }
+     }
+    });
+
+    modify.addActionListener(new ActionListener() {
+      public void actionPerformed(ActionEvent e) {
+        int row = table.getSelectedRow();
+        if (row == -1) return;
+       String[] old = Globals.prefs.customExports.getElementAt(row);
+       CustomExportDialog ecd = new CustomExportDialog(frame, old[0], old[1], old[2]);
+       ecd.show();
+       if (ecd.okPressed()) {
+         old[0] = ecd.name();
+         old[1] = ecd.layoutFile();
+         old[2] = ecd.extension();
+         table.revalidate();
+         table.repaint();
+         frame.setUpCustomExportMenu();
+       }
+     }
+    });
+
+    remove.addActionListener(new ActionListener() {
+      public void actionPerformed(ActionEvent e) {
+        int row = table.getSelectedRow();
+        if (row == -1) return;
+        Globals.prefs.customExports.remove(row);
+        table.revalidate();
+        table.repaint();
+        frame.setUpCustomExportMenu();
+      }
+    });
+
+    AbstractAction closeAction = new AbstractAction() {
+      public void actionPerformed(ActionEvent e) {
+        dispose();
+      }
+    };
+
+    close.addActionListener(closeAction);
+
+    help.addActionListener(new HelpAction(frame.helpDiag, GUIGlobals.exportCustomizationHelp,
+                                          "Help"));
+
+    ExportTableModel tableModel = new ExportTableModel();
+    table = new JTable(tableModel);
+    TableColumnModel cm = table.getColumnModel();
+    cm.getColumn(0).setPreferredWidth(GUIGlobals.EXPORT_DIALOG_COL_0_WIDTH);
+    cm.getColumn(1).setPreferredWidth(GUIGlobals.EXPORT_DIALOG_COL_1_WIDTH);
+    cm.getColumn(2).setPreferredWidth(GUIGlobals.EXPORT_DIALOG_COL_2_WIDTH);
+    JScrollPane sp = new JScrollPane(table, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
+                                     JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
+    table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+    table.setPreferredScrollableViewportSize(
+      new Dimension(500, 150));
+    if (table.getRowCount() > 0)
+      table.setRowSelectionInterval(0, 0);
+
+    // Key bindings:
+    ActionMap am = main.getActionMap();
+    InputMap im = main.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
+    im.put(frame.prefs().getKey("Close dialog"), "close");
+    am.put("close", closeAction);
+    //am = table.getActionMap();
+    //im = table.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
+    //im.put(frame.prefs().getKey("Close dialog"), "close");
+    //am.put("close", closeAction);
+    main.setLayout(new BorderLayout());
+    main.add(sp, BorderLayout.CENTER);
+    options.add(addExport);
+    options.add(modify);
+    options.add(remove);
+    options.add(close);
+    options.add(Box.createHorizontalStrut(5));
+    options.add(help);
+
+    getContentPane().add(main, BorderLayout.CENTER);
+    getContentPane().add(options, BorderLayout.SOUTH);
+    pack();
+    Util.placeDialog(this, frame);
+    new FocusRequester(table);
+  }
+
+  class ExportTableModel extends AbstractTableModel {
+    public int getColumnCount() {
+      return 3;
+    }
+
+    public int getRowCount() {
+      return Globals.prefs.customExports.size();
+    }
+
+    public String getColumnName(int col) {
+      switch (col) {
+        case 0:
+          return Globals.lang("Export name");
+        case 1:
+          return Globals.lang("Main layout file");
+        default:
+          return Globals.lang("File extension");
+      }
+    }
+
+    public Object getValueAt(int rowIndex, int columnIndex) {
+      String[] s = Globals.prefs.customExports.getElementAt(rowIndex);
+      return s[columnIndex];
+    }
+
+  }
+
+}
diff --git a/src/java/net/sf/jabref/export/FieldFormatter.java b/src/java/net/sf/jabref/export/FieldFormatter.java
new file mode 100644
index 0000000..e01c14c
--- /dev/null
+++ b/src/java/net/sf/jabref/export/FieldFormatter.java
@@ -0,0 +1,43 @@
+/*
+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;
+
+/**
+ * DOCUMENT ME!
+ *
+ * @author $author$
+ * @version $Revision: 1.4 $
+ */
+public interface FieldFormatter
+{
+    //~ Methods ////////////////////////////////////////////////////////////////
+
+    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
new file mode 100644
index 0000000..daa5611
--- /dev/null
+++ b/src/java/net/sf/jabref/export/FileActions.java
@@ -0,0 +1,724 @@
+/*
+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.
+
+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;
+
+import javax.xml.transform.*;
+import javax.xml.transform.dom.*;
+import javax.xml.transform.stream.*;
+import java.io.*;
+import java.net.URL;
+import java.util.*;
+import java.util.regex.Pattern;
+import java.util.regex.Matcher;
+
+import net.sf.jabref.export.layout.Layout;
+import net.sf.jabref.export.layout.LayoutHelper;
+import net.sf.jabref.export.layout.LayoutFormatter;
+import net.sf.jabref.export.layout.format.*;
+import net.sf.jabref.*;
+import net.sf.jabref.mods.*;
+import ca.odell.glazedlists.BasicEventList;
+import ca.odell.glazedlists.SortedList;
+
+public class FileActions
+{
+
+    private static Pattern refPat = Pattern.compile("(#[A-Za-z]+#)"); // Used to detect string references in strings
+
+
+    private static void writePreamble(Writer fw, String preamble) throws IOException {
+    if (preamble != null) {
+        fw.write("@PREAMBLE{");
+        fw.write(preamble);
+        fw.write("}"+Globals.NEWLINE +Globals.NEWLINE);
+    }
+    }
+
+    /**
+     * Write all strings in alphabetical order, modified to produce a safe (for BibTeX) order of the strings
+     * if they reference each other.
+     * @param fw The Writer to send the output to.
+     * @param database The database whose strings we should write.
+     * @throws IOException If anthing goes wrong in writing.
+     */
+    private static void writeStrings(Writer fw, BibtexDatabase database) throws IOException {
+        List strings = new ArrayList();
+        for (Iterator i = database.getStringKeySet().iterator(); i.hasNext();) {
+            strings.add(database.getString(i.next()));
+        }
+        Collections.sort(strings, new BibtexStringComparator(false));
+        // First, make a Map of all entries:
+        HashMap remaining = new HashMap();
+        for (Iterator i=strings.iterator(); i.hasNext();) {
+            BibtexString string = (BibtexString)i.next();
+            remaining.put(string.getName(), string);
+        }
+        for (Iterator i = strings.iterator(); i.hasNext();) {
+            BibtexString bs = (BibtexString) i.next();
+            if (remaining.containsKey(bs.getName()))
+                writeString(fw, bs, remaining);
+        }
+    }
+
+    private static void writeString(Writer fw, BibtexString bs, HashMap remaining) throws IOException {
+        // First remove this from the "remaining" list so it can't cause problem with circular refs:
+        remaining.remove(bs.getName());
+
+        // Then we go through the string looking for references to other strings. If we find references
+        // to strings that we will write, but still haven't, we write those before proceeding. This ensures
+        // that the string order will be acceptable for BibTeX.
+        String content = bs.getContent();
+        Matcher m;
+        while ((m = refPat.matcher(content)).find()) {
+            String foundLabel = m.group(1);
+            int restIndex = content.indexOf(foundLabel)+foundLabel.length();
+            content = content.substring(restIndex);
+            Object referred = remaining.get(foundLabel.substring(1, foundLabel.length()-1));
+            // If the label we found exists as a key in the "remaining" Map, we go on and write it now:
+            if (referred != null)
+                writeString(fw, (BibtexString)referred, remaining);
+        }
+
+        fw.write("@STRING{" + bs.getName() + " = ");
+        if (!bs.getContent().equals(""))
+            fw.write((new LatexFieldFormatter()).format(bs.getContent(), Globals.BIBTEX_STRING));
+        else
+            fw.write("{}");
+
+        fw.write("}" + Globals.NEWLINE + Globals.NEWLINE);
+    }
+
+    /**
+     * Writes the JabRef signature and the encoding.
+     *
+     * @param encoding String the name of the encoding, which is part of the header.
+     */
+    private static void writeBibFileHeader(Writer out, String encoding) throws IOException {
+      out.write(GUIGlobals.SIGNATURE);
+      out.write(" "+GUIGlobals.version+"."+Globals.NEWLINE +GUIGlobals.encPrefix+encoding+Globals.NEWLINE +Globals.NEWLINE);
+    }
+
+    /**
+     * Saves the database to file. Two boolean values indicate whether
+     * only entries with a nonzero Globals.SEARCH value and only
+     * entries with a nonzero Globals.GROUPSEARCH value should be
+     * saved. This can be used to let the user save only the results of
+     * a search. False and false means all entries are saved.
+     */
+    public static SaveSession saveDatabase(BibtexDatabase database, MetaData metaData,
+                                           File file, JabRefPreferences prefs, boolean checkSearch,
+                                           boolean checkGroup, String encoding) throws SaveException
+    {
+        BibtexEntry be = null;
+        TreeMap types = new TreeMap(); // Map to collect entry type definitions
+        // that we must save along with entries using them.
+
+        boolean backup = prefs.getBoolean("backup");
+
+        SaveSession session;
+        try {
+            session = new SaveSession(file, encoding, backup);
+        } catch (IOException e) {
+            throw new SaveException(e.getMessage());
+        }
+
+        try
+        {
+
+            // Get our data stream. This stream writes only to a temporary file, until committed.
+            VerifyingWriter fw = session.getWriter();
+
+            // Write signature.
+            writeBibFileHeader(fw, encoding);
+
+            // Write preamble if there is one.
+            writePreamble(fw, database.getPreamble());
+
+            // Write strings if there are any.
+            writeStrings(fw, database);
+
+            // Write database entries. Take care, using CrossRefEntry-
+            // Comparator, that referred entries occur after referring
+            // ones. Apart from crossref requirements, entries will be
+            // sorted as they appear on the screen.
+            List sorter = getSortedEntries(database, null, true);
+
+            FieldFormatter ff = new LatexFieldFormatter();
+
+            for (Iterator i = sorter.iterator(); i.hasNext();) {
+                be = (BibtexEntry) (i.next());
+
+        // Check if we must write the type definition for this
+        // entry, as well. Our criterion is that all non-standard
+        // types (*not* customized standard types) must be written.
+        BibtexEntryType tp = be.getType();
+        if (BibtexEntryType.getStandardType(tp.getName()) == null) {
+            types.put(tp.getName(), tp);
+        }
+
+                // Check if the entry should be written.
+                boolean write = true;
+
+                if (checkSearch && !nonZeroField(be, Globals.SEARCH))
+                {
+                    write = false;
+                }
+
+                if (checkGroup && !nonZeroField(be, Globals.GROUPSEARCH))
+                {
+                    write = false;
+                }
+
+                if (write)
+                {
+                    be.write(fw, ff, true);
+                    fw.write(Globals.NEWLINE);
+                }
+            }
+
+            // Write meta data.
+            if (metaData != null)
+            {
+                metaData.writeMetaData(fw);
+            }
+
+        // Write type definitions, if any:
+        if (types.size() > 0) {
+        for (Iterator i=types.keySet().iterator(); i.hasNext();) {
+            CustomEntryType tp = (CustomEntryType)types.get(i.next());
+            tp.save(fw);
+            fw.write(Globals.NEWLINE);
+        }
+
+        }
+
+
+            fw.close();
+        }
+         catch (Throwable ex)
+        {
+            ex.printStackTrace();
+            try {
+                session.cancel();
+                //repairAfterError(file, backup, INIT_OK);
+            } catch (IOException e) {
+                // Argh, another error? Can we do anything?
+                e.printStackTrace();
+                throw new SaveException(ex.getMessage()+"\n"+
+                        Globals.lang("Warning: could not complete file repair; your file may "
+                        +"have been corrupted. Error message: ")+e.getMessage());
+            }
+            throw new SaveException(ex.getMessage(), be);
+    }
+
+    return session;
+
+    }
+
+    /**
+     * Saves the database to file, including only the entries included
+     * in the supplied input array bes.
+     *
+     * @return A List containing warnings, if any.
+     */
+    public static SaveSession savePartOfDatabase(BibtexDatabase database, MetaData metaData,
+                                                 File file, JabRefPreferences prefs, BibtexEntry[] bes, String encoding) throws SaveException
+    {
+
+    TreeMap types = new TreeMap(); // Map to collect entry type definitions
+    // that we must save along with entries using them.
+
+        BibtexEntry be = null;
+        boolean backup = prefs.getBoolean("backup");
+
+        SaveSession session;
+        try {
+            session = new SaveSession(file, encoding, backup);
+        } catch (IOException e) {
+            throw new SaveException(e.getMessage());
+        }
+
+        try
+        {
+
+            // Define our data stream.
+            VerifyingWriter fw = session.getWriter();
+
+            // Write signature.
+            writeBibFileHeader(fw, encoding);
+
+            // Write preamble if there is one.
+            writePreamble(fw, database.getPreamble());
+
+            // Write strings if there are any.
+        writeStrings(fw, database);
+
+            // Write database entries. Take care, using CrossRefEntry-
+            // Comparator, that referred entries occur after referring
+            // ones. Apart from crossref requirements, entries will be
+            // sorted as they appear on the screen.
+        String pri, sec, ter;
+
+        boolean priD, secD, terD, priBinary=false;
+        if (!prefs.getBoolean("saveInStandardOrder")) {
+        // The setting is to save according to the current table order.
+            priBinary = prefs.getBoolean("priBinary");
+        pri = prefs.get("priSort");
+        sec = prefs.get("secSort");
+        // sorted as they appear on the screen.
+        ter = prefs.get("terSort");
+        priD = prefs.getBoolean("priDescending");
+        secD = prefs.getBoolean("secDescending");
+        terD = prefs.getBoolean("terDescending");
+        } else {
+        // The setting is to save in standard order: author, editor, year
+        pri = "author";
+        sec = "editor";
+        ter = "year";
+        priD = false;
+        secD = false;
+        terD = true;
+        }
+
+        List comparators = new ArrayList();
+        comparators.add(new CrossRefEntryComparator());
+        comparators.add(new FieldComparator(pri, priD));
+        comparators.add(new FieldComparator(sec, secD));
+        comparators.add(new FieldComparator(ter, terD));
+        comparators.add(new FieldComparator(Globals.KEY_FIELD));
+        // Use glazed lists to get a sorted view of the entries:
+        BasicEventList entryList = new BasicEventList();
+        SortedList sorter = new SortedList(entryList, new FieldComparatorStack(comparators));
+
+        if ((bes != null) && (bes.length > 0))
+        for (int i=0; i<bes.length; i++) {
+            sorter.add(bes[i]);
+        }
+
+            FieldFormatter ff = new LatexFieldFormatter();
+
+            for (Iterator i = sorter.iterator(); i.hasNext();)
+            {
+                be = (BibtexEntry) (i.next());
+
+        // Check if we must write the type definition for this
+        // entry, as well. Our criterion is that all non-standard
+        // types (*not* customized standard types) must be written.
+        BibtexEntryType tp = be.getType();
+        if (BibtexEntryType.getStandardType(tp.getName()) == null) {
+            types.put(tp.getName(), tp);
+        }
+
+        be.write(fw, ff, true);
+        fw.write(Globals.NEWLINE);
+        }
+
+            // Write meta data.
+            if (metaData != null)
+            {
+                metaData.writeMetaData(fw);
+            }
+
+        // Write type definitions, if any:
+        if (types.size() > 0) {
+        for (Iterator i=types.keySet().iterator(); i.hasNext();) {
+            CustomEntryType tp = (CustomEntryType)types.get(i.next());
+            tp.save(fw);
+            fw.write(Globals.NEWLINE);
+        }
+
+        }
+
+            fw.close();
+        }
+         catch (Throwable ex)
+        {
+            try {
+                session.cancel();
+                //repairAfterError(file, backup, status);
+            } catch (IOException e) {
+                // Argh, another error? Can we do anything?
+                e.printStackTrace();
+                throw new SaveException(ex.getMessage()+"\n"+
+                        Globals.lang("Warning: could not complete file repair; your file may "
+                        +"have been corrupted. Error message: ")+e.getMessage());
+            }
+            throw new SaveException(ex.getMessage(), be);
+    }
+
+        return session;
+
+    }
+
+
+    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 exportToCSV(BibtexDatabase database,
+                                   File outFile, JabRefPreferences prefs)
+        throws Exception {
+
+    HashMap fieldFormatters = new HashMap();
+    fieldFormatters.put("default", new RemoveLatexCommands());
+    fieldFormatters.put("author", new Object[] {new AuthorLastFirst(),
+                            new RemoveLatexCommands()});
+    fieldFormatters.put("pdf", new ResolvePDF());
+
+    String SEPARATOR = "\t";
+    List sorted = getSortedEntries(database, null, true);
+    Set fields = new TreeSet();
+    for (int i=0; i<GUIGlobals.ALL_FIELDS.length; i++)
+        fields.add(GUIGlobals.ALL_FIELDS[i]);
+
+    //	try {
+    Object[] o = fields.toArray();
+    FileWriter out = new FileWriter(outFile);
+    out.write((String)o[0]);
+    for (int i=1; i<o.length; i++) {
+        out.write(SEPARATOR+(String)o[i]);
+    }
+    out.write(Globals.NEWLINE);
+
+    for (Iterator i=sorted.iterator(); i.hasNext();) {
+        BibtexEntry entry = (BibtexEntry)i.next();
+        writeField(database, entry, (String)o[0], fieldFormatters, out);
+        for (int j=1; j<o.length; j++) {
+        out.write(SEPARATOR);
+        writeField(database, entry, (String)o[j], fieldFormatters, out);
+        }
+        out.write(Globals.NEWLINE);
+    }
+
+
+    out.close();
+    //	} catch (Throwable ex) {}
+
+
+    }
+
+
+
+    private static void writeField(BibtexDatabase database, BibtexEntry entry, String field,
+                                   HashMap fieldFormatters, Writer out)
+    throws IOException {
+
+    String s = (String)entry.getField(field);
+    if (s == null) {
+        return;
+    }
+        s = database.resolveForStrings(s);
+    Object form = fieldFormatters.get(field);
+    if (form == null)
+        form = fieldFormatters.get("default");
+
+    if (form instanceof LayoutFormatter) {
+        s = ((LayoutFormatter)form).format(s);
+    } else if (form instanceof Object[]) {
+        Object[] forms = (Object[])form;
+        for (int i=0; i<forms.length; i++) {
+        s = ((LayoutFormatter)(forms[i])).format(s);
+        }
+    }
+
+    out.write(s);
+    }
+
+    /**
+     * This method attempts to get a Reader for the file path given, either by
+     * 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 {
+      Reader reader = null;
+      // Try loading as a resource first. This works for files inside the jar:
+      URL reso = JabRefFrame.class.getResource(name);
+
+      // If that didn't work, try loading as a normal file URL:
+      if (reso != null) {
+        try {
+          reader = new InputStreamReader(reso.openStream());
+        } catch (FileNotFoundException ex) {
+          throw new IOException(Globals.lang("Could not find layout file")+": '"+name+"'.");
+        }
+      } else {
+        File f = new File(name);
+        try {
+          reader = new FileReader(f);
+        } catch (FileNotFoundException ex) {
+          throw new IOException(Globals.lang("Could not find layout file")+": '"+name+"'.");
+        }
+      }
+
+      return reader;
+    }
+
+    /*
+    * We have begun to use getSortedEntries() for both database save operations
+    * and non-database save operations.  In a non-database save operation
+    * (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) {
+        String pri, sec, ter;
+        boolean priD, secD, terD, priBinary = false;
+        if (!isSaveOperation || !Globals.prefs.getBoolean("saveInStandardOrder")) {
+            // The setting is to save according to the current table order.
+            priBinary = Globals.prefs.getBoolean("priBinary");
+            pri = Globals.prefs.get("priSort");
+            sec = Globals.prefs.get("secSort");
+            // sorted as they appear on the screen.
+            ter = Globals.prefs.get("terSort");
+            priD = Globals.prefs.getBoolean("priDescending");
+            secD = Globals.prefs.getBoolean("secDescending");
+            terD = Globals.prefs.getBoolean("terDescending");
+        } else {
+            // The setting is to save in standard order: author, editor, year
+            pri = "author";
+            sec = "editor";
+            ter = "year";
+            priD = false;
+            secD = false;
+            terD = true;
+        }
+
+        List comparators = new ArrayList();
+        comparators.add(new CrossRefEntryComparator());
+        comparators.add(new FieldComparator(pri, priD));
+        comparators.add(new FieldComparator(sec, secD));
+        comparators.add(new FieldComparator(ter, terD));
+        comparators.add(new FieldComparator(Globals.KEY_FIELD));
+        // Use glazed lists to get a sorted view of the entries:
+        BasicEventList entryList = new BasicEventList();
+        SortedList sorter = new SortedList(entryList, new FieldComparatorStack(comparators));
+
+        if (keySet == null)
+            keySet = database.getKeySet();
+
+        if (keySet != null) {
+            Iterator i = keySet.iterator();
+
+            for (; i.hasNext();) {
+                sorter.add(database.getEntryById((String) (i.next())));
+            }
+        }
+        return sorter;
+    }
+
+    /** Returns true iff the entry has a nonzero value in its field.
+     */
+    private static boolean nonZeroField(BibtexEntry be, String field)
+    {
+        String o = (String) (be.getField(field));
+
+        return ((o != null) && !o.equals("0"));
+    }
+}
+
+
+
+///////////////////////////////////////////////////////////////////////////////
+//  END OF FILE.
+///////////////////////////////////////////////////////////////////////////////
diff --git a/src/java/net/sf/jabref/export/LatexFieldFormatter.java b/src/java/net/sf/jabref/export/LatexFieldFormatter.java
new file mode 100644
index 0000000..d278459
--- /dev/null
+++ b/src/java/net/sf/jabref/export/LatexFieldFormatter.java
@@ -0,0 +1,201 @@
+/*
+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.
+
+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;
+
+import net.sf.jabref.Globals;
+import net.sf.jabref.GUIGlobals;
+import java.util.Vector;
+import net.sf.jabref.Util;
+import net.sf.jabref.JabRefPreferences;
+
+public class LatexFieldFormatter implements FieldFormatter {
+
+    StringBuffer sb;
+    int col; // First line usually starts about so much further to the right.
+    final int STARTCOL = 4;
+
+    public String format(String text, String fieldName)
+    throws IllegalArgumentException {
+
+        if (Globals.prefs.putBracesAroundCapitals(fieldName) && !Globals.BIBTEX_STRING.equals(fieldName)) {
+            text = Util.putBracesAroundCapitals(text);
+        }
+
+    // If the field is non-standard, we will just append braces,
+    // wrap and write.
+    if (!GUIGlobals.isStandardField(fieldName) && !Globals.BIBTEX_STRING.equals(fieldName)) {
+          int brc = 0;
+          boolean ok = true;
+          for (int i=0; i<text.length(); i++) {
+            char c = text.charAt(i);
+            //Util.pr(""+c);
+            if (c == '{') brc++;
+            if (c == '}') brc--;
+            if (brc < 0) {
+              ok = false;
+              break;
+            }
+          }
+          if (brc > 0)
+            ok = false;
+          if (!ok)
+            throw new IllegalArgumentException("Curly braces { and } must be balanced.");
+
+          sb = new StringBuffer(Globals.getOpeningBrace());
+          // No formatting at all for these fields, to allow custom formatting?
+          //if (Globals.prefs.getBoolean("preserveFieldFormatting"))
+          //  sb.append(text);
+          //else
+          if (!Globals.prefs.isNonWrappableField(fieldName))
+            sb.append(Util.wrap2(text, GUIGlobals.LINE_LENGTH));
+          else
+            sb.append(text);
+
+          sb.append(Globals.getClosingBrace());
+
+          return sb.toString();
+    }
+
+    sb = new StringBuffer();
+    int pivot = 0, pos1, pos2;
+    col = STARTCOL;
+    // Here we assume that the user encloses any bibtex strings in #, e.g.:
+    // #jan# - #feb#
+    // ...which will be written to the file like this:
+    // jan # { - } # feb
+    checkBraces(text);
+
+    while (pivot < text.length()) {
+        int goFrom = pivot;
+        pos1 = pivot;
+        while (goFrom == pos1) {
+        pos1 = text.indexOf('#',goFrom);
+        if ((pos1 > 0) && (text.charAt(pos1-1) == '\\')) {
+            goFrom = pos1+1;
+            pos1++;
+        } else
+            goFrom = pos1-1; // Ends the loop.
+        }
+
+        if (pos1 == -1) {
+        pos1 = text.length(); // No more occurences found.
+        pos2 = -1;
+        } else {
+        pos2 = text.indexOf('#',pos1+1);
+        //System.out.println("pos2:"+pos2);
+        if (pos2 == -1) {
+            throw new IllegalArgumentException
+            (Globals.lang("The # character is not allowed in BibTeX fields")+".\n"+
+             Globals.lang("In JabRef, use pairs of # characters to indicate "
+                      +"a string.")+"\n"+
+             Globals.lang("Note that the entry causing the problem has been selected."));
+        }
+        }
+
+        if (pos1 > pivot)
+        writeText(text, pivot, pos1);
+        if ((pos1 < text.length()) && (pos2-1 > pos1))
+        // We check that the string label is not empty. That means
+        // an occurence of ## will simply be ignored. Should it instead
+        // cause an error message?
+        writeStringLabel(text, pos1+1, pos2, (pos1 == pivot),
+                 (pos2+1 == text.length()));
+
+        if (pos2 > -1) pivot = pos2+1;
+        else pivot = pos1+1;
+        //if (tell++ > 10) System.exit(0);
+    }
+
+        if (!Globals.prefs.isNonWrappableField(fieldName))
+            return Util.wrap2(sb.toString(), GUIGlobals.LINE_LENGTH);
+          else
+            return sb.toString();
+
+
+    }
+
+    private void writeText(String text, int start_pos,
+                           int end_pos) {
+    /*sb.append("{");
+     sb.append(text.substring(start_pos, end_pos));
+     sb.append("}");*/
+    sb.append(Globals.getOpeningBrace());
+    boolean escape = false;
+    char c;
+    for (int i=start_pos; i<end_pos; i++) {
+        c = text.charAt(i);
+        if ((c == '&') && !escape)
+        sb.append("\\&");
+        else
+        sb.append(c);
+        escape = (c == '\\');
+    }
+    sb.append(Globals.getClosingBrace());
+    }
+
+    private void writeStringLabel(String text, int start_pos, int end_pos,
+                                  boolean first, boolean last) {
+    //sb.append(Util.wrap2((first ? "" : " # ") + text.substring(start_pos, end_pos)
+    //		     + (last ? "" : " # "), GUIGlobals.LINE_LENGTH));
+    putIn((first ? "" : " # ") + text.substring(start_pos, end_pos)
+          + (last ? "" : " # "));
+    }
+
+    private void putIn(String s) {
+    sb.append(Util.wrap2(s, GUIGlobals.LINE_LENGTH));
+    }
+
+
+    private void checkBraces(String text) throws IllegalArgumentException {
+
+    Vector
+        left = new Vector(5, 3),
+        right = new Vector(5, 3);
+    int current = -1;
+
+    // First we collect all occurences:
+    while ((current = text.indexOf('{', current+1)) != -1)
+        left.add(new Integer(current));
+    while ((current = text.indexOf('}', current+1)) != -1)
+        right.add(new Integer(current));
+
+    // Then we throw an exception if the error criteria are met.
+    if ((right.size() > 0) && (left.size() == 0))
+        throw new IllegalArgumentException
+        ("'}' character ends string prematurely.");
+    if ((right.size() > 0) && (((Integer)right.elementAt(0)).intValue()
+                   < ((Integer)left.elementAt(0)).intValue()))
+        throw new IllegalArgumentException
+        ("'}' character ends string prematurely.");
+    if (left.size() != right.size())
+        throw new IllegalArgumentException
+        ("Braces don't match.");
+
+    }
+
+}
diff --git a/src/java/net/sf/jabref/export/OOCalcDatabase.java b/src/java/net/sf/jabref/export/OOCalcDatabase.java
new file mode 100644
index 0000000..3812a21
--- /dev/null
+++ b/src/java/net/sf/jabref/export/OOCalcDatabase.java
@@ -0,0 +1,196 @@
+/*
+ * Created on Oct 23, 2004
+ *
+ * TODO To change the template for this generated file go to
+ * Window - Preferences - Java - Code Style - Code Templates
+ */
+package net.sf.jabref.export;
+
+import net.sf.jabref.export.layout.format.*;
+import net.sf.jabref.*;
+import java.util.*;
+import javax.xml.parsers.*;
+import org.w3c.dom.*;
+import ca.odell.glazedlists.BasicEventList;
+import ca.odell.glazedlists.SortedList;
+
+/**
+ * @author Morten O. Alver.
+ * Based on net.sf.jabref.MODSDatabase by Michael Wrighton
+ *
+ * TODO To change the template for this generated type comment go to
+ * Window - Preferences - Java - Code Style - Code Templates
+ */
+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();
+        // Make a list of comparators for sorting the entries:
+        List comparators = new ArrayList();
+        comparators.add(new FieldComparator("author"));
+        comparators.add(new FieldComparator("year"));
+        comparators.add(new FieldComparator(Globals.KEY_FIELD));
+        // Use glazed lists to get a sorted view of the entries:
+        BasicEventList entryList = new BasicEventList();
+        entryList.addAll(bibtex.getEntries());
+        entries = new SortedList(entryList, new FieldComparatorStack(comparators));
+        
+    }
+    public Document getDOMrepresentation() {
+        Document result = null;
+        try {
+            DocumentBuilder dbuild = DocumentBuilderFactory.newInstance().newDocumentBuilder();
+            result = dbuild.newDocument();
+            Element collection = result.createElement("office:document-content");
+            //collection.setAttribute("xmlns", "http://openoffice.org/2000/office");
+            collection.setAttribute("xmlns:office", "http://openoffice.org/2000/office");
+            collection.setAttribute("xmlns:style", "http://openoffice.org/2000/style");
+            collection.setAttribute("xmlns:text", "http://openoffice.org/2000/text");
+            collection.setAttribute("xmlns:table", "http://openoffice.org/2000/table");
+            collection.setAttribute("xmlns:office:class", "spreadsheet");
+            collection.setAttribute("xmlns:office:version", "1.0");
+            collection.setAttribute("xmlns:fo", "http://www.w3.org/1999/XSL/Format");
+            Element el = result.createElement("office:script");
+            collection.appendChild(el);
+
+            el = result.createElement("office:automatic-styles");
+            Element el2 = result.createElement("style:style");
+            el2.setAttribute("style:name", "ro1");
+            el2.setAttribute("style:family", "table-row");
+            Element el3 = result.createElement("style.properties");
+            el3.setAttribute("style:row-height", "0.1681inch");
+            el3.setAttribute("fo:break-before", "auto");
+            el3.setAttribute("style:use-optimal-row-height", "true");
+            el2.appendChild(el3);
+            el.appendChild(el2);
+            el2 = result.createElement("style:style");
+            el2.setAttribute("style:name", "ta1");
+            el2.setAttribute("style:family", "table");
+            el2.setAttribute("style:master-page-name", "Default");
+            el3 = result.createElement("style:properties");
+            el3.setAttribute("table:display", "true");
+            el2.appendChild(el3);
+            el.appendChild(el2);
+            collection.appendChild(el);
+
+            Element body = result.createElement("office:body"),
+                    table = result.createElement("table:table");
+            table.setAttribute("table:name", "biblio");
+            table.setAttribute("table.style-name", "ta1");
+
+            Element row = result.createElement("table:table-row");
+            row.setAttribute("table.style-name", "ro1");
+            addTableCell(result, row, "Type");
+            addTableCell(result, row, "ISBN");
+            addTableCell(result, row, "Identifier");
+            addTableCell(result, row, "Author");
+            addTableCell(result, row, "Title");
+            addTableCell(result, row, "Journal");
+            addTableCell(result, row, "Volume");
+            addTableCell(result, row, "Number");
+            addTableCell(result, row, "Month");
+            addTableCell(result, row, "Pages");
+            addTableCell(result, row, "Year");
+            addTableCell(result, row, "Address");
+            addTableCell(result, row, "Note");
+            addTableCell(result, row, "URL");
+            addTableCell(result, row, "Booktitle");
+            addTableCell(result, row, "Chapter");
+            addTableCell(result, row, "Edition");
+            addTableCell(result, row, "Series");
+            addTableCell(result, row, "Editor");
+            addTableCell(result, row, "Publisher");
+            addTableCell(result, row, "ReportType");
+            addTableCell(result, row, "Howpublished");
+            addTableCell(result, row, "Institution");
+            addTableCell(result, row, "Organization");
+            addTableCell(result, row, "School");
+            addTableCell(result, row, "Annote");
+            addTableCell(result, row, "Custom1");
+            addTableCell(result, row, "Custom2");
+            addTableCell(result, row, "Custom3");
+            addTableCell(result, row, "Custom4");
+            addTableCell(result, row, "Custom5");
+            table.appendChild(row);
+
+            for(Iterator iter = entries.iterator(); iter.hasNext(); ) {
+                BibtexEntry e = (BibtexEntry)iter.next();
+                row = result.createElement("table:table-row");
+                addTableCell(result, row, new GetOpenOfficeType().format(e.getType().getName()));
+                addTableCell(result, row, getField(e, "isbn"));
+                addTableCell(result, row, getField(e, Globals.KEY_FIELD));
+                addTableCell(result, row, getField(e, "author"));//new AuthorLastFirst().format(getField(e, "author")));
+                addTableCell(result, row, new RemoveWhitespace().format(new RemoveBrackets().format(getField(e, "title"))));
+                addTableCell(result, row, getField(e, "journal"));
+                addTableCell(result, row, getField(e, "volume"));
+                addTableCell(result, row, getField(e, "number"));
+                addTableCell(result, row, getField(e, "month"));
+                addTableCell(result, row, getField(e, "pages"));
+                addTableCell(result, row, getField(e, "year"));
+                addTableCell(result, row, getField(e, "address"));
+                addTableCell(result, row, getField(e, "note"));
+                addTableCell(result, row, getField(e, "url"));
+                addTableCell(result, row, getField(e, "booktitle"));
+                addTableCell(result, row, getField(e, "chapter"));
+                addTableCell(result, row, getField(e, "edition"));
+                addTableCell(result, row, getField(e, "series"));
+                addTableCell(result, row, getField(e, "editor"));//new AuthorLastFirst().format(getField(e, "editor")));
+                addTableCell(result, row, getField(e, "publisher"));
+                addTableCell(result, row, getField(e, "reporttype"));
+                addTableCell(result, row, getField(e, "howpublished"));
+                addTableCell(result, row, getField(e, "institution"));
+                addTableCell(result, row, getField(e, "organization"));
+                addTableCell(result, row, getField(e, "school"));
+                addTableCell(result, row, getField(e, "annote"));
+                addTableCell(result, row, "");
+                addTableCell(result, row, "");
+                addTableCell(result, row, "");
+                addTableCell(result, row, "");
+                addTableCell(result, row, "");
+                table.appendChild(row);
+            }
+
+            body.appendChild(table);
+            collection.appendChild(body);
+
+            result.appendChild(collection);
+        } catch (Exception e) {
+            System.out.println("Exception caught..." + e);
+            e.printStackTrace();
+        }
+        return result;
+    }
+
+    protected String getField(BibtexEntry e, String field) {
+        Object o = e.getField(field);
+        return o == null ? "" : o.toString();
+    }
+
+    protected void addTableCell(Document doc, Element parent, String content) {
+        Element cell = doc.createElement("table:table-cell"),
+                text = doc.createElement("text:p");
+    Text textNode = doc.createTextNode(content);
+    text.appendChild(textNode);
+        //text.setTextContent(content);
+        cell.appendChild(text);
+        parent.appendChild(cell);
+    }
+}
diff --git a/src/java/net/sf/jabref/export/OpenDocumentRepresentation.java b/src/java/net/sf/jabref/export/OpenDocumentRepresentation.java
new file mode 100644
index 0000000..afdaaa7
--- /dev/null
+++ b/src/java/net/sf/jabref/export/OpenDocumentRepresentation.java
@@ -0,0 +1,199 @@
+/*
+ * Created on Oct 23, 2004
+ *
+ * TODO To change the template for this generated file go to
+ * Window - Preferences - Java - Code Style - Code Templates
+ */
+package net.sf.jabref.export;
+
+import net.sf.jabref.export.layout.format.*;
+import net.sf.jabref.*;
+import java.util.*;
+import javax.xml.parsers.*;
+import org.w3c.dom.*;
+import ca.odell.glazedlists.SortedList;
+import ca.odell.glazedlists.EventList;
+import ca.odell.glazedlists.BasicEventList;
+
+/**
+ * @author Morten O. Alver.
+ * Based on net.sf.jabref.MODSDatabase by Michael Wrighton
+ *
+ * TODO To change the template for this generated type comment go to
+ * Window - Preferences - Java - Code Style - Code Templates
+ */
+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();
+        // Make a list of comparators for sorting the entries:
+        List comparators = new ArrayList();
+        comparators.add(new FieldComparator("author"));
+        comparators.add(new FieldComparator("year"));
+        comparators.add(new FieldComparator(Globals.KEY_FIELD));
+        // Use glazed lists to get a sorted view of the entries:
+        BasicEventList entryList = new BasicEventList();
+        entryList.addAll(bibtex.getEntries());
+        entries = new SortedList(entryList, new FieldComparatorStack(comparators));
+    }
+    public Document getDOMrepresentation() {
+        Document result = null;
+        try {
+            DocumentBuilder dbuild = DocumentBuilderFactory.newInstance().newDocumentBuilder();
+            result = dbuild.newDocument();
+            Element collection = result.createElement("office:document-content");
+            //collection.setAttribute("xmlns", "http://openoffice.org/2000/office");
+            collection.setAttribute("xmlns:office", "urn:oasis:names:tc:opendocument:xmlns:office:1.0");
+            collection.setAttribute("xmlns:style", "urn:oasis:names:tc:opendocument:xmlns:style:1.0");
+            collection.setAttribute("xmlns:text", "urn:oasis:names:tc:opendocument:xmlns:text:1.0");
+            collection.setAttribute("xmlns:table", "urn:oasis:names:tc:opendocument:xmlns:table:1.0");
+            collection.setAttribute("xmlns:meta", "urn:oasis:names:tc:opendocument:xmlns:meta:1.0");
+            collection.setAttribute("office:version", "1.0");
+            collection.setAttribute("xmlns:fo", "urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0");
+            collection.setAttribute("xmlns:xlink", "http://www.w3.org/1999/xlink");
+            Element el = result.createElement("office:scripts");
+            collection.appendChild(el);
+
+            el = result.createElement("office:automatic-styles");
+            Element el2 = result.createElement("style:style");
+            el2.setAttribute("style:name", "ro1");
+            el2.setAttribute("style:family", "table-row");
+            Element el3 = result.createElement("style.table-row-properties");
+            el3.setAttribute("style:row-height", "0.1681inch");
+            el3.setAttribute("fo:break-before", "auto");
+            el3.setAttribute("style:use-optimal-row-height", "true");
+            el2.appendChild(el3);
+            el.appendChild(el2);
+            el2 = result.createElement("style:style");
+            el2.setAttribute("style:name", "ta1");
+            el2.setAttribute("style:family", "table");
+            el2.setAttribute("style:master-page-name", "Default");
+            el3 = result.createElement("style:properties");
+            el3.setAttribute("table:display", "true");
+            el2.appendChild(el3);
+            el.appendChild(el2);
+            collection.appendChild(el);
+
+            Element body = result.createElement("office:body"),
+                    spreadsheet = result.createElement("office:spreadsheet"),
+                    table = result.createElement("table:table");
+            table.setAttribute("table:name", "biblio");
+            table.setAttribute("table.style-name", "ta1");
+
+            Element row = result.createElement("table:table-row");
+            row.setAttribute("table.style-name", "ro1");
+            addTableCell(result, row, "Identifier");
+            addTableCell(result, row, "Type");
+            addTableCell(result, row, "Address");
+            addTableCell(result, row, "Annote");
+            addTableCell(result, row, "Author");
+            addTableCell(result, row, "Booktitle");
+            addTableCell(result, row, "Chapter");
+            addTableCell(result, row, "Edition");
+            addTableCell(result, row, "Editor");
+            addTableCell(result, row, "Howpublish");
+            addTableCell(result, row, "Institutn");
+            addTableCell(result, row, "Journal");
+            addTableCell(result, row, "Month");
+            addTableCell(result, row, "Note");
+            addTableCell(result, row, "Number");
+            addTableCell(result, row, "Organizat");
+            addTableCell(result, row, "Pages");
+            addTableCell(result, row, "Publisher");
+            addTableCell(result, row, "School");
+            addTableCell(result, row, "Series");
+            addTableCell(result, row, "Title");
+            addTableCell(result, row, "RepType");
+            addTableCell(result, row, "Volume");
+            addTableCell(result, row, "Year");
+            addTableCell(result, row, "URL");
+            addTableCell(result, row, "Custom1");
+            addTableCell(result, row, "Custom2");
+            addTableCell(result, row, "Custom3");
+            addTableCell(result, row, "Custom4");
+            addTableCell(result, row, "Custom5");
+            addTableCell(result, row, "ISBN");
+            table.appendChild(row);
+
+            for(Iterator iter = entries.iterator(); iter.hasNext(); ) {
+                BibtexEntry e = (BibtexEntry)iter.next();
+                row = result.createElement("table:table-row");
+                addTableCell(result, row, getField(e, Globals.KEY_FIELD));
+                addTableCell(result, row, new GetOpenOfficeType().format(e.getType().getName()));
+                addTableCell(result, row, getField(e, "address"));
+                addTableCell(result, row, getField(e, "annote"));
+                addTableCell(result, row, getField(e, "author"));//new AuthorLastFirst().format(getField(e, "author")));
+                addTableCell(result, row, getField(e, "booktitle"));
+                addTableCell(result, row, getField(e, "chapter"));
+                addTableCell(result, row, getField(e, "edition"));
+                addTableCell(result, row, getField(e, "editor"));//new AuthorLastFirst().format(getField(e, "editor")));
+                addTableCell(result, row, getField(e, "howpublished"));
+                addTableCell(result, row, getField(e, "institution"));
+                addTableCell(result, row, getField(e, "journal"));
+                addTableCell(result, row, getField(e, "month"));
+                addTableCell(result, row, getField(e, "note"));
+                addTableCell(result, row, getField(e, "number"));
+                addTableCell(result, row, getField(e, "organization"));
+                addTableCell(result, row, getField(e, "pages"));
+                addTableCell(result, row, getField(e, "publisher"));
+                addTableCell(result, row, getField(e, "school"));
+                addTableCell(result, row, getField(e, "series"));
+                addTableCell(result, row, new RemoveWhitespace().format(new RemoveBrackets().format(getField(e, "title"))));
+                addTableCell(result, row, getField(e, "reporttype"));
+                addTableCell(result, row, getField(e, "volume"));
+                addTableCell(result, row, getField(e, "year"));
+                addTableCell(result, row, getField(e, "url"));
+                addTableCell(result, row, "");
+                addTableCell(result, row, "");
+                addTableCell(result, row, "");
+                addTableCell(result, row, "");
+                addTableCell(result, row, "");
+                addTableCell(result, row, getField(e, "isbn"));
+                table.appendChild(row);
+            }
+
+            spreadsheet.appendChild(table);
+            body.appendChild(spreadsheet);
+            collection.appendChild(body);
+
+            result.appendChild(collection);
+        } catch (Exception e) {
+            System.out.println("Exception caught..." + e);
+            e.printStackTrace();
+        }
+        return result;
+    }
+
+    protected String getField(BibtexEntry e, String field) {
+        Object o = e.getField(field);
+        return o == null ? "" : o.toString();
+    }
+
+    protected void addTableCell(Document doc, Element parent, String content) {
+        Element cell = doc.createElement("table:table-cell"),
+                text = doc.createElement("text:p");
+    Text textNode = doc.createTextNode(content);
+    text.appendChild(textNode);
+        //text.setTextContent(content);
+        cell.appendChild(text);
+        parent.appendChild(cell);
+    }
+}
diff --git a/src/java/net/sf/jabref/export/OpenDocumentSpreadsheetCreator.java b/src/java/net/sf/jabref/export/OpenDocumentSpreadsheetCreator.java
new file mode 100644
index 0000000..c61b183
--- /dev/null
+++ b/src/java/net/sf/jabref/export/OpenDocumentSpreadsheetCreator.java
@@ -0,0 +1,115 @@
+/*
+ * OpenOfficeDocumentCreator.java
+ *
+ * Created on February 16, 2005, 8:04 PM
+ */
+
+package net.sf.jabref.export;
+
+import net.sf.jabref.*;
+
+import java.io.*;
+import java.util.zip.*;
+import java.net.URL;
+import javax.xml.transform.*;
+import javax.xml.transform.dom.*;
+import javax.xml.transform.stream.*;
+
+/**
+ * @author alver
+ */
+public class OpenDocumentSpreadsheetCreator {
+
+    /**
+     * Creates a new instance of OpenOfficeDocumentCreator
+     */
+    private OpenDocumentSpreadsheetCreator() {
+    }
+
+    public static void storeOpenDocumentSpreadsheetFile(File file, InputStream source) throws Exception {
+        ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(file)));
+        try {
+            ZipEntry zipEntry = new ZipEntry("content.xml");
+            out.putNextEntry(zipEntry);
+            int c = -1;
+            while ((c = source.read()) >= 0) {
+                out.write(c);
+            }
+            out.closeEntry();
+
+            // Add manifest (required for OOo 2.0) and "meta.xml": These are in the
+            // resource/ods directory, and are copied verbatim into the zip file.
+            addResourceFile("meta.xml", "/resource/ods/meta.xml", out);
+            //addResourceFile("mimetype", "/resource/openoffice/mimetype", out);
+            addResourceFile("META-INF/manifest.xml", "/resource/ods/manifest.xml", out);
+
+            //zipEntry = new ZipEntry()
+
+        } finally {
+            out.close();
+        }
+    }
+
+    public static void exportOpenDocumentSpreadsheet(File file, BibtexDatabase database) throws Exception {
+
+        // First store the xml formatted content to a temporary file.
+        File tmpFile = File.createTempFile("opendocument", null);
+        exportOpenDocumentSpreadsheetXML(tmpFile, database);
+
+        // Then add the content to the zip file:
+        BufferedInputStream in = new BufferedInputStream(new FileInputStream(tmpFile));
+        storeOpenDocumentSpreadsheetFile(file, in);
+
+        // Delete the temporary file:
+        tmpFile.delete();
+    }
+
+    public static void exportOpenDocumentSpreadsheetXML(File tmpFile, BibtexDatabase database) {
+        OpenDocumentRepresentation od = new OpenDocumentRepresentation(database);
+
+        try {
+            Writer ps = new OutputStreamWriter(new FileOutputStream(tmpFile), "UTF8");
+            try {
+
+                //            Writer ps = new FileWriter(tmpFile);
+                DOMSource source = new DOMSource(od.getDOMrepresentation());
+                StreamResult result = new StreamResult(ps);
+                Transformer trans = TransformerFactory.newInstance().newTransformer();
+                trans.setOutputProperty(OutputKeys.INDENT, "yes");
+                trans.transform(source, result);
+            } finally {
+                ps.close();
+            }
+        } catch (Exception e) {
+            throw new Error(e);
+        }
+
+        return;
+    }
+
+    private static void addResourceFile(String name, String resource, ZipOutputStream out) throws IOException {
+        ZipEntry zipEntry = new ZipEntry(name);
+        out.putNextEntry(zipEntry);
+        addFromResource(resource, out);
+        out.closeEntry();
+    }
+
+    private static void addFromResource(String resource, OutputStream out) {
+        URL url = OpenDocumentSpreadsheetCreator.class.getResource(resource);
+        try {
+            InputStream in = url.openStream();
+            byte[] buffer = new byte[256];
+            synchronized (in) {
+                synchronized (out) {
+                    while (true) {
+                        int bytesRead = in.read(buffer);
+                        if (bytesRead == -1) break;
+                        out.write(buffer, 0, bytesRead);
+                    }
+                }
+            }
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+}
diff --git a/src/java/net/sf/jabref/export/OpenOfficeDocumentCreator.java b/src/java/net/sf/jabref/export/OpenOfficeDocumentCreator.java
new file mode 100644
index 0000000..95673be
--- /dev/null
+++ b/src/java/net/sf/jabref/export/OpenOfficeDocumentCreator.java
@@ -0,0 +1,116 @@
+/*
+ * OpenOfficeDocumentCreator.java
+ *
+ * Created on February 16, 2005, 8:04 PM
+ */
+
+package net.sf.jabref.export;
+
+import net.sf.jabref.*;
+
+import java.io.*;
+import java.util.zip.*;
+import java.net.URL;
+import javax.xml.parsers.*;
+import javax.xml.transform.*;
+import javax.xml.transform.dom.*;
+import javax.xml.transform.stream.*;
+
+/**
+ * @author alver
+ */
+public class OpenOfficeDocumentCreator {
+
+    /**
+     * Creates a new instance of OpenOfficeDocumentCreator
+     */
+    private OpenOfficeDocumentCreator() {
+    }
+
+    public static void storeOpenOfficeFile(File file, InputStream source) throws Exception {
+        ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(file)));
+        try {
+            ZipEntry zipEntry = new ZipEntry("content.xml");
+            out.putNextEntry(zipEntry);
+            int c = -1;
+            while ((c = source.read()) >= 0) {
+                out.write(c);
+            }
+            out.closeEntry();
+
+            // Add manifest (required for OOo 2.0), "meta.xml", "mimetype" files. These are in the
+            // resource/openoffice directory, and are copied verbatim into the zip file.
+            addResourceFile("meta.xml", "/resource/openoffice/meta.xml", out);
+            addResourceFile("mimetype", "/resource/openoffice/mimetype", out);
+            addResourceFile("META-INF/manifest.xml", "/resource/openoffice/manifest.xml", out);
+
+            //zipEntry = new ZipEntry()
+
+        } finally {
+            out.close();
+        }
+    }
+
+    public static void exportOpenOfficeCalc(File file, BibtexDatabase database) throws Exception {
+
+        // First store the xml formatted content to a temporary file.
+        File tmpFile = File.createTempFile("oocalc", null);
+        exportOpenOfficeCalcXML(tmpFile, database);
+
+        // Then add the content to the zip file:
+        BufferedInputStream in = new BufferedInputStream(new FileInputStream(tmpFile));
+        storeOpenOfficeFile(file, in);
+
+        // Delete the temporary file:
+        tmpFile.delete();
+    }
+
+    public static void exportOpenOfficeCalcXML(File tmpFile, BibtexDatabase database) {
+        OOCalcDatabase od = new OOCalcDatabase(database);
+
+        try {
+            Writer ps = new OutputStreamWriter(new FileOutputStream(tmpFile), "UTF8");
+            try {
+
+                //            Writer ps = new FileWriter(tmpFile);
+                DOMSource source = new DOMSource(od.getDOMrepresentation());
+                StreamResult result = new StreamResult(ps);
+                Transformer trans = TransformerFactory.newInstance().newTransformer();
+                trans.setOutputProperty(OutputKeys.INDENT, "yes");
+                trans.transform(source, result);
+            } finally {
+                ps.close();
+            }
+        } catch (Exception e) {
+            throw new Error(e);
+        }
+
+        return;
+    }
+
+    private static void addResourceFile(String name, String resource, ZipOutputStream out) throws IOException {
+        ZipEntry zipEntry = new ZipEntry(name);
+        out.putNextEntry(zipEntry);
+        addFromResource(resource, out);
+        out.closeEntry();
+    }
+
+    private static void addFromResource(String resource, OutputStream out) {
+        URL url = OpenOfficeDocumentCreator.class.getResource(resource);
+        try {
+            InputStream in = url.openStream();
+            byte[] buffer = new byte[256];
+            synchronized (in) {
+                synchronized (out) {
+                    while (true) {
+                        int bytesRead = in.read(buffer);
+                        if (bytesRead == -1) break;
+                        out.write(buffer, 0, bytesRead);
+                    }
+                }
+            }
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+}
diff --git a/src/java/net/sf/jabref/export/RtfSelection.java b/src/java/net/sf/jabref/export/RtfSelection.java
new file mode 100644
index 0000000..d1e49d2
--- /dev/null
+++ b/src/java/net/sf/jabref/export/RtfSelection.java
@@ -0,0 +1,50 @@
+package net.sf.jabref.export;
+
+import java.awt.datatransfer.*;
+import java.io.*;
+
+
+public class RtfSelection implements Transferable {
+    DataFlavor rtfFlavor;
+    DataFlavor[] supportedFlavors;
+    private String content;
+
+    public RtfSelection(String s) {
+        content = s;
+        try {
+            rtfFlavor = new DataFlavor
+                    ("text/rtf; class=java.io.InputStream");
+            supportedFlavors = new DataFlavor[]
+            {rtfFlavor, DataFlavor.stringFlavor};
+        } catch (ClassNotFoundException ex) {
+            ex.printStackTrace();
+        }
+    }
+
+    public boolean isDataFlavorSupported(DataFlavor flavor) {
+        return flavor.equals(rtfFlavor) ||
+                flavor.equals(DataFlavor.stringFlavor);
+    }
+
+    public java.awt.datatransfer.DataFlavor[] getTransferDataFlavors() {
+        //System.out.println("..");
+        return supportedFlavors;
+    }
+
+    public Object getTransferData(DataFlavor flavor)
+            throws UnsupportedFlavorException, IOException {
+
+        if (flavor.equals(DataFlavor.stringFlavor)) {
+            //System.out.println("Delivering string data.");
+            return content;
+        } else if (flavor.equals(rtfFlavor)) {
+            //System.out.println("Delivering rtf data.");
+            byte[] byteArray = content.getBytes();
+            return new ByteArrayInputStream(byteArray);
+        }
+        throw new UnsupportedFlavorException(flavor);
+    }
+}
+
+
+
diff --git a/src/java/net/sf/jabref/export/SaveException.java b/src/java/net/sf/jabref/export/SaveException.java
new file mode 100644
index 0000000..ee2afa1
--- /dev/null
+++ b/src/java/net/sf/jabref/export/SaveException.java
@@ -0,0 +1,82 @@
+/*
+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.
+
+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;
+
+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
+{
+    //~ Instance fields ////////////////////////////////////////////////////////
+
+    private BibtexEntry entry;
+    private int status;
+    //~ Constructors ///////////////////////////////////////////////////////////
+
+    public SaveException(String message)
+    {
+        super(message);
+        entry = null;
+    }
+
+    public SaveException(String message, int status)
+        {
+            super(message);
+            entry = null;
+            this.status = status;
+        }
+
+
+    public SaveException(String message, BibtexEntry entry)
+    {
+        super(message);
+        this.entry = entry;
+    }
+
+    //~ Methods ////////////////////////////////////////////////////////////////
+
+    public int getStatus() {
+        return status;
+    }
+
+    public BibtexEntry getEntry()
+    {
+        return entry;
+    }
+
+    public boolean specificEntry()
+    {
+        return (entry != null);
+    }
+}
+///////////////////////////////////////////////////////////////////////////////
+//  END OF FILE.
+///////////////////////////////////////////////////////////////////////////////
diff --git a/src/java/net/sf/jabref/export/SaveSession.java b/src/java/net/sf/jabref/export/SaveSession.java
new file mode 100644
index 0000000..3823ab3
--- /dev/null
+++ b/src/java/net/sf/jabref/export/SaveSession.java
@@ -0,0 +1,78 @@
+package net.sf.jabref.export;
+
+import net.sf.jabref.Globals;
+import net.sf.jabref.Util;
+import net.sf.jabref.GUIGlobals;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.FileOutputStream;
+
+/**
+ * Class used to handle safe storage to disk. Usage: create a SaveSession giving the file to save to, the
+ * encoding, and whether to make a backup. The SaveSession will provide a Writer to store to, which actually
+ * goes to a temporary file. The Writer keeps track of whether all characters could be saved, and if not,
+ * which characters were not encodable.
+ * After saving is finished, the client should close the Writer. If the save should be put into effect, call
+ * commit(), otherwise call cancel(). When cancelling, the temporary file is simply deleted and the target
+ * file remains unchanged. When committing, the temporary file is copied to the target file after making
+ * a backup if requested and if the target file already existed, and finally the temporary file is deleted.
+ * If committing fails, the temporary file will not be deleted.
+ */
+public class SaveSession {
+
+    private static final String TEMP_PREFIX = "jabref";
+    private static final String TEMP_SUFFIX = "save.bib";
+    File file, tmp, backupFile;
+    String encoding;
+    boolean backup;
+    VerifyingWriter writer;
+
+    public SaveSession(File file, String encoding, boolean backup) throws IOException {
+        this.file = file;
+        tmp = File.createTempFile(TEMP_PREFIX, TEMP_SUFFIX);
+        this.backup = backup;
+        this.encoding = encoding;
+        writer = new VerifyingWriter(new FileOutputStream(tmp), encoding);
+    }
+
+    public VerifyingWriter getWriter() {
+        return writer;
+    }
+
+    public String getEncoding() {
+        return encoding;
+    }
+
+    public void commit() throws SaveException {
+        if (file.exists() && backup) {
+            String name = file.getName();
+            String path = file.getParent();
+            File backupFile = new File(path, name + GUIGlobals.backupExt);
+            try {
+                Util.copyFile(file, backupFile, true);
+            } catch (IOException ex) {
+                throw new SaveException(Globals.lang("Save failed during backup creation")+": "+ex.getMessage());
+            }
+        }
+        try {
+            Util.copyFile(tmp, file, true);
+        } catch (IOException ex2) {
+            // If something happens here, what can we do to correct the problem? The file is corrupted, but we still
+            // have a clean copy in tmp. However, we just failed to copy tmp to file, so it's not likely that
+            // repeating the action will have a different result.
+            // On the other hand, our temporary file should still be clean, and won't be deleted.
+            throw new SaveException(Globals.lang("Save failed while committing changes")+": "+ex2.getMessage());
+        }
+
+        tmp.delete();
+    }
+
+    public void cancel() throws IOException {
+        tmp.delete();
+    }
+
+    public File getTemporaryFile() {
+        return tmp;
+    }
+}
diff --git a/src/java/net/sf/jabref/export/VerifyingWriter.java b/src/java/net/sf/jabref/export/VerifyingWriter.java
new file mode 100644
index 0000000..86061a8
--- /dev/null
+++ b/src/java/net/sf/jabref/export/VerifyingWriter.java
@@ -0,0 +1,51 @@
+package net.sf.jabref.export;
+
+import sun.misc.CharacterEncoder;
+
+import java.io.*;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetEncoder;
+import java.util.TreeSet;
+import java.util.Iterator;
+
+import net.sf.jabref.Globals;
+
+/**
+ * Writer that extends OutputStreamWriter, but also checks if the chosen encoding supports all
+ * text that is written. Currently only a boolean value is stored to remember whether everything
+ * has gone well or not.
+ */
+public class VerifyingWriter extends OutputStreamWriter {
+
+    CharsetEncoder encoder;
+    private boolean couldEncodeAll = true;
+    private TreeSet problemCharacters = new TreeSet();
+
+    public VerifyingWriter(OutputStream out, String encoding) throws UnsupportedEncodingException {
+        super(out, encoding);
+        encoder = Charset.forName(encoding).newEncoder();
+     }
+
+    public void write(String str) throws IOException {
+        super.write(str);
+        if (!encoder.canEncode(str)) {
+            for (int i=0; i<str.length(); i++) {
+                if (!encoder.canEncode(str.charAt(i)))
+                    problemCharacters.add(new Character(str.charAt(i)));
+            }
+            couldEncodeAll = false;
+        }
+    }
+
+    public boolean couldEncodeAll() {
+        return couldEncodeAll;
+    }
+
+    public String getProblemCharacters() {
+        StringBuffer chars = new StringBuffer();
+        for (Iterator i=problemCharacters.iterator(); i.hasNext();) {
+            chars.append(((Character)i.next()).charValue());
+        }
+        return chars.toString();
+    }
+}
diff --git a/src/java/net/sf/jabref/export/layout/EntryLayout.java b/src/java/net/sf/jabref/export/layout/EntryLayout.java
new file mode 100755
index 0000000..8165fc6
--- /dev/null
+++ b/src/java/net/sf/jabref/export/layout/EntryLayout.java
@@ -0,0 +1,39 @@
+/*
+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;
+
+/**
+ * DOCUMENT ME!
+ *
+ * @author $author$
+ * @version $Revision: 1.1 $
+ */
+public class EntryLayout
+{
+}
+///////////////////////////////////////////////////////////////////////////////
+//  END OF FILE.
+///////////////////////////////////////////////////////////////////////////////
diff --git a/src/java/net/sf/jabref/export/layout/FieldLayout.java b/src/java/net/sf/jabref/export/layout/FieldLayout.java
new file mode 100755
index 0000000..1432d42
--- /dev/null
+++ b/src/java/net/sf/jabref/export/layout/FieldLayout.java
@@ -0,0 +1,39 @@
+/*
+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;
+
+/**
+ * DOCUMENT ME!
+ *
+ * @author $author$
+ * @version $Revision: 1.1 $
+ */
+public class FieldLayout
+{
+}
+///////////////////////////////////////////////////////////////////////////////
+//  END OF FILE.
+///////////////////////////////////////////////////////////////////////////////
diff --git a/src/java/net/sf/jabref/export/layout/FieldLayoutFormatter.java b/src/java/net/sf/jabref/export/layout/FieldLayoutFormatter.java
new file mode 100755
index 0000000..723b6dc
--- /dev/null
+++ b/src/java/net/sf/jabref/export/layout/FieldLayoutFormatter.java
@@ -0,0 +1,42 @@
+/*
+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;
+
+/**
+ * DOCUMENT ME!
+ *
+ * @author $author$
+ * @version $Revision: 1.1 $
+ */
+public interface FieldLayoutFormatter
+{
+    //~ Methods ////////////////////////////////////////////////////////////////
+
+    public String format(String s);
+}
+///////////////////////////////////////////////////////////////////////////////
+//  END OF FILE.
+///////////////////////////////////////////////////////////////////////////////
diff --git a/src/java/net/sf/jabref/export/layout/Layout.java b/src/java/net/sf/jabref/export/layout/Layout.java
new file mode 100755
index 0000000..c01c3f6
--- /dev/null
+++ b/src/java/net/sf/jabref/export/layout/Layout.java
@@ -0,0 +1,266 @@
+/*
+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;
+
+import wsi.ra.types.StringInt;
+
+import java.util.Vector;
+
+import net.sf.jabref.BibtexDatabase;
+import net.sf.jabref.BibtexEntry;
+import java.io.IOException;
+
+
+/**
+ * DOCUMENT ME!
+ *
+ * @author $author$
+ * @version $Revision: 1.7 $
+ */
+public class Layout
+{
+    //~ Instance fields ////////////////////////////////////////////////////////
+
+    private LayoutEntry[] layoutEntries;
+
+    //~ Constructors ///////////////////////////////////////////////////////////
+
+    public Layout(Vector parsedEntries, String classPrefix)  throws Exception
+    {
+        StringInt si;
+        Vector tmpEntries = new Vector(parsedEntries.size());
+
+        //layoutEntries=new LayoutEntry[parsedEntries.size()];
+        Vector blockEntries = null;
+        LayoutEntry le;
+        String blockStart = null;
+
+        for (int i = 0; i < parsedEntries.size(); i++)
+        {
+            si = (StringInt) parsedEntries.get(i);
+
+            //System.out.println("PARSED: "+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)
+            {
+                blockEntries = new Vector();
+                blockStart = si.s;
+            }
+            else if (si.i == LayoutHelper.IS_FIELD_END)
+            {
+                if (blockStart.equals(si.s))
+                {
+                    blockEntries.add(si);
+                    le = new LayoutEntry(blockEntries, classPrefix, LayoutHelper.IS_FIELD_START);
+                    tmpEntries.add(le);
+                    blockEntries = null;
+                }
+                else
+                {
+                    System.out.println(
+                        "Nested field entries are not implemented !!!");
+                    //System.out.println("..."+blockStart+"..."+si.s+"...");
+                    Thread.dumpStack();
+                }
+            }
+            else if (si.i == LayoutHelper.IS_GROUP_START)
+            {
+                blockEntries = new Vector();
+                blockStart = si.s;
+            }
+            else if (si.i == LayoutHelper.IS_GROUP_END)
+            {
+                if (blockStart.equals(si.s))
+                {
+                    blockEntries.add(si);
+                    le = new LayoutEntry(blockEntries, classPrefix, LayoutHelper.IS_GROUP_START);
+                    tmpEntries.add(le);
+                    blockEntries = null;
+                } else
+                {
+                    System.out.println(
+                        "Nested field entries are not implemented !!!");
+                    Thread.dumpStack();
+
+                }                
+            }
+            else if (si.i == LayoutHelper.IS_OPTION_FIELD)
+            {
+            }
+
+            //			else if (si.i == LayoutHelper.IS_OPTION_FIELD_PARAM)
+            //			{
+            //			}
+            if (blockEntries == null)
+            {
+                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 ////////////////////////////////////////////////////////////////
+
+    /**
+     * Returns the processed bibtex entry. If the database argument is
+     * null, no string references will be resolved. Otherwise all valid
+     * string references will be replaced by the strings' contents. Even
+     * recursive string references are resolved.
+     */
+    public String doLayout(BibtexEntry bibtex, BibtexDatabase database)
+    {
+        //System.out.println("LAYOUT: " + bibtex.getId());
+        StringBuffer sb = new StringBuffer(100);
+        String fieldText;
+        boolean previousSkipped = false;
+
+        for (int i = 0; i < layoutEntries.length; i++)
+        {
+            fieldText = layoutEntries[i].doLayout(bibtex, database);
+
+            // 2005.05.05 M. Alver
+            // The following change means we treat null fields as "". This is to fix the
+            // problem of whitespace disappearing after missing fields. Hoping there are
+            // no side effects.
+            if (fieldText == null)
+                fieldText = "";
+            /*if (fieldText == null)
+            {
+                if ((i + 1) < layoutEntries.length)
+                {
+                    if (layoutEntries[i + 1].doLayout(bibtex, database).trim().length() == 0)
+                    {
+                        //sb.append("MISSING");
+                        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();
+    }
+    
+    // added section - begin (arudert)
+    // note: string resolving not implemented yet
+    /**
+     * Returns the processed text. If the database argument is
+     * null, no string references will be resolved. Otherwise all valid
+     * string references will be replaced by the strings' contents. Even
+     * recursive string references are resolved.
+     */
+    public String doLayout(BibtexDatabase database)
+    {
+        //System.out.println("LAYOUT: " + bibtex.getId());
+        StringBuffer sb = new StringBuffer(100);
+        String fieldText;
+        boolean previousSkipped = false;
+
+        for (int i = 0; i < layoutEntries.length; i++)
+        {
+            fieldText = layoutEntries[i].doLayout(database);
+
+            if (fieldText == null) 
+            {
+                fieldText = "";
+                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
+            {
+                sb.append(fieldText);
+            }
+
+            previousSkipped = false;
+        }
+
+        return sb.toString();
+    }
+    // added section - end (arudert)
+}
+///////////////////////////////////////////////////////////////////////////////
+//  END OF FILE.
+///////////////////////////////////////////////////////////////////////////////
diff --git a/src/java/net/sf/jabref/export/layout/LayoutEntry.java b/src/java/net/sf/jabref/export/layout/LayoutEntry.java
new file mode 100755
index 0000000..dbfb840
--- /dev/null
+++ b/src/java/net/sf/jabref/export/layout/LayoutEntry.java
@@ -0,0 +1,447 @@
+/*
+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;
+
+import wsi.ra.tool.WSITools;
+
+import wsi.ra.types.StringInt;
+
+import java.util.Vector;
+
+import net.sf.jabref.BibtexDatabase;
+import net.sf.jabref.BibtexEntry;
+import net.sf.jabref.Globals;
+
+
+/**
+ * DOCUMENT ME!
+ *
+ * @author $author$
+ * @version $Revision: 1.8 $
+ */
+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) {
+      String res = (String)bibtex.getField(field);
+	    if ((res != null) && (database != null))
+		res = database.resolveForStrings(res);
+	    return res;
+    }
+}
+///////////////////////////////////////////////////////////////////////////////
+//  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
new file mode 100755
index 0000000..97a4a64
--- /dev/null
+++ b/src/java/net/sf/jabref/export/layout/LayoutFormatter.java
@@ -0,0 +1,42 @@
+/*
+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;
+
+/**
+ * DOCUMENT ME!
+ *
+ * @author $author$
+ * @version $Revision: 1.1 $
+ */
+public interface LayoutFormatter
+{
+    //~ Methods ////////////////////////////////////////////////////////////////
+
+    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
new file mode 100755
index 0000000..10b140e
--- /dev/null
+++ b/src/java/net/sf/jabref/export/layout/LayoutHelper.java
@@ -0,0 +1,672 @@
+/*
+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.
+
+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;
+
+import wsi.ra.types.StringInt;
+
+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.Vector;
+
+
+/**
+ * DOCUMENT ME!
+ *
+ * @author $author$
+ * @version $Revision: 1.7 $
+ */
+public class LayoutHelper
+{
+    //~ Static fields/initializers /////////////////////////////////////////////
+
+    public static final int IS_LAYOUT_TEXT = 1;
+    public static final int IS_SIMPLE_FIELD = 2;
+    public static final int IS_FIELD_START = 3;
+    public static final int IS_FIELD_END = 4;
+    public static final int IS_OPTION_FIELD = 5;
+    public static final int IS_GROUP_START = 6;
+    public static final int IS_GROUP_END = 7;
+    private static String currentGroup = null;
+    
+    //~ Instance fields ////////////////////////////////////////////////////////
+
+
+    //public static final int IS_OPTION_FIELD_PARAM = 6;
+    private PushbackReader _in;
+    private Vector parsedEntries = new Vector();
+
+    //private HashMap _meta;
+    private boolean _eof = false;
+    private int line = 1;
+
+    //~ Constructors ///////////////////////////////////////////////////////////
+
+    public LayoutHelper(Reader in)
+    {
+
+        if (in == null)
+        {
+            throw new NullPointerException();
+        }
+
+        _in = new PushbackReader(in);
+    }
+
+    //~ Methods ////////////////////////////////////////////////////////////////
+
+    public Layout getLayoutFromText(String classPrefix) throws Exception
+    {
+        parse();
+
+        StringInt si;
+
+        for (int i = 0; i < parsedEntries.size(); i++)
+        {
+            si = (StringInt) parsedEntries.get(i);
+
+            if ((si.i == IS_SIMPLE_FIELD) || (si.i == IS_FIELD_START) ||
+                    (si.i == IS_FIELD_END) || (si.i == IS_GROUP_START) ||
+                    (si.i == IS_GROUP_END))
+            {
+                si.s = si.s.trim().toLowerCase();
+            }
+        }
+
+        Layout layout = new Layout(parsedEntries, classPrefix);
+
+        return layout;
+    }
+
+    
+    public static String getCurrentGroup() {
+        return currentGroup;
+    }
+    
+    public static void setCurrentGroup(String newGroup) {
+        currentGroup = newGroup;
+    }
+    
+    /**
+     *
+     */
+    private String getBracketedField(int _field) throws IOException
+    {
+        StringBuffer buffer = null;
+        int previous = -1;
+        int c;
+        boolean start = false;
+
+        while (!_eof)
+        {
+            c = read();
+
+            //System.out.println((char)c);
+            if (c == -1)
+            {
+                _eof = true;
+
+                if (buffer != null)
+                {
+                    //myStrings.add(buffer.toString());
+                    parsedEntries.add(new StringInt(buffer.toString(), _field));
+
+                    //System.out.println("\nbracketedEOF: " + buffer.toString());
+                }
+
+                //myStrings.add(buffer.toString());
+                //System.out.println("aha: " + buffer.toString());
+                return null;
+            }
+
+            if ((c == '{') || (c == '}'))
+            {
+                if (c == '}')
+                {
+                    if (buffer != null)
+                    {
+                        //myStrings.add(buffer.toString());
+                        parsedEntries.add(new StringInt(buffer.toString(),
+                                _field));
+
+                        //System.out.println("\nbracketed: " + buffer.toString());
+                        return null;
+                    }
+                }
+                else
+                {
+                    start = true;
+                }
+            }
+            else
+            {
+                if (buffer == null)
+                {
+                    buffer = new StringBuffer(100);
+                }
+
+                if (start)
+                {
+                    if (c == '}')
+                    {
+                    }
+                    else
+                    {
+                        buffer.append((char) c);
+                    }
+                }
+            }
+
+            previous = c;
+        }
+
+        return null;
+    }
+
+    /**
+     *
+     */
+    private String getBracketedOptionField(int _field)
+        throws IOException
+    {
+        StringBuffer buffer = null;
+        int previous = -1;
+        int c;
+        boolean start = false;
+        String option = null;
+        String tmp;
+
+        while (!_eof)
+        {
+            c = read();
+
+            //System.out.println((char)c);
+            if (c == -1)
+            {
+                _eof = true;
+
+                if (buffer != null)
+                {
+                    //myStrings.add(buffer.toString());
+                    if (option != null)
+                    {
+                        tmp = buffer.toString() + "\n" + option;
+                    }
+                    else
+                    {
+                        tmp = buffer.toString();
+                    }
+
+                    parsedEntries.add(new StringInt(tmp, IS_OPTION_FIELD));
+
+                    //System.out.println("\nbracketedOptionEOF: " + buffer.toString());
+                }
+
+                return null;
+            }
+
+            if ((c == '{') || (c == '}') || (c == ']') || (c == '['))
+            {
+                if ((c == '}') || (c == ']'))
+                {
+                    // changed section start - arudert
+                    // buffer may be null for parameters
+                    //if (buffer != null)
+                    //{
+                        if (c == ']' && buffer != null)
+                        {
+                    // changed section end - arudert
+                            option = buffer.toString();
+                            buffer = null;
+                            start = false;
+                        }
+
+                        //myStrings.add(buffer.toString());
+                        //System.out.println("\nbracketedOption: " + buffer.toString());
+                        
+                        // changed section begin - arudert
+                        // bracketed option must be followed by an (optionally empty) parameter
+                        // if empty, the parameter is set to " " (whitespace to avoid that the tokenizer that
+                        // splits the string later on ignores the empty parameter)
+                        //if (buffer != null)
+                        else if (c == '}')
+                        {
+                           String parameter = buffer == null ? " " : buffer.toString();
+                           if (option != null)
+                            {
+                                tmp = parameter + "\n" + option;
+                            }
+                            else
+                            {
+                                tmp = parameter;
+                            }
+
+                            //System.out.println("FORMAT: '"+tmp+"'");
+                            parsedEntries.add(new StringInt(tmp, IS_OPTION_FIELD));
+
+                            return null;
+                        }
+                        // changed section end - arudert
+                     // changed section start - arudert
+                     // }
+                     // changed section end - arudert
+                }
+                else
+                {
+                    start = true;
+                }
+            }
+            else
+            {
+                if (buffer == null)
+                {
+                    buffer = new StringBuffer(100);
+                }
+
+                if (start)
+                {
+                  
+                    if ((c == '}') || (c == ']'))
+                    {
+                    }
+                    else
+                    {
+                        // changed section begin - arudert
+                        // keep the backslash so we know wether this is a fieldname or an ordinary parameter
+                        //if (c != '\\')
+                        //{
+                            buffer.append((char) c);
+                        //}
+                        // changed section end - arudert
+                    }
+                }
+            }
+
+            previous = c;
+        }
+
+        return null;
+    }
+
+    private Object parse() throws IOException
+    {
+        //_meta = new HashMap(); // Metadata in comments for Bibkeeper.
+        skipWhitespace();
+
+        int c;
+
+        StringBuffer buffer = null;
+        int previous = -1;
+        boolean justParsedTag = false;
+
+        while (!_eof)
+        {
+            c = read();
+
+            //System.out.println((char)c);
+            if (c == -1)
+            {
+                _eof = true;
+                parsedEntries.add(new StringInt(buffer.toString(),
+                        IS_LAYOUT_TEXT));
+
+                //System.out.println("aha: " + buffer.toString());
+                return null;
+            }
+
+            if ((c == '\\') && (peek() != '\\') && (justParsedTag || (previous != '\\')))
+            {
+                if (buffer != null)
+                {
+                    parsedEntries.add(new StringInt(buffer.toString(),
+                            IS_LAYOUT_TEXT));
+                    
+                    buffer = null;
+                }
+
+                parseField();
+
+                // To make sure the next character, if it is a backslash, doesn't get ignored,
+                // since "previous" now holds a backslash:
+                justParsedTag = true;
+
+            }
+            else
+            {
+                justParsedTag = false;
+
+                if (buffer == null)
+                {
+                    buffer = new StringBuffer(100);
+                }
+
+                if (!((c == '\\') && (previous == '\\')))
+                {
+                    buffer.append((char) c);
+                }
+            }
+
+            previous = c;
+        }
+
+        return null;
+    }
+
+    /**
+     *
+     */
+    private void parseField() throws IOException
+    {
+        int c;
+        StringBuffer buffer = null;
+        String name;
+
+        while (!_eof)
+        {
+            c = read();
+            //System.out.print((char)c);
+            if (c == -1)
+            {
+                _eof = true;
+            }
+
+            if (!Character.isLetter((char) c))
+            {
+                unread(c);
+
+                //System.out.println("\n#" + (char) c);
+                name = buffer != null ? buffer.toString() : "";
+
+                //System.out.println("NAME:" + name);
+                buffer = null;
+
+                if (name.charAt(0) == 'b')
+                {
+                    if (name.equalsIgnoreCase("begin"))
+                    {
+                        // get field name
+                        getBracketedField(IS_FIELD_START);
+
+                        return;
+                    }
+                    else if (name.equalsIgnoreCase("begingroup"))
+                    {
+                        // get field name
+                        getBracketedField(IS_GROUP_START);
+                        return;                    
+                    }
+                }
+                else if (name.charAt(0) == 'f')
+                {
+                    if (name.equalsIgnoreCase("format"))
+                    {
+                        if (c == '[')
+                        {
+                            // get format parameter
+                            // get field name
+                            getBracketedOptionField(IS_OPTION_FIELD);
+
+                            return;
+                        }
+                        else
+                        {
+                            // get field name
+                            getBracketedField(IS_OPTION_FIELD);
+
+                            return;
+                        }
+                    }
+                }
+                else if (name.charAt(0) == 'e')
+                {
+                    if (name.equalsIgnoreCase("end"))
+                    {
+                        // get field name
+                        getBracketedField(IS_FIELD_END);
+                        
+                        return;
+                    }
+                    else if (name.equalsIgnoreCase("endgroup"))
+                    {
+                        // get field name
+                        getBracketedField(IS_GROUP_END);                        
+                    }                                        
+                }
+                
+                // for all other cases
+                parsedEntries.add(new StringInt(name, IS_SIMPLE_FIELD));
+
+                //System.out.println(name);
+                return;
+            }
+            else
+            {
+                if (buffer == null)
+                {
+                    buffer = new StringBuffer(100);
+                }
+
+                buffer.append((char) c);
+            }
+        }
+    }
+
+    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++;
+        }
+
+        //System.out.print((char) c);
+        return c;
+    }
+
+    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
+            {
+                unread(c);
+            }
+
+            break;
+        }
+    }
+
+    private void unread(int c) throws IOException
+    {
+        if (c == '\n')
+        {
+            line--;
+        }
+
+        _in.unread(c);
+    }
+
+    //
+    //	private String parseFieldContent() throws IOException
+    //	{
+    //		skipWhitespace();
+    //		consume('=');
+    //		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 == '"')
+    //			{
+    //				// 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('"');
+    //
+    //			}
+    //			skipWhitespace();
+    //		}
+    //		//Util.pr("Returning field content: "+value.toString());
+    //		return value.toString();
+    //
+    //	}
+    //
+    //	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 (Character.isWhitespace((char) j))
+    //			{
+    //				value.append(' ');
+    //				skipWhitespace();
+    //			}
+    //			else
+    //				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 void consumeUncritically(char expected) throws IOException
+    //	{
+    //		int c;
+    //		while (((c = read()) != expected) && (c != -1) && (c != 65535));
+    //		if ((c == -1) || (c == 65535))
+    //			_eof = true;
+    //	}
+    //
+    //	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);
+    //		}
+    //
+    //	}
+}
+///////////////////////////////////////////////////////////////////////////////
+//  END OF FILE.
+///////////////////////////////////////////////////////////////////////////////
diff --git a/src/java/net/sf/jabref/export/layout/format/AuthorAbbreviator.java b/src/java/net/sf/jabref/export/layout/format/AuthorAbbreviator.java
new file mode 100644
index 0000000..bedf0f3
--- /dev/null
+++ b/src/java/net/sf/jabref/export/layout/format/AuthorAbbreviator.java
@@ -0,0 +1,133 @@
+/*
+ * Created on 12/10/2004
+ */
+package net.sf.jabref.export.layout.format;
+
+import net.sf.jabref.export.layout.LayoutFormatter;
+
+/**
+ * 
+ * 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.
+ * 
+ * @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) 
+	{
+
+		String[] authors = fieldText.split(" and ");
+
+		String abbrev = getAbbreviations(authors);
+		return abbrev;
+
+	}
+				
+	/**
+	 * Abbreviates the names in the Last First format.
+	 * 
+	 * @param authors List of authors or editors.
+	 * @return the names abbreviated.
+	 * @throws RequiredOrderException
+	 * 
+	 */
+	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;
+	}
+
+	/**
+	 * 
+	 * 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
new file mode 100644
index 0000000..10615e4
--- /dev/null
+++ b/src/java/net/sf/jabref/export/layout/format/AuthorAndsCommaReplacer.java
@@ -0,0 +1,44 @@
+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
+ * of more than two authors).
+ *
+ * @author Carlos Silla
+ */
+public class AuthorAndsCommaReplacer implements LayoutFormatter {
+
+    /* (non-Javadoc)
+	 * @see net.sf.jabref.export.layout.LayoutFormatter#format(java.lang.String)
+	 */
+	public String format(String fieldText) {
+
+		String[] authors = fieldText.split(" and ");
+		String s;
+
+		switch(authors.length) {
+			case 1:
+				//Does nothing;
+				s = authors[0];
+			break;
+			case 2:
+				s = authors[0] + " & " + authors[1];
+			break;
+			default:
+				int i = 0, x = authors.length;
+				StringBuffer sb = new StringBuffer();
+
+				for(i=0;i<x-2;i++) {
+                    sb.append(authors[i]).append(", ");
+				}
+                sb.append(authors[i]).append(" & ").append(authors[i + 1]);
+				s = new String(sb);
+			break;
+		}
+
+		return s;
+
+	}
+}
diff --git a/src/java/net/sf/jabref/export/layout/format/AuthorAndsReplacer.java b/src/java/net/sf/jabref/export/layout/format/AuthorAndsReplacer.java
new file mode 100644
index 0000000..092d024
--- /dev/null
+++ b/src/java/net/sf/jabref/export/layout/format/AuthorAndsReplacer.java
@@ -0,0 +1,50 @@
+/*
+ * Created on 10/10/2004
+ * 
+ */
+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
+ * of more than two authors).
+ * 
+ * @author Carlos Silla
+ */
+public class AuthorAndsReplacer implements LayoutFormatter {
+
+	/* (non-Javadoc)
+	 * @see net.sf.jabref.export.layout.LayoutFormatter#format(java.lang.String)
+	 */
+	public String format(String fieldText) {
+
+        if (fieldText == null)
+            return null;
+        String[] authors = fieldText.split(" and ");
+		String s;
+	
+		switch(authors.length) {
+			case 1:
+				//Does nothing;
+				s = authors[0];
+			break;
+			case 2:
+				s = authors[0] + " & " + authors[1];
+			break;
+			default:
+				int i = 0, x = authors.length;
+				StringBuffer sb = new StringBuffer();
+				
+				for(i=0;i<x-2;i++) {
+                    sb.append(authors[i]).append("; ");
+				}
+                sb.append(authors[i]).append(" & ").append(authors[i + 1]);
+				s = new String(sb);				
+			break;		
+		}
+		
+		return s;
+ 
+	}
+}
diff --git a/src/java/net/sf/jabref/export/layout/format/AuthorFirstAbbrLastCommas.java b/src/java/net/sf/jabref/export/layout/format/AuthorFirstAbbrLastCommas.java
new file mode 100644
index 0000000..6b36f9c
--- /dev/null
+++ b/src/java/net/sf/jabref/export/layout/format/AuthorFirstAbbrLastCommas.java
@@ -0,0 +1,26 @@
+/*
+ * AuthorFirstAbbrLastCommas.java
+ *
+ * Created on September 7, 2005, 1:15 PM
+ *
+ * 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
+ */
+public class AuthorFirstAbbrLastCommas implements LayoutFormatter {
+
+    public String format(String fieldText) {
+        return AuthorList.fixAuthor_firstNameFirstCommas(fieldText, 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
new file mode 100644
index 0000000..ecb539c
--- /dev/null
+++ b/src/java/net/sf/jabref/export/layout/format/AuthorFirstFirst.java
@@ -0,0 +1,46 @@
+///////////////////////////////////////////////////////////////////////////////
+//  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.
+///////////////////////////////////////////////////////////////////////////////
+
+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 $
+ */
+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
new file mode 100644
index 0000000..e418e5b
--- /dev/null
+++ b/src/java/net/sf/jabref/export/layout/format/AuthorFirstLastCommas.java
@@ -0,0 +1,26 @@
+/*
+ * AuthorFirstLastCommas.java
+ *
+ * Created on September 7, 2005, 1:06 PM
+ *
+ * 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
+ */
+public class AuthorFirstLastCommas implements LayoutFormatter {
+
+    public String format(String fieldText) {
+        return AuthorList.fixAuthor_firstNameFirstCommas(fieldText, false);
+    }
+
+}
\ 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
new file mode 100644
index 0000000..1a28d06
--- /dev/null
+++ b/src/java/net/sf/jabref/export/layout/format/AuthorLastFirst.java
@@ -0,0 +1,34 @@
+/*  Version:  $Revision: 1.3 $
+              $Date: 2005/10/30 05:59:25 $
+              $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.
+  ///////////////////////////////////////////////////////////////////////////// */
+
+package net.sf.jabref.export.layout.format;
+
+import net.sf.jabref.export.layout.LayoutFormatter;
+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
new file mode 100644
index 0000000..6730b4f
--- /dev/null
+++ b/src/java/net/sf/jabref/export/layout/format/AuthorLastFirstAbbrCommas.java
@@ -0,0 +1,26 @@
+/*
+ * AuthorLastFirstAbbrCommas.java
+ *
+ * Created on September 7, 2005, 1:18 PM
+ *
+ * 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
+ */
+public class AuthorLastFirstAbbrCommas implements LayoutFormatter {
+
+    public String format(String fieldText) {
+        return AuthorList.fixAuthor_lastNameFirstCommas(fieldText, 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
new file mode 100644
index 0000000..2eedef6
--- /dev/null
+++ b/src/java/net/sf/jabref/export/layout/format/AuthorLastFirstAbbreviator.java
@@ -0,0 +1,150 @@
+/*
+ * Created on 12/10/2004
+ */
+package net.sf.jabref.export.layout.format;
+
+import net.sf.jabref.export.layout.LayoutFormatter;
+
+/**
+ * 
+ * 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.
+ * 
+ * @author Carlos Silla
+ */
+public class AuthorLastFirstAbbreviator implements LayoutFormatter {
+
+	/* (non-Javadoc)
+	 * @see net.sf.jabref.export.layout.LayoutFormatter#format(java.lang.String)
+	 */
+	public String format(String fieldText) 
+	{
+
+		String[] authors = fieldText.split(" and ");
+
+		String abbrev = getAbbreviations(authors);
+		return (abbrev==null ? "" : abbrev);
+
+	}
+				
+	/**
+	 * Abbreviates the names in the Last First format.
+	 * 
+	 * @param authors List of authors or editors.
+	 * @return the names abbreviated.
+	 * @throws RequiredOrderException
+	 * 
+	 */
+	private String getAbbreviations(String[] authors)
+	{
+		String s = null;
+		
+		try
+		{
+			verifyProperFormat(authors);
+		
+			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;
+	}
+
+	/**
+	 * Method that verifies if the author names are in the Last First format.
+	 * 
+	 * @param authors List of author or editor names.
+	 * @throws Exception
+	 */
+	private void verifyProperFormat(String[] authors) throws Exception 
+	{
+		int i = 0;
+		
+		for(i=0; i<authors.length; i++)
+		{
+			//If the name contains a space, but does not have the comma it is not in the 
+                        // appropriate format.
+			if((authors[i].indexOf(' ') >= 0) && (authors[i].lastIndexOf(',')==-1))
+			{
+                System.out.println(": '"+authors[i]+"'");
+                            Exception e = new Exception("Error: names must be rearranged in Last, First format before formatted with AuthorLastFirstAbbreviator");
+                            e.printStackTrace();
+                            throw e;
+			}
+		}
+	}
+
+	/**
+	 * 
+	 * Abbreviates all but the last name of the author.
+	 * 
+	 * @param string
+	 * @return
+	 */
+	private String getAbbreviation(String string) {
+		String[] author = string.split(", ");
+                
+                // If there is no comma in the name, we return it as it is:
+		if (author.length < 2)
+                    return string;
+                
+		char c;
+		String s;
+		//Gets the name:
+		StringBuffer sb = new StringBuffer(author[0] + ", ");
+		
+		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
+			String[] nameParts = author[1].split(" ");
+			
+			int i = 0;
+			
+			for(i=0;i<nameParts.length;i++)
+			{
+				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:
+		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/AuthorLastFirstCommas.java b/src/java/net/sf/jabref/export/layout/format/AuthorLastFirstCommas.java
new file mode 100644
index 0000000..b193818
--- /dev/null
+++ b/src/java/net/sf/jabref/export/layout/format/AuthorLastFirstCommas.java
@@ -0,0 +1,26 @@
+/*
+ * AuthorLastFirstCommas.java
+ *
+ * Created on September 7, 2005, 1:17 PM
+ *
+ * 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
+ */
+public class AuthorLastFirstCommas implements LayoutFormatter {
+
+    public String format(String fieldText) {
+        return AuthorList.fixAuthor_lastNameFirstCommas(fieldText, false);
+    }
+
+}
\ No newline at end of file
diff --git a/src/java/net/sf/jabref/export/layout/format/CreateDocBookAuthors.java b/src/java/net/sf/jabref/export/layout/format/CreateDocBookAuthors.java
new file mode 100755
index 0000000..29260ab
--- /dev/null
+++ b/src/java/net/sf/jabref/export/layout/format/CreateDocBookAuthors.java
@@ -0,0 +1,134 @@
+///////////////////////////////////////////////////////////////////////////////
+//  Filename: $RCSfile: CreateDocBookAuthors.java,v $
+//  Purpose:  Atom representation.
+//  Language: Java
+//  Compiler: JDK 1.4
+//  Authors:  Joerg K. Wegner
+//  Version:  $Revision: 1.8 $
+//            $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.
+///////////////////////////////////////////////////////////////////////////////
+package net.sf.jabref.export.layout.format;
+
+import wsi.ra.tool.WSITools;
+
+import java.util.Vector;
+
+import net.sf.jabref.export.layout.LayoutFormatter;
+import net.sf.jabref.AuthorList;
+
+
+/**
+ * Create DocBook authors formatter.
+ *
+ * @author $author$
+ * @version $Revision: 1.8 $
+ */
+public class CreateDocBookAuthors implements LayoutFormatter
+{
+    //~ Methods ////////////////////////////////////////////////////////////////
+
+    public String format(String fieldText)
+    {
+        //		<author><firstname>L.</firstname><surname>Xue</surname></author>
+        //     <author><firstname>F.</firstname><othername role="mi">L.</othername><surname>Stahura</surname></author>
+        //     <author><firstname>J.</firstname><othername role="mi">W.</othername><surname>Godden</surname></author>
+        //     <author><firstname>J.</firstname><surname>Bajorath</surname></author>
+
+        int index = 0;
+        int oldPos = 0;
+        String author;
+        StringBuffer sb = new StringBuffer(100);
+        //fieldText = (new ConvertSpecialCharactersForXML()).format(fieldText);
+
+        if (fieldText.indexOf(" and ") == -1)
+        {
+          sb.append("<author>");
+          singleAuthor(sb, fieldText);
+          sb.append("</author>");
+        }
+        else
+        {
+            String[] names = fieldText.split(" and ");
+            for (int i=0; i<names.length; i++)
+            {
+              sb.append("<author>");
+              singleAuthor(sb, names[i]);
+              sb.append("</author>");
+              if (i < names.length -1)
+                sb.append("\n       ");
+            }
+        }
+
+
+
+        fieldText = sb.toString();
+
+        return fieldText;
+    }
+
+    /**
+     * @param sb
+     * @param fieldText
+     */
+    protected void singleAuthor(StringBuffer sb, String author)
+    {
+        // TODO: replace special characters
+        Vector v = new Vector();
+        String authorMod = AuthorList.fixAuthor_firstNameFirst(author);
+
+        WSITools.tokenize(v, authorMod, " \n\r");
+
+        if (v.size() == 1)
+        {
+            sb.append("<surname>");
+            sb.append(v.get(0));
+            sb.append("</surname>");
+        }
+        else if (v.size() == 2)
+        {
+            sb.append("<firstname>");
+            sb.append(v.get(0));
+            sb.append("</firstname>");
+            sb.append("<surname>");
+            sb.append(v.get(1));
+            sb.append("</surname>");
+        }
+        else
+        {
+            sb.append("<firstname>");
+            sb.append(v.get(0));
+            sb.append("</firstname>");
+            sb.append("<othername role=\"mi\">");
+
+            for (int i = 1; i < (v.size() - 1); i++)
+            {
+                sb.append(v.get(i));
+
+                if (i < (v.size() - 2))
+                {
+                    sb.append(' ');
+                }
+            }
+
+            sb.append("</othername>");
+            sb.append("<surname>");
+            sb.append(v.get(v.size() - 1));
+            sb.append("</surname>");
+        }
+    }
+}
+///////////////////////////////////////////////////////////////////////////////
+//  END OF FILE.
+///////////////////////////////////////////////////////////////////////////////
diff --git a/src/java/net/sf/jabref/export/layout/format/CreateDocBookEditors.java b/src/java/net/sf/jabref/export/layout/format/CreateDocBookEditors.java
new file mode 100755
index 0000000..e147850
--- /dev/null
+++ b/src/java/net/sf/jabref/export/layout/format/CreateDocBookEditors.java
@@ -0,0 +1,79 @@
+///////////////////////////////////////////////////////////////////////////////
+//  Filename: $RCSfile: CreateDocBookEditors.java,v $
+//  Purpose:  Atom representation.
+//  Language: Java
+//  Compiler: JDK 1.4
+//  Authors:  Joerg K. Wegner
+//  Version:  $Revision: 1.1 $
+//            $Date: 2005/01/27 21:28:01 $
+//            $Author: egonw $
+//
+//  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.
+///////////////////////////////////////////////////////////////////////////////
+package net.sf.jabref.export.layout.format;
+
+import wsi.ra.tool.WSITools;
+
+import java.util.Vector;
+
+import net.sf.jabref.export.layout.LayoutFormatter;
+import net.sf.jabref.imports.*;
+
+
+/**
+ * Create DocBook editors formatter.
+ *
+ * @author $author$
+ * @version $Revision: 1.1 $
+ */
+public class CreateDocBookEditors extends CreateDocBookAuthors
+{
+    //~ Methods ////////////////////////////////////////////////////////////////
+
+    public String format(String fieldText)
+    {
+        //		<editor><firstname>L.</firstname><surname>Xue</surname></editor>
+
+        int index = 0;
+        int oldPos = 0;
+        String author;
+        StringBuffer sb = new StringBuffer(100);
+        //fieldText = (new ConvertSpecialCharactersForXML()).format(fieldText);
+
+        if (fieldText.indexOf(" and ") == -1)
+        {
+          sb.append("<editor>");
+          singleAuthor(sb, fieldText);
+          sb.append("</editor>");
+        }
+        else
+        {
+            String[] names = fieldText.split(" and ");
+            for (int i=0; i<names.length; i++)
+            {
+              sb.append("<editor>");
+              singleAuthor(sb, names[i]);
+              sb.append("</editor>");
+              if (i < names.length -1)
+                sb.append("\n       ");
+            }
+        }
+
+        fieldText = sb.toString();
+
+        return fieldText;
+    }
+
+}
+///////////////////////////////////////////////////////////////////////////////
+//  END OF FILE.
+///////////////////////////////////////////////////////////////////////////////
diff --git a/src/java/net/sf/jabref/export/layout/format/CurrentDate.java b/src/java/net/sf/jabref/export/layout/format/CurrentDate.java
new file mode 100644
index 0000000..8e077d8
--- /dev/null
+++ b/src/java/net/sf/jabref/export/layout/format/CurrentDate.java
@@ -0,0 +1,59 @@
+/*
+ Copyright (C) 2005 Andreas Rudert
+
+ 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 java.util.Date;
+import java.text.SimpleDateFormat;
+
+import net.sf.jabref.export.layout.LayoutFormatter;
+
+
+/**
+ * Inserts the current date (the time a database is being exported).
+ * 
+ * <p>If a fieldText is given, it must be a valid {@link SimpleDateFormat} pattern.
+ * If none is given, the format pattern will be <code>yyyy.MM.dd hh:mm:ss z</code></p>
+ *
+ * @author andreas_sf at rudert-home dot de
+ * @version $Revision: 1.1 $
+ */
+public class CurrentDate implements LayoutFormatter
+{
+    private static final String defaultFormat = "yyyy.MM.dd hh:mm:ss z";
+    
+    /*
+     *  (non-Javadoc)
+     * @see net.sf.jabref.export.layout.LayoutFormatter#format(java.lang.String)
+     */ 
+    public String format(String fieldText)
+    {
+      String format = defaultFormat;
+      if (fieldText != null && !"".equals(fieldText.trim())) {
+        format = fieldText;
+      }
+      return new SimpleDateFormat(format).format(new Date());
+    }
+}
diff --git a/src/java/net/sf/jabref/export/layout/format/FormatPagesForHTML.java b/src/java/net/sf/jabref/export/layout/format/FormatPagesForHTML.java
new file mode 100644
index 0000000..01ba1e1
--- /dev/null
+++ b/src/java/net/sf/jabref/export/layout/format/FormatPagesForHTML.java
@@ -0,0 +1,10 @@
+package net.sf.jabref.export.layout.format;
+
+import net.sf.jabref.export.layout.*;
+
+public class FormatPagesForHTML implements LayoutFormatter {
+
+  public String format(String field) {
+    return field.replaceAll("--", "-");
+  }
+}
diff --git a/src/java/net/sf/jabref/export/layout/format/FormatPagesForXML.java b/src/java/net/sf/jabref/export/layout/format/FormatPagesForXML.java
new file mode 100644
index 0000000..c03b42d
--- /dev/null
+++ b/src/java/net/sf/jabref/export/layout/format/FormatPagesForXML.java
@@ -0,0 +1,10 @@
+package net.sf.jabref.export.layout.format;
+
+import net.sf.jabref.export.layout.*;
+
+public class FormatPagesForXML implements LayoutFormatter {
+
+  public String format(String field) {
+    return field.replaceAll("--", "&#x2013;");
+  }
+}
diff --git a/src/java/net/sf/jabref/export/layout/format/GetOpenOfficeType.java b/src/java/net/sf/jabref/export/layout/format/GetOpenOfficeType.java
new file mode 100755
index 0000000..ffb02de
--- /dev/null
+++ b/src/java/net/sf/jabref/export/layout/format/GetOpenOfficeType.java
@@ -0,0 +1,62 @@
+///////////////////////////////////////////////////////////////////////////////
+//  Filename: $RCSfile: GetOpenOfficeType.java,v $
+//  Purpose:  Atom representation.
+//  Language: Java
+//  Compiler: JDK 1.4
+//  Authors:  Joerg K. Wegner
+//  Version:  $Revision: 1.2 $
+//            $Date: 2005/03/06 21:02:19 $
+//            $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.
+///////////////////////////////////////////////////////////////////////////////
+
+package net.sf.jabref.export.layout.format;
+
+import net.sf.jabref.export.layout.LayoutFormatter;
+
+
+/**
+ * Change type of record to match the one used by OpenOffice formatter.
+ * 
+ * Based on the RemoveBrackets.java class (Revision 1.2) by mortenalver
+ * @author $author$
+ * @version $Revision: 1.2 $
+ */
+public class GetOpenOfficeType implements LayoutFormatter
+{
+    //~ Methods ////////////////////////////////////////////////////////////////
+
+    public String format(String fieldText)
+    {
+        String fieldEntry = fieldText;
+		if (fieldEntry.equalsIgnoreCase("Article")) return "7";
+		if (fieldEntry.equalsIgnoreCase("Book")) return "1";
+		if (fieldEntry.equalsIgnoreCase("Booklet")) return "2";
+		if (fieldEntry.equalsIgnoreCase("Inbook")) return "5";
+		if (fieldEntry.equalsIgnoreCase("Incollection")) return "5";
+		if (fieldEntry.equalsIgnoreCase("Inproceedings")) return "6";
+		if (fieldEntry.equalsIgnoreCase("Manual")) return "8";
+		if (fieldEntry.equalsIgnoreCase("Mastersthesis")) return "9";
+		if (fieldEntry.equalsIgnoreCase("Misc")) return "10";
+		if (fieldEntry.equalsIgnoreCase("Other")) return "10";
+		if (fieldEntry.equalsIgnoreCase("Phdthesis")) return "9";
+		if (fieldEntry.equalsIgnoreCase("Proceedings")) return "3";
+		if (fieldEntry.equalsIgnoreCase("Techreport")) return "13";
+		if (fieldEntry.equalsIgnoreCase("Unpublished")) return "14";
+	// Default, Miscelaneous
+		return "10";
+    }
+}
+///////////////////////////////////////////////////////////////////////////////
+//  END OF FILE.
+///////////////////////////////////////////////////////////////////////////////
diff --git a/src/java/net/sf/jabref/export/layout/format/HTMLChars.java b/src/java/net/sf/jabref/export/layout/format/HTMLChars.java
new file mode 100644
index 0000000..e1165f7
--- /dev/null
+++ b/src/java/net/sf/jabref/export/layout/format/HTMLChars.java
@@ -0,0 +1,139 @@
+package net.sf.jabref.export.layout.format;
+
+import net.sf.jabref.export.layout.*;
+import net.sf.jabref.Globals;
+
+public class HTMLChars 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);
+            }
+            Object result = Globals.HTMLCHARS.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("<em>").append(part.s).append("</em>");
+            }
+            else if (command.equals("textbf")) {
+              IntAndString part = getPart(field, i);
+              i += part.i;
+                sb.append("<b>").append(part.s).append("</b>");
+            }
+          } 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.replaceAll("&|\\\\&","&").replaceAll("[\\n]{1,}","<p>");//.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;
+    }
+  }
+}
diff --git a/src/java/net/sf/jabref/export/layout/format/RTFChars.java b/src/java/net/sf/jabref/export/layout/format/RTFChars.java
new file mode 100644
index 0000000..eee15ce
--- /dev/null
+++ b/src/java/net/sf/jabref/export/layout/format/RTFChars.java
@@ -0,0 +1,140 @@
+package net.sf.jabref.export.layout.format;
+
+import net.sf.jabref.export.layout.*;
+import net.sf.jabref.Globals;
+
+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.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;
+    }
+  }
+}
diff --git a/src/java/net/sf/jabref/export/layout/format/RemoveBrackets.java b/src/java/net/sf/jabref/export/layout/format/RemoveBrackets.java
new file mode 100755
index 0000000..2245395
--- /dev/null
+++ b/src/java/net/sf/jabref/export/layout/format/RemoveBrackets.java
@@ -0,0 +1,59 @@
+///////////////////////////////////////////////////////////////////////////////
+//  Filename: $RCSfile: RemoveBrackets.java,v $
+//  Purpose:  Atom representation.
+//  Language: Java
+//  Compiler: JDK 1.4
+//  Authors:  Joerg K. Wegner
+//  Version:  $Revision: 1.2 $
+//            $Date: 2004/01/31 19:27:40 $
+//            $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.
+///////////////////////////////////////////////////////////////////////////////
+
+package net.sf.jabref.export.layout.format;
+
+import net.sf.jabref.export.layout.LayoutFormatter;
+
+
+/**
+ * Remove brackets formatter.
+ *
+ * @author $author$
+ * @version $Revision: 1.2 $
+ */
+public class RemoveBrackets implements LayoutFormatter
+{
+    //~ Methods ////////////////////////////////////////////////////////////////
+
+    public String format(String fieldText)
+    {
+        String fieldEntry = fieldText;
+        StringBuffer sb = new StringBuffer(fieldEntry.length());
+
+        for (int i = 0; i < fieldEntry.length(); i++)
+        {
+            //System.out.print(fieldEntry.charAt(i));
+            if ((fieldEntry.charAt(i) != '{') && (fieldEntry.charAt(i) != '}'))
+            {
+                //System.out.print(fieldEntry.charAt(i));
+                sb.append(fieldEntry.charAt(i));
+            }
+        }
+
+        fieldEntry = sb.toString();
+        return fieldEntry;
+    }
+}
+///////////////////////////////////////////////////////////////////////////////
+//  END OF FILE.
+///////////////////////////////////////////////////////////////////////////////
diff --git a/src/java/net/sf/jabref/export/layout/format/RemoveBracketsAddComma.java b/src/java/net/sf/jabref/export/layout/format/RemoveBracketsAddComma.java
new file mode 100644
index 0000000..a210615
--- /dev/null
+++ b/src/java/net/sf/jabref/export/layout/format/RemoveBracketsAddComma.java
@@ -0,0 +1,64 @@
+///////////////////////////////////////////////////////////////////////////////
+//  Filename: $RCSfile: RemoveBracketsAddComma.java,v $
+//  Purpose:  Atom representation.
+//  Language: Java
+//  Compiler: JDK 1.4
+//  Authors:  Joerg K. Wegner
+//  Version:  $Revision: 1.1 $
+//            $Date: 2005/01/18 20:44:29 $
+//            $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.
+///////////////////////////////////////////////////////////////////////////////
+
+package net.sf.jabref.export.layout.format;
+
+import net.sf.jabref.export.layout.LayoutFormatter;
+
+
+/**
+ * Remove brackets formatter.
+ *
+ * @author $author$
+ * @version $Revision: 1.1 $
+ */
+public class RemoveBracketsAddComma implements LayoutFormatter
+{
+    //~ Methods ////////////////////////////////////////////////////////////////
+
+    public String format(String fieldText)
+    {
+        String fieldEntry = fieldText;
+        StringBuffer sb = new StringBuffer(fieldEntry.length());
+
+        for (int i = 0; i < fieldEntry.length(); i++)
+	    {
+		//System.out.print(fieldEntry.charAt(i));
+		if ((fieldEntry.charAt(i) != '{') && (fieldEntry.charAt(i) != '}'))
+		    {
+			//System.out.print(fieldEntry.charAt(i));
+			sb.append(fieldEntry.charAt(i));
+		    }
+		if (fieldEntry.charAt(i) == '}')
+		    {
+			sb.append(",");
+		    }
+	    }
+	
+        fieldEntry = sb.toString();
+        return fieldEntry;
+    }
+}
+///////////////////////////////////////////////////////////////////////////////
+//  END OF FILE.
+///////////////////////////////////////////////////////////////////////////////
+
diff --git a/src/java/net/sf/jabref/export/layout/format/RemoveLatexCommands.java b/src/java/net/sf/jabref/export/layout/format/RemoveLatexCommands.java
new file mode 100644
index 0000000..93e18d5
--- /dev/null
+++ b/src/java/net/sf/jabref/export/layout/format/RemoveLatexCommands.java
@@ -0,0 +1,110 @@
+package net.sf.jabref.export.layout.format;
+
+import net.sf.jabref.export.layout.*;
+import net.sf.jabref.Globals;
+
+public class RemoveLatexCommands implements LayoutFormatter {
+
+  int i;
+
+  public String format(String 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);
+             }
+             Object result = Globals.HTMLCHARS.get(command+combody);
+             if (result != null)
+               sb.append((String)result);
+ */
+             incommand = false;
+             escaped = false;
+
+           }
+
+        }
+      }
+
+      else if (Character.isLetter((char)c)) {
+        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);
+      }
+      else {
+        //if (!incommand || ((c!='{') && !Character.isWhitespace(c)))
+        if (!incommand || (!Character.isWhitespace(c) && (c != '{')))
+          sb.append((char)c);
+        else {
+          if (c != '{')
+            sb.append((char)c);
+        }
+        incommand = false;
+        escaped = false;
+      }
+    }
+
+    return sb.toString();
+        //field.replaceAll("\\\\emph", "").replaceAll("\\\\em", "").replaceAll("\\\\textbf", "");
+  }
+
+  private String getPart(String text) {
+    char c;
+    boolean found = false;
+    StringBuffer part = new StringBuffer();
+    while (!found && (i < text.length())) {
+      i++;
+      c = text.charAt(i);
+      if (c == '}')
+        found = true;
+      else
+        part.append((char)c);
+    }
+    return part.toString();
+  }
+}
diff --git a/src/java/net/sf/jabref/export/layout/format/RemoveWhitespace.java b/src/java/net/sf/jabref/export/layout/format/RemoveWhitespace.java
new file mode 100755
index 0000000..495f259
--- /dev/null
+++ b/src/java/net/sf/jabref/export/layout/format/RemoveWhitespace.java
@@ -0,0 +1,60 @@
+///////////////////////////////////////////////////////////////////////////////
+//  Filename: $RCSfile: RemoveWhitespace.java,v $
+//  Purpose:  Atom representation.
+//  Language: Java
+//  Compiler: JDK 1.4
+//  Authors:  Joerg K. Wegner
+//  Version:  $Revision: 1.2 $
+//            $Date: 2005/03/06 21:02:19 $
+//            $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.
+///////////////////////////////////////////////////////////////////////////////
+
+package net.sf.jabref.export.layout.format;
+
+import net.sf.jabref.export.layout.LayoutFormatter;
+
+
+/**
+ * Remove non printable character formatter.
+ *
+ * Based on the RemoveBrackets.java class (Revision 1.2) by mortenalver
+ * @author $author$
+ * @version $Revision: 1.2 $
+ */
+public class RemoveWhitespace implements LayoutFormatter
+{
+    //~ Methods ////////////////////////////////////////////////////////////////
+
+    public String format(String fieldText)
+    {
+        String fieldEntry = fieldText;
+        StringBuffer sb = new StringBuffer(fieldEntry.length());
+
+        for (int i = 0; i < fieldEntry.length(); i++)
+        {
+            //System.out.print(fieldEntry.charAt(i));
+            if ( !Character.isWhitespace(fieldEntry.charAt(i)) || Character.isSpaceChar(fieldEntry.charAt(i)))
+            {
+                //System.out.print(fieldEntry.charAt(i));
+                sb.append(fieldEntry.charAt(i));
+            }
+        }
+
+        fieldEntry = sb.toString();
+        return fieldEntry;
+    }
+}
+///////////////////////////////////////////////////////////////////////////////
+//  END OF FILE.
+///////////////////////////////////////////////////////////////////////////////
diff --git a/src/java/net/sf/jabref/export/layout/format/ResolvePDF.java b/src/java/net/sf/jabref/export/layout/format/ResolvePDF.java
new file mode 100644
index 0000000..59fc3d8
--- /dev/null
+++ b/src/java/net/sf/jabref/export/layout/format/ResolvePDF.java
@@ -0,0 +1,16 @@
+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;
+
+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);
+  }
+}
diff --git a/src/java/net/sf/jabref/export/layout/format/ToLowerCase.java b/src/java/net/sf/jabref/export/layout/format/ToLowerCase.java
new file mode 100755
index 0000000..7545e0c
--- /dev/null
+++ b/src/java/net/sf/jabref/export/layout/format/ToLowerCase.java
@@ -0,0 +1,46 @@
+///////////////////////////////////////////////////////////////////////////////
+//  Filename: $RCSfile: ToLowerCase.java,v $
+//  Purpose:  Atom representation.
+//  Language: Java
+//  Compiler: JDK 1.4
+//  Authors:  Egon Willighagen
+//  Version:  $Revision: 1.2 $
+//            $Date: 2004/05/02 16:25:43 $
+//            $Author: mortenalver $
+//
+//  Copyright (c) Egon Willighagen
+//
+//  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.
+///////////////////////////////////////////////////////////////////////////////
+
+package net.sf.jabref.export.layout.format;
+
+import net.sf.jabref.export.layout.LayoutFormatter;
+
+
+/**
+ * Remove brackets formatter.
+ *
+ * @author $author$
+ * @version $Revision: 1.2 $
+ */
+public class ToLowerCase implements LayoutFormatter
+{
+    //~ Methods ////////////////////////////////////////////////////////////////
+
+    public String format(String fieldText)
+    {
+        String fieldEntry = fieldText.toLowerCase();
+       return fieldEntry;
+    }
+}
+///////////////////////////////////////////////////////////////////////////////
+//  END OF FILE.
+///////////////////////////////////////////////////////////////////////////////
diff --git a/src/java/net/sf/jabref/export/layout/format/XMLChars.java b/src/java/net/sf/jabref/export/layout/format/XMLChars.java
new file mode 100644
index 0000000..adc3f1e
--- /dev/null
+++ b/src/java/net/sf/jabref/export/layout/format/XMLChars.java
@@ -0,0 +1,71 @@
+///////////////////////////////////////////////////////////////////////////////
+//  Filename: $RCSfile: XMLChars.java,v $
+//  Purpose:  Atom representation.
+//  Language: Java
+//  Compiler: JDK 1.4
+//  Authors:  Joerg K. Wegner, Morten O. Alver
+//  Version:  $Revision: 1.2 $
+//            $Date: 2004/11/28 23:25:27 $
+//            $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.
+///////////////////////////////////////////////////////////////////////////////
+
+package net.sf.jabref.export.layout.format;
+
+import net.sf.jabref.export.layout.LayoutFormatter;
+import java.util.regex.*;
+import java.util.Iterator;
+import net.sf.jabref.Util;
+import net.sf.jabref.Globals;
+
+/**
+ * Changes {\^o} or {\^{o}} to ?
+ *
+ * @author $author$
+ * @version $Revision: 1.2 $
+ */
+public class XMLChars implements LayoutFormatter
+{
+    //~ Methods ////////////////////////////////////////////////////////////////
+    //Pattern pattern = Pattern.compile(".*\\{..[a-zA-Z].\\}.*");
+    Pattern pattern = Pattern.compile(".*\\{\\\\.*[a-zA-Z]\\}.*");
+
+    public String format(String fieldText)
+    {
+ 
+	fieldText = firstFormat(fieldText);
+
+	//if (!pattern.matcher(fieldText).matches())
+	//    return restFormat(fieldText);
+        
+	for (Iterator i=Globals.HTML_CHARS.keySet().iterator(); i.hasNext();) {
+	    String s = (String)i.next();         
+            String repl = (String)Globals.XML_CHARS.get(s);
+            if (repl != null)
+                fieldText = fieldText.replaceAll(s, repl);
+	}
+	//RemoveBrackets rb = new RemoveBrackets();
+	return restFormat(fieldText);
+    }
+
+    private String firstFormat(String s) {
+	return s.replaceAll("&|\\\\&","&#x0026;").replaceAll("--", "&#x2013;");
+    }
+
+    private String restFormat(String s) {
+	return s.replaceAll("\\}","").replaceAll("\\{","").replaceAll("<", "&#x3c;");
+    }
+}
+///////////////////////////////////////////////////////////////////////////////
+//  END OF FILE.
+///////////////////////////////////////////////////////////////////////////////
diff --git a/src/java/net/sf/jabref/external/AutoSetExternalFileForEntries.java b/src/java/net/sf/jabref/external/AutoSetExternalFileForEntries.java
new file mode 100644
index 0000000..9284e98
--- /dev/null
+++ b/src/java/net/sf/jabref/external/AutoSetExternalFileForEntries.java
@@ -0,0 +1,293 @@
+package net.sf.jabref.external;
+
+import net.sf.jabref.*;
+import net.sf.jabref.gui.AttachFileDialog;
+import net.sf.jabref.undo.NamedCompound;
+import net.sf.jabref.undo.UndoableFieldChange;
+
+import javax.swing.*;
+import java.io.File;
+import java.awt.*;
+import java.awt.event.ActionListener;
+import java.awt.event.ActionEvent;
+
+import com.jgoodies.forms.layout.FormLayout;
+import com.jgoodies.forms.builder.DefaultFormBuilder;
+import com.jgoodies.forms.builder.ButtonBarBuilder;
+
+/**
+ * This action goes through all selected entries in the BasePanel, and attempts to autoset the
+ * given external file (pdf, ps, ...) based on the same algorithm used for the "Auto" button in
+ * EntryEditor.
+ */
+public class AutoSetExternalFileForEntries extends AbstractWorker {
+
+    private String fieldName;
+    private BasePanel panel;
+    private BibtexEntry[] sel = null;
+    private OptionsDialog optDiag = null;
+
+    Object[] brokenLinkOptions =
+        { Globals.lang("Ignore"), Globals.lang("Assign new file"), Globals.lang("Clear field"),
+            Globals.lang("Quit synchronization")};
+
+    private boolean goOn = true, autoSet = true, overWriteAllowed = true, checkExisting = true;
+
+    private int skipped=0, entriesChanged=0, brokenLinks=0;
+
+    public AutoSetExternalFileForEntries(BasePanel panel, String fieldName) {
+        this.fieldName = fieldName;
+        this.panel = panel;
+    }
+
+    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) {
+            goOn = false;
+            return;
+        }
+
+        // Ask about rules for the operation:
+        if (optDiag == null)
+            optDiag = new OptionsDialog(panel.frame(), fieldName);
+        Util.placeDialog(optDiag, panel.frame());
+        optDiag.setVisible(true);
+        if (optDiag.canceled()) {
+            goOn = false;
+            return;
+        }
+        autoSet = !optDiag.autoSetNone.isSelected();
+        overWriteAllowed = optDiag.autoSetAll.isSelected();
+        checkExisting = optDiag.checkLinks.isSelected();
+
+        panel.output(Globals.lang("Synchronizing %0 links...", fieldName.toUpperCase()));
+    }
+
+    public void run() {
+
+        if (!goOn)
+            return;
+
+        skipped=0;
+        entriesChanged=0;
+        brokenLinks=0;
+        NamedCompound ce = new NamedCompound(Globals.lang("Autoset %0 field", fieldName));
+
+        final OpenFileFilter off = Util.getFileFilterForField(fieldName);
+
+        ExternalFilePanel extPan = new ExternalFilePanel(fieldName, null, off);
+        FieldTextField editor = new FieldTextField(fieldName, "", false);
+        String dir = Globals.prefs.get(fieldName+"Directory");
+        // First we try to autoset fields
+        if (autoSet) {
+            for (int i=0; i<sel.length; i++) {
+                final Object old = sel[i].getField(fieldName);
+                // Check if a link is already set, and if so, if we are allowed to overwrite it:
+                if ((old != null) && !old.equals("") && !overWriteAllowed)
+                    continue;
+                extPan.setEntry(sel[i]);
+                editor.setText((old != null) ? (String)old : "");
+                Thread t = extPan.autoSetFile(fieldName, editor);
+                // Wait for the autoset process to finish:
+                if (t != null)
+                    try {
+                        t.join();
+                    } catch (InterruptedException e) {
+                        e.printStackTrace();
+                    }
+                // If something was found, entriesChanged it:
+                if (!editor.getText().equals("") && !editor.getText().equals(old)) {
+                    // Store an undo edit:
+                    //System.out.println("Setting: "+sel[i].getCiteKey()+" "+editor.getText());
+                    ce.addEdit(new UndoableFieldChange(sel[i], fieldName, old, editor.getText()));
+                    sel[i].setField(fieldName, editor.getText());
+                    entriesChanged++;
+                }
+            }
+        }
+        //System.out.println("Done setting");
+        // The following loop checks all external links that are already set.
+        if (checkExisting) {
+            mainLoop: for (int i=0; i<sel.length; i++) {
+                final Object old = sel[i].getField(fieldName);
+                // Check if a link is set:
+                if ((old != null) && !((String)old).equals("")) {
+                    // Get an absolute path representation:
+                    File file = Util.expandFilename((String)old, dir);
+
+                    if ((file == null) || !file.exists()) {
+
+                        int answer =
+                            JOptionPane.showOptionDialog(panel.frame(),
+                            Globals.lang("<HTML>Could not find file '%0'<BR>linked from entry '%1'</HTML>",
+                                new String[] {(String)old, sel[i].getCiteKey()}),
+                                    Globals.lang("Broken link"),
+                                    JOptionPane.YES_NO_CANCEL_OPTION,
+                                    JOptionPane.QUESTION_MESSAGE, null, brokenLinkOptions, brokenLinkOptions[0]);
+                        switch (answer) {
+                            case 1:
+                                // Assign new file.
+                                AttachFileDialog afd = new AttachFileDialog(panel.frame(), sel[i], fieldName);
+                                Util.placeDialog(afd, panel.frame());
+                                afd.setVisible(true);
+                                if (!afd.cancelled()) {
+                                    ce.addEdit(new UndoableFieldChange(sel[i], fieldName, old, afd.getValue()));
+                                    sel[i].setField(fieldName, afd.getValue());
+                                    entriesChanged++;
+                                }
+                                break;
+                            case 2:
+                                 // Clear field
+                                ce.addEdit(new UndoableFieldChange(sel[i], fieldName, old, null));
+                                sel[i].setField(fieldName, null);
+                                entriesChanged++;
+                                break;
+                            case 3:
+                                // Cancel
+                                break mainLoop;
+                        }
+                        brokenLinks++;
+                    }
+
+                    continue;
+                }
+            }
+        }
+
+        if (entriesChanged > 0) {
+            // Add the undo edit:
+            ce.end();
+            panel.undoManager.addEdit(ce);
+        }
+    }
+
+    public void update() {
+        if (!goOn)
+            return;
+
+        panel.output(Globals.lang("Finished synchronizing %0 links. Entries changed%c %1.",
+                new String[] {fieldName.toUpperCase(), String.valueOf(entriesChanged)}));
+        if (entriesChanged > 0) {
+            panel.markBaseChanged();
+        }
+    }
+
+    static class OptionsDialog extends JDialog {
+        JRadioButton autoSetUnset, autoSetAll, autoSetNone;
+        JCheckBox checkLinks;
+        JButton ok = new JButton(Globals.lang("Ok")),
+            cancel = new JButton(Globals.lang("Cancel"));
+        JLabel description;
+        private boolean canceled = true;
+        private String fieldName;
+
+        public OptionsDialog(JFrame parent, String fieldName) {
+            super(parent, Globals.lang("Synchronize %0 links", fieldName.toUpperCase()), true);
+            final String fn = fieldName.toUpperCase();
+            this.fieldName = fieldName;
+            ok.addActionListener(new ActionListener () {
+                public void actionPerformed(ActionEvent e) {
+                    canceled = false;
+                    dispose();
+                }
+            });
+
+            Action closeAction = new AbstractAction () {
+                public void actionPerformed(ActionEvent e) {
+                    dispose();
+                }
+            };
+
+
+            cancel.addActionListener(closeAction);
+
+            InputMap im = cancel.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
+	        ActionMap am = cancel.getActionMap();
+            im.put(Globals.prefs.getKey("Close dialog"), "close");
+	        am.put("close", closeAction);
+
+            fieldName = fieldName.toUpperCase();
+            autoSetUnset =  new JRadioButton(Globals.lang("Autoset %0 links. Do not overwrite existing links.", fn), true);
+            autoSetAll =  new JRadioButton(Globals.lang("Autoset %0 links. Allow overwriting existing links.", fn), false);
+            autoSetNone =  new JRadioButton(Globals.lang("Do not autoset"), false);
+            checkLinks = new JCheckBox(Globals.lang("Check existing %0 links", fn), true);
+            ButtonGroup bg = new ButtonGroup();
+            bg.add(autoSetUnset);
+            bg.add(autoSetNone);
+            bg.add(autoSetAll);
+            FormLayout layout = new FormLayout("fill:pref","");
+	        DefaultFormBuilder builder = new DefaultFormBuilder(layout);
+            description = new JLabel("<HTML>"+
+                    Globals.lang(//"This function helps you keep your external %0 links up-to-date." +
+                            "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.", fn)
+                    +"</HTML>");
+            //            description.setVerticalAlignment(JLabel.TOP);
+            builder.appendSeparator(Globals.lang("Autoset"));
+            builder.append(description);
+            builder.nextLine();
+            builder.append(autoSetUnset);
+            builder.nextLine();
+            builder.append(autoSetAll);
+            builder.nextLine();
+            builder.append(autoSetNone);
+            builder.nextLine();
+            builder.appendSeparator(Globals.lang("Check links"));
+
+            description = new JLabel("<HTML>"+
+                    Globals.lang("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.", fn)
+                +"</HTML>");
+            builder.append(description);
+            builder.nextLine();
+            builder.append(checkLinks);
+            builder.nextLine();
+            builder.appendSeparator();
+
+
+
+            JPanel main = builder.getPanel();
+            main.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+
+            ButtonBarBuilder bb = new ButtonBarBuilder();
+            bb.addGlue();
+            bb.addGridded(ok);
+            bb.addGridded(cancel);
+            bb.addGlue();
+            getContentPane().add(main, BorderLayout.CENTER);
+            getContentPane().add(bb.getPanel(), BorderLayout.SOUTH);
+
+            pack();
+        }
+
+        public void setVisible(boolean visible) {
+            if (visible)
+                canceled = true;
+
+            String dir = Globals.prefs.get(fieldName+"Directory");
+            if ((dir == null) || (dir.trim().length() == 0)) {
+
+                autoSetNone.setSelected(true);
+                autoSetNone.setEnabled(false);
+                autoSetAll.setEnabled(false);
+                autoSetUnset.setEnabled(false);
+            }
+            else {
+                autoSetNone.setEnabled(true);
+                autoSetAll.setEnabled(true);
+                autoSetUnset.setEnabled(true);
+            }
+
+            new FocusRequester(ok);
+            super.setVisible(visible);
+
+        }
+
+        public boolean canceled() {
+            return canceled;
+        }
+    }
+}
diff --git a/src/java/net/sf/jabref/external/ExternalFilePanel.java b/src/java/net/sf/jabref/external/ExternalFilePanel.java
new file mode 100644
index 0000000..8dfaf52
--- /dev/null
+++ b/src/java/net/sf/jabref/external/ExternalFilePanel.java
@@ -0,0 +1,273 @@
+package net.sf.jabref.external;
+
+import net.sf.jabref.*;
+import net.sf.jabref.net.URLDownload;
+
+import javax.swing.*;
+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;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: alver
+ * Date: May 7, 2005
+ * Time: 7:17:42 PM
+ * To change this template use File | Settings | File Templates.
+ */
+public class ExternalFilePanel extends JPanel {
+
+    private JButton browseBut, download, auto;
+    private EntryEditor entryEditor;
+    private JabRefFrame frame;
+    private OpenFileFilter off;
+    private BibtexEntry entry = null;
+
+    public ExternalFilePanel(final String fieldName, final BibtexEntry entry, final OpenFileFilter off) {
+        this(null, null, fieldName, off, null);
+        this.entry = entry;
+    }
+
+    public ExternalFilePanel(final JabRefFrame frame, final EntryEditor entryEditor,
+                             final String fieldName, final OpenFileFilter off, final FieldEditor editor) {
+
+        this.frame = frame;
+        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(Globals.KEY_FIELD) :
+            entryEditor.getEntry().getField(Globals.KEY_FIELD));
+    }
+
+    protected void output(String s) {
+        if (frame != null)
+            frame.output(s);
+    }
+
+    public void browseFile(final String fieldName, final FieldEditor editor) {
+        String directory = Globals.prefs.get(fieldName+"Directory");
+        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, Globals.prefs, 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;
+
+                public Downloader(String res) {
+                    this.res = res;
+                }
+
+                public void run() {
+                    URL url;
+                    String textToSet = editor.getText();
+                    editor.setEnabled(false);
+                    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;
+                        }
+                        File file = new File(new File(Globals.prefs.get(fieldName+"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());
+                        }
+
+                        output(Globals.lang("Download completed"));
+                        String filename = file.getPath();
+                        //System.out.println(filename);
+                        String directory = Globals.prefs.get(fieldName+"Directory");
+                        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;
+                       //editor.setText(filename);
+                        SwingUtilities.invokeLater(new Thread() {
+                            public void run() {
+                                if (entryEditor != null)
+                                    entryEditor.updateField(editor);
+                            }
+                        });
+                    } catch (MalformedURLException e1) {
+                        JOptionPane.showMessageDialog(parent, "Invalid URL: "+e1.getMessage(),
+                                "Download file", JOptionPane.ERROR_MESSAGE);
+                    } finally {
+                        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();
+                String found = Util.findPdf((String) o, fieldName, Globals.prefs.get(fieldName+"Directory"), 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;
+
+    }
+
+}
diff --git a/src/java/net/sf/jabref/external/PushToEmacs.java b/src/java/net/sf/jabref/external/PushToEmacs.java
new file mode 100644
index 0000000..cbdcd56
--- /dev/null
+++ b/src/java/net/sf/jabref/external/PushToEmacs.java
@@ -0,0 +1,87 @@
+package net.sf.jabref.external;
+
+import net.sf.jabref.BaseAction;
+import net.sf.jabref.Globals;
+import net.sf.jabref.BasePanel;
+
+import javax.swing.*;
+import java.util.List;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.InputStream;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: alver
+ * Date: Jan 14, 2006
+ * Time: 4:55:23 PM
+ * To change this template use File | Settings | File Templates.
+ */
+public class PushToEmacs extends BaseAction {
+
+    private BasePanel panel;
+
+    public PushToEmacs(BasePanel panel) {
+        this.panel = panel;
+    }
+
+    public void action() {
+
+        int numSelected = panel.mainTable.getSelectedRowCount();
+
+        if (numSelected > 0) {
+            String keys = panel.getKeysForSelection();
+            StringBuffer command = new StringBuffer("(insert\"\\\\")
+                    .append(Globals.prefs.get("citeCommand")).append("{");
+            if (keys.length() == 0)
+                panel.output(Globals.lang("Please define BibTeX key first"));
+            else {
+                try {
+                    command.append(keys);
+                    command.append("}\")");
+                    String[] com = new String[]{"gnuclient", "-batch", "-eval",
+                        command.toString()};
+                    final Process p = Runtime.getRuntime().exec(com);
+
+                    Runnable errorListener = new Runnable() {
+                        public void run() {
+                            InputStream out = p.getErrorStream();
+                            int c;
+                            StringBuffer sb = new StringBuffer();
+                            try {
+                                while ((c = out.read()) != -1)
+                                    sb.append((char) c);
+                            } catch (IOException e) {
+                                e.printStackTrace();
+                            }
+                            // Error stream has been closed. See if there were any errors:
+                            if (sb.toString().trim().length() > 0) {
+                                JOptionPane.showMessageDialog(
+                                        panel.frame(),
+                                        "<HTML>"+
+                                        Globals.lang("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').")
+                                        +"</HTML>",
+                                        Globals.lang("Error"), JOptionPane.ERROR_MESSAGE);
+                            }
+                            else {
+                                panel.output(Globals.lang("Pushed citations to Emacs"));
+                            }
+                        }
+                    };
+                    (new Thread(errorListener)).start();
+
+                }
+                catch (IOException excep) {
+                    JOptionPane.showMessageDialog(
+                        panel.frame(),
+                        Globals.lang("Could not run the 'gnuclient' program. Make sure you have "
+                        +"the gnuserv/gnuclient programs installed."),
+                        Globals.lang("Error"), JOptionPane.ERROR_MESSAGE);
+                }
+            }
+        }
+    }
+}
+
diff --git a/src/java/net/sf/jabref/external/PushToLyx.java b/src/java/net/sf/jabref/external/PushToLyx.java
new file mode 100644
index 0000000..7c790be
--- /dev/null
+++ b/src/java/net/sf/jabref/external/PushToLyx.java
@@ -0,0 +1,94 @@
+package net.sf.jabref.external;
+
+import net.sf.jabref.*;
+import java.io.*;
+import java.awt.event.*;
+
+public class PushToLyx extends BaseAction {
+
+    private BasePanel panel;
+
+    public PushToLyx(BasePanel panel) {
+	this.panel = panel;
+    }
+
+    public void action() {
+	final BibtexEntry[] entries = panel.getSelectedEntries();
+	if (entries == null)
+	    return;
+	final int numSelected = entries.length;
+	// Globals.logger("Pushing " +numSelected+(numSelected>1? " entries" : "entry") + " to LyX");
+	// check if lyxpipe is defined
+	final File lyxpipe = new File( Globals.prefs.get("lyxpipe") +".in"); // this needs to fixed because it gives "asdf" when going prefs.get("lyxpipe")
+	if( !lyxpipe.exists() || !lyxpipe.canWrite()){
+	    panel.output(Globals.lang("Error")+": "+Globals.lang("verify that LyX is running and that the lyxpipe is valid")
+		   +". [" + Globals.prefs.get("lyxpipe") +"]");
+	    return;
+	}
+	//Util.pr("tre");
+	if( numSelected > 0){
+	    Thread pushThread = new Thread()
+		{
+		    public void run()
+		    {
+			try {
+                            FileWriter fw = new FileWriter(lyxpipe);
+                            BufferedWriter lyx_out = new BufferedWriter(fw);
+                            String citeStr = "", citeKey = "", message = "";
+                            for (int i = 0; i < numSelected; i++)
+				{
+				    BibtexEntry bes = entries[i];//database.getEntryById(tableModel.getNameFromNumber(rows[
+				    //													      i]));
+				    citeKey = (String) bes.getField(GUIGlobals.KEY_FIELD);
+				    // if the key is empty we give a warning and ignore this entry
+				    if (citeKey == null || citeKey.equals(""))
+					continue;
+				    if (citeStr.equals(""))
+					citeStr = citeKey;
+				    else
+					citeStr += "," + citeKey;
+				    if (i > 0)
+					message += ", ";
+				    //message += (1 + rows[i]);
+				}
+                            if (citeStr.equals(""))
+				panel.output(Globals.lang("Please define BibTeX key first"));
+                            else
+				{
+				    citeStr = "LYXCMD:sampleclient:citation-insert:" + citeStr;
+				    lyx_out.write(citeStr + "\n");
+				    panel.output(Globals.lang("Pushed the citations for the following rows to")+" Lyx: " +
+					   message);
+				}
+                            lyx_out.close();
+			    
+			}
+			catch (IOException excep) {
+                            panel.output(Globals.lang("Error")+": "+Globals.lang("unable to write to")+" " + Globals.prefs.get("lyxpipe") +
+                                   ".in");
+			}
+			// catch (InterruptedException e2) {}
+		    }
+		};
+	    pushThread.start();
+	    Timeout t = new Timeout(2000, pushThread, Globals.lang("Error")+": "+
+				    Globals.lang("unable to access LyX-pipe"));
+	    t.start();
+	}
+    }
+
+  class Timeout extends javax.swing.Timer
+  {
+    public Timeout(int timeout, final Thread toStop, final String message) {
+      super(timeout, new ActionListener() {
+        public void actionPerformed(ActionEvent e) {
+          toStop.stop();         // !!! <- deprecated
+          // toStop.interrupt(); // better ?, interrupts wait and IO
+          //stop();
+          //output(message);
+        }
+      });
+    }
+  }
+
+}
diff --git a/src/java/net/sf/jabref/groups/AbstractGroup.java b/src/java/net/sf/jabref/groups/AbstractGroup.java
new file mode 100644
index 0000000..9162d88
--- /dev/null
+++ b/src/java/net/sf/jabref/groups/AbstractGroup.java
@@ -0,0 +1,213 @@
+/*
+ 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.groups;
+
+import java.util.Map;
+
+import javax.swing.undo.AbstractUndoableEdit;
+
+import net.sf.jabref.*;
+
+/**
+ * A group of BibtexEntries.
+ */
+public abstract class AbstractGroup {
+	/** The group's name (every type of group has one). */
+	protected String m_name;
+
+	/**
+	 * The hierarchical context of the group (INDEPENDENT, REFINING, or
+	 * INCLUDING). Defaults to INDEPENDENT, which will be used if and
+	 * only if the context specified in the constructor is invalid.
+	 */
+	protected int m_context = INDEPENDENT;
+
+	public AbstractGroup(String name, int context) {
+		m_name = name;
+		setHierarchicalContext(context);
+	}
+
+	/** Group's contents are independent of its hierarchical position. */
+	public static final int INDEPENDENT = 0;
+	/**
+	 * Group's content is the intersection of its own content with its
+	 * supergroup's content.
+	 */
+	public static final int REFINING = 1;
+	/**
+	 * Group's content is the union of its own content with its subgroups'
+	 * content.
+	 */
+	public static final int INCLUDING = 2;
+
+	/** Character used for quoting in the string representation. */
+	protected static final char QUOTE_CHAR = '\\';
+
+	/**
+	 * For separating units (e.g. name, which every group has) in the string
+	 * representation
+	 */
+	protected static final String SEPARATOR = ";";
+
+	/**
+	 * @return A search rule that will identify this group's entries.
+	 */
+	public abstract SearchRule getSearchRule();
+
+	/**
+	 * Re-create a group instance from a textual representation.
+	 * 
+	 * @param s
+	 *            The result from the group's toString() method.
+	 * @return New instance of the encoded group.
+	 * @throws Exception
+	 *             If an error occured and a group could not be created, e.g.
+	 *             due to a malformed regular expression.
+	 */
+	public static AbstractGroup fromString(String s, BibtexDatabase db,
+			int version) throws Exception {
+		if (s.startsWith(KeywordGroup.ID))
+			return KeywordGroup.fromString(s, db, version);
+		if (s.startsWith(AllEntriesGroup.ID))
+			return AllEntriesGroup.fromString(s, db, version);
+		if (s.startsWith(SearchGroup.ID))
+			return SearchGroup.fromString(s, db, version);
+		if (s.startsWith(ExplicitGroup.ID))
+			return ExplicitGroup.fromString(s, db, version);
+		return null; // unknown group
+	}
+
+	/** Returns this group's name, e.g. for display in a list/tree. */
+	public final String getName() {
+		return m_name;
+	}
+
+	/** Sets the group's name. */
+	public final void setName(String name) {
+		m_name = name;
+	}
+
+	/**
+	 * @return true if this type of group supports the explicit adding of
+	 *         entries.
+	 */
+	public abstract boolean supportsAdd();
+
+	/**
+	 * @return true if this type of group supports the explicit removal of
+	 *         entries.
+	 */
+	public abstract boolean supportsRemove();
+
+	/**
+	 * Adds the specified entries to this group.
+	 * 
+	 * @return If this group or one or more entries was/were modified as a
+	 *         result of this operation, an object is returned that allows to
+	 *         undo this change. null is returned otherwise.
+	 */
+	public abstract AbstractUndoableEdit add(BibtexEntry[] entries);
+
+	/**
+	 * Removes the specified entries from this group.
+	 * 
+	 * @return If this group or one or more entries was/were modified as a
+	 *         result of this operation, an object is returned that allows to
+	 *         undo this change. null is returned otherwise.
+	 */
+	public abstract AbstractUndoableEdit remove(BibtexEntry[] entries);
+
+	/**
+	 * @param searchOptions
+	 *            The search options to apply.
+	 * @return true if this group contains the specified entry, false otherwise.
+	 */
+	public abstract boolean contains(Map searchOptions, BibtexEntry entry);
+
+	/**
+	 * @return true if this group contains the specified entry, false otherwise.
+	 */
+	public abstract boolean contains(BibtexEntry entry);
+
+	/**
+	 * @return true if this group contains any of the specified entries, false
+	 *         otherwise.
+	 */
+	public boolean containsAny(BibtexEntry[] entries) {
+		for (int i = 0; i < entries.length; ++i)
+			if (contains(entries[i]))
+				return true;
+		return false;
+	}
+
+	/**
+	 * @return true if this group contains all of the specified entries, false
+	 *         otherwise.
+	 */
+	public boolean containsAll(BibtexEntry[] entries) {
+		for (int i = 0; i < entries.length; ++i)
+			if (!contains(entries[i]))
+				return false;
+		return true;
+	}
+
+	/**
+	 * Returns true if this group is dynamic, i.e. uses a search definition or
+	 * equiv. that might match new entries, or false if this group contains a
+	 * fixed set of entries and thus will never match a new entry that was not
+	 * explicitly added to it.
+	 */
+	public abstract boolean isDynamic();
+
+	/** Sets the groups's hierarchical context. If context is not a valid
+	 * value, the call is ignored. */
+	public void setHierarchicalContext(int context) {
+		if (context != INDEPENDENT && context != REFINING
+				&& context != INCLUDING)
+			return;
+		m_context = context;
+	}
+	
+	/** Returns the group's hierarchical context. */
+	public int getHierarchicalContext() {
+		return m_context;
+	}
+	
+	/** Returns a lengthy textual description of this instance (for 
+     * the groups editor). */
+	public abstract String getDescription();
+
+	/**
+	 * @return A deep copy of this object.
+	 */
+	public abstract AbstractGroup deepCopy();
+
+	/** Returns a short description of the group in HTML (for a tooltip). */
+	public abstract String getShortDescription();
+
+	// by general AbstractGroup contract, toString() must return
+	// something from which this object can be reconstructed
+	// using fromString(String).
+
+	// by general AbstractGroup contract, equals() must be implemented
+}
diff --git a/src/java/net/sf/jabref/groups/AddToGroupAction.java b/src/java/net/sf/jabref/groups/AddToGroupAction.java
new file mode 100644
index 0000000..faa8101
--- /dev/null
+++ b/src/java/net/sf/jabref/groups/AddToGroupAction.java
@@ -0,0 +1,124 @@
+/*
+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.groups;
+
+import java.awt.event.ActionEvent;
+import java.util.*;
+
+import javax.swing.*;
+import javax.swing.undo.AbstractUndoableEdit;
+
+import net.sf.jabref.*;
+import net.sf.jabref.undo.NamedCompound;
+
+public class AddToGroupAction extends AbstractAction {
+    protected GroupTreeNode m_node;
+    protected final boolean m_move;
+    protected BasePanel m_panel;
+    /**
+     * @param move If true, remove node from all other groups.
+     */
+    public AddToGroupAction(GroupTreeNode node, boolean move,
+            BasePanel panel) {
+        super(node.getGroup().getName());
+        m_node = node;
+        m_move = move;
+        m_panel = panel;
+    }
+    public AddToGroupAction(boolean move) {
+        super(Globals.lang(move ? "Assign entry selection exclusively to this group"
+                : "Add entry selection to this group")); // JZTODO lyrics
+        m_move = move;
+    }
+    public void setBasePanel(BasePanel panel) {
+        m_panel = panel;
+    }
+    public void setNode(GroupTreeNode node) {
+        m_node = node;
+    }
+    public void actionPerformed(ActionEvent evt) {
+        final BibtexEntry[] entries = m_panel.getSelectedEntries();
+        final Vector removeGroupsNodes = new Vector(); // used only when moving
+        
+        if (m_move) {
+            // collect warnings for removal
+            Enumeration e = ((GroupTreeNode) m_node.getRoot()).preorderEnumeration();
+            GroupTreeNode node;
+            while (e.hasMoreElements()) {
+                node = (GroupTreeNode) e.nextElement();
+                if (!node.getGroup().supportsRemove())
+                    continue;
+                for (int i = 0; i < entries.length; ++i) {
+                    if (node.getGroup().contains(entries[i]))
+                        removeGroupsNodes.add(node);
+                }
+            }
+            // warning for all groups from which the entries are removed, and 
+            // for the one to which they are added! hence the magical +1
+            AbstractGroup[] groups = new AbstractGroup[removeGroupsNodes.size()+1];
+            for (int i = 0; i < removeGroupsNodes.size(); ++i)
+                groups[i] = ((GroupTreeNode) removeGroupsNodes.elementAt(i)).getGroup();
+            groups[groups.length-1] = m_node.getGroup();
+            if (!Util.warnAssignmentSideEffects(groups,
+                    entries, m_panel.getDatabase(), m_panel.frame()))
+                return; // user aborted operation
+        } else {
+            // warn if assignment has undesired side effects (modifies a field != keywords)
+            if (!Util.warnAssignmentSideEffects(new AbstractGroup[]{m_node.getGroup()},
+                    entries, m_panel.getDatabase(), m_panel.frame()))
+                return; // user aborted operation
+        }
+        
+        // if an editor is showing, its fields must be updated
+        // after the assignment, and before that, the current
+        // edit has to be stored:
+        m_panel.storeCurrentEdit();
+        
+        NamedCompound undoAll = new NamedCompound(Globals.lang("change assignment of entries")); 
+        
+        if (m_move) {
+            // first remove
+            for (int i = 0; i < removeGroupsNodes.size(); ++i) {
+                GroupTreeNode node = (GroupTreeNode) removeGroupsNodes.elementAt(i);
+                if (node.getGroup().containsAny(entries))
+                    undoAll.addEdit(node.removeFromGroup(entries));
+            }
+            // then add
+            AbstractUndoableEdit undoAdd = m_node.addToGroup(entries);
+            if (undoAdd != null)
+                undoAll.addEdit(undoAdd);
+        } else {
+            AbstractUndoableEdit undoAdd = m_node.addToGroup(entries);
+            if (undoAdd == null)
+                return; // no changed made
+            undoAll.addEdit(undoAdd);
+        }
+        
+        undoAll.end();
+        
+        m_panel.undoManager.addEdit(undoAll);
+        m_panel.markBaseChanged();
+        m_panel.updateEntryEditorIfShowing();
+        m_panel.getGroupSelector().valueChanged(null);
+    }
+}
diff --git a/src/java/net/sf/jabref/groups/AllEntriesGroup.java b/src/java/net/sf/jabref/groups/AllEntriesGroup.java
new file mode 100644
index 0000000..c59eef9
--- /dev/null
+++ b/src/java/net/sf/jabref/groups/AllEntriesGroup.java
@@ -0,0 +1,117 @@
+/*
+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.groups;
+
+import java.util.Map;
+
+import javax.swing.undo.AbstractUndoableEdit;
+
+import net.sf.jabref.*;
+
+/**
+ * This group contains all entries.
+ */
+public class AllEntriesGroup extends AbstractGroup implements SearchRule {
+    public static final String ID = "AllEntriesGroup:";
+
+    public AllEntriesGroup() {
+        super(Globals.lang("All Entries"), AbstractGroup.INDEPENDENT);
+    }
+    
+    public static AbstractGroup fromString(String s, BibtexDatabase db, int version) throws Exception {
+        if (!s.startsWith(ID))
+            throw new Exception(
+                    "Internal error: AllEntriesGroup cannot be created from \""
+                            + s + "\". "
+                            + "Please report this on www.sf.net/projects/jabref");
+        switch (version) {
+        case 0:
+        case 1:
+        case 2:
+        case 3:
+            return new AllEntriesGroup();
+        default:
+            throw new UnsupportedVersionException("AllEntriesGroup", version); 
+        }
+    }
+
+    public SearchRule getSearchRule() {
+        return this;
+    }
+
+    public boolean supportsAdd() {
+        return false;
+    }
+
+    public boolean supportsRemove() {
+        return false;
+    }
+
+    public AbstractUndoableEdit add(BibtexEntry[] entries) {
+        // not supported -> ignore
+        return null;
+    }
+
+    public AbstractUndoableEdit remove(BibtexEntry[] entries) {
+        // not supported -> ignore
+        return null;
+    }
+
+    public boolean contains(Map searchOptions, BibtexEntry entry) {
+        return true; // contains everything
+    }
+
+    public AbstractGroup deepCopy() {
+        return new AllEntriesGroup();
+    }
+
+    public int applyRule(Map searchStrings, BibtexEntry bibtexEntry) {
+        return 1; // contains everything
+    }
+
+    public boolean equals(Object o) {
+        return o instanceof AllEntriesGroup;
+    }
+
+    public String toString() {
+        return ID;
+    }
+
+    public boolean contains(BibtexEntry entry) {
+        return true;
+    }
+    
+    public boolean isDynamic() {
+    	// this is actually a special case; I define it as non-dynamic
+    	return false;
+    }
+
+	public String getDescription() {
+		return "This group contains all entries. It cannot be edited or removed.";
+		// JZTODO lyrics
+	}
+	
+	public String getShortDescription() {
+		return "<b>All Entries</b> (this group cannot be edited or removed)";
+	}
+}
diff --git a/src/java/net/sf/jabref/groups/AndOrSearchRuleSet.java b/src/java/net/sf/jabref/groups/AndOrSearchRuleSet.java
new file mode 100644
index 0000000..408a9d6
--- /dev/null
+++ b/src/java/net/sf/jabref/groups/AndOrSearchRuleSet.java
@@ -0,0 +1,68 @@
+/*
+ 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.
+
+ 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.groups;
+
+import java.util.*;
+
+import net.sf.jabref.*;
+
+/**
+ * Subclass of SearchRuleSet that ANDs or ORs between its rules, eturning 0 or
+ * 1.
+ */
+class AndOrSearchRuleSet extends SearchRuleSet {
+
+    private boolean and, invert;
+
+    public AndOrSearchRuleSet(boolean and, boolean invert) {
+        this.and = and;
+        this.invert = invert;
+    }
+
+    public int applyRule(Map searchString, BibtexEntry bibtexEntry) {
+        int score = 0;
+        Enumeration e = ruleSet.elements();
+
+        // We let each rule add a maximum of 1 to the score.
+        while (e.hasMoreElements()) {
+            score += (((SearchRule) e.nextElement()).applyRule(searchString,
+                    bibtexEntry) > 0 ? 1 : 0);
+        }
+
+        // Then an AND rule demands that score == number of rules, and
+        // an OR rule demands score > 0.
+        boolean res;
+        if (and)
+            res = (score == ruleSet.size());
+        else
+            res = (score > 0);
+
+        if (invert)
+            return (res ? 0 : 1);
+        return (res ? 1 : 0);
+    }
+}
diff --git a/src/java/net/sf/jabref/groups/AutoGroupDialog.java b/src/java/net/sf/jabref/groups/AutoGroupDialog.java
new file mode 100644
index 0000000..1059f75
--- /dev/null
+++ b/src/java/net/sf/jabref/groups/AutoGroupDialog.java
@@ -0,0 +1,221 @@
+/*
+ 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.
+
+ 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.groups;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.util.*;
+
+import javax.swing.*;
+import javax.swing.event.*;
+import javax.swing.event.CaretListener;
+
+import net.sf.jabref.*;
+import net.sf.jabref.undo.NamedCompound;
+
+/**
+ * Dialog for creating or modifying groups. Operates directly on the Vector
+ * containing group information.
+ */
+class AutoGroupDialog extends JDialog implements CaretListener {
+    JTextField remove = new JTextField(60), field = new JTextField(60),
+            deliminator = new JTextField(60);
+    JLabel nf = new JLabel(Globals.lang("Field to group by") + ":"),
+            nr = new JLabel(Globals.lang("Characters to ignore") + ":");
+    JCheckBox nd = new JCheckBox(Globals.lang(
+    		"Use the following delimiter character(s)")
+            + ":"); // JZTODO lyrics
+    JButton ok = new JButton(Globals.lang("Ok")), cancel = new JButton(Globals
+            .lang("Cancel"));
+    JPanel main = new JPanel(), opt = new JPanel();
+    private boolean ok_pressed = false;
+    private GroupTreeNode m_groupsRoot;
+    private JabRefFrame frame;
+    private BasePanel panel;
+    private GroupSelector gs;
+    private String oldRemove, oldField;
+    GridBagLayout gbl = new GridBagLayout();
+    GridBagConstraints con = new GridBagConstraints();
+
+    /**
+     * @param groupsRoot
+     *            The original set of groups, which is required as undo
+     *            information when all groups are cleared.
+     */
+    public AutoGroupDialog(JabRefFrame jabrefFrame, BasePanel basePanel,
+            GroupSelector groupSelector, GroupTreeNode groupsRoot,
+            String defaultField, String defaultRemove, String defaultDeliminator) {
+        super(jabrefFrame, Globals.lang("Automatically create groups"), true);
+        frame = jabrefFrame;
+        gs = groupSelector;
+        panel = basePanel;
+        m_groupsRoot = groupsRoot;
+        field.setText(defaultField);
+        remove.setText(defaultRemove);
+        deliminator.setText(defaultDeliminator);
+        nd.setSelected(true);
+        ActionListener okListener = new ActionListener() {
+            public void actionPerformed(ActionEvent e) {
+                ok_pressed = true;
+                dispose();
+
+                GroupTreeNode autoGroupsRoot = new GroupTreeNode(
+                        new ExplicitGroup(Globals.lang("Automatically created groups"),
+                        		AbstractGroup.INCLUDING));
+                HashSet hs = null;
+                if (nd.isSelected()) {
+                    hs = Util
+                            .findDeliminatedWordsInField(panel.getDatabase(),
+                                    field().toLowerCase().trim(), deliminator
+                                            .getText());
+                } else {
+                    hs = Util.findAllWordsInField(panel.getDatabase(), field()
+                            .toLowerCase().trim(), remove());
+                }
+                Iterator i = hs.iterator();
+                while (i.hasNext()) {
+                    String keyword = i.next().toString();
+                    KeywordGroup group = new KeywordGroup(keyword, field(),
+                            keyword, false, false, AbstractGroup.INDEPENDENT);
+                    autoGroupsRoot.add(new GroupTreeNode(group));
+                }
+
+                m_groupsRoot.add(autoGroupsRoot);
+                NamedCompound ce = new NamedCompound(Globals
+                        .lang("Autogenerate groups"));
+                UndoableAddOrRemoveGroup undo = new UndoableAddOrRemoveGroup(
+                        gs, m_groupsRoot, autoGroupsRoot,
+                        UndoableAddOrRemoveGroup.ADD_NODE);
+                undo.setRevalidate(true);
+                ce.addEdit(undo);
+
+                panel.markBaseChanged(); // a change always occurs
+                gs.revalidateGroups();
+                frame.output(Globals.lang("Created groups."));
+                ce.end();
+                panel.undoManager.addEdit(ce);
+            }
+        };
+        remove.addActionListener(okListener);
+        field.addActionListener(okListener);
+        field.addCaretListener(this);
+        AbstractAction cancelAction = new AbstractAction() {
+            public void actionPerformed(ActionEvent e) {
+                dispose();
+            }
+        };
+        cancel.addActionListener(cancelAction);
+        ok.addActionListener(okListener);
+        // Key bindings:
+        ActionMap am = main.getActionMap();
+        InputMap im = main.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
+        im.put(frame.prefs().getKey("Close dialog"), "close");
+        am.put("close", cancelAction);
+        // Layout starts here.
+        main.setLayout(gbl);
+        opt.setLayout(gbl);
+        main.setBorder(BorderFactory.createTitledBorder(BorderFactory
+                .createEtchedBorder(), Globals.lang("Group properties")));
+        // Main panel:
+        con.weightx = 0;
+        con.gridwidth = 1;
+        con.insets = new Insets(3, 5, 3, 5);
+        con.anchor = GridBagConstraints.EAST;
+        con.fill = GridBagConstraints.NONE;
+        con.gridx = 0;
+        con.gridy = 0;
+        gbl.setConstraints(nf, con);
+        main.add(nf);
+        con.gridy = 1;
+        gbl.setConstraints(nr, con);
+        main.add(nr);
+        con.gridy = 2;
+        gbl.setConstraints(nd, con);
+        main.add(nd);
+        con.weightx = 1;
+        con.anchor = GridBagConstraints.WEST;
+        con.fill = GridBagConstraints.HORIZONTAL;
+        con.gridy = 0;
+        con.gridx = 1;
+        gbl.setConstraints(field, con);
+        main.add(field);
+        con.gridy = 1;
+        gbl.setConstraints(remove, con);
+        main.add(remove);
+        con.gridy = 2;
+        gbl.setConstraints(deliminator, con);
+        main.add(deliminator);
+        // Option buttons:
+        con.gridx = GridBagConstraints.RELATIVE;
+        con.gridy = GridBagConstraints.RELATIVE;
+        con.weightx = 1;
+        con.gridwidth = 1;
+        con.anchor = GridBagConstraints.EAST;
+        con.fill = GridBagConstraints.NONE;
+        gbl.setConstraints(ok, con);
+        opt.add(ok);
+        con.anchor = GridBagConstraints.WEST;
+        con.gridwidth = GridBagConstraints.REMAINDER;
+        gbl.setConstraints(cancel, con);
+        opt.add(cancel);
+        getContentPane().add(main, BorderLayout.CENTER);
+        getContentPane().add(opt, BorderLayout.SOUTH);
+        // pack();
+        updateComponents();
+        setSize(400, 200);
+        Util.placeDialog(this, frame);
+    }
+
+    public boolean okPressed() {
+        return ok_pressed;
+    }
+
+    public String oldField() {
+        return oldField;
+    }
+
+    public String oldRemove() {
+        return oldRemove;
+    }
+
+    public String field() {
+        return field.getText();
+    }
+
+    public String remove() {
+        return remove.getText();
+    }
+
+    public void caretUpdate(CaretEvent e) {
+        updateComponents();
+    }
+    
+    protected void updateComponents() {
+        String groupField = field.getText().trim();
+        ok.setEnabled(groupField.matches("\\w+"));
+    }
+}
diff --git a/src/java/net/sf/jabref/groups/EntryTableTransferHandler.java b/src/java/net/sf/jabref/groups/EntryTableTransferHandler.java
new file mode 100644
index 0000000..adcdb54
--- /dev/null
+++ b/src/java/net/sf/jabref/groups/EntryTableTransferHandler.java
@@ -0,0 +1,75 @@
+/*
+ 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.groups;
+
+import java.awt.datatransfer.*;
+import java.awt.dnd.DnDConstants;
+import java.awt.event.InputEvent;
+
+import javax.swing.*;
+
+import net.sf.jabref.EntryTable;
+import net.sf.jabref.gui.MainTable;
+
+public class EntryTableTransferHandler extends TransferHandler {
+    protected final MainTable entryTable;
+
+    public EntryTableTransferHandler(MainTable entryTable) {
+        this.entryTable = entryTable;
+    }
+
+    public int getSourceActions(JComponent c) {
+        return DnDConstants.ACTION_LINK;
+    }
+
+    public Transferable createTransferable(JComponent c) {
+        return new TransferableEntrySelection(entryTable.getSelectedEntries());
+    }
+
+    // add-ons -----------------------
+
+    public boolean importData(JComponent comp, Transferable t) {
+        // for accepting drags (we don't to that)
+        return false;
+    }
+
+    public boolean canImport(JComponent comp, DataFlavor[] transferFlavors) {
+        // for accepting drags (we don't to that)
+        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);
+    }
+}
\ No newline at end of file
diff --git a/src/java/net/sf/jabref/groups/ExplicitGroup.java b/src/java/net/sf/jabref/groups/ExplicitGroup.java
new file mode 100644
index 0000000..8ab2a9c
--- /dev/null
+++ b/src/java/net/sf/jabref/groups/ExplicitGroup.java
@@ -0,0 +1,240 @@
+/*
+ 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.groups;
+
+import java.util.*;
+
+import javax.swing.undo.AbstractUndoableEdit;
+
+import net.sf.jabref.*;
+import net.sf.jabref.util.QuotedStringTokenizer;
+
+/**
+ * @author jzieren
+ * 
+ */
+public class ExplicitGroup extends AbstractGroup implements SearchRule {
+    public static final String ID = "ExplicitGroup:";
+
+    private final Set m_entries;
+
+    public ExplicitGroup(String name, int context) {
+        super(name, context);
+        m_entries = new HashSet();
+    }
+
+    public static AbstractGroup fromString(String s, BibtexDatabase db,
+            int version) throws Exception {
+        if (!s.startsWith(ID))
+            throw new Exception(
+                    "Internal error: ExplicitGroup cannot be created from \""
+                            + s
+                            + "\". "
+                            + "Please report this on www.sf.net/projects/jabref");
+        QuotedStringTokenizer tok = new QuotedStringTokenizer(s.substring(ID
+                .length()), SEPARATOR, QUOTE_CHAR);
+        switch (version) {
+        case 0:
+        case 1:
+        case 2: {
+            ExplicitGroup newGroup = new ExplicitGroup(tok.nextToken(),
+                    AbstractGroup.INDEPENDENT);
+            newGroup.addEntries(tok, db);
+            return newGroup;
+        }
+        case 3: {
+            String name = tok.nextToken();
+            int context = Integer.parseInt(tok.nextToken());
+            ExplicitGroup newGroup = new ExplicitGroup(name, context);
+            newGroup.addEntries(tok, db);
+            return newGroup;
+        }
+        default:
+            throw new UnsupportedVersionException("ExplicitGroup", version);
+        }
+    }
+
+    /** Called only when created fromString */
+    protected void addEntries(QuotedStringTokenizer tok, BibtexDatabase db) {
+        BibtexEntry[] entries;
+        while (tok.hasMoreTokens()) {
+            entries = db.getEntriesByKey(Util.unquote(tok.nextToken(),
+                    QUOTE_CHAR));
+            for (int i = 0; i < entries.length; ++i)
+                m_entries.add(entries[i]);
+        }
+    }
+
+    public SearchRule getSearchRule() {
+        return this;
+    }
+
+    public boolean supportsAdd() {
+        return true;
+    }
+
+    public boolean supportsRemove() {
+        return true;
+    }
+
+    public AbstractUndoableEdit add(BibtexEntry[] entries) {
+        if (entries.length == 0)
+            return null; // nothing to do
+
+        HashSet entriesBeforeEdit = new HashSet(m_entries);
+        for (int i = 0; i < entries.length; ++i)
+            m_entries.add(entries[i]);
+
+        return new UndoableChangeAssignment(entriesBeforeEdit, m_entries);
+    }
+
+    public boolean addEntry(BibtexEntry entry) {
+        return m_entries.add(entry);
+    }
+
+    public AbstractUndoableEdit remove(BibtexEntry[] entries) {
+        if (entries.length == 0)
+            return null; // nothing to do
+
+        HashSet entriesBeforeEdit = new HashSet(m_entries);
+        for (int i = 0; i < entries.length; ++i)
+            m_entries.remove(entries[i]);
+
+        return new UndoableChangeAssignment(entriesBeforeEdit, m_entries);
+    }
+
+    public boolean removeEntry(BibtexEntry entry) {
+        return m_entries.remove(entry);
+    }
+
+    public boolean contains(BibtexEntry entry) {
+        return m_entries.contains(entry);
+    }
+
+    public boolean contains(Map searchOptions, BibtexEntry entry) {
+        return contains(entry);
+    }
+
+    public int applyRule(Map searchStrings, BibtexEntry bibtexEntry) {
+        return contains(searchStrings, bibtexEntry) ? 1 : 0;
+    }
+
+    public AbstractGroup deepCopy() {
+        ExplicitGroup copy = new ExplicitGroup(m_name, m_context);
+        copy.m_entries.addAll(m_entries);
+        return copy;
+    }
+
+    public boolean equals(Object o) {
+        if (!(o instanceof ExplicitGroup))
+            return false;
+        ExplicitGroup other = (ExplicitGroup) o;
+        // compare entries assigned to both groups
+        if (m_entries.size() != other.m_entries.size())
+            return false; // add/remove
+        HashSet keys = new HashSet();
+        BibtexEntry entry;
+        String key;
+        // compare bibtex keys for all entries that have one
+        for (Iterator it = m_entries.iterator(); it.hasNext(); ) {
+            entry = (BibtexEntry) it.next();
+            key = entry.getCiteKey();
+            if (key != null)
+                keys.add(key);
+        }
+        for (Iterator it = other.m_entries.iterator(); it.hasNext(); ) {
+            entry = (BibtexEntry) it.next();
+            key = entry.getCiteKey();
+            if (key != null)
+                if (!keys.remove(key))
+                    return false;
+        }
+        if (!keys.isEmpty())
+            return false;
+        return other.m_name.equals(m_name)
+                && other.getHierarchicalContext() == getHierarchicalContext();
+    }
+
+    /**
+     * Returns a String representation of this group and its entries. Entries
+     * are referenced by their Bibtexkey. Entries that do not have a Bibtexkey
+     * are not included in the representation and will thus not be available
+     * upon recreation.
+     */
+    public String toString() {
+        StringBuffer sb = new StringBuffer();
+        sb.append(ID).append(Util.quote(m_name, SEPARATOR, QUOTE_CHAR)).append(SEPARATOR).append(m_context).append(SEPARATOR);
+        String s;
+        // write entries in well-defined order for CVS compatibility
+        Set sortedKeys = new TreeSet();
+        for (Iterator it = m_entries.iterator(); it.hasNext();) {
+            s = ((BibtexEntry) it.next()).getCiteKey();
+            if (s != null && !s.equals("")) // entries without a key are lost
+                sortedKeys.add(s);
+        }
+        for (Iterator it = sortedKeys.iterator(); it.hasNext();) {
+            sb.append(Util.quote((String) it.next(), SEPARATOR, QUOTE_CHAR)).append(SEPARATOR);
+        }
+        return sb.toString();
+    }
+
+    /** Remove all assignments, resulting in an empty group. */
+    public void clearAssignments() {
+        m_entries.clear();
+    }
+
+    public boolean isDynamic() {
+        return false;
+    }
+
+    public String getDescription() {
+        return getDescriptionForPreview();
+    }
+
+    public static String getDescriptionForPreview() {
+        return Globals
+                .lang("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.");
+    }
+
+    public String getShortDescription() {
+        StringBuffer sb = new StringBuffer();
+        sb.append("<b>").append(getName()).append("</b> - static group");
+        switch (getHierarchicalContext()) {
+        case AbstractGroup.INCLUDING:
+            sb.append(", includes subgroups");
+            break;
+        case AbstractGroup.REFINING:
+            sb.append(", refines supergroup");
+            break;
+        default:
+            break;
+        }
+        return sb.toString();
+    }
+}
diff --git a/src/java/net/sf/jabref/groups/GroupDialog.java b/src/java/net/sf/jabref/groups/GroupDialog.java
new file mode 100644
index 0000000..0781e3a
--- /dev/null
+++ b/src/java/net/sf/jabref/groups/GroupDialog.java
@@ -0,0 +1,556 @@
+/*
+ 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.
+
+ 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.groups;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.util.*;
+import java.util.regex.*;
+
+import javax.swing.*;
+import javax.swing.event.*;
+import javax.swing.undo.AbstractUndoableEdit;
+
+import net.sf.jabref.*;
+import net.sf.jabref.search.*;
+import antlr.collections.AST;
+
+import com.jgoodies.forms.builder.DefaultFormBuilder;
+import com.jgoodies.forms.layout.*;
+
+/**
+ * Dialog for creating or modifying groups. Operates directly on the Vector
+ * containing group information.
+ */
+class GroupDialog extends JDialog {
+	private static final int INDEX_EXPLICITGROUP = 0;
+	private static final int INDEX_KEYWORDGROUP = 1;
+	private static final int INDEX_SEARCHGROUP = 2;
+	private static final int TEXTFIELD_LENGTH = 30;
+	// for all types
+	private JTextField m_name = new JTextField(TEXTFIELD_LENGTH);
+	private JRadioButton m_explicitRadioButton = new JRadioButton(Globals
+			.lang("Statically group entries by manual assignment"));
+	private JRadioButton m_keywordsRadioButton = new JRadioButton(
+			Globals.lang("Dynamically group entries by searching a field for a keyword"));
+	private JRadioButton m_searchRadioButton = new JRadioButton(Globals
+			.lang("Dynamically group entries by a free-form search expression"));
+	private JRadioButton m_independentButton = new JRadioButton( // JZTODO lyrics
+			Globals.lang("Independent group: When selected, view only this group's entries"));
+	private JRadioButton m_intersectionButton = new JRadioButton( // JZTODO lyrics
+			Globals.lang("Refine supergroup: When selected, view entries contained in both this group and its supergroup"));
+	private JRadioButton m_unionButton = new JRadioButton( // JZTODO lyrics
+			Globals.lang("Include subgroups: When selected, view entries contained in this group or its subgroups"));
+	// for KeywordGroup
+	private JTextField m_kgSearchField = new JTextField(TEXTFIELD_LENGTH);
+	private FieldTextField m_kgSearchTerm = new FieldTextField("keywords", "",
+			false);
+	private JCheckBox m_kgCaseSensitive = new JCheckBox(Globals
+			.lang("Case sensitive"));
+	private JCheckBox m_kgRegExp = new JCheckBox(Globals
+			.lang("Regular Expression"));
+	// for SearchGroup
+	private JTextField m_sgSearchExpression = new JTextField(TEXTFIELD_LENGTH);
+	private JCheckBox m_sgCaseSensitive = new JCheckBox(Globals
+			.lang("Case sensitive"));
+	private JCheckBox m_sgRegExp = new JCheckBox(Globals
+			.lang("Regular Expression"));
+	// for all types
+	private JButton m_ok = new JButton(Globals.lang("Ok"));
+	private JButton m_cancel = new JButton(Globals.lang("Cancel"));
+	private JPanel m_optionsPanel = new JPanel();
+	private JLabel m_description = new JLabel() {
+		public Dimension getPreferredSize() {
+			Dimension d = super.getPreferredSize();
+			// width must be smaller than width of enclosing JScrollPane
+			// to prevent a horizontal scroll bar
+			d.width = 1;
+			return d;
+		}
+	};
+
+	private boolean m_okPressed = false;
+
+	private final JabRefFrame m_parent;
+
+	private final BasePanel m_basePanel;
+
+	private AbstractGroup m_resultingGroup;
+
+	private AbstractUndoableEdit m_undoAddPreviousEntires = null;
+
+	private final AbstractGroup m_editedGroup;
+
+	private CardLayout m_optionsLayout = new CardLayout();
+
+	/**
+	 * Shows a group add/edit dialog.
+	 * 
+	 * @param jabrefFrame
+	 *            The parent frame.
+	 * @param defaultField
+	 *            The default grouping field.
+	 * @param editedGroup
+	 *            The group being edited, or null if a new group is to be
+	 *            created.
+	 */
+	public GroupDialog(JabRefFrame jabrefFrame, BasePanel basePanel,
+			AbstractGroup editedGroup) {
+		super(jabrefFrame, Globals.lang("Edit group"), true);
+		m_basePanel = basePanel;
+		m_parent = jabrefFrame;
+		m_editedGroup = editedGroup;
+
+		// set default values (overwritten if editedGroup != null)
+		m_kgSearchField.setText(jabrefFrame.prefs().get("groupsDefaultField"));
+
+		// configure elements
+		ButtonGroup groupType = new ButtonGroup();
+		groupType.add(m_explicitRadioButton);
+		groupType.add(m_keywordsRadioButton);
+		groupType.add(m_searchRadioButton);
+		ButtonGroup groupHierarchy = new ButtonGroup();
+		groupHierarchy.add(m_independentButton);
+		groupHierarchy.add(m_intersectionButton);
+		groupHierarchy.add(m_unionButton);
+		m_description.setVerticalAlignment(JLabel.TOP);
+		getRootPane().setDefaultButton(m_ok);
+
+		// build individual layout cards for each group
+		m_optionsPanel.setLayout(m_optionsLayout);
+		// ... for explicit group
+		m_optionsPanel.add(new JPanel(), "" + INDEX_EXPLICITGROUP);
+		// ... for keyword group
+		FormLayout layoutKG = new FormLayout(
+				"right:pref, 4dlu, fill:1dlu:grow, 2dlu, left:pref");
+		DefaultFormBuilder builderKG = new DefaultFormBuilder(layoutKG);
+		builderKG.append(Globals.lang("Field"));
+		builderKG.append(m_kgSearchField, 3);
+		builderKG.nextLine();
+		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));
+		builderKG.nextLine();
+		builderKG.append(m_kgCaseSensitive, 3);
+		builderKG.nextLine();
+		builderKG.append(m_kgRegExp, 3);
+		m_optionsPanel.add(builderKG.getPanel(), "" + INDEX_KEYWORDGROUP);
+		// ... for search group
+		FormLayout layoutSG = new FormLayout("right:pref, 4dlu, fill:1dlu:grow");
+		DefaultFormBuilder builderSG = new DefaultFormBuilder(layoutSG);
+		builderSG.append(Globals.lang("Search expression"));
+		builderSG.append(m_sgSearchExpression);
+		builderSG.nextLine();
+		builderSG.append(m_sgCaseSensitive, 3);
+		builderSG.nextLine();
+		builderSG.append(m_sgRegExp, 3);
+		m_optionsPanel.add(builderSG.getPanel(), "" + INDEX_SEARCHGROUP);
+		// ... for buttons panel
+		FormLayout layoutBP = new FormLayout("pref, 4dlu, pref", "p");
+		layoutBP.setColumnGroups(new int[][] { { 1, 3 } });
+		DefaultFormBuilder builderBP = new DefaultFormBuilder(layoutBP);
+		builderBP.append(m_ok);
+		builderBP.add(m_cancel);
+
+		// create layout
+		FormLayout layoutAll = new FormLayout(
+				"right:pref, 4dlu, fill:600px, 4dlu, fill:pref",
+				"p, 3dlu, p, 3dlu, p, 0dlu, p, 0dlu, p, 3dlu, p, 3dlu, p, "
+						+ "0dlu, p, 0dlu, p, 3dlu, p, 3dlu, "
+						+ "p, 3dlu, p, 3dlu, top:80dlu, 9dlu, p, , 9dlu, p");
+
+		DefaultFormBuilder builderAll = new DefaultFormBuilder(layoutAll);
+		builderAll.setDefaultDialogBorder();
+		builderAll.appendSeparator(Globals.lang("General"));
+		builderAll.nextLine();
+		builderAll.nextLine();
+		builderAll.append(Globals.lang("Name"));
+		builderAll.append(m_name);
+		builderAll.nextLine();
+		builderAll.nextLine();
+		builderAll.append(m_explicitRadioButton, 5);
+		builderAll.nextLine();
+		builderAll.nextLine();
+		builderAll.append(m_keywordsRadioButton, 5);
+		builderAll.nextLine();
+		builderAll.nextLine();
+		builderAll.append(m_searchRadioButton, 5);
+		builderAll.nextLine();
+		builderAll.nextLine();
+		builderAll.appendSeparator(Globals.lang("Hierarchical context")); // JZTODO lyrics
+		builderAll.nextLine();
+		builderAll.nextLine();
+		builderAll.append(m_independentButton, 5);
+		builderAll.nextLine();
+		builderAll.nextLine();
+		builderAll.append(m_intersectionButton, 5);
+		builderAll.nextLine();
+		builderAll.nextLine();
+		builderAll.append(m_unionButton, 5);
+		builderAll.nextLine();
+		builderAll.nextLine();
+		builderAll.appendSeparator(Globals.lang("Options"));
+		builderAll.nextLine();
+		builderAll.nextLine();
+		builderAll.append(m_optionsPanel, 5);
+		builderAll.nextLine();
+		builderAll.nextLine();
+		builderAll.appendSeparator(Globals.lang("Description"));
+		builderAll.nextLine();
+		builderAll.nextLine();
+		JScrollPane sp = new JScrollPane(m_description,
+				JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
+				JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED) {
+			public Dimension getPreferredSize() {
+				return getMaximumSize();
+			}
+		};
+		builderAll.append(sp, 5);
+		builderAll.nextLine();
+		builderAll.nextLine();
+		builderAll.appendSeparator();
+		builderAll.nextLine();
+		builderAll.nextLine();
+		CellConstraints cc = new CellConstraints();
+		builderAll.add(builderBP.getPanel(), cc.xyw(builderAll.getColumn(),
+				builderAll.getRow(), 5, "center, fill"));
+
+		Container cp = getContentPane();
+		cp.setLayout(new BoxLayout(cp, BoxLayout.Y_AXIS));
+		cp.add(builderAll.getPanel());
+		pack();
+		setResizable(false);
+		updateComponents();
+		setLayoutForSelectedGroup();
+		Util.placeDialog(this, m_parent);
+
+		// add listeners
+		ItemListener radioButtonItemListener = new ItemListener() {
+			public void itemStateChanged(ItemEvent e) {
+				setLayoutForSelectedGroup();
+				updateComponents();
+			}
+		};
+		m_explicitRadioButton.addItemListener(radioButtonItemListener);
+		m_keywordsRadioButton.addItemListener(radioButtonItemListener);
+		m_searchRadioButton.addItemListener(radioButtonItemListener);
+
+		m_cancel.addActionListener(new ActionListener() {
+			public void actionPerformed(ActionEvent e) {
+				dispose();
+			}
+		});
+
+		m_ok.addActionListener(new ActionListener() {
+			public void actionPerformed(ActionEvent e) {
+				m_okPressed = true;
+				if (m_explicitRadioButton.isSelected()) {
+					if (m_editedGroup instanceof ExplicitGroup) {
+						// keep assignments from possible previous ExplicitGroup
+						m_resultingGroup = m_editedGroup.deepCopy();
+						m_resultingGroup.setName(m_name.getText().trim());
+						m_resultingGroup.setHierarchicalContext(getContext());
+					} else {
+						m_resultingGroup = new ExplicitGroup(m_name.getText()
+								.trim(), getContext());
+						if (m_editedGroup != null)
+							addPreviousEntries();
+					}
+				} else if (m_keywordsRadioButton.isSelected()) {
+					// regex is correct, otherwise OK would have been disabled
+					// therefore I don't catch anything here
+					m_resultingGroup = new KeywordGroup(
+							m_name.getText().trim(), m_kgSearchField.getText()
+									.trim(), m_kgSearchTerm.getText().trim(),
+							m_kgCaseSensitive.isSelected(), m_kgRegExp
+									.isSelected(), getContext());
+					if ((m_editedGroup instanceof ExplicitGroup || m_editedGroup instanceof SearchGroup)
+							&& m_resultingGroup.supportsAdd()) {
+						addPreviousEntries();
+					}
+				} else if (m_searchRadioButton.isSelected()) {
+					try {
+						// regex is correct, otherwise OK would have been
+						// disabled
+						// therefore I don't catch anything here
+						m_resultingGroup = new SearchGroup(m_name.getText()
+								.trim(), m_sgSearchExpression.getText().trim(),
+								m_sgCaseSensitive.isSelected(), m_sgRegExp
+										.isSelected(), getContext());
+					} catch (Exception e1) {
+						// should never happen
+					}
+				}
+				dispose();
+			}
+		});
+
+		CaretListener caretListener = new CaretListener() {
+			public void caretUpdate(CaretEvent e) {
+				updateComponents();
+			}
+		};
+
+		ItemListener itemListener = new ItemListener() {
+			public void itemStateChanged(ItemEvent e) {
+				updateComponents();
+			}
+		};
+
+		m_name.addCaretListener(caretListener);
+		m_kgSearchField.addCaretListener(caretListener);
+		m_kgSearchTerm.addCaretListener(caretListener);
+		m_kgCaseSensitive.addItemListener(itemListener);
+		m_kgRegExp.addItemListener(itemListener);
+		m_sgSearchExpression.addCaretListener(caretListener);
+		m_sgRegExp.addItemListener(itemListener);
+		m_sgCaseSensitive.addItemListener(itemListener);
+
+		// configure for current type
+		if (editedGroup instanceof KeywordGroup) {
+			KeywordGroup group = (KeywordGroup) editedGroup;
+			m_name.setText(group.getName());
+			m_kgSearchField.setText(group.getSearchField());
+			m_kgSearchTerm.setText(group.getSearchExpression());
+			m_kgCaseSensitive.setSelected(group.isCaseSensitive());
+			m_kgRegExp.setSelected(group.isRegExp());
+			m_keywordsRadioButton.setSelected(true);
+			setContext(editedGroup.getHierarchicalContext());
+		} else if (editedGroup instanceof SearchGroup) {
+			SearchGroup group = (SearchGroup) editedGroup;
+			m_name.setText(group.getName());
+			m_sgSearchExpression.setText(group.getSearchExpression());
+			m_sgCaseSensitive.setSelected(group.isCaseSensitive());
+			m_sgRegExp.setSelected(group.isRegExp());
+			m_searchRadioButton.setSelected(true);
+			setContext(editedGroup.getHierarchicalContext());
+		} else if (editedGroup instanceof ExplicitGroup) {
+			m_name.setText(editedGroup.getName());
+			m_explicitRadioButton.setSelected(true);
+			setContext(editedGroup.getHierarchicalContext());
+		} else { // creating new group -> defaults!
+			m_explicitRadioButton.setSelected(true);
+			setContext(AbstractGroup.INDEPENDENT);
+		}
+	}
+
+	public boolean okPressed() {
+		return m_okPressed;
+	}
+
+	public AbstractGroup getResultingGroup() {
+		return m_resultingGroup;
+	}
+
+	private void setLayoutForSelectedGroup() {
+		if (m_explicitRadioButton.isSelected())
+			m_optionsLayout.show(m_optionsPanel, String
+					.valueOf(INDEX_EXPLICITGROUP));
+		else if (m_keywordsRadioButton.isSelected())
+			m_optionsLayout.show(m_optionsPanel, String
+					.valueOf(INDEX_KEYWORDGROUP));
+		else if (m_searchRadioButton.isSelected())
+			m_optionsLayout.show(m_optionsPanel, String
+					.valueOf(INDEX_SEARCHGROUP));
+	}
+
+	private void updateComponents() {
+		// all groups need a name
+		boolean okEnabled = m_name.getText().trim().length() > 0;
+		if (!okEnabled) {
+			setDescription(Globals.lang("Please enter a name for the group."));
+			m_ok.setEnabled(false);
+			return;
+		}
+		String s1, s2;
+		if (m_keywordsRadioButton.isSelected()) {
+			s1 = m_kgSearchField.getText().trim();
+			okEnabled = okEnabled && s1.matches("\\w+");
+			s2 = m_kgSearchTerm.getText().trim();
+			okEnabled = okEnabled && s2.length() > 0;
+			if (!okEnabled) {
+				setDescription(Globals
+						.lang("Please enter the field to search (e.g. <b>keywords</b>) and the keyword to search it for (e.g. <b>electrical</b>)."));
+			} else {
+				if (m_kgRegExp.isSelected()) {
+					try {
+						Pattern.compile(s2);
+						setDescription(KeywordGroup.getDescriptionForPreview(s1, s2,
+								m_kgCaseSensitive.isSelected(), m_kgRegExp
+										.isSelected()));
+					} catch (Exception e) {
+						okEnabled = false;
+						setDescription(formatRegExException(s2, e));
+					}
+				} else {
+					setDescription(KeywordGroup.getDescriptionForPreview(s1, s2,
+							m_kgCaseSensitive.isSelected(), m_kgRegExp
+									.isSelected()));
+				}
+			}
+			setNameFontItalic(true);
+		} else if (m_searchRadioButton.isSelected()) {
+			s1 = m_sgSearchExpression.getText().trim();
+			okEnabled = okEnabled & s1.length() > 0;
+			if (!okEnabled) {
+				setDescription(Globals
+						.lang("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>"));
+			} else {
+				AST ast = SearchExpressionParser
+						.checkSyntax(s1, m_sgCaseSensitive.isSelected(),
+								m_sgRegExp.isSelected());
+				setDescription(SearchGroup.getDescriptionForPreview(s1, ast,
+						m_sgCaseSensitive.isSelected(), m_sgRegExp.isSelected()));
+				if (m_sgRegExp.isSelected()) {
+					try {
+						Pattern.compile(s1);
+					} catch (Exception e) {
+						okEnabled = false;
+						setDescription(formatRegExException(s1, e));
+					}
+				}
+			}
+			setNameFontItalic(true);
+		} else if (m_explicitRadioButton.isSelected()) {
+			setDescription(ExplicitGroup.getDescriptionForPreview());
+			setNameFontItalic(false);
+		}
+		m_ok.setEnabled(okEnabled);
+	}
+
+	/**
+	 * This is used when a group is converted and the new group supports
+	 * explicit adding of entries: All entries that match the previous group are
+	 * added to the new group.
+	 */
+	private void addPreviousEntries() {
+		// JZTODO lyrics...
+		int i = JOptionPane.showConfirmDialog(m_basePanel.frame(), Globals
+				.lang("Assign the original group's entries to this group?"),
+				Globals.lang("Change of Grouping Method"),
+				JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
+		if (i == JOptionPane.NO_OPTION)
+			return;
+		BibtexEntry entry;
+		Vector vec = new Vector();
+		for (Iterator it = m_basePanel.database().getEntries().iterator(); it
+				.hasNext();) {
+			entry = (BibtexEntry) it.next();
+			if (m_editedGroup.contains(entry))
+				vec.add(entry);
+		}
+		if (vec.size() > 0) {
+			BibtexEntry[] entries = new BibtexEntry[vec.size()];
+			vec.toArray(entries);
+			if (!Util.warnAssignmentSideEffects(new AbstractGroup[]{m_resultingGroup}, 
+					entries, m_basePanel.getDatabase(), this))
+				return;
+			// the undo information for a conversion to an ExplicitGroup is
+			// contained completely in the UndoableModifyGroup object.
+			if (!(m_resultingGroup instanceof ExplicitGroup))
+				m_undoAddPreviousEntires = m_resultingGroup.add(entries);
+		}
+	}
+
+	protected void setDescription(String description) {
+		m_description.setText("<html>" + description + "</html>");
+	}
+
+	protected String formatRegExException(String regExp, Exception e) {
+        String[] sa = e.getMessage().split("\\n");
+        StringBuffer sb = new StringBuffer();
+        for (int i = 0; i < sa.length; ++i) {
+            if (i > 0)
+                sb.append("<br>");
+            sb.append(Util.quoteForHTML(sa[i]));
+        }
+		String s = Globals.lang(
+				"The regular expression <b>%0</b> is invalid%c", 
+                Util.quoteForHTML(regExp))
+				+ "<p><tt>"
+				+ sb.toString()
+				+ "</tt>";
+		if (!(e instanceof PatternSyntaxException))
+			return s;
+		int lastNewline = s.lastIndexOf("<br>");
+		int hat = s.lastIndexOf("^");
+		if (lastNewline >= 0 && hat >= 0 && hat > lastNewline)
+			return s.substring(0, lastNewline + 4)
+					+ s.substring(lastNewline + 4).replaceAll(" ", " ");
+		return s;
+	}
+
+	/**
+	 * Returns an undo object for adding the edited group's entries to the new
+	 * group, or null if this did not occur.
+	 */
+	public AbstractUndoableEdit getUndoForAddPreviousEntries() {
+		return m_undoAddPreviousEntires;
+	}
+
+	/** Sets the font of the name entry field. */
+	protected void setNameFontItalic(boolean italic) {
+		Font f = m_name.getFont();
+		if (f.isItalic() != italic) {
+			f = f.deriveFont(italic ? Font.ITALIC : Font.PLAIN);
+			m_name.setFont(f);
+		}
+	}
+
+	/**
+	 * Returns the int representing the selected hierarchical group context.
+	 */
+	protected int getContext() {
+		if (m_independentButton.isSelected())
+			return AbstractGroup.INDEPENDENT;
+		if (m_intersectionButton.isSelected())
+			return AbstractGroup.REFINING;
+		if (m_unionButton.isSelected())
+			return AbstractGroup.INCLUDING;
+		return AbstractGroup.INDEPENDENT; // default
+	}
+	
+	protected void setContext(int context) {
+		switch (context) {
+		case AbstractGroup.REFINING:
+			m_intersectionButton.setSelected(true);
+			return;
+		case AbstractGroup.INCLUDING:
+			m_unionButton.setSelected(true);
+			return;
+		case AbstractGroup.INDEPENDENT:
+		default:
+			m_independentButton.setSelected(true);
+			return;
+		}
+	}
+
+}
diff --git a/src/java/net/sf/jabref/groups/GroupMatcher.java b/src/java/net/sf/jabref/groups/GroupMatcher.java
new file mode 100644
index 0000000..2874c91
--- /dev/null
+++ b/src/java/net/sf/jabref/groups/GroupMatcher.java
@@ -0,0 +1,19 @@
+package net.sf.jabref.groups;
+
+import ca.odell.glazedlists.matchers.Matcher;
+import net.sf.jabref.BibtexEntry;
+
+/**
+ * Matcher for filtering or sorting the table according to whether entries
+ * are tagged as group matches.
+ */
+public class GroupMatcher implements Matcher {
+
+    public static GroupMatcher INSTANCE = new GroupMatcher();
+
+    public boolean matches(Object object) {
+        BibtexEntry entry = (BibtexEntry)object;
+        return entry.isGroupHit();
+    }
+}
+
diff --git a/src/java/net/sf/jabref/groups/GroupSelector.java b/src/java/net/sf/jabref/groups/GroupSelector.java
new file mode 100644
index 0000000..8875fd4
--- /dev/null
+++ b/src/java/net/sf/jabref/groups/GroupSelector.java
@@ -0,0 +1,1265 @@
+/*
+ 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.
+
+ 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.groups;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.util.*;
+import java.util.List;
+
+import javax.swing.*;
+import javax.swing.event.*;
+import javax.swing.tree.*;
+import javax.swing.undo.*;
+
+import net.sf.jabref.*;
+import net.sf.jabref.search.SearchMatcher;
+import net.sf.jabref.undo.NamedCompound;
+
+public class GroupSelector extends SidePaneComponent implements
+        TreeSelectionListener, ActionListener, ErrorMessageDisplay {
+    JButton newButton = new JButton(new ImageIcon(GUIGlobals.newSmallIconFile)),
+            helpButton = new JButton(
+                    new ImageIcon(GUIGlobals.helpSmallIconFile)),
+            refresh = new JButton(
+                    new ImageIcon(GUIGlobals.refreshSmallIconFile)),
+            autoGroup = new JButton(new ImageIcon(GUIGlobals.autoGroupIcon)),
+            openset = new JButton(Globals.lang("Settings"));
+    Color bgColor = Color.white;
+    GroupsTree groupsTree;
+    DefaultTreeModel groupsTreeModel;
+    GroupTreeNode groupsRoot;
+    JScrollPane sp;
+    GridBagLayout gbl = new GridBagLayout();
+    GridBagConstraints con = new GridBagConstraints();
+    JabRefFrame frame;
+
+    String searchField;
+    JPopupMenu groupsContextMenu = new JPopupMenu();
+    JPopupMenu settings = new JPopupMenu();
+    private JRadioButtonMenuItem hideNonHits, grayOut;
+    JRadioButtonMenuItem andCb = new JRadioButtonMenuItem(Globals
+            .lang("Intersection"), true);
+    JRadioButtonMenuItem orCb = new JRadioButtonMenuItem(Globals.lang("Union"),
+            false);
+    JRadioButtonMenuItem floatCb = new JRadioButtonMenuItem(Globals
+            .lang("Float"), true);
+    JRadioButtonMenuItem highlCb = new JRadioButtonMenuItem(Globals
+            .lang("Highlight"), false);
+    JCheckBoxMenuItem invCb = new JCheckBoxMenuItem(Globals.lang("Inverted"),
+            false), select = new JCheckBoxMenuItem(Globals
+            .lang("Select matches"), false);
+    JCheckBoxMenuItem showOverlappingGroups = new JCheckBoxMenuItem(
+    		Globals.lang("Highlight overlapping groups")); // JZTODO lyrics
+    ButtonGroup bgr = new ButtonGroup();
+    ButtonGroup visMode = new ButtonGroup();
+    ButtonGroup nonHits = new ButtonGroup();
+    JButton expand = new JButton(new ImageIcon(GUIGlobals.downIconFile)),
+            reduce = new JButton(new ImageIcon(GUIGlobals.upIconFile));
+    SidePaneManager manager;
+
+
+    /**
+     * The first element for each group defines which field to use for the
+     * quicksearch. The next two define the name and regexp for the group.
+     * 
+     * @param groupData
+     *            The group meta data in raw format.
+     */
+    public GroupSelector(JabRefFrame frame, SidePaneManager manager) {
+        super(manager, GUIGlobals.groupsIconFile, Globals.lang("Groups"));
+        this.groupsRoot = new GroupTreeNode(new AllEntriesGroup());
+
+        this.manager = manager;
+        this.frame = frame;
+        hideNonHits = new JRadioButtonMenuItem(Globals.lang("Hide non-hits"),
+                !Globals.prefs.getBoolean("grayOutNonHits"));
+        grayOut = new JRadioButtonMenuItem(Globals.lang("Gray out non-hits"),
+                Globals.prefs.getBoolean("grayOutNonHits"));
+        nonHits.add(hideNonHits);
+        nonHits.add(grayOut);
+        floatCb.addChangeListener(new ChangeListener() {
+            public void stateChanged(ChangeEvent event) {
+                Globals.prefs.putBoolean("groupFloatSelections", floatCb.isSelected());
+            }
+        });
+        andCb.addChangeListener(new ChangeListener() {
+            public void stateChanged(ChangeEvent event) {
+                Globals.prefs.putBoolean("groupIntersectSelections", andCb
+                        .isSelected());
+            }
+        });
+        invCb.addChangeListener(new ChangeListener() {
+            public void stateChanged(ChangeEvent event) {
+                Globals.prefs.putBoolean("groupInvertSelections", invCb.isSelected());
+            }
+        });
+        showOverlappingGroups.addChangeListener(new ChangeListener() {
+            public void stateChanged(ChangeEvent event) {
+                Globals.prefs.putBoolean("groupShowOverlapping", 
+                		showOverlappingGroups.isSelected());
+                if (!showOverlappingGroups.isSelected())
+                    groupsTree.setHighlight2Cells(null);
+            }
+        });
+
+        select.addChangeListener(new ChangeListener() {
+            public void stateChanged(ChangeEvent event) {
+                Globals.prefs.putBoolean("groupSelectMatches", select.isSelected());
+            }
+        });
+        grayOut.addChangeListener(new ChangeListener() {
+            public void stateChanged(ChangeEvent event) {
+                Globals.prefs.putBoolean("grayOutNonHits", grayOut.isSelected());
+            }
+        });
+        
+        if (Globals.prefs.getBoolean("groupFloatSelections")) {
+
+            floatCb.setSelected(true);
+            highlCb.setSelected(false);
+        } else {
+            highlCb.setSelected(true);
+            floatCb.setSelected(false);
+        }
+        if (Globals.prefs.getBoolean("groupIntersectSelections")) {
+            andCb.setSelected(true);
+            orCb.setSelected(false);
+        } else {
+            orCb.setSelected(true);
+            andCb.setSelected(false);
+        }
+        
+        invCb.setSelected(Globals.prefs.getBoolean("groupInvertSelections"));
+        showOverlappingGroups.setSelected(Globals.prefs.getBoolean("groupShowOverlapping"));
+        select.setSelected(Globals.prefs.getBoolean("groupSelectMatches"));
+
+        openset.setMargin(new Insets(0, 0, 0, 0));
+        settings.add(andCb);
+        settings.add(orCb);
+        settings.addSeparator();
+        settings.add(invCb);
+        settings.addSeparator();
+        //settings.add(highlCb);
+        //settings.add(floatCb);
+        //settings.addSeparator();
+        settings.add(select);
+        settings.addSeparator();
+        settings.add(grayOut);
+        settings.add(hideNonHits);
+        settings.addSeparator();
+        settings.add(showOverlappingGroups);
+
+        // settings.add(moreRow);
+        // settings.add(lessRow);
+        openset.addActionListener(new ActionListener() {
+            public void actionPerformed(ActionEvent e) {
+                if (settings.isVisible()) {
+                    // System.out.println("oee");
+                    // settings.setVisible(false);
+                } else {
+                    JButton src = (JButton) e.getSource();
+                    settings.show(src, 0, openset.getHeight());
+                }
+            }
+        });
+        expand.addActionListener(new ActionListener() {
+            public void actionPerformed(ActionEvent e) {
+                int i = Globals.prefs.getInt("groupsVisibleRows") + 1;
+                groupsTree.setVisibleRowCount(i);
+                groupsTree.revalidate();
+                groupsTree.repaint();
+                GroupSelector.this.revalidate();
+                GroupSelector.this.repaint();
+                Globals.prefs.putInt("groupsVisibleRows", i);
+            }
+        });
+        reduce.addActionListener(new ActionListener() {
+            public void actionPerformed(ActionEvent e) {
+                int i = Globals.prefs.getInt("groupsVisibleRows") - 1;
+                if (i < 1)
+                    i = 1;
+                groupsTree.setVisibleRowCount(i);
+                groupsTree.revalidate();
+                groupsTree.repaint();
+                GroupSelector.this.revalidate();
+                // _panel.sidePaneManager.revalidate();
+                GroupSelector.this.repaint();
+                Globals.prefs.putInt("groupsVisibleRows", i);
+            }
+        });
+        Dimension butDim = new Dimension(20, 20);
+        Dimension butDim2 = new Dimension(40, 20);
+        newButton.setPreferredSize(butDim);
+        newButton.setMinimumSize(butDim);
+        refresh.setPreferredSize(butDim);
+        refresh.setMinimumSize(butDim);
+        helpButton.setPreferredSize(butDim);
+        helpButton.setMinimumSize(butDim);
+        autoGroup.setPreferredSize(butDim);
+        autoGroup.setMinimumSize(butDim);
+        openset.setPreferredSize(butDim2);
+        openset.setMinimumSize(butDim2);
+        expand.setPreferredSize(butDim);
+        expand.setMinimumSize(butDim);
+        reduce.setPreferredSize(butDim);
+        reduce.setMinimumSize(butDim);
+        Insets butIns = new Insets(0, 0, 0, 0);
+        helpButton.setMargin(butIns);
+        reduce.setMargin(butIns);
+        expand.setMargin(butIns);
+        openset.setMargin(butIns);
+        newButton.addActionListener(this);
+        refresh.addActionListener(this);
+        andCb.addActionListener(this);
+        orCb.addActionListener(this);
+        invCb.addActionListener(this);
+        showOverlappingGroups.addActionListener(this);
+        autoGroup.addActionListener(this);
+        floatCb.addActionListener(this);
+        highlCb.addActionListener(this);
+        select.addActionListener(this);
+        hideNonHits.addActionListener(this);
+        grayOut.addActionListener(this);
+        newButton.setToolTipText(Globals.lang("New group"));
+        refresh.setToolTipText(Globals.lang("Refresh view"));
+        andCb.setToolTipText(Globals
+                .lang("Display only entries belonging to all selected"
+                        + " groups."));
+        orCb.setToolTipText(Globals
+                .lang("Display all entries belonging to one or more "
+                        + "of the selected groups."));
+        autoGroup.setToolTipText(Globals
+                .lang("Automatically create groups for database."));
+        invCb.setToolTipText(Globals
+                .lang("Show entries *not* in group selection"));
+        showOverlappingGroups.setToolTipText( // JZTODO lyrics
+        		"Highlight groups that contain entries contained in any currently selected group");
+        floatCb.setToolTipText(Globals
+                .lang("Move entries in group selection to the top"));
+        highlCb.setToolTipText(Globals
+                .lang("Gray out entries not in group selection"));
+        select
+                .setToolTipText(Globals
+                        .lang("Select entries in group selection"));
+        expand.setToolTipText(Globals.lang("Show one more row"));
+        reduce.setToolTipText(Globals.lang("Show one less rows"));
+        bgr.add(andCb);
+        bgr.add(orCb);
+        visMode.add(floatCb);
+        visMode.add(highlCb);
+        JPanel main = new JPanel();
+        main.setLayout(gbl);
+        /*SidePaneHeader header = new SidePaneHeader("Groups",
+                GUIGlobals.groupsIconFile, this);
+        con.gridwidth = GridBagConstraints.REMAINDER;
+        gbl.setConstraints(header, con);
+        main.add(header);*/
+        con.fill = GridBagConstraints.BOTH;
+        //con.insets = new Insets(0, 0, 2, 0);
+        con.weightx = 1;
+        con.gridwidth = 1;
+        //con.insets = new Insets(1, 1, 1, 1);
+        gbl.setConstraints(newButton, con);
+        main.add(newButton);
+        gbl.setConstraints(refresh, con);
+        main.add(refresh);
+        gbl.setConstraints(autoGroup, con);
+        main.add(autoGroup);
+        con.gridwidth = GridBagConstraints.REMAINDER;
+        HelpAction helpAction = new HelpAction(frame.helpDiag,
+                GUIGlobals.groupsHelp, "Help on groups");
+        helpButton.addActionListener(helpAction);
+        helpButton.setToolTipText(Globals.lang("Help on groups"));
+        gbl.setConstraints(helpButton, con);
+        main.add(helpButton);
+        // header.setBorder(BorderFactory.createMatteBorder(1,1,1,1,Color.red));
+        // helpButton.setBorder(BorderFactory.createMatteBorder(1,1,1,1,Color.red));
+        groupsTree = new GroupsTree(this);
+        groupsTree.addTreeSelectionListener(this);
+        groupsTree.setModel(groupsTreeModel = new DefaultTreeModel(groupsRoot));
+        sp = new JScrollPane(groupsTree,
+                JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
+                JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
+        revalidateGroups();
+        con.gridwidth = GridBagConstraints.REMAINDER;
+        con.weighty = 1;
+        gbl.setConstraints(sp, con);
+        main.add(sp);
+        JPanel pan = new JPanel();
+        GridBagLayout gb = new GridBagLayout();
+        con.weighty = 0;
+        gbl.setConstraints(pan, con);
+        pan.setLayout(gb);
+        con.weightx = 1;
+        con.gridwidth = 1;
+        gb.setConstraints(openset, con);
+        pan.add(openset);
+        con.weightx = 0;
+        gb.setConstraints(expand, con);
+        pan.add(expand);
+        con.gridwidth = GridBagConstraints.REMAINDER;
+        gb.setConstraints(reduce, con);
+        pan.add(reduce);
+        main.add(pan);
+        main.setBorder(BorderFactory.createEmptyBorder(1,1,1,1));
+        add(main, BorderLayout.CENTER);
+        definePopup();
+        moveNodeUpAction.putValue(Action.ACCELERATOR_KEY, 
+                KeyStroke.getKeyStroke(KeyEvent.VK_UP, KeyEvent.CTRL_MASK));
+        moveNodeDownAction.putValue(Action.ACCELERATOR_KEY, 
+                KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, KeyEvent.CTRL_MASK));
+        moveNodeLeftAction.putValue(Action.ACCELERATOR_KEY, 
+                KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, KeyEvent.CTRL_MASK));
+        moveNodeRightAction.putValue(Action.ACCELERATOR_KEY, 
+                KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, KeyEvent.CTRL_MASK));
+    }
+
+    private void definePopup() {
+        // These key bindings are just to have the shortcuts displayed
+        // in the popup menu. The actual keystroke processing is in 
+        // BasePanel (entryTable.addKeyListener(...)).
+        groupsContextMenu.add(editGroupPopupAction);
+        groupsContextMenu.add(addGroupPopupAction);
+        groupsContextMenu.add(addSubgroupPopupAction);
+        groupsContextMenu.addSeparator();
+        groupsContextMenu.add(removeGroupAndSubgroupsPopupAction);
+        groupsContextMenu.add(removeGroupKeepSubgroupsPopupAction);
+        groupsContextMenu.add(removeSubgroupsPopupAction);
+        groupsContextMenu.addSeparator();
+        groupsContextMenu.add(expandSubtreePopupAction);
+        groupsContextMenu.add(collapseSubtreePopupAction);
+        groupsContextMenu.addSeparator();
+        groupsContextMenu.add(moveSubmenu);
+        sortSubmenu.add(sortDirectSubgroupsPopupAction);
+        sortSubmenu.add(sortAllSubgroupsPopupAction);
+        groupsContextMenu.add(sortSubmenu);
+        moveSubmenu.add(moveNodeUpPopupAction);
+        moveSubmenu.add(moveNodeDownPopupAction);
+        moveSubmenu.add(moveNodeLeftPopupAction);
+        moveSubmenu.add(moveNodeRightPopupAction);
+        groupsContextMenu.addSeparator();
+        groupsContextMenu.add(addToGroup);
+        groupsContextMenu.add(moveToGroup);
+        groupsContextMenu.add(removeFromGroup);
+        groupsTree.addMouseListener(new MouseAdapter() {
+            public void mousePressed(MouseEvent e) {
+                if (e.isPopupTrigger())
+                    showPopup(e);
+            }
+
+            public void mouseReleased(MouseEvent e) {
+                if (e.isPopupTrigger())
+                    showPopup(e);
+            }
+
+            public void mouseClicked(MouseEvent e) {
+                TreePath path = groupsTree.getPathForLocation(e.getPoint().x, e
+                        .getPoint().y);
+                if (path == null)
+                    return;
+                GroupTreeNode node = (GroupTreeNode) path
+                        .getLastPathComponent();
+                // the root node is "AllEntries" and cannot be edited
+                if (node.isRoot())
+                    return;
+                if (e.getClickCount() == 2
+                        && e.getButton() == MouseEvent.BUTTON1) { // edit
+                    editGroupAction.actionPerformed(null); // dummy event
+                }
+            }
+        });
+        // be sure to remove a possible border highlight when the popup menu
+        // disappears
+        groupsContextMenu.addPopupMenuListener(new PopupMenuListener() {
+            public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
+                // nothing to do
+            }
+            public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
+                groupsTree.setHighlightBorderCell(null);
+            }
+            public void popupMenuCanceled(PopupMenuEvent e) {
+                groupsTree.setHighlightBorderCell(null);
+            }            
+        });
+    }
+
+    private void showPopup(MouseEvent e) {
+        final TreePath path = groupsTree.getPathForLocation(e.getPoint().x, e
+                .getPoint().y);
+        addGroupPopupAction.setEnabled(true);
+        addSubgroupPopupAction.setEnabled(path != null);
+        editGroupPopupAction.setEnabled(path != null);
+        removeGroupAndSubgroupsPopupAction.setEnabled(path != null);
+        removeGroupKeepSubgroupsPopupAction.setEnabled(path != null);
+        moveSubmenu.setEnabled(path != null);
+        expandSubtreePopupAction.setEnabled(path != null);
+        collapseSubtreePopupAction.setEnabled(path != null);
+        removeSubgroupsPopupAction.setEnabled(path != null);
+        sortSubmenu.setEnabled(path != null);
+        addToGroup.setEnabled(false);
+        moveToGroup.setEnabled(false);
+        removeFromGroup.setEnabled(false);
+        if (path != null) { // some path dependent enabling/disabling
+            GroupTreeNode node = (GroupTreeNode) path.getLastPathComponent();
+            editGroupPopupAction.setNode(node);
+            addSubgroupPopupAction.setNode(node);
+            removeGroupAndSubgroupsPopupAction.setNode(node);
+            removeSubgroupsPopupAction.setNode(node);
+            removeGroupKeepSubgroupsPopupAction.setNode(node);
+            expandSubtreePopupAction.setNode(node);
+            collapseSubtreePopupAction.setNode(node);
+            sortDirectSubgroupsPopupAction.setNode(node);
+            sortAllSubgroupsPopupAction.setNode(node);
+            groupsTree.setHighlightBorderCell(node);
+            AbstractGroup group = node.getGroup();
+            if (group instanceof AllEntriesGroup) {
+                editGroupPopupAction.setEnabled(false);
+                addGroupPopupAction.setEnabled(false);
+                removeGroupAndSubgroupsPopupAction.setEnabled(false);
+                removeGroupKeepSubgroupsPopupAction.setEnabled(false);
+            } else {
+                editGroupPopupAction.setEnabled(true);
+                addGroupPopupAction.setEnabled(true);
+                addGroupPopupAction.setNode(node);
+                removeGroupAndSubgroupsPopupAction.setEnabled(true);
+                removeGroupKeepSubgroupsPopupAction.setEnabled(true);
+            }
+			expandSubtreePopupAction.setEnabled(groupsTree.isCollapsed(path) ||
+					groupsTree.hasCollapsedDescendant(path));
+			collapseSubtreePopupAction.setEnabled(groupsTree.isExpanded(path) ||
+					groupsTree.hasExpandedDescendant(path));
+            sortSubmenu.setEnabled(!node.isLeaf());
+            removeSubgroupsPopupAction.setEnabled(!node.isLeaf());
+            moveNodeUpPopupAction.setEnabled(node.canMoveUp());
+            moveNodeDownPopupAction.setEnabled(node.canMoveDown());
+            moveNodeLeftPopupAction.setEnabled(node.canMoveLeft());
+            moveNodeRightPopupAction.setEnabled(node.canMoveRight());
+            moveSubmenu.setEnabled(moveNodeUpPopupAction.isEnabled()
+                    || moveNodeDownPopupAction.isEnabled() 
+                    || moveNodeLeftPopupAction.isEnabled()
+                    || moveNodeRightPopupAction.isEnabled());
+            moveNodeUpPopupAction.setNode(node);
+            moveNodeDownPopupAction.setNode(node);
+            moveNodeLeftPopupAction.setNode(node);
+            moveNodeRightPopupAction.setNode(node);
+            // add/remove entries to/from group
+            BibtexEntry[] selection = frame.basePanel().getSelectedEntries();
+            if (selection.length > 0) {
+                if (node.getGroup().supportsAdd() && !node.getGroup().
+                        containsAll(selection)) {
+                    addToGroup.setNode(node);
+                    addToGroup.setBasePanel(panel);
+                    addToGroup.setEnabled(true);
+                    moveToGroup.setNode(node);
+                    moveToGroup.setBasePanel(panel);
+                    moveToGroup.setEnabled(true);
+                }
+                if (node.getGroup().supportsRemove() && node.getGroup().
+                        containsAny(selection)) {
+                    removeFromGroup.setNode(node);
+                    removeFromGroup.setBasePanel(panel);
+                    removeFromGroup.setEnabled(true);
+                }
+            }
+        } else {
+            editGroupPopupAction.setNode(null);
+            addGroupPopupAction.setNode(null);
+            addSubgroupPopupAction.setNode(null);
+            removeGroupAndSubgroupsPopupAction.setNode(null);
+            removeSubgroupsPopupAction.setNode(null);
+            removeGroupKeepSubgroupsPopupAction.setNode(null);
+            moveNodeUpPopupAction.setNode(null);
+            moveNodeDownPopupAction.setNode(null);
+            moveNodeLeftPopupAction.setNode(null);
+            moveNodeRightPopupAction.setNode(null);
+            expandSubtreePopupAction.setNode(null);
+            collapseSubtreePopupAction.setNode(null);
+            sortDirectSubgroupsPopupAction.setNode(null);
+            sortAllSubgroupsPopupAction.setNode(null);
+        }
+        groupsContextMenu.show(groupsTree, e.getPoint().x, e.getPoint().y);
+    }
+
+    public void valueChanged(TreeSelectionEvent e) {
+        if (panel == null) // sorry, we're closed!
+            return; // ignore this event
+        final TreePath[] selection = groupsTree.getSelectionPaths();
+        if (selection == null
+                || selection.length == 0
+                || (selection.length == 1 && ((GroupTreeNode) selection[0]
+                        .getLastPathComponent()).getGroup() instanceof AllEntriesGroup)) {
+            panel.stopShowingGroup();
+            panel.mainTable.stopShowingFloatGrouping();
+            if (showOverlappingGroups.isSelected())
+                groupsTree.setHighlight2Cells(null);
+            frame.output(Globals.lang("Displaying no groups") + ".");
+            return;
+        }
+        final AndOrSearchRuleSet searchRules = new AndOrSearchRuleSet(andCb
+                .isSelected(), invCb.isSelected());
+
+        for (int i = 0; i < selection.length; ++i) {
+			searchRules.addRule(((GroupTreeNode) selection[i]
+					.getLastPathComponent()).getSearchRule());
+		}
+        Hashtable searchOptions = new Hashtable();
+        searchOptions.put("option", "dummy");
+        GroupingWorker worker = new GroupingWorker(searchRules, searchOptions);
+        worker.getWorker().run();
+        worker.getCallBack().update();
+        /*panel.setGroupMatcher(new SearchMatcher(searchRules, searchOptions));
+        DatabaseSearch search = new DatabaseSearch(this, searchOptions, searchRules,
+                panel, Globals.GROUPSEARCH, floatCb.isSelected(), Globals.prefs
+                        .getBoolean("grayOutNonHits"),
+                //true,
+                select.isSelected());
+        search.start();*/
+
+
+    }
+
+    class GroupingWorker extends AbstractWorker {
+        private SearchRuleSet rules;
+        private Hashtable searchTerm;
+        private ArrayList matches = new ArrayList();
+        private boolean showOverlappingGroupsP;
+        int hits = 0;
+
+        public GroupingWorker(SearchRuleSet rules, Hashtable searchTerm) {
+            this.rules = rules;
+            this.searchTerm = searchTerm;
+            showOverlappingGroupsP = showOverlappingGroups.isSelected();
+        }
+
+        public void run() {
+            Collection entries = panel.getDatabase().getEntries();
+            for (Iterator i = entries.iterator(); i.hasNext();) {
+                BibtexEntry entry = (BibtexEntry) i.next();
+                boolean hit = rules.applyRule(searchTerm, entry) > 0;
+                entry.setGroupHit(hit);
+                if (hit) {
+                    hits++;
+                    if (showOverlappingGroupsP)
+                        matches.add(entry);
+                }
+            }
+        }
+
+        public void update() {
+            // Show the result in the chosen way:
+            if (hideNonHits.isSelected()) {
+                panel.mainTable.stopShowingFloatGrouping(); // Turn off shading, if active.
+                panel.setGroupMatcher(GroupMatcher.INSTANCE); // Turn on filtering.
+
+            }
+            else if (grayOut.isSelected()) {
+                panel.stopShowingGroup(); // Turn off filtering, if active.
+                panel.mainTable.showFloatGrouping(GroupMatcher.INSTANCE); // Turn on shading.
+            }
+
+            if (showOverlappingGroupsP) {
+				showOverlappingGroups(matches);
+        }
+            frame.output(Globals.lang("Updated group selection") + ".");
+        }
+    }
+
+    /** 
+     * Revalidate the groups tree (e.g. after the data stored in the model has
+     * been changed) and set the specified selection and expansion state. */
+    public void revalidateGroups(TreePath[] selectionPaths, 
+            Enumeration expandedNodes) {
+        groupsTreeModel.reload();
+        groupsTree.clearSelection();
+        if (selectionPaths != null) {
+            groupsTree.setSelectionPaths(selectionPaths);
+        }
+        // tree is completely collapsed here
+        if (expandedNodes != null) {
+            while (expandedNodes.hasMoreElements())
+                groupsTree.expandPath((TreePath)expandedNodes.nextElement());
+        }
+        groupsTree.revalidate();
+    }
+    
+    /** 
+     * Revalidate the groups tree (e.g. after the data stored in the model has
+     * been changed) and maintain the current selection and expansion state. */
+    public void revalidateGroups() {
+        revalidateGroups(groupsTree.getSelectionPaths(),getExpandedPaths());
+    }
+
+    public void actionPerformed(ActionEvent e) {
+        if (e.getSource() == refresh) {
+            valueChanged(null);
+        } else if (e.getSource() == newButton) {
+            GroupDialog gd = new GroupDialog(frame, panel, null);
+            gd.show();
+            if (gd.okPressed()) {
+                AbstractGroup newGroup = gd.getResultingGroup();
+                GroupTreeNode newNode = new GroupTreeNode(newGroup);
+                groupsRoot.add(newNode);
+                revalidateGroups();
+                UndoableAddOrRemoveGroup undo = new UndoableAddOrRemoveGroup(
+                        GroupSelector.this, groupsRoot, newNode,
+                        UndoableAddOrRemoveGroup.ADD_NODE);
+                panel.undoManager.addEdit(undo);
+                panel.markBaseChanged();
+                frame.output(Globals.lang("Created_group_\"%0\".",
+                        newGroup.getName()));
+            }
+        } else if (e.getSource() == autoGroup) {
+            AutoGroupDialog gd = new AutoGroupDialog(frame, panel,
+                    GroupSelector.this, groupsRoot, Globals.prefs
+                            .get("groupsDefaultField"), " .,", ",");
+            gd.show();
+            // gd does the operation itself
+        } else if (e.getSource() instanceof JCheckBox) {
+            valueChanged(null);
+        } else if (e.getSource() instanceof JCheckBoxMenuItem) {
+            valueChanged(null);
+        } else if (e.getSource() instanceof JRadioButtonMenuItem) {
+            valueChanged(null);
+        }
+    }
+
+    public void componentOpening() {
+        valueChanged(null);
+    }
+
+    public void componentClosing() {
+        if (panel != null) {// panel may be null if no file is open any more
+            panel.stopShowingGroup();
+            panel.mainTable.stopShowingFloatGrouping();
+        }
+        frame.groupToggle.setSelected(false);
+    }
+
+    public void setGroups(GroupTreeNode groupsRoot) {
+        groupsTree.setModel(groupsTreeModel = new DefaultTreeModel(groupsRoot));
+        this.groupsRoot = groupsRoot;
+        if (Globals.prefs.getBoolean("groupExpandTree"))
+        	groupsTree.expandSubtree(groupsRoot);
+    }
+
+    /**
+     * Adds the specified node as a child of the current root. The group
+     * contained in <b>newGroups </b> must not be of type AllEntriesGroup, since
+     * every tree has exactly one AllEntriesGroup (its root). The <b>newGroups
+     * </b> are inserted directly, i.e. they are not deepCopy()'d.
+     */
+    public void addGroups(GroupTreeNode newGroups, CompoundEdit ce) {
+        // paranoia: ensure that there are never two instances of AllEntriesGroup
+        if (newGroups.getGroup() instanceof AllEntriesGroup)
+            return; // this should be impossible anyway
+        groupsRoot.add(newGroups);
+        UndoableAddOrRemoveGroup undo = new UndoableAddOrRemoveGroup(this,
+                groupsRoot, newGroups, UndoableAddOrRemoveGroup.ADD_NODE);
+        ce.addEdit(undo);
+    }
+    
+    private abstract class NodeAction extends AbstractAction {
+        protected GroupTreeNode m_node = null;
+        public NodeAction(String s) {
+            super(s);
+        }
+        public GroupTreeNode getNode() {
+            return m_node;
+        }
+        public void setNode(GroupTreeNode node) {
+            this.m_node = node;
+        }
+        /** Returns the node to use in this action. If a node has been
+         * set explicitly (via setNode), it is returned. Otherwise, the first
+         * node in the current selection is returned. If all this fails, null
+         * is returned. */
+        public GroupTreeNode getNodeToUse() {
+            if (m_node != null)
+                return m_node;
+            TreePath path = groupsTree.getSelectionPath();
+            if (path != null)
+                return (GroupTreeNode) path.getLastPathComponent();
+            return null;
+        }
+    }
+    
+    final AbstractAction editGroupAction = new EditGroupAction();
+    final NodeAction editGroupPopupAction = new EditGroupAction();
+    final NodeAction addGroupPopupAction = new AddGroupAction();
+    final NodeAction addSubgroupPopupAction = new AddSubgroupAction();
+    final NodeAction removeGroupAndSubgroupsPopupAction = new RemoveGroupAndSubgroupsAction();
+    final NodeAction removeSubgroupsPopupAction = new RemoveSubgroupsAction();
+    final NodeAction removeGroupKeepSubgroupsPopupAction = new RemoveGroupKeepSubgroupsAction();
+    final NodeAction moveNodeUpPopupAction = new MoveNodeUpAction();
+    final NodeAction moveNodeDownPopupAction = new MoveNodeDownAction();
+    final NodeAction moveNodeLeftPopupAction = new MoveNodeLeftAction();
+    final NodeAction moveNodeRightPopupAction = new MoveNodeRightAction();
+    final NodeAction moveNodeUpAction = new MoveNodeUpAction();
+    final NodeAction moveNodeDownAction = new MoveNodeDownAction();
+    final NodeAction moveNodeLeftAction = new MoveNodeLeftAction();
+    final NodeAction moveNodeRightAction = new MoveNodeRightAction();
+    final NodeAction expandSubtreePopupAction = new ExpandSubtreeAction();
+    final NodeAction collapseSubtreePopupAction = new CollapseSubtreeAction();
+    final NodeAction sortDirectSubgroupsPopupAction = new SortDirectSubgroupsAction();
+    final NodeAction sortAllSubgroupsPopupAction = new SortAllSubgroupsAction();
+    final AddToGroupAction addToGroup = new AddToGroupAction(false);
+    final AddToGroupAction moveToGroup = new AddToGroupAction(true);
+    final RemoveFromGroupAction removeFromGroup = new RemoveFromGroupAction();
+    
+    private class EditGroupAction extends NodeAction {
+        public EditGroupAction() {
+            super(Globals.lang("Edit group"));
+        }
+        public void actionPerformed(ActionEvent e) {
+            final GroupTreeNode node = getNodeToUse();
+            final AbstractGroup oldGroup = node.getGroup();
+            final GroupDialog gd = new GroupDialog(frame, panel, oldGroup);
+            gd.setVisible(true);
+            if (gd.okPressed()) {
+                AbstractGroup newGroup = gd.getResultingGroup();
+                AbstractUndoableEdit undoAddPreviousEntries
+                    = gd.getUndoForAddPreviousEntries(); 
+                UndoableModifyGroup undo = new UndoableModifyGroup(
+                        GroupSelector.this, groupsRoot, node, newGroup);
+                node.setGroup(newGroup);
+                revalidateGroups();
+                // Store undo information.
+                if (undoAddPreviousEntries == null) {
+                    panel.undoManager.addEdit(undo);
+                } else {
+                    NamedCompound nc = new NamedCompound("Modify Group"); // JZTODO lyrics
+                    nc.addEdit(undo);
+                    nc.addEdit(undoAddPreviousEntries);
+                    nc.end();
+                    panel.undoManager.addEdit(nc);
+                }
+                panel.markBaseChanged();
+                frame.output(Globals.lang("Modified group \"%0\".",
+                        newGroup.getName()));
+            }
+        }
+    }
+    
+    private class AddGroupAction extends NodeAction {
+        public AddGroupAction() {
+            super(Globals.lang("Add Group"));
+        }
+        public void actionPerformed(ActionEvent e) {
+            final GroupTreeNode node = getNodeToUse();
+            final GroupDialog gd = new GroupDialog(frame, panel, null);
+            gd.setVisible(true);
+            if (!gd.okPressed())
+                return; // ignore
+            final AbstractGroup newGroup = gd.getResultingGroup();
+            final GroupTreeNode newNode = new GroupTreeNode(newGroup);
+            if (node == null)
+                groupsRoot.add(newNode);
+            else
+                ((GroupTreeNode) node.getParent()).insert(newNode, node
+                        .getParent().getIndex(node) + 1);
+            UndoableAddOrRemoveGroup undo = new UndoableAddOrRemoveGroup(
+                    GroupSelector.this, groupsRoot, newNode,
+                    UndoableAddOrRemoveGroup.ADD_NODE);
+            revalidateGroups();
+            groupsTree.expandPath(new TreePath(
+                    (node != null ? node : groupsRoot).getPath()));
+            // Store undo information.
+            panel.undoManager.addEdit(undo);
+            panel.markBaseChanged();
+            frame.output(Globals.lang("Added group \"%0\".",
+                    newGroup.getName()));
+        }
+    }
+    
+    private class AddSubgroupAction extends NodeAction {
+        public AddSubgroupAction() {
+            super(Globals.lang("Add Subgroup"));
+        }
+        public void actionPerformed(ActionEvent e) {
+            final GroupTreeNode node = getNodeToUse();
+            final GroupDialog gd = new GroupDialog(frame, panel, null);
+            gd.setVisible(true);
+            if (!gd.okPressed())
+                return; // ignore
+            final AbstractGroup newGroup = gd.getResultingGroup();
+            final GroupTreeNode newNode = new GroupTreeNode(newGroup);
+            node.add(newNode);
+            UndoableAddOrRemoveGroup undo = new UndoableAddOrRemoveGroup(
+                    GroupSelector.this, groupsRoot, newNode,
+                    UndoableAddOrRemoveGroup.ADD_NODE);
+            revalidateGroups();
+            groupsTree.expandPath(new TreePath(node.getPath()));
+            // Store undo information.
+            panel.undoManager.addEdit(undo);
+            panel.markBaseChanged();
+            frame.output(Globals.lang("Added group \"%0\".",
+                    newGroup.getName()));
+        }
+    }
+
+    private class RemoveGroupAndSubgroupsAction extends NodeAction {
+        public RemoveGroupAndSubgroupsAction() {
+            super(Globals.lang("Remove group and subgroups"));
+        }
+        public void actionPerformed(ActionEvent e) {
+            final GroupTreeNode node = getNodeToUse();
+            final AbstractGroup group = node.getGroup();
+            int conf = JOptionPane.showConfirmDialog(frame, Globals
+                    .lang("Remove group \"%0\" and its subgroups?",group.getName()), 
+                    Globals.lang("Remove group and subgroups"),
+                    JOptionPane.YES_NO_OPTION);
+            if (conf == JOptionPane.YES_OPTION) {
+                final UndoableAddOrRemoveGroup undo = new UndoableAddOrRemoveGroup(
+                        GroupSelector.this, groupsRoot, node,
+                        UndoableAddOrRemoveGroup.REMOVE_NODE_AND_CHILDREN);
+                node.removeFromParent();
+                revalidateGroups();
+                // Store undo information.
+                panel.undoManager.addEdit(undo);
+                panel.markBaseChanged();
+                frame.output(Globals.lang("Removed group \"%0\" and its subgroups.",
+                        group.getName()));
+            }
+        }
+    };
+
+    private class RemoveSubgroupsAction extends NodeAction {
+        public RemoveSubgroupsAction() {
+            super(Globals.lang("Remove all subgroups"));
+        }
+        public void actionPerformed(ActionEvent e) {
+            final GroupTreeNode node = getNodeToUse();
+            final AbstractGroup group = node.getGroup();
+            int conf = JOptionPane.showConfirmDialog(frame, Globals
+                    .lang("Remove all subgroups of \"%0\"?",group.getName()), 
+                    Globals.lang("Remove all subgroups"),
+                    JOptionPane.YES_NO_OPTION);
+            if (conf == JOptionPane.YES_OPTION) {
+                final UndoableModifySubtree undo = new UndoableModifySubtree(
+                        GroupSelector.this, node,
+                        "Remove all subgroups");
+                node.removeAllChildren();
+                revalidateGroups();
+                // Store undo information.
+                panel.undoManager.addEdit(undo);
+                panel.markBaseChanged();
+                frame.output(Globals.lang("Removed all subgroups of group \"%0\".",
+                        group.getName()));
+            }
+        }
+    };
+
+    private class RemoveGroupKeepSubgroupsAction extends NodeAction {
+        public RemoveGroupKeepSubgroupsAction() {
+            super(Globals.lang("Remove group, keep subgroups"));
+        }
+        public void actionPerformed(ActionEvent e) {
+            final GroupTreeNode node = getNodeToUse();
+            final AbstractGroup group = node.getGroup();
+            int conf = JOptionPane.showConfirmDialog(frame, Globals
+                    .lang("Remove group \"%0\"?", group.getName()), Globals
+                    .lang("Remove group"), JOptionPane.YES_NO_OPTION);
+            if (conf == JOptionPane.YES_OPTION) {
+                final UndoableAddOrRemoveGroup undo = new UndoableAddOrRemoveGroup(
+                        GroupSelector.this, groupsRoot, node,
+                        UndoableAddOrRemoveGroup.REMOVE_NODE_KEEP_CHILDREN);
+                final GroupTreeNode parent = (GroupTreeNode) node.getParent();
+                final int childIndex = parent.getIndex(node);
+                node.removeFromParent();
+                while (node.getChildCount() > 0)
+                    parent.insert((GroupTreeNode) node.getFirstChild(),
+                            childIndex);
+                revalidateGroups();
+                // Store undo information.
+                panel.undoManager.addEdit(undo);
+                panel.markBaseChanged();
+                frame.output(Globals.lang("Removed group \"%0\".",
+                        group.getName()));
+            }
+        }
+    };
+    
+    public TreePath getSelectionPath() {
+        return groupsTree.getSelectionPath();
+    }
+    
+    private class SortDirectSubgroupsAction extends NodeAction {
+        public SortDirectSubgroupsAction() {
+            super(Globals.lang("Immediate subgroups"));
+        }
+        public void actionPerformed(ActionEvent ae) {
+            final GroupTreeNode node = getNodeToUse();
+            final UndoableModifySubtree undo = new UndoableModifySubtree(
+                    GroupSelector.this, node, Globals.lang("sort subgroups"));
+            groupsTree.sort(node, false);
+            panel.undoManager.addEdit(undo);
+            panel.markBaseChanged();
+            frame.output(Globals.lang("Sorted immediate subgroups."));
+        }
+    }
+    
+    private class SortAllSubgroupsAction extends NodeAction {
+        public SortAllSubgroupsAction() {
+            super(Globals.lang("All subgroups (recursively)"));
+        }
+        public void actionPerformed(ActionEvent ae) {
+            final GroupTreeNode node = getNodeToUse();
+            final UndoableModifySubtree undo = new UndoableModifySubtree(
+                    GroupSelector.this, node, Globals.lang("sort subgroups"));
+            groupsTree.sort(node, true);
+            panel.undoManager.addEdit(undo);
+            panel.markBaseChanged(); // JZTODO lyrics
+            frame.output(Globals.lang("Sorted all subgroups recursively."));
+        }
+    };
+    
+    public final AbstractAction clearHighlightAction = new AbstractAction(Globals.lang("Clear highlight")) {
+        public void actionPerformed(ActionEvent ae) {
+            groupsTree.setHighlight3Cells(null);
+        }
+    };
+    
+    private class ExpandSubtreeAction extends NodeAction {
+        public ExpandSubtreeAction() {
+            super(Globals.lang("Expand subtree"));
+        }
+        public void actionPerformed(ActionEvent ae) {
+            final GroupTreeNode node = getNodeToUse();
+            TreePath path = new TreePath(node.getPath());
+            groupsTree.expandSubtree((GroupTreeNode) path.getLastPathComponent());
+            revalidateGroups();
+        }
+    }
+    
+    private class CollapseSubtreeAction extends NodeAction {
+        public CollapseSubtreeAction() {
+            super(Globals.lang("Collapse subtree"));
+        }
+        public void actionPerformed(ActionEvent ae) {
+            final GroupTreeNode node = getNodeToUse();
+            TreePath path = new TreePath(node.getPath());
+            groupsTree.collapseSubtree((GroupTreeNode) path.getLastPathComponent());
+            revalidateGroups();
+        }
+    }
+    
+    private class MoveNodeUpAction extends NodeAction {
+        public MoveNodeUpAction() {
+            super(Globals.lang("Up"));
+        }
+        public void actionPerformed(ActionEvent e) {
+            final GroupTreeNode node = getNodeToUse();
+            moveNodeUp(node, false);
+        }
+    }
+    
+    private class MoveNodeDownAction extends NodeAction {
+        public MoveNodeDownAction() {
+            super(Globals.lang("Down"));
+        }
+        public void actionPerformed(ActionEvent e) {
+            final GroupTreeNode node = getNodeToUse();
+            moveNodeDown(node, false);
+        }
+    }
+    
+    private class MoveNodeLeftAction extends NodeAction {
+        public MoveNodeLeftAction() {
+            super(Globals.lang("Left"));
+        }
+        public void actionPerformed(ActionEvent e) {
+            final GroupTreeNode node = getNodeToUse();
+            moveNodeLeft(node, false);
+        }
+    }
+    
+    private class MoveNodeRightAction extends NodeAction {
+        public MoveNodeRightAction() {
+            super(Globals.lang("Right"));
+        }
+        public void actionPerformed(ActionEvent e) {
+            final GroupTreeNode node = getNodeToUse();
+            moveNodeRight(node, false);
+        }
+    }
+
+    /**
+     * @param node The node to move
+     * @return true if move was successful, false if not.
+     */
+    public boolean moveNodeUp(GroupTreeNode node, boolean checkSingleSelection) {
+        if (checkSingleSelection) {
+            if (groupsTree.getSelectionCount() != 1) {
+                frame.output(Globals.lang("Please select exactly one group to move."));
+                return false; // not possible
+            }
+        }
+        AbstractUndoableEdit undo = null;
+        if (!node.canMoveUp() || (undo = node.moveUp(GroupSelector.this)) == null) {
+            frame.output(Globals.lang(
+                    "Cannot move group \"%0\" up.", node.getGroup().getName()));
+            return false; // not possible
+        }
+        // update selection/expansion state (not really needed when
+        // moving among siblings, but I'm paranoid)
+        revalidateGroups(groupsTree.refreshPaths(groupsTree.getSelectionPaths()),
+                groupsTree.refreshPaths(getExpandedPaths()));
+        concludeMoveGroup(undo, node);
+        return true;
+    }
+    
+    /**
+     * @param node The node to move
+     * @return true if move was successful, false if not.
+     */
+    public boolean moveNodeDown(GroupTreeNode node, boolean checkSingleSelection) {
+        if (checkSingleSelection) {
+            if (groupsTree.getSelectionCount() != 1) {
+                frame.output(Globals.lang("Please select exactly one group to move."));
+                return false; // not possible
+            }
+        }
+        AbstractUndoableEdit undo = null;
+        if (!node.canMoveDown() || (undo = node.moveDown(GroupSelector.this)) == null) {
+            frame.output(Globals.lang(
+                    "Cannot move group \"%0\" down.", node.getGroup().getName()));
+            return false; // not possible
+        }
+        // update selection/expansion state (not really needed when
+        // moving among siblings, but I'm paranoid)
+        revalidateGroups(groupsTree.refreshPaths(groupsTree.getSelectionPaths()),
+                groupsTree.refreshPaths(getExpandedPaths()));
+        concludeMoveGroup(undo, node);
+        return true;
+    }
+    
+    /**
+     * @param node The node to move
+     * @return true if move was successful, false if not.
+     */
+    public boolean moveNodeLeft(GroupTreeNode node, boolean checkSingleSelection) {
+        if (checkSingleSelection) {
+            if (groupsTree.getSelectionCount() != 1) {
+                frame.output(Globals.lang("Please select exactly one group to move."));
+                return false; // not possible
+            }
+        }
+        AbstractUndoableEdit undo = null;
+        if (!node.canMoveLeft() || (undo = node.moveLeft(GroupSelector.this)) == null) {
+            frame.output(Globals.lang(
+                    "Cannot move group \"%0\" left.", node.getGroup().getName()));
+            return false; // not possible
+        }
+        // update selection/expansion state
+        revalidateGroups(groupsTree.refreshPaths(groupsTree.getSelectionPaths()),
+                groupsTree.refreshPaths(getExpandedPaths()));
+        concludeMoveGroup(undo, node);
+        return true;
+    }
+    
+    /**
+     * @param node The node to move
+     * @return true if move was successful, false if not.
+     */
+    public boolean moveNodeRight(GroupTreeNode node, boolean checkSingleSelection) {
+        if (checkSingleSelection) {
+            if (groupsTree.getSelectionCount() != 1) {
+                frame.output(Globals.lang("Please select exactly one group to move."));
+                return false; // not possible
+            }
+        }
+        AbstractUndoableEdit undo = null;
+        if (!node.canMoveRight() || (undo = node.moveRight(GroupSelector.this)) == null) {
+            frame.output(Globals.lang(
+                    "Cannot move group \"%0\" right.", node.getGroup().getName()));
+            return false; // not possible
+        }
+        // update selection/expansion state
+        revalidateGroups(groupsTree.refreshPaths(groupsTree.getSelectionPaths()),
+                groupsTree.refreshPaths(getExpandedPaths()));
+        concludeMoveGroup(undo, node);
+        return true;
+    }
+    
+    /**
+     * Concludes the moving of a group tree node by storing the specified
+     * undo information, marking the change, and setting the status line.
+     * @param undo Undo information for the move operation. 
+     * @param node The node that has been moved.
+     */
+    public void concludeMoveGroup(AbstractUndoableEdit undo, GroupTreeNode node) {
+        panel.undoManager.addEdit(undo);
+        panel.markBaseChanged();
+        frame.output(Globals.lang("Moved group \"%0\".", 
+                node.getGroup().getName()));
+    }
+    
+    public void concludeAssignment(AbstractUndoableEdit undo, GroupTreeNode node, int assignedEntries) {
+        if (undo == null) {
+            frame.output(Globals.lang("The group \"%0\" already contains the selection.",
+                    new String[]{node.getGroup().getName()}));
+            return;
+        }
+        panel.undoManager.addEdit(undo);
+        panel.markBaseChanged();
+        panel.updateEntryEditorIfShowing(); 
+        final String groupName = node.getGroup().getName();
+        if (assignedEntries == 1)
+            frame.output(Globals.lang("Assigned 1 entry to group \"%0\".", groupName));
+        else
+            frame.output(Globals.lang("Assigned %0 entries to group \"%1\".", 
+                    String.valueOf(assignedEntries), groupName));
+    }
+    
+    JMenu moveSubmenu = new JMenu(Globals.lang("Move"));
+    JMenu sortSubmenu = new JMenu(Globals.lang("Sort alphabetically")); // JZTODO lyrics
+
+    public GroupTreeNode getGroupTreeRoot() {
+        return groupsRoot;
+    }
+    
+    public Enumeration getExpandedPaths() {
+        return groupsTree.getExpandedDescendants(
+                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");
+            return;
+        }
+        MetaData metaData = panel.metaData();
+        if (metaData.getGroups() != null) {
+            setGroups(metaData.getGroups());
+        } else {
+            GroupTreeNode newGroupsRoot = new GroupTreeNode(new AllEntriesGroup());
+            metaData.setGroups(newGroupsRoot);
+            setGroups(newGroupsRoot);
+        }
+        
+        // auto show/hide groups interface
+        if (Globals.prefs.getBoolean("groupAutoShow") &&
+        		!groupsRoot.isLeaf()) { // groups were defined
+            frame.sidePaneManager.ensureVisible("groups");
+            frame.groupToggle.setSelected(true);
+        } else if (Globals.prefs.getBoolean("groupAutoHide") &&
+        		groupsRoot.isLeaf()) { // groups were not defined
+            frame.sidePaneManager.ensureNotVisible("groups");
+            frame.groupToggle.setSelected(false);
+        }
+        
+        validateTree();
+    }
+
+
+    /**
+     * This method is required by the ErrorMessageDisplay interface, and lets this class
+     * serve as a callback for regular expression exceptions happening in DatabaseSearch.
+     * @param errorMessage
+     */
+    public void reportError(String errorMessage) {
+        // this should never happen, since regular expressions are checked for
+        // correctness by the edit group dialog, and no other errors should
+        // occur in a search
+        System.err.println("Error in group search: "+errorMessage
+                + ". Please report this on www.sf.net/projects/jabref");
+    }
+
+    /**
+     * This method is required by the ErrorMessageDisplay interface, and lets this class
+     * serve as a callback for regular expression exceptions happening in DatabaseSearch.
+     * @param errorMessage
+     */
+    public void reportError(String errorMessage, Exception exception) {
+        reportError(errorMessage);
+    }
+    
+    /**
+     * Highlight all groups that contain any/all of the specified entries.
+     * If entries is null, highlight is cleared. 
+     */
+    public void showMatchingGroups(BibtexEntry[] entries, boolean requireAll) {
+        if (entries == null) { // nothing selected
+            groupsTree.setHighlight3Cells(null);
+            groupsTree.revalidate();
+            return;
+        }
+        GroupTreeNode node;
+        AbstractGroup group;
+        Vector vec = new Vector();
+        for (Enumeration e = groupsRoot.preorderEnumeration(); e.hasMoreElements(); ) {
+            node = (GroupTreeNode) e.nextElement();
+            group = node.getGroup();
+            int i;
+            for (i = 0; i < entries.length; ++i) {
+                if (requireAll) {
+                    if (!group.contains(entries[i]))
+                        break;
+                } else {
+                    if (group.contains(entries[i]))
+                        vec.add(node);
+                } 
+            }
+            if (requireAll && i >= entries.length) // did not break from loop
+                vec.add(node);
+        }
+        groupsTree.setHighlight3Cells(vec.toArray());
+        // ensure that all highlighted nodes are visible
+        for (int i = 0; i < vec.size(); ++i) {
+            node = (GroupTreeNode)((GroupTreeNode)vec.elementAt(i)).getParent();
+            if (node != null)
+                groupsTree.expandPath(new TreePath(node.getPath()));
+        }
+        groupsTree.revalidate();
+    }
+    
+    /** Show groups that, if selected, would show at least one
+     * of the entries found in the specified search. */
+    protected void showOverlappingGroups(List matches) { //DatabaseSearch search) {
+      GroupTreeNode node;
+      SearchRule rule;
+      BibtexEntry entry;
+      Vector vec = new Vector();
+      Map dummyMap = new HashMap(); // just because I don't want to use null...
+      for (Enumeration e = groupsRoot.depthFirstEnumeration(); e.hasMoreElements(); ) {
+          node = (GroupTreeNode) e.nextElement();
+          rule = node.getSearchRule(); 
+          for (Iterator it = matches.iterator(); it.hasNext(); ) {
+              entry = (BibtexEntry) it.next();
+              if (rule.applyRule(dummyMap, entry) == 0)
+            	  continue;
+              vec.add(node);
+              break;
+          }
+      }
+      groupsTree.setHighlight2Cells(vec.toArray());
+    }
+}
+
diff --git a/src/java/net/sf/jabref/groups/GroupTreeCellRenderer.java b/src/java/net/sf/jabref/groups/GroupTreeCellRenderer.java
new file mode 100644
index 0000000..0108ddb
--- /dev/null
+++ b/src/java/net/sf/jabref/groups/GroupTreeCellRenderer.java
@@ -0,0 +1,159 @@
+/*
+ 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.groups;
+
+import java.awt.*;
+
+import javax.swing.*;
+import javax.swing.tree.DefaultTreeCellRenderer;
+
+import net.sf.jabref.*;
+
+/**
+ * Renders a GroupTreeNode using its group's getName() method, rather that its
+ * toString() method.
+ * 
+ * @author jzieren
+ */
+public class GroupTreeCellRenderer extends DefaultTreeCellRenderer {
+    /** The cell over which the user is currently dragging */
+    protected Object highlight1Cell = null;
+    protected Object[] highlight2Cells = null;
+    protected Object[] highlight3Cells = null;
+    protected Object highlightBorderCell = null;
+
+    public Component getTreeCellRendererComponent(JTree tree, Object value,
+            boolean selected, boolean expanded, boolean leaf, int row,
+            boolean hasFocus) {
+        if (value == highlight1Cell)
+            selected = true; // show as selected
+        Component c = super.getTreeCellRendererComponent(tree, value, selected,
+                expanded, leaf, row, hasFocus);
+        // this is sometimes called from deep within somewhere, with a dummy 
+        // value (probably for layout etc.), so we've got to check here!
+        if (!(value instanceof GroupTreeNode))
+            return c;
+        AbstractGroup group = ((GroupTreeNode) value).getGroup();
+        if (group == null || !(c instanceof JLabel))
+            return c; // sanity check
+        JLabel label = (JLabel) c;
+        if (highlightBorderCell != null && highlightBorderCell == value)
+            label.setBorder(BorderFactory.createLineBorder(Color.BLACK));
+        else
+            label.setBorder(BorderFactory.createEmptyBorder());
+        boolean italics = Globals.prefs.getBoolean("groupShowDynamic")
+        && group.isDynamic();
+        boolean red = false;
+        if (highlight2Cells != null) {
+            for (int i = 0; i < highlight2Cells.length; ++i) {
+                if (highlight2Cells[i] == value) {
+                    // label.setForeground(Color.RED);
+                    red = true;
+                    break;
+                }
+            }
+        }
+        boolean underline = false;
+        if (highlight3Cells != null) {
+            for (int i = 0; i < highlight3Cells.length; ++i) {
+                if (highlight3Cells[i] == value) {
+                    underline = true;
+                    break;
+                }
+            }
+        }
+        StringBuffer sb = new StringBuffer();
+        sb.append("<html>");
+        if (red)
+            sb.append("<font color=\"#FF0000\">");
+        if (underline)
+            sb.append("<u>");
+        if (italics)
+            sb.append("<i>");
+        sb.append(Util.quoteForHTML(group.getName()));
+        if (italics)
+            sb.append("</i>");
+        if (underline)
+            sb.append("</u>");
+        if (red)
+            sb.append("</font>");
+        sb.append("</html>");
+        final String text = sb.toString();
+        if (!label.getText().equals(text))
+            label.setText(text);
+        label.setToolTipText("<html>" + group.getShortDescription() + "</html>");
+        if (Globals.prefs.getBoolean("groupShowIcons")) {
+            switch (group.getHierarchicalContext()) {
+            case AbstractGroup.REFINING:
+                if (label.getIcon() != GUIGlobals.groupRefiningIcon)
+                    label.setIcon(GUIGlobals.groupRefiningIcon);
+                break;
+            case AbstractGroup.INCLUDING:
+                if (label.getIcon() != GUIGlobals.groupIncludingIcon)
+                    label.setIcon(GUIGlobals.groupIncludingIcon);
+                break;
+            default:
+                if (label.getIcon() != GUIGlobals.groupRegularIcon)
+                    label.setIcon(GUIGlobals.groupRegularIcon);
+                break;
+            }
+        } else {
+            label.setIcon(null);
+        }
+        return c;
+    }
+
+    /**
+     * For use when dragging: The sepcified cell is always rendered as selected.
+     * 
+     * @param cell
+     *            The cell over which the user is currently dragging.
+     */
+    void setHighlight1Cell(Object cell) {
+        this.highlight1Cell = cell;
+    }
+
+    /**
+     * Highlights the specified cells (in red), or disables highlight if cells ==
+     * null.
+     */
+    void setHighlight2Cells(Object[] cells) {
+        this.highlight2Cells = cells;
+    }
+
+    /**
+     * Highlights the specified cells (by unterlining), or disables highlight if
+     * cells == null.
+     */
+    void setHighlight3Cells(Object[] cells) {
+        this.highlight3Cells = cells;
+    }
+
+    /**
+     * Highlights the specified cells (by drawing a border around it), 
+     * or disables highlight if highlightBorderCell == null.
+     */
+    void setHighlightBorderCell(Object highlightBorderCell) {
+        this.highlightBorderCell = highlightBorderCell;
+    }
+}
diff --git a/src/java/net/sf/jabref/groups/GroupTreeNode.java b/src/java/net/sf/jabref/groups/GroupTreeNode.java
new file mode 100644
index 0000000..2d1e5e2
--- /dev/null
+++ b/src/java/net/sf/jabref/groups/GroupTreeNode.java
@@ -0,0 +1,343 @@
+/*
+ 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.groups;
+
+import java.awt.datatransfer.*;
+import java.awt.datatransfer.Transferable;
+import java.io.IOException;
+import java.util.*;
+
+import javax.swing.tree.*;
+import javax.swing.undo.AbstractUndoableEdit;
+
+import net.sf.jabref.*;
+
+/**
+ * A node in the groups tree that holds exactly one AbstractGroup.
+ * 
+ * @author jzieren
+ */
+public class GroupTreeNode extends DefaultMutableTreeNode implements
+		Transferable {
+	public static final DataFlavor flavor;
+	public static final DataFlavor[] flavors;
+
+	static {
+		DataFlavor df = null;
+		try {
+			df = new DataFlavor(DataFlavor.javaJVMLocalObjectMimeType
+					+ ";class=net.sf.jabref.groups.GroupTreeNode");
+		} catch (ClassNotFoundException e) {
+			// never happens
+		}
+		flavor = df;
+		flavors = new DataFlavor[] { flavor };
+	}
+
+	/**
+	 * Creates this node and associates the specified group with it.
+	 */
+	public GroupTreeNode(AbstractGroup group) {
+		setGroup(group);
+	}
+
+	/**
+	 * @return The group associated with this node.
+	 */
+	public AbstractGroup getGroup() {
+		return (AbstractGroup) getUserObject();
+	}
+
+	/**
+	 * Associates the specified group with this node.
+	 */
+	public void setGroup(AbstractGroup group) {
+		setUserObject(group);
+	}
+
+	/**
+	 * Returns a textual representation of this node and its children. This
+	 * representation contains both the tree structure and the textual
+	 * representations of the group associated with each node. It thus allows a
+	 * complete reconstruction of this object and its children.
+	 */
+	public String getTreeAsString() {
+		StringBuffer sb = new StringBuffer();
+		Enumeration e = preorderEnumeration();
+		GroupTreeNode cursor;
+		while (e.hasMoreElements()) {
+			cursor = (GroupTreeNode) e.nextElement();
+            sb.append(cursor.getLevel()).append(" ").append(cursor.getGroup().toString()).append("\n");
+		}
+		return sb.toString();
+	}
+
+	/**
+	 * Creates a deep copy of this node and all of its children, including all
+	 * groups.
+	 * 
+	 * @return This object's deep copy.
+	 */
+	public GroupTreeNode deepCopy() {
+		GroupTreeNode copy = new GroupTreeNode(getGroup());
+		for (int i = 0; i < getChildCount(); ++i)
+			copy.add(((GroupTreeNode) getChildAt(i)).deepCopy());
+		return copy;
+	}
+
+	/**
+	 * @return An indexed path from the root node to this node. The elements in
+	 *         the returned array represent the child index of each node in the
+	 *         path. If this node is the root node, the returned array has zero
+	 *         elements.
+	 */
+	public int[] getIndexedPath() {
+		TreeNode[] path = getPath();
+		int[] indexedPath = new int[path.length - 1];
+		for (int i = 1; i < path.length; ++i)
+			indexedPath[i - 1] = path[i - 1].getIndex(path[i]);
+		return indexedPath;
+	}
+
+	/**
+	 * Returns the node indicated by the specified indexedPath, which contains
+	 * child indices obtained e.g. by getIndexedPath().
+	 */
+	public GroupTreeNode getNode(int[] indexedPath) {
+		GroupTreeNode cursor = this;
+		for (int i = 0; i < indexedPath.length; ++i)
+			cursor = (GroupTreeNode) cursor.getChildAt(indexedPath[i]);
+		return cursor;
+	}
+
+	/**
+	 * @param indexedPath
+	 *            A sequence of child indices that describe a path from this
+	 *            node to one of its desendants. Be aware that if <b>indexedPath
+	 *            </b> was obtained by getIndexedPath(), this node should
+	 *            usually be the root node.
+	 * @return The descendant found by evaluating <b>indexedPath </b>. If the
+	 *         path could not be traversed completely (i.e. one of the child
+	 *         indices did not exist), null will be returned.
+	 */
+	public GroupTreeNode getDescendant(int[] indexedPath) {
+		GroupTreeNode cursor = this;
+		for (int i = 0; i < indexedPath.length && cursor != null; ++i)
+			cursor = (GroupTreeNode) cursor.getChildAt(indexedPath[i]);
+		return cursor;
+	}
+
+	/**
+	 * A GroupTreeNode can create a SearchRule that finds elements contained in
+	 * its own group, or the union of those elements in its own group and its
+	 * children's groups (recursively), or the intersection of the elements in
+	 * its own group and its parent's group. This setting is configured in the
+	 * group contained in this node.
+	 * 
+	 * @return A SearchRule that finds the desired elements.
+	 */
+	public SearchRule getSearchRule() {
+		return getSearchRule(getGroup().getHierarchicalContext());
+	}
+
+	protected SearchRule getSearchRule(int originalContext) {
+		final int context = getGroup().getHierarchicalContext();
+		if (context == AbstractGroup.INDEPENDENT)
+			return getGroup().getSearchRule();
+		AndOrSearchRuleSet searchRule = new AndOrSearchRuleSet(
+				context == AbstractGroup.REFINING, false);
+		searchRule.addRule(getGroup().getSearchRule());
+		if (context == AbstractGroup.INCLUDING
+				&& originalContext != AbstractGroup.REFINING) {
+			for (int i = 0; i < getChildCount(); ++i)
+				searchRule.addRule(((GroupTreeNode) getChildAt(i))
+						.getSearchRule(originalContext));
+		} else if (context == AbstractGroup.REFINING && !isRoot()
+				&& originalContext != AbstractGroup.INCLUDING) {
+			searchRule.addRule(((GroupTreeNode) getParent())
+					.getSearchRule(originalContext));
+		}
+		return searchRule;
+	}
+
+	/**
+	 * Scans the subtree rooted at this node.
+	 * 
+	 * @return All groups that contain the specified entry.
+	 */
+	public AbstractGroup[] getMatchingGroups(BibtexEntry entry) {
+		Vector matchingGroups = new Vector();
+		Enumeration e = preorderEnumeration();
+		AbstractGroup group;
+		while (e.hasMoreElements()) {
+			group = ((GroupTreeNode) e.nextElement()).getGroup();
+			if (group.contains(null, entry)) // first argument is never used
+				matchingGroups.add(group);
+		}
+		AbstractGroup[] matchingGroupsArray = new AbstractGroup[matchingGroups
+				.size()];
+		return (AbstractGroup[]) matchingGroups.toArray(matchingGroupsArray);
+	}
+
+	public boolean canMoveUp() {
+		return getPreviousSibling() != null
+				&& !(getGroup() instanceof AllEntriesGroup);
+	}
+
+	public boolean canMoveDown() {
+		return getNextSibling() != null
+				&& !(getGroup() instanceof AllEntriesGroup);
+	}
+
+	public boolean canMoveLeft() {
+		return !(getGroup() instanceof AllEntriesGroup)
+				&& !(((GroupTreeNode) getParent()).getGroup() instanceof AllEntriesGroup);
+	}
+
+	public boolean canMoveRight() {
+		return getPreviousSibling() != null
+				&& !(getGroup() instanceof AllEntriesGroup);
+	}
+
+	public AbstractUndoableEdit moveUp(GroupSelector groupSelector) {
+		final GroupTreeNode myParent = (GroupTreeNode) getParent();
+		final int index = myParent.getIndex(this);
+		if (index > 0) {
+			UndoableMoveGroup undo = new UndoableMoveGroup(groupSelector,
+					groupSelector.getGroupTreeRoot(), this, myParent, index - 1);
+			myParent.insert(this, index - 1);
+			return undo;
+		}
+		return null;
+	}
+
+	public AbstractUndoableEdit moveDown(GroupSelector groupSelector) {
+		final GroupTreeNode myParent = (GroupTreeNode) getParent();
+		final int index = myParent.getIndex(this);
+		if (index < parent.getChildCount() - 1) {
+			UndoableMoveGroup undo = new UndoableMoveGroup(groupSelector,
+					groupSelector.getGroupTreeRoot(), this, myParent, index + 1);
+			myParent.insert(this, index + 1);
+			return undo;
+		}
+		return null;
+	}
+
+	public AbstractUndoableEdit moveLeft(GroupSelector groupSelector) {
+		final GroupTreeNode myParent = (GroupTreeNode) getParent();
+		final GroupTreeNode myGrandParent = (GroupTreeNode) myParent
+				.getParent();
+		// paranoia
+		if (myGrandParent == null)
+			return null;
+		final int index = myGrandParent.getIndex(myParent);
+		UndoableMoveGroup undo = new UndoableMoveGroup(groupSelector,
+				groupSelector.getGroupTreeRoot(), this, myGrandParent,
+				index + 1);
+		myGrandParent.insert(this, index + 1);
+		return undo;
+	}
+
+	public AbstractUndoableEdit moveRight(GroupSelector groupSelector) {
+		final GroupTreeNode myPreviousSibling = (GroupTreeNode) getPreviousSibling();
+		// paranoia
+		if (myPreviousSibling == null)
+			return null;
+		UndoableMoveGroup undo = new UndoableMoveGroup(groupSelector,
+				groupSelector.getGroupTreeRoot(), this, myPreviousSibling,
+				myPreviousSibling.getChildCount());
+		myPreviousSibling.add(this);
+		return undo;
+	}
+
+	/**
+	 * @param path
+	 *            A sequence of child indices that designate a node relative to
+	 *            this node.
+	 * @return The node designated by the specified path, or null if one or more
+	 *         indices in the path could not be resolved.
+	 */
+	public GroupTreeNode getChildAt(int[] path) {
+		GroupTreeNode cursor = this;
+		for (int i = 0; i < path.length && cursor != null; ++i)
+			cursor = (GroupTreeNode) cursor.getChildAt(path[i]);
+		return cursor;
+	}
+
+	/** Adds the selected entries to this node's group. */
+	public AbstractUndoableEdit addToGroup(BibtexEntry[] entries) {
+		if (getGroup() == null)
+			return null; // paranoia
+		AbstractUndoableEdit undo = getGroup().add(entries);
+		if (undo instanceof UndoableChangeAssignment)
+			((UndoableChangeAssignment) undo).setEditedNode(this);
+		return undo;
+	}
+
+	/** Removes the selected entries from this node's group. */
+	public AbstractUndoableEdit removeFromGroup(BibtexEntry[] entries) {
+		if (getGroup() == null)
+			return null; // paranoia
+		AbstractUndoableEdit undo = getGroup().remove(entries);
+		if (undo instanceof UndoableChangeAssignment)
+			((UndoableChangeAssignment) undo).setEditedNode(this);
+		return undo;
+	}
+
+	public DataFlavor[] getTransferDataFlavors() {
+		return flavors;
+	}
+
+	public boolean isDataFlavorSupported(DataFlavor someFlavor) {
+		return someFlavor.equals(GroupTreeNode.flavor);
+	}
+
+	public Object getTransferData(DataFlavor someFlavor)
+			throws UnsupportedFlavorException, IOException {
+		if (!isDataFlavorSupported(someFlavor))
+			throw new UnsupportedFlavorException(someFlavor);
+		return this;
+	}
+
+	/**
+	 * Recursively compares this node's group and all subgroups.
+	 */
+	public boolean equals(Object other) {
+		if (!(other instanceof GroupTreeNode))
+			return false;
+		final GroupTreeNode otherNode = (GroupTreeNode) other;
+		if (getChildCount() != otherNode.getChildCount())
+			return false;
+		AbstractGroup g1 = getGroup();
+		AbstractGroup g2 = otherNode.getGroup();
+		if ((g1 == null && g2 != null) || (g1 != null && g2 == null))
+			return false;
+		if (g1 != null && g2 != null && !g1.equals(g2))
+			return false;
+		for (int i = 0; i < getChildCount(); ++i) {
+			if (!getChildAt(i).equals(otherNode.getChildAt(i)))
+				return false;
+		}
+		return true;
+	}
+}
diff --git a/src/java/net/sf/jabref/groups/GroupsPrefsTab.java b/src/java/net/sf/jabref/groups/GroupsPrefsTab.java
new file mode 100644
index 0000000..0a8dcd9
--- /dev/null
+++ b/src/java/net/sf/jabref/groups/GroupsPrefsTab.java
@@ -0,0 +1,121 @@
+package net.sf.jabref.groups;
+
+import java.awt.BorderLayout;
+import java.awt.event.FocusEvent;
+import java.awt.event.FocusListener;
+
+import javax.swing.BorderFactory;
+import javax.swing.JCheckBox;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JTextField;
+
+import net.sf.jabref.Globals;
+import net.sf.jabref.JabRefPreferences;
+import net.sf.jabref.PrefsTab;
+
+import com.jgoodies.forms.builder.DefaultFormBuilder;
+import com.jgoodies.forms.layout.FormLayout;
+
+// JZTODO lyrics
+public class GroupsPrefsTab extends JPanel implements PrefsTab {
+	private final JCheckBox showIcons = new JCheckBox(Globals.lang("Show icons for groups"));
+	private final JCheckBox showDynamic = new JCheckBox(
+			"<html>"+Globals.lang("Show dynamic groups in <i>italics</i>")+"</html>");
+	private final JCheckBox expandTree = new JCheckBox(
+			Globals.lang("Initially show groups tree expanded"));
+	private final JCheckBox autoShow = new JCheckBox(
+			Globals.lang("Automatically show groups interface when switching to a database that contains groups"));
+	private final JCheckBox autoHide = new JCheckBox(
+			Globals.lang("Automatically hide groups interface when switching to a database that contains no groups"));
+	private JTextField groupingField = new JTextField(20);
+	private JTextField keywordSeparator = new JTextField(2);
+
+	private final JabRefPreferences prefs;
+
+	public GroupsPrefsTab(JabRefPreferences prefs) {
+		this.prefs = prefs;
+		
+		keywordSeparator.addFocusListener(new FocusListener() {
+			public void focusGained(FocusEvent e) {
+				keywordSeparator.selectAll();
+			}
+			public void focusLost(FocusEvent e) {
+				// deselection is automatic
+			}
+		});
+		
+		FormLayout layout = new FormLayout("9dlu, 500px",
+				"p, 3dlu, p, 3dlu, p, 3dlu, p, 3dlu, p, 3dlu, p, 3dlu, p, 3dlu, " +
+				"p, 3dlu, p");
+		DefaultFormBuilder builder = new DefaultFormBuilder(layout);
+		builder.appendSeparator(Globals.lang("View"));
+		builder.nextLine();
+		builder.nextLine();
+		builder.nextColumn();
+		builder.append(showIcons);
+		builder.nextLine();
+		builder.nextLine();
+		builder.nextColumn();
+		builder.append(showDynamic);
+		builder.nextLine();
+		builder.nextLine();
+		builder.nextColumn();
+		builder.append(expandTree);
+		builder.nextLine();
+		builder.nextLine();
+		builder.nextColumn();
+		builder.append(autoShow);
+		builder.nextLine();
+		builder.nextLine();
+		builder.nextColumn();
+		builder.append(autoHide);
+		builder.nextLine();
+		builder.nextLine();
+		builder.appendSeparator(Globals.lang("Dynamic groups"));
+		builder.nextLine();
+		builder.nextLine();
+		builder.nextColumn();
+			// build subcomponent
+			FormLayout layout2 = new FormLayout("left:pref, 2dlu, left:pref", 
+					"p, 3dlu, p");
+			DefaultFormBuilder builder2 = new DefaultFormBuilder(layout2);
+			builder2.append(new JLabel(Globals.lang("Default grouping field") + ":"));
+			builder2.append(groupingField);
+			builder2.nextLine();
+			builder2.nextLine();
+			builder2.append(new JLabel(Globals.lang("When adding/removing keywords, separate them by")+":"));
+			builder2.append(keywordSeparator);
+		builder.append(builder2.getPanel());
+
+		setLayout(new BorderLayout());
+		JPanel panel = builder.getPanel();
+		panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
+		add(panel, BorderLayout.CENTER);
+	}
+
+	public void setValues() {
+		showIcons.setSelected(prefs.getBoolean("groupShowIcons"));
+		showDynamic.setSelected(prefs.getBoolean("groupShowDynamic"));
+		expandTree.setSelected(prefs.getBoolean("groupExpandTree"));
+		groupingField.setText(prefs.get("groupsDefaultField"));
+		autoShow.setSelected(prefs.getBoolean("groupAutoShow"));
+		autoHide.setSelected(prefs.getBoolean("groupAutoHide"));
+		keywordSeparator.setText(prefs.get("groupKeywordSeparator"));
+	}
+
+	public void storeSettings() {
+		prefs.putBoolean("groupShowIcons", showIcons.isSelected());
+		prefs.putBoolean("groupShowDynamic", showDynamic.isSelected());
+		prefs.putBoolean("groupExpandTree", expandTree.isSelected());
+		prefs.put("groupsDefaultField", groupingField.getText().trim());
+		prefs.putBoolean("groupAutoShow", autoShow.isSelected());
+		prefs.putBoolean("groupAutoHide", autoHide.isSelected());
+		prefs.put("groupKeywordSeparator", keywordSeparator.getText());
+	}
+
+	public boolean readyToClose() {
+		return true;
+	}
+
+}
diff --git a/src/java/net/sf/jabref/groups/GroupsTree.java b/src/java/net/sf/jabref/groups/GroupsTree.java
new file mode 100644
index 0000000..6209947
--- /dev/null
+++ b/src/java/net/sf/jabref/groups/GroupsTree.java
@@ -0,0 +1,451 @@
+/*
+ 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.groups;
+
+import java.awt.*;
+import java.awt.datatransfer.*;
+import java.awt.dnd.*;
+import java.awt.event.InputEvent;
+import java.io.IOException;
+import java.util.*;
+
+import javax.swing.*;
+import javax.swing.tree.*;
+import javax.swing.undo.AbstractUndoableEdit;
+
+import net.sf.jabref.*;
+
+public class GroupsTree extends JTree implements DragSourceListener,
+		DropTargetListener, DragGestureListener {
+	/** distance from component borders from which on autoscrolling starts. */
+	private static final int dragScrollActivationMargin = 10;
+
+	/** number of pixels to scroll each time handler is called. */
+	private static final int dragScrollDistance = 5;
+
+	/** time of last autoscroll event (for limiting speed). */
+	private static long lastDragAutoscroll = 0L;
+
+	/** minimum interval between two autoscroll events (for limiting speed). */
+	private static final long minAutoscrollInterval = 50L;
+
+	/**
+	 * the point on which the cursor is currently idling during a drag
+	 * operation.
+	 */
+	private Point idlePoint;
+
+	/** time since which cursor is idling. */
+	private long idleStartTime = 0L;
+
+	/** max. distance cursor may move in x or y direction while idling. */
+	private static final int idleMargin = 1;
+
+	/** idle time after which the node below is expanded. */
+	private static final long idleTimeToExpandNode = 1000L;
+
+	private GroupSelector groupSelector;
+
+	private GroupTreeNode dragNode = null;
+
+	private final GroupTreeCellRenderer cellRenderer = new GroupTreeCellRenderer();
+
+	public GroupsTree(GroupSelector groupSelector) {
+		this.groupSelector = groupSelector;
+		DragGestureRecognizer dgr = DragSource.getDefaultDragSource()
+				.createDefaultDragGestureRecognizer(this,
+						DnDConstants.ACTION_MOVE, this);
+		// Eliminates right mouse clicks as valid actions
+		dgr.setSourceActions(dgr.getSourceActions() & ~InputEvent.BUTTON3_MASK);
+		DropTarget dropTarget = new DropTarget(this, this);
+		setCellRenderer(cellRenderer);
+		setFocusable(false);
+		setToggleClickCount(0);
+		ToolTipManager.sharedInstance().registerComponent(this);
+		setShowsRootHandles(false);
+		setVisibleRowCount(Globals.prefs.getInt("groupsVisibleRows"));
+		getSelectionModel().setSelectionMode(
+				TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION);
+	}
+
+	public void dragEnter(DragSourceDragEvent dsde) {
+		// ignore
+	}
+
+	/** This is for moving of nodes within myself */
+	public void dragOver(DragSourceDragEvent dsde) {
+		final Point p = dsde.getLocation(); // screen coordinates!
+		SwingUtilities.convertPointFromScreen(p, this);
+		final TreePath path = getPathForLocation(p.x, p.y);
+		if (path == null) {
+			dsde.getDragSourceContext().setCursor(DragSource.DefaultMoveNoDrop);
+			return;
+		}
+		final GroupTreeNode target = (GroupTreeNode) path
+				.getLastPathComponent();
+		if (target == null || dragNode.isNodeDescendant(target)
+				|| dragNode == target) {
+			dsde.getDragSourceContext().setCursor(DragSource.DefaultMoveNoDrop);
+			return;
+		}
+		dsde.getDragSourceContext().setCursor(DragSource.DefaultMoveDrop);
+	}
+
+	public void dropActionChanged(DragSourceDragEvent dsde) {
+		// ignore
+	}
+
+	public void dragDropEnd(DragSourceDropEvent dsde) {
+		dragNode = null;
+	}
+
+	public void dragExit(DragSourceEvent dse) {
+		// ignore
+	}
+
+	public void dragEnter(DropTargetDragEvent dtde) {
+		// ignore
+	}
+
+	/** This handles dragging of nodes (from myself) or entries (from the table) */
+	public void dragOver(DropTargetDragEvent dtde) {
+		final Point cursor = dtde.getLocation();
+		final long currentTime = System.currentTimeMillis();
+		if (idlePoint == null)
+			idlePoint = cursor;
+
+		// determine node over which the user is dragging
+		final TreePath path = getPathForLocation(cursor.x, cursor.y);
+		final GroupTreeNode target = path == null ? null : (GroupTreeNode) path
+				.getLastPathComponent();
+		setHighlight1Cell(target);
+
+		// accept or reject
+		if (dtde.isDataFlavorSupported(GroupTreeNode.flavor)) {
+			// accept: move nodes within tree
+			dtde.acceptDrag(DnDConstants.ACTION_MOVE);
+		} else if (dtde
+				.isDataFlavorSupported(TransferableEntrySelection.flavorInternal)) {
+			// check if node accepts explicit assignment
+			if (path == null) {
+				dtde.rejectDrag();
+			} else {
+				// this would be the place to check if the dragging entries
+				// maybe are in this group already, but I think that's not
+				// worth the bother (DropTargetDragEvent does not provide
+				// access to the drag object)...
+				// it might even be irritating to the user.
+				if (target.getGroup().supportsAdd()) {
+					// accept: assignment from EntryTable
+					dtde.acceptDrag(DnDConstants.ACTION_LINK);
+				} else {
+					dtde.rejectDrag();
+				}
+			}
+		} else {
+			dtde.rejectDrag();
+		}
+
+		// auto open
+		if (Math.abs(cursor.x - idlePoint.x) < idleMargin
+				&& Math.abs(cursor.y - idlePoint.y) < idleMargin) {
+			if (currentTime - idleStartTime >= idleTimeToExpandNode) {
+				if (path != null) {
+					expandPath(path);
+				}
+			}
+		} else {
+			idlePoint = cursor;
+			idleStartTime = currentTime;
+		}
+
+		// autoscrolling
+		if (currentTime - lastDragAutoscroll < minAutoscrollInterval)
+			return;
+		final Rectangle r = getVisibleRect();
+		final boolean scrollUp = cursor.y - r.y < dragScrollActivationMargin;
+		final boolean scrollDown = r.y + r.height - cursor.y < dragScrollActivationMargin;
+		final boolean scrollLeft = cursor.x - r.x < dragScrollActivationMargin;
+		final boolean scrollRight = r.x + r.width - cursor.x < dragScrollActivationMargin;
+		if (scrollUp)
+			r.translate(0, -dragScrollDistance);
+		else if (scrollDown)
+			r.translate(0, +dragScrollDistance);
+		if (scrollLeft)
+			r.translate(-dragScrollDistance, 0);
+		else if (scrollRight)
+			r.translate(+dragScrollDistance, 0);
+		scrollRectToVisible(r);
+		lastDragAutoscroll = currentTime;
+	}
+
+	public void dropActionChanged(DropTargetDragEvent dtde) {
+		// ignore
+	}
+
+	public void drop(DropTargetDropEvent dtde) {
+		setHighlight1Cell(null);
+		try {
+			// initializations common to all flavors
+			final Transferable transferable = dtde.getTransferable();
+			final Point p = dtde.getLocation();
+			final TreePath path = getPathForLocation(p.x, p.y);
+			if (path == null) {
+				dtde.rejectDrop();
+				return;
+			}
+			final GroupTreeNode target = (GroupTreeNode) path
+					.getLastPathComponent();
+			// check supported flavors
+			if (transferable.isDataFlavorSupported(GroupTreeNode.flavor)) {
+				GroupTreeNode source = (GroupTreeNode) transferable
+						.getTransferData(GroupTreeNode.flavor);
+				if (source == target) {
+					dtde.rejectDrop(); // ignore this
+					return;
+				}
+				if (source.isNodeDescendant(target)) {
+					dtde.rejectDrop();
+					return;
+				}
+				Enumeration expandedPaths = groupSelector.getExpandedPaths();
+				UndoableMoveGroup undo = new UndoableMoveGroup(groupSelector,
+						groupSelector.getGroupTreeRoot(), source, target,
+						target.getChildCount());
+				target.add(source);
+				dtde.getDropTargetContext().dropComplete(true);
+				// update selection/expansion state
+				groupSelector.revalidateGroups(new TreePath[] { new TreePath(
+						source.getPath()) }, refreshPaths(expandedPaths));
+				groupSelector.concludeMoveGroup(undo, source);
+			} else if (transferable
+					.isDataFlavorSupported(TransferableEntrySelection.flavorInternal)) {
+				final AbstractGroup group = target.getGroup();
+				if (!group.supportsAdd()) {
+					// this should never happen, because the same condition
+					// is checked in dragOver already
+					dtde.rejectDrop();
+					return;
+				}
+				final TransferableEntrySelection selection = (TransferableEntrySelection) transferable
+						.getTransferData(TransferableEntrySelection.flavorInternal);
+				final BibtexEntry[] entries = selection.getSelection();
+				int assignedEntries = 0;
+				for (int i = 0; i < entries.length; ++i) {
+					if (!target.getGroup().contains(entries[i]))
+						++assignedEntries;
+				}
+
+				// warn if assignment has undesired side effects (modifies a
+				// field != keywords)
+				if (!Util.warnAssignmentSideEffects(
+						new AbstractGroup[] { group },
+						selection.getSelection(), groupSelector
+								.getActiveBasePanel().getDatabase(),
+						groupSelector.frame))
+					return; // user aborted operation
+
+				// if an editor is showing, its fields must be updated
+				// after the assignment, and before that, the current
+				// edit has to be stored:
+				groupSelector.getActiveBasePanel().storeCurrentEdit();
+
+				AbstractUndoableEdit undo = group.add(selection.getSelection());
+				if (undo instanceof UndoableChangeAssignment)
+					((UndoableChangeAssignment) undo).setEditedNode(target);
+				dtde.getDropTargetContext().dropComplete(true);
+				groupSelector.revalidateGroups();
+				groupSelector.concludeAssignment(undo, target, assignedEntries);
+			} else {
+				dtde.rejectDrop();
+				return;
+			}
+		} catch (IOException ioe) {
+			// ignore
+		} catch (UnsupportedFlavorException e) {
+			// ignore
+		}
+	}
+
+	public void dragExit(DropTargetEvent dte) {
+		setHighlight1Cell(null);
+	}
+
+	public void dragGestureRecognized(DragGestureEvent dge) {
+		GroupTreeNode selectedNode = getSelectedNode();
+		if (selectedNode == null)
+			return; // nothing to transfer (select manually?)
+		Cursor cursor = DragSource.DefaultMoveDrop;
+		dragNode = selectedNode;
+		dge.getDragSource().startDrag(dge, cursor, selectedNode, this);
+	}
+
+	/** Returns the first selected node, or null if nothing is selected. */
+	public GroupTreeNode getSelectedNode() {
+		TreePath selectionPath = getSelectionPath();
+		return selectionPath != null ? (GroupTreeNode) selectionPath
+				.getLastPathComponent() : null;
+	}
+
+    /**
+     * Refresh paths that may have become invalid due to node movements within
+     * the tree. This method creates new paths to the last path components
+     * (which must still exist) of the specified paths.
+     * 
+     * @param paths
+     *            Paths that may have become invalid.
+     * @return Refreshed paths that are all valid.
+     */
+    public Enumeration refreshPaths(Enumeration paths) {
+        Vector freshPaths = new Vector();
+        while (paths.hasMoreElements()) {
+            freshPaths.add(new TreePath(
+                    ((DefaultMutableTreeNode) ((TreePath) paths.nextElement())
+                            .getLastPathComponent()).getPath()));
+        }
+        return freshPaths.elements();
+    }
+
+    /**
+     * Refresh paths that may have become invalid due to node movements within
+     * the tree. This method creates new paths to the last path components
+     * (which must still exist) of the specified paths.
+     * 
+     * @param paths
+     *            Paths that may have become invalid.
+     * @return Refreshed paths that are all valid.
+     */
+    public TreePath[] refreshPaths(TreePath[] paths) {
+        TreePath[] freshPaths = new TreePath[paths.length];
+        for (int i = 0; i < paths.length; ++i) {
+            freshPaths[i] = new TreePath(((DefaultMutableTreeNode) paths[i]
+                            .getLastPathComponent()).getPath());
+        }
+        return freshPaths;
+    }
+
+	/** Highlights the specified cell or disables highlight if cell == null */
+	public void setHighlight1Cell(Object cell) {
+		cellRenderer.setHighlight1Cell(cell);
+		repaint();
+	}
+
+	/** Highlights the specified cells or disables highlight if cells == null */
+	public void setHighlight2Cells(Object[] cells) {
+		cellRenderer.setHighlight2Cells(cells);
+		repaint();
+	}
+
+	/** Highlights the specified cells or disables highlight if cells == null */
+	public void setHighlight3Cells(Object[] cells) {
+		cellRenderer.setHighlight3Cells(cells);
+		repaint();
+	}
+    
+    /** Highlights the specified cell or disables highlight if cell == null */
+    public void setHighlightBorderCell(GroupTreeNode node) {
+        cellRenderer.setHighlightBorderCell(node);
+        repaint();
+    }
+
+	/** Sort immediate children of the specified node alphabetically. */
+	public void sort(GroupTreeNode node, boolean recursive) {
+		sortWithoutRevalidate(node, recursive);
+		groupSelector.revalidateGroups();
+	}
+
+	/** This sorts without revalidation of groups */
+	protected void sortWithoutRevalidate(GroupTreeNode node, boolean recursive) {
+		if (node.isLeaf())
+			return; // nothing to sort
+		GroupTreeNode child1, child2;
+		int j = node.getChildCount() - 1;
+		int lastModified;
+		while (j > 0) {
+			lastModified = j + 1;
+			j = -1;
+			for (int i = 1; i < lastModified; ++i) {
+				child1 = (GroupTreeNode) node.getChildAt(i - 1);
+				child2 = (GroupTreeNode) node.getChildAt(i);
+				if (child2.getGroup().getName().compareToIgnoreCase(
+						child1.getGroup().getName()) < 0) {
+					node.remove(child1);
+					node.insert(child1, i);
+					j = i;
+				}
+			}
+		}
+		if (recursive) {
+			for (int i = 0; i < node.getChildCount(); ++i) {
+				sortWithoutRevalidate((GroupTreeNode) node.getChildAt(i), true);
+			}
+		}
+	}
+
+	/** Expand this node and all its children. */
+	public void expandSubtree(GroupTreeNode node) {
+		for (Enumeration e = node.depthFirstEnumeration(); e.hasMoreElements();)
+			expandPath(new TreePath(((GroupTreeNode) e.nextElement()).getPath()));
+	}
+
+	/** Collapse this node and all its children. */
+	public void collapseSubtree(GroupTreeNode node) {
+		for (Enumeration e = node.depthFirstEnumeration(); e.hasMoreElements();)
+			collapsePath(new TreePath(((GroupTreeNode) e.nextElement())
+					.getPath()));
+	}
+
+	/**
+	 * Returns true if the node specified by path has at least one descendant
+	 * that is currently expanded.
+	 */
+	public boolean hasExpandedDescendant(TreePath path) {
+		GroupTreeNode node = (GroupTreeNode) path.getLastPathComponent();
+		for (Enumeration e = node.children(); e.hasMoreElements();) {
+			GroupTreeNode child = (GroupTreeNode) e.nextElement();
+			if (child.isLeaf())
+				continue; // don't care about this case
+			TreePath pathToChild = path.pathByAddingChild(child);
+			if (isExpanded(pathToChild) || hasExpandedDescendant(pathToChild))
+				return true;
+		}
+		return false;
+	}
+
+	/**
+	 * Returns true if the node specified by path has at least one descendant
+	 * that is currently collapsed.
+	 */
+	public boolean hasCollapsedDescendant(TreePath path) {
+		GroupTreeNode node = (GroupTreeNode) path.getLastPathComponent();
+		for (Enumeration e = node.children(); e.hasMoreElements();) {
+			GroupTreeNode child = (GroupTreeNode) e.nextElement();
+			if (child.isLeaf())
+				continue; // don't care about this case
+			TreePath pathToChild = path.pathByAddingChild(child);
+			if (isCollapsed(pathToChild) || hasCollapsedDescendant(pathToChild))
+				return true;
+		}
+		return false;
+	}
+}
diff --git a/src/java/net/sf/jabref/groups/KeywordGroup.java b/src/java/net/sf/jabref/groups/KeywordGroup.java
new file mode 100644
index 0000000..58d28a9
--- /dev/null
+++ b/src/java/net/sf/jabref/groups/KeywordGroup.java
@@ -0,0 +1,370 @@
+/*
+ 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.groups;
+
+import java.util.Map;
+import java.util.regex.*;
+
+import javax.swing.undo.AbstractUndoableEdit;
+
+import net.sf.jabref.*;
+import net.sf.jabref.undo.*;
+import net.sf.jabref.util.QuotedStringTokenizer;
+
+/**
+ * @author jzieren
+ */
+public class KeywordGroup extends AbstractGroup implements SearchRule {
+	public static final String ID = "KeywordGroup:";
+	private final String m_searchField;
+	private final String m_searchExpression;
+	private final boolean m_caseSensitive;
+	private final boolean m_regExp;
+	private Pattern m_pattern = null;
+
+	/**
+	 * Creates a KeywordGroup with the specified properties.
+	 */
+	public KeywordGroup(String name, String searchField,
+			String searchExpression, boolean caseSensitive, boolean regExp,
+			int context) throws IllegalArgumentException,
+			PatternSyntaxException {
+		super(name, context);
+		m_searchField = searchField;
+		m_searchExpression = searchExpression;
+		m_caseSensitive = caseSensitive;
+		m_regExp = regExp;
+		if (m_regExp)
+			compilePattern();
+	}
+
+	protected void compilePattern() throws IllegalArgumentException,
+			PatternSyntaxException {
+		m_pattern = m_caseSensitive ? Pattern.compile(m_searchExpression)
+				: Pattern.compile(m_searchExpression, Pattern.CASE_INSENSITIVE);
+	}
+
+	/**
+	 * Parses s and recreates the KeywordGroup from it.
+	 * 
+	 * @param s
+	 *            The String representation obtained from
+	 *            KeywordGroup.toString()
+	 */
+	public static AbstractGroup fromString(String s, BibtexDatabase db,
+			int version) throws Exception {
+		if (!s.startsWith(ID))
+			throw new Exception(
+					"Internal error: KeywordGroup cannot be created from \""
+							+ s
+							+ "\". "
+							+ "Please report this on www.sf.net/projects/jabref");
+		QuotedStringTokenizer tok = new QuotedStringTokenizer(s.substring(ID
+				.length()), SEPARATOR, QUOTE_CHAR);
+		switch (version) {
+		case 0: {
+			String name = tok.nextToken();
+			String field = tok.nextToken();
+			String expression = tok.nextToken();
+			// assume caseSensitive=false and regExp=true for old groups
+			return new KeywordGroup(Util.unquote(name, QUOTE_CHAR), Util
+					.unquote(field, QUOTE_CHAR), Util.unquote(expression,
+					QUOTE_CHAR), false, true, AbstractGroup.INDEPENDENT);
+		}
+		case 1:
+		case 2: {
+			String name = tok.nextToken();
+			String field = tok.nextToken();
+			String expression = tok.nextToken();
+			boolean caseSensitive = Integer.parseInt(tok.nextToken()) == 1;
+			boolean regExp = Integer.parseInt(tok.nextToken()) == 1;
+			return new KeywordGroup(Util.unquote(name, QUOTE_CHAR), Util
+					.unquote(field, QUOTE_CHAR), Util.unquote(expression,
+					QUOTE_CHAR), caseSensitive, regExp,
+					AbstractGroup.INDEPENDENT);
+		}
+		case 3: {
+			String name = tok.nextToken();
+			int context = Integer.parseInt(tok.nextToken());
+			String field = tok.nextToken();
+			String expression = tok.nextToken();
+			boolean caseSensitive = Integer.parseInt(tok.nextToken()) == 1;
+			boolean regExp = Integer.parseInt(tok.nextToken()) == 1;
+			return new KeywordGroup(Util.unquote(name, QUOTE_CHAR), Util
+					.unquote(field, QUOTE_CHAR), Util.unquote(expression,
+					QUOTE_CHAR), caseSensitive, regExp, context);
+		}
+		default:
+			throw new UnsupportedVersionException("KeywordGroup", version);
+		}
+	}
+
+	/**
+	 * @see net.sf.jabref.groups.AbstractGroup#getSearchRule()
+	 */
+	public SearchRule getSearchRule() {
+		return this;
+	}
+
+	/**
+	 * Returns a String representation of this object that can be used to
+	 * reconstruct it.
+	 */
+	public String toString() {
+		return ID + Util.quote(m_name, SEPARATOR, QUOTE_CHAR) + SEPARATOR
+				+ m_context + SEPARATOR
+				+ Util.quote(m_searchField, SEPARATOR, QUOTE_CHAR) + SEPARATOR
+				+ Util.quote(m_searchExpression, SEPARATOR, QUOTE_CHAR)
+				+ SEPARATOR + (m_caseSensitive ? "1" : "0") + SEPARATOR
+				+ (m_regExp ? "1" : "0") + SEPARATOR;
+	}
+
+	public boolean supportsAdd() {
+		return !m_regExp;
+	}
+
+	public boolean supportsRemove() {
+		return !m_regExp;
+	}
+
+	public AbstractUndoableEdit add(BibtexEntry[] entries) {
+		if (!supportsAdd())
+			return null;
+		if ((entries != null) && (entries.length > 0)) {
+			NamedCompound ce = new NamedCompound(Globals
+					.lang("add entries to group"));
+			boolean modified = false;
+			for (int i = 0; i < entries.length; i++) {
+				if (applyRule(null, entries[i]) == 0) {
+					String oldContent = (String) entries[i]
+							.getField(m_searchField), 
+							pre = Globals.prefs.get("groupKeywordSeparator");
+					String newContent = (oldContent == null ? "" : oldContent
+							+ pre)
+							+ m_searchExpression;
+					entries[i].setField(m_searchField, newContent);
+
+					// Store undo information.
+					ce.addEdit(new UndoableFieldChange(entries[i],
+							m_searchField, oldContent, newContent));
+					modified = true;
+				}
+			}
+			if (modified)
+				ce.end();
+
+			return modified ? ce : null;
+		}
+
+		return null;
+	}
+
+	public AbstractUndoableEdit remove(BibtexEntry[] entries) {
+		if (!supportsRemove())
+			return null;
+
+		if ((entries != null) && (entries.length > 0)) {
+			NamedCompound ce = new NamedCompound(Globals
+					.lang("remove from group"));
+			boolean modified = false;
+			for (int i = 0; i < entries.length; ++i) {
+				if (applyRule(null, entries[i]) > 0) {
+					String oldContent = (String) entries[i]
+							.getField(m_searchField);
+					removeMatches(entries[i]);
+					// Store undo information.
+					ce.addEdit(new UndoableFieldChange(entries[i],
+							m_searchField, oldContent, entries[i]
+									.getField(m_searchField)));
+					modified = true;
+				}
+			}
+			if (modified)
+				ce.end();
+
+			return modified ? ce : null;
+		}
+
+		return null;
+	}
+
+	public boolean equals(Object o) {
+		if (!(o instanceof KeywordGroup))
+			return false;
+		KeywordGroup other = (KeywordGroup) o;
+		return m_name.equals(other.m_name)
+				&& m_searchField.equals(other.m_searchField)
+				&& m_searchExpression.equals(other.m_searchExpression)
+				&& m_caseSensitive == other.m_caseSensitive
+				&& m_regExp == other.m_regExp
+                && getHierarchicalContext() == other.getHierarchicalContext();
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see net.sf.jabref.groups.AbstractGroup#contains(java.util.Map,
+	 *      net.sf.jabref.BibtexEntry)
+	 */
+	public boolean contains(Map searchOptions, BibtexEntry entry) {
+		return contains(entry);
+	}
+
+	public boolean contains(BibtexEntry entry) {
+		String content = (String) entry.getField(m_searchField);
+		if (content == null)
+			return false;
+		if (m_regExp)
+			return m_pattern.matcher(content).find();
+		if (m_caseSensitive)
+			return content.indexOf(m_searchExpression) >= 0;
+		content = content.toLowerCase();
+		return content.indexOf(m_searchExpression.toLowerCase()) >= 0;
+	}
+
+	/**
+	 * Removes matches of searchString in the entry's field. This is only
+	 * possible if the search expression is not a regExp.
+	 */
+	private void removeMatches(BibtexEntry entry) {
+		String content = (String) entry.getField(m_searchField);
+		if (content == null)
+			return; // nothing to modify
+		StringBuffer sbOrig = new StringBuffer(content);
+		StringBuffer sbLower = new StringBuffer(content.toLowerCase());
+		StringBuffer haystack = m_caseSensitive ? sbOrig : sbLower;
+		String needle = m_caseSensitive ? m_searchExpression
+				: m_searchExpression.toLowerCase();
+		int i, j, k;
+		final String separator = Globals.prefs.get("groupKeywordSeparator");
+		while ((i = haystack.indexOf(needle)) >= 0) {
+			sbOrig.replace(i, i + needle.length(), "");
+			sbLower.replace(i, i + needle.length(), "");
+			// reduce spaces at i to 1
+			j = i;
+			k = i;
+			while (j - 1 >= 0 && separator.indexOf(haystack.charAt(j - 1)) >= 0)
+				--j;
+			while (k < haystack.length() && separator.indexOf(haystack.charAt(k)) >= 0)
+				++k;
+			sbOrig.replace(j, k, j >= 0 && k < sbOrig.length() ? separator : "");
+			sbLower.replace(j, k, j >= 0 && k < sbOrig.length() ? separator : "");
+		}
+
+		String result = sbOrig.toString().trim();
+		entry.setField(m_searchField, (result.length() > 0 ? result : null));
+	}
+
+	public int applyRule(Map searchOptions, BibtexEntry entry) {
+		return contains(searchOptions, entry) ? 1 : 0;
+	}
+
+	public AbstractGroup deepCopy() {
+		try {
+			return new KeywordGroup(m_name, m_searchField, m_searchExpression,
+					m_caseSensitive, m_regExp, m_context);
+		} catch (Throwable t) {
+			// this should never happen, because the constructor obviously
+			// succeeded in creating _this_ instance!
+			System.err.println("Internal error: Exception " + t
+					+ " in KeywordGroup.deepCopy(). "
+					+ "Please report this on www.sf.net/projects/jabref");
+			return null;
+		}
+	}
+
+	public boolean isCaseSensitive() {
+		return m_caseSensitive;
+	}
+
+	public boolean isRegExp() {
+		return m_regExp;
+	}
+
+	public String getSearchExpression() {
+		return m_searchExpression;
+	}
+
+	public String getSearchField() {
+		return m_searchField;
+	}
+
+	public boolean isDynamic() {
+		return true;
+	}
+	
+	public String getDescription() {
+		return getDescriptionForPreview(m_searchField, m_searchExpression, m_caseSensitive,
+				m_regExp); 
+	}
+	
+	public static String getDescriptionForPreview(String field, String expr,
+            boolean caseSensitive, boolean regExp) {
+        StringBuffer sb = new StringBuffer();
+        sb.append(regExp ? Globals.lang(
+                "This group contains entries whose <b>%0</b> field contains the regular expression <b>%1</b>",
+                field, Util.quoteForHTML(expr))
+                : Globals.lang(
+                        "This group contains entries whose <b>%0</b> field contains the keyword <b>%1</b>",
+                        field, Util.quoteForHTML(expr)));
+        sb.append(" (").append(caseSensitive ? Globals.lang("case sensitive")
+                : Globals.lang("case insensitive")).append("). ");
+        sb.append(regExp ? Globals.lang(
+                "Entries cannot be manually assigned to or removed from this group.")
+                : Globals.lang(
+                        "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.",
+                        field, Util.quoteForHTML(expr)));
+        return sb.toString();
+    }
+
+	public String getShortDescription() {
+		StringBuffer sb = new StringBuffer();
+		sb.append("<b>");
+		if (Globals.prefs.getBoolean("groupShowDynamic"))
+            sb.append("<i>").append(Util.quoteForHTML(getName())).append("</i>");
+		else
+			sb.append(Util.quoteForHTML(getName()));
+        sb.append("</b> - dynamic group (<b>").append(m_searchField).
+            append("</b> contains <b>").
+            append(Util.quoteForHTML(m_searchExpression)).append("</b>)");
+		switch (getHierarchicalContext()) {
+		case AbstractGroup.INCLUDING:
+			sb.append(", includes subgroups");
+			break;
+		case AbstractGroup.REFINING:
+			sb.append(", refines supergroup");
+			break;
+		default:
+			break;
+		}
+		return sb.toString();
+	}
+}
diff --git a/src/java/net/sf/jabref/groups/RemoveFromGroupAction.java b/src/java/net/sf/jabref/groups/RemoveFromGroupAction.java
new file mode 100644
index 0000000..629037d
--- /dev/null
+++ b/src/java/net/sf/jabref/groups/RemoveFromGroupAction.java
@@ -0,0 +1,66 @@
+/*
+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.groups;
+
+import java.awt.event.ActionEvent;
+
+import javax.swing.AbstractAction;
+import javax.swing.undo.AbstractUndoableEdit;
+
+import net.sf.jabref.*;
+
+public class RemoveFromGroupAction extends AbstractAction {
+    protected GroupTreeNode m_node;
+    protected BasePanel m_panel;
+    public RemoveFromGroupAction(GroupTreeNode node, BasePanel panel) {
+        super(node.getGroup().getName());
+        m_node = node;
+        m_panel = panel;
+    }
+    public RemoveFromGroupAction() {
+        super(Globals.lang("Remove entry selection from this group")); // JZTODO lyrics
+    }
+    public void setNode(GroupTreeNode node) {
+        m_node = node;
+    }
+    public void setBasePanel(BasePanel panel) {
+        m_panel = panel;
+    }
+    public void actionPerformed(ActionEvent evt) {
+        // warn if assignment has undesired side effects (modifies a field != keywords)
+        if (!Util.warnAssignmentSideEffects(new AbstractGroup[]{m_node.getGroup()},
+                m_panel.getSelectedEntries(),
+                m_panel.getDatabase(),
+                m_panel.frame()))
+            return; // user aborted operation
+        
+        AbstractUndoableEdit undo = m_node.removeFromGroup(m_panel.getSelectedEntries());
+        if (undo == null)
+            return; // no changed made
+        
+        m_panel.undoManager.addEdit(undo);
+        m_panel.markBaseChanged();
+        m_panel.updateEntryEditorIfShowing();
+        m_panel.getGroupSelector().valueChanged(null);
+    }
+}
diff --git a/src/java/net/sf/jabref/groups/SearchGroup.java b/src/java/net/sf/jabref/groups/SearchGroup.java
new file mode 100644
index 0000000..74f85ae
--- /dev/null
+++ b/src/java/net/sf/jabref/groups/SearchGroup.java
@@ -0,0 +1,400 @@
+/*
+ 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.groups;
+
+import java.io.StringReader;
+import java.util.*;
+import java.util.regex.Pattern;
+
+import javax.swing.undo.AbstractUndoableEdit;
+
+import net.sf.jabref.*;
+import net.sf.jabref.search.*;
+import net.sf.jabref.util.QuotedStringTokenizer;
+import antlr.RecognitionException;
+import antlr.collections.AST;
+
+/**
+ * @author jzieren
+ * 
+ * TODO To change the template for this generated type comment go to Window -
+ * Preferences - Java - Code Style - Code Templates
+ */
+public class SearchGroup extends AbstractGroup implements SearchRule {
+	public static final String ID = "SearchGroup:";
+
+	private final String m_searchExpression;
+
+	private final boolean m_caseSensitive;
+
+	private final boolean m_regExp;
+
+	private final AST m_ast;
+
+	private static final SearchExpressionTreeParser m_treeParser = new SearchExpressionTreeParser();
+
+	/**
+	 * If m_searchExpression is in valid syntax for advanced search, <b>this
+	 * </b> will do the search; otherwise, either <b>RegExpRule </b> or
+	 * <b>SimpleSearchRule </b> will be used.
+	 */
+	private final SearchRule m_searchRule;
+
+	/**
+	 * Creates a SearchGroup with the specified properties.
+	 */
+	public SearchGroup(String name, String searchExpression,
+			boolean caseSensitive, boolean regExp, int context) {
+		super(name, context);
+		m_searchExpression = searchExpression;
+		m_caseSensitive = caseSensitive;
+		m_regExp = regExp;
+
+		// create AST
+		AST ast = null;
+		try {
+			SearchExpressionParser parser = new SearchExpressionParser(
+					new SearchExpressionLexer(new StringReader(
+							m_searchExpression)));
+			parser.caseSensitive = m_caseSensitive;
+			parser.regex = m_regExp;
+			parser.searchExpression();
+			ast = parser.getAST();
+		} catch (Exception e) {
+			ast = null;
+			// nothing to do; set m_ast to null -> regular plaintext search
+		}
+		m_ast = ast;
+
+		if (m_ast != null) { // do advanced search
+			m_searchRule = this;
+		} else { // do plaintext search
+			if (m_regExp)
+				m_searchRule = new RegExpRule(m_caseSensitive);
+			else
+				m_searchRule = new SimpleSearchRule(m_caseSensitive);
+		}
+
+	}
+
+	/**
+	 * Parses s and recreates the SearchGroup from it.
+	 * 
+	 * @param s
+	 *            The String representation obtained from
+	 *            SearchGroup.toString(), or null if incompatible
+	 */
+	public static AbstractGroup fromString(String s, BibtexDatabase db,
+			int version) throws Exception {
+		if (!s.startsWith(ID))
+			throw new Exception(
+					"Internal error: SearchGroup cannot be created from \"" + s
+					+ "\". "
+					+ "Please report this on www.sf.net/projects/jabref");
+		QuotedStringTokenizer tok = new QuotedStringTokenizer(s.substring(ID
+				.length()), SEPARATOR, QUOTE_CHAR);
+		switch (version) {
+		case 0:
+		case 1:
+		case 2: {
+			String name = tok.nextToken();
+			String expression = tok.nextToken();
+			boolean caseSensitive = Integer.parseInt(tok.nextToken()) == 1;
+			boolean regExp = Integer.parseInt(tok.nextToken()) == 1;
+			// version 0 contained 4 additional booleans to specify search
+			// fields; these are ignored now, all fields are always searched
+			return new SearchGroup(Util.unquote(name, QUOTE_CHAR), Util
+					.unquote(expression, QUOTE_CHAR), caseSensitive, regExp,
+					AbstractGroup.INDEPENDENT);
+		}
+		case 3: {
+			String name = tok.nextToken();
+			int context = Integer.parseInt(tok.nextToken());
+			String expression = tok.nextToken();
+			boolean caseSensitive = Integer.parseInt(tok.nextToken()) == 1;
+			boolean regExp = Integer.parseInt(tok.nextToken()) == 1;
+			// version 0 contained 4 additional booleans to specify search
+			// fields; these are ignored now, all fields are always searched
+			return new SearchGroup(Util.unquote(name, QUOTE_CHAR), Util
+					.unquote(expression, QUOTE_CHAR), caseSensitive, regExp,
+					context);
+		}
+		default:
+			throw new UnsupportedVersionException("SearchGroup", version);
+		}
+	}
+
+	/**
+	 * @see net.sf.jabref.groups.AbstractGroup#getSearchRule()
+	 */
+	public SearchRule getSearchRule() {
+		return this;
+	}
+
+	/**
+	 * Returns a String representation of this object that can be used to
+	 * reconstruct it.
+	 */
+	public String toString() {
+		return ID + Util.quote(m_name, SEPARATOR, QUOTE_CHAR) + SEPARATOR
+				+ m_context + SEPARATOR
+				+ Util.quote(m_searchExpression, SEPARATOR, QUOTE_CHAR)
+				+ SEPARATOR + (m_caseSensitive ? "1" : "0") + SEPARATOR
+				+ (m_regExp ? "1" : "0") + SEPARATOR;
+	}
+
+	public String getSearchExpression() {
+		return m_searchExpression;
+	}
+
+	public boolean supportsAdd() {
+		return false;
+	}
+
+	public boolean supportsRemove() {
+		return false;
+	}
+
+	public AbstractUndoableEdit add(BibtexEntry[] entries) {
+		// nothing to do, add is not supported
+		return null;
+	}
+
+	public AbstractUndoableEdit remove(BibtexEntry[] entries) {
+		// nothing to do, remove is not supported
+		return null;
+	}
+
+	public boolean equals(Object o) {
+		if (!(o instanceof SearchGroup))
+			return false;
+		SearchGroup other = (SearchGroup) o;
+		return m_name.equals(other.m_name)
+				&& m_searchExpression.equals(other.m_searchExpression)
+				&& m_caseSensitive == other.m_caseSensitive
+				&& m_regExp == other.m_regExp
+                && getHierarchicalContext() == other.getHierarchicalContext();
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see net.sf.jabref.groups.AbstractGroup#contains(java.util.Map,
+	 *      net.sf.jabref.BibtexEntry)
+	 */
+	public boolean contains(Map searchOptions, BibtexEntry entry) {
+		return applyRule(searchOptions, entry) == 0 ? false : true;
+	}
+
+	public boolean contains(BibtexEntry entry) {
+		// use dummy map
+		return contains(new HashMap(), entry);
+	}
+
+	public int applyRule(Map searchOptions, BibtexEntry entry) {
+		if (m_ast == null) {
+			// the searchOptions object is a dummy; we need to insert
+			// the actual search expression.
+			searchOptions.put("option", m_searchExpression);
+			return m_searchRule.applyRule(searchOptions, entry);
+		}
+		try {
+			return m_treeParser.apply(m_ast, entry);
+		} catch (RecognitionException e) {
+			return 0; // this should never occur
+		}
+	}
+
+	public AbstractGroup deepCopy() {
+		try {
+			return new SearchGroup(m_name, m_searchExpression, m_caseSensitive,
+					m_regExp, m_context);
+		} catch (Throwable t) {
+			// this should never happen, because the constructor obviously
+			// succeeded in creating _this_ instance!
+			System.err.println("Internal error: Exception " + t
+					+ " in SearchGroup.deepCopy(). "
+					+ "Please report this on www.sf.net/projects/jabref");
+			return null;
+		}
+	}
+
+	public boolean isCaseSensitive() {
+		return m_caseSensitive;
+	}
+
+	public boolean isRegExp() {
+		return m_regExp;
+	}
+
+	public boolean isDynamic() {
+		return true;
+	}
+	
+	public String getDescription() {
+		return getDescriptionForPreview(m_searchExpression, m_ast, m_caseSensitive,
+				m_regExp);
+	}
+	
+	public static String getDescriptionForPreview(String expr, AST ast,
+			boolean caseSensitive, boolean regExp) {
+		StringBuffer sb = new StringBuffer();
+		if (ast == null) {
+			sb.append(regExp ? Globals.lang(
+			        "This group contains entries in which any field contains the regular expression <b>%0</b>",
+                    Util.quoteForHTML(expr))
+                    : Globals.lang(
+                            "This group contains entries in which any field contains the term <b>%0</b>",
+                            Util.quoteForHTML(expr)));
+            sb.append(" (").append(caseSensitive ? Globals.lang("case sensitive")
+                    : Globals.lang("case insensitive")).append("). ");
+			sb.append(Globals.lang(
+                    "Entries cannot be manually assigned to or removed from this group."));
+            sb.append("<p><br>").append(Globals.lang(
+                    "Hint%c To search specific fields only, enter for example%c<p><tt>author%esmith and title%eelectrical</tt>"));
+			return sb.toString();
+		}
+		// describe advanced search expression
+        sb.append(Globals.lang("This group contains entries in which")).append(" ");
+		sb.append(describeNode(ast, regExp, false, false, false));
+		sb.append(". ");
+		sb.append(caseSensitive ? Globals.lang("The search is case sensitive.")
+				: Globals.lang("The search is case insensitive."));
+		return sb.toString();
+	}
+
+	protected static String describeNode(AST node, boolean regExp,
+			boolean not, boolean and, boolean or) {
+		StringBuffer sb = new StringBuffer();
+		switch (node.getType()) {
+		case SearchExpressionTreeParserTokenTypes.And:
+			if (not)
+                sb.append(Globals.lang("not")).append(" ");
+			// if there was an "or" in this subtree so far, braces may be needed
+			if (or || not)
+				sb.append("(");
+            sb.append(describeNode(node.getFirstChild(), regExp,
+                    false, true, false)).append(" ").append(Globals.lang("and")).append(" ").append(describeNode(node.getFirstChild()
+                    .getNextSibling(), regExp, false, true, false));
+			if (or || not)
+				sb.append(")");
+			return sb.toString();
+		case SearchExpressionTreeParserTokenTypes.Or:
+			if (not)
+                sb.append(Globals.lang("not")).append(" ");
+			// if there was an "and" in this subtree so far, braces may be
+			// needed
+			if (and || not)
+				sb.append("(");
+            sb.append(describeNode(node.getFirstChild(), regExp,
+                    false, false, true)).append(" ").append(Globals.lang("or")).append(" ").append(describeNode(node.getFirstChild()
+                    .getNextSibling(), regExp, false, false, true));
+			if (and || not)
+				sb.append(")");
+			return sb.toString();
+		case SearchExpressionTreeParserTokenTypes.Not:
+			return describeNode(node.getFirstChild(), regExp, !not,
+					and, or);
+		default:
+			node = node.getFirstChild();
+			final String field = node.getText();
+			final boolean regExpFieldSpec = !Pattern.matches("\\w+", field);
+			node = node.getNextSibling();
+			final int type = node.getType();
+			node = node.getNextSibling();
+			final String term = node.getText();
+			final String fieldSpec = regExpFieldSpec ? Globals.lang(
+					"any field that matches the regular expression <b>%0</b>",
+                    Util.quoteForHTML(field)) : Globals.lang("the field <b>%0</b>", 
+                            Util.quoteForHTML(field));
+			switch (type) {
+			case SearchExpressionTreeParserTokenTypes.LITERAL_contains:
+			case SearchExpressionTreeParserTokenTypes.EQUAL:
+				if (regExp)
+					return not ? Globals.lang(
+					        "%0 doesn't contain the Regular Expression <b>%1</b>",
+                            Util.quoteForHTML(fieldSpec), Util.quoteForHTML(term))
+							: Globals.lang(
+							        "%0 contains the Regular Expression <b>%1</b>",
+                                    Util.quoteForHTML(fieldSpec), Util.quoteForHTML(term));
+				return not ? Globals.lang(
+						"%0 doesn't contain the term <b>%1</b>", Util.quoteForHTML(fieldSpec),
+                        Util.quoteForHTML(term)) : Globals.lang("%0 contains the term <b>%1</b>",
+                                Util.quoteForHTML(fieldSpec), Util.quoteForHTML(term));
+			case SearchExpressionTreeParserTokenTypes.LITERAL_matches:
+			case SearchExpressionTreeParserTokenTypes.EEQUAL:
+				if (regExp)
+					return not ? Globals.lang(
+					        "%0 doesn't match the Regular Expression <b>%1</b>",
+                            Util.quoteForHTML(fieldSpec), Util.quoteForHTML(term))
+							: Globals.lang(
+                                    "%0 matches the Regular Expression <b>%1</b>",
+                                    Util.quoteForHTML(fieldSpec), Util.quoteForHTML(term));
+				return not ? Globals.lang(
+						"%0 doesn't match the term <b>%1</b>", 
+                        Util.quoteForHTML(fieldSpec), Util.quoteForHTML(term))
+						: Globals.lang("%0 matches the term <b>%1</b>",
+                                Util.quoteForHTML(fieldSpec), 
+                                Util.quoteForHTML(term));
+			case SearchExpressionTreeParserTokenTypes.NEQUAL:
+				if (regExp)
+					return not ? Globals.lang(
+							"%0 contains the Regular Expression <b>%1</b>",
+                            Util.quoteForHTML(fieldSpec), Util.quoteForHTML(term))
+							: Globals.lang(
+                                    "%0 doesn't contain the Regular Expression <b>%1</b>",
+                                    Util.quoteForHTML(fieldSpec), Util.quoteForHTML(term));
+				return not ? Globals.lang("%0 contains the term <b>%1</b>",
+                        Util.quoteForHTML(fieldSpec), Util.quoteForHTML(term)) : Globals.lang(
+						"%0 doesn't contain the term <b>%1</b>", Util.quoteForHTML(fieldSpec),
+                        Util.quoteForHTML(term));
+			default:
+				return "Internal error: Unknown AST node type. "
+						+ "Please report this on www.sf.net/projects/jabref";
+				// this should never happen
+			}
+		}
+	}
+
+	public String getShortDescription() {
+		StringBuffer sb = new StringBuffer();
+		sb.append("<b>");
+		if (Globals.prefs.getBoolean("groupShowDynamic"))
+            sb.append("<i>").append(Util.quoteForHTML(getName())).append("</i>");
+		else
+			sb.append(Util.quoteForHTML(getName()));
+        sb.append("</b> - dynamic group (" + "search expression: <b>").
+            append(Util.quoteForHTML(m_searchExpression)).append("</b>)");
+		switch (getHierarchicalContext()) {
+		case AbstractGroup.INCLUDING:
+			sb.append(", includes subgroups");
+			break;
+		case AbstractGroup.REFINING:
+			sb.append(", refines supergroup");
+			break;
+		default:
+			break;
+		}
+		return sb.toString();
+	}
+}
diff --git a/src/java/net/sf/jabref/groups/TransferableEntrySelection.java b/src/java/net/sf/jabref/groups/TransferableEntrySelection.java
new file mode 100644
index 0000000..9aaeb4d
--- /dev/null
+++ b/src/java/net/sf/jabref/groups/TransferableEntrySelection.java
@@ -0,0 +1,99 @@
+/*
+ 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.groups;
+
+import java.awt.datatransfer.*;
+import java.io.*;
+import java.io.IOException;
+
+import javax.print.FlavorException;
+
+import net.sf.jabref.BibtexEntry;
+
+public class TransferableEntrySelection implements Transferable {
+    public static final DataFlavor flavorInternal;
+    public static final DataFlavor flavorExternal;
+    public static final DataFlavor[] flavors;
+    public final BibtexEntry[] selectedEntries;
+    public final String selectedEntriesCiteKeys;
+    
+    protected boolean includeCiteKeyword = false;
+
+    static {
+        DataFlavor df1 = null;
+        DataFlavor df2 = null;
+        try {
+            df1 = new DataFlavor(DataFlavor.javaJVMLocalObjectMimeType
+                    + ";class=net.sf.jabref.groups.TransferableEntrySelection");
+            df2 = DataFlavor.getTextPlainUnicodeFlavor();
+        } catch (ClassNotFoundException e) {
+            // never happens
+        }
+        flavorInternal = df1;
+        flavorExternal = df2;
+        flavors = new DataFlavor[] { flavorInternal, flavorExternal };
+    }
+
+    public TransferableEntrySelection(BibtexEntry[] selectedEntries) {
+        this.selectedEntries = selectedEntries;
+        StringBuffer keys = new StringBuffer();
+        for (int i = 0; i < selectedEntries.length; ++i) {
+            keys.append(selectedEntries[i].getCiteKey());
+            if (i + 1 < selectedEntries.length)
+                keys.append(",");
+        }
+        selectedEntriesCiteKeys = keys.toString();
+    }
+
+    public DataFlavor[] getTransferDataFlavors() {
+        return flavors;
+    }
+
+    public boolean isDataFlavorSupported(DataFlavor someFlavor) {
+        return someFlavor.equals(flavorInternal)
+                || someFlavor.equals(flavorExternal);
+    }
+
+    public Object getTransferData(DataFlavor someFlavor)
+            throws UnsupportedFlavorException, IOException {
+        if (!isDataFlavorSupported(someFlavor))
+            throw new UnsupportedFlavorException(someFlavor);
+        if (someFlavor.equals(flavorInternal))
+            return this;
+        String s = includeCiteKeyword ?
+                "\\cite{" + selectedEntriesCiteKeys + "}" 
+                : selectedEntriesCiteKeys;
+        return new ByteArrayInputStream(s.getBytes(
+                flavorExternal.getParameter("charset").trim()));
+    }
+
+    public BibtexEntry[] getSelection() {
+        return selectedEntries;
+    }
+
+    public void setIncludeCiteKeyword(boolean includeCiteKeyword) {
+        this.includeCiteKeyword = includeCiteKeyword;
+    }
+    
+
+}
diff --git a/src/java/net/sf/jabref/groups/UndoableAddOrRemoveGroup.java b/src/java/net/sf/jabref/groups/UndoableAddOrRemoveGroup.java
new file mode 100644
index 0000000..1eb2924
--- /dev/null
+++ b/src/java/net/sf/jabref/groups/UndoableAddOrRemoveGroup.java
@@ -0,0 +1,177 @@
+/*
+ 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.
+
+ 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.groups;
+
+import javax.swing.undo.AbstractUndoableEdit;
+
+import net.sf.jabref.Globals;
+
+class UndoableAddOrRemoveGroup extends AbstractUndoableEdit {
+    /** The root of the global groups tree */
+    private final GroupTreeNode m_groupsRootHandle;
+    /** The subtree that was added or removed */
+    private final GroupTreeNode m_subtreeBackup;
+    /**
+     * In case of removing a node but keeping all of its children, the number of
+     * children has to be stored.
+     */
+    private final int m_subtreeRootChildCount;
+    /** The path to the edited subtree's root node */
+    private final int[] m_pathToNode;
+    /**
+     * The type of the editing (ADD_NODE, REMOVE_NODE_KEEP_CHILDREN,
+     * REMOVE_NODE_AND_CHILDREN)
+     */
+    private final int m_editType;
+    private final GroupSelector m_groupSelector;
+    private boolean m_revalidate = true;
+    /** Adding of a single node (group). */
+    public static final int ADD_NODE = 0;
+    /** Removal of a single node. Children, if any, are kept. */
+    public static final int REMOVE_NODE_KEEP_CHILDREN = 1;
+    /** Removal of a node and all of its children. */
+    public static final int REMOVE_NODE_AND_CHILDREN = 2;
+
+    /**
+     * Creates an object that can undo/redo an edit event.
+     * 
+     * @param groupsRoot
+     *            The global groups root.
+     * @param editType
+     *            The type of editing (ADD_NODE, REMOVE_NODE_KEEP_CHILDREN,
+     *            REMOVE_NODE_AND_CHILDREN)
+     * @param editedNode
+     *            The edited node (which was added or will be removed). The node
+     *            must be a descendant of node <b>groupsRoot</b>! This means
+     *            that, in case of adding, you first have to add it to the tree,
+     *            then call this constructor. When removing, you first have to
+     *            call this constructor, then remove the node.
+     */
+    public UndoableAddOrRemoveGroup(GroupSelector gs, GroupTreeNode groupsRoot,
+            GroupTreeNode editedNode, int editType) {
+        m_groupSelector = gs;
+        m_groupsRootHandle = groupsRoot;
+        m_editType = editType;
+        m_subtreeRootChildCount = editedNode.getChildCount();
+        // storing a backup of the whole subtree is not required when children
+        // are kept
+        m_subtreeBackup = editType != REMOVE_NODE_KEEP_CHILDREN ? editedNode
+                .deepCopy() : new GroupTreeNode(editedNode.getGroup().deepCopy());
+        // remember path to edited node. this cannot be stored as a reference,
+        // because the reference itself might change. the method below is more
+        // robust.
+        m_pathToNode = editedNode.getIndexedPath();
+    }
+
+    public String getUndoPresentationName() {
+        return Globals.lang("Undo") + ": " + getName();
+    }
+
+    public String getName() {
+        switch (m_editType) {
+        case ADD_NODE:
+            return Globals.lang("add group");
+        case REMOVE_NODE_KEEP_CHILDREN:
+            return Globals.lang("remove group (keep subgroups)");
+        case REMOVE_NODE_AND_CHILDREN:
+            return Globals.lang("remove group and subgroups");
+        }
+        return "? (" + Globals.lang("unknown edit") + ")";
+    }
+
+    public String getRedoPresentationName() {
+        return Globals.lang("Redo") + ": " + getName();
+    }
+
+    public void undo() {
+        super.undo();
+        doOperation(true);
+    }
+
+    public void redo() {
+        super.redo();
+        doOperation(false);
+    }
+
+    private void doOperation(boolean undo) {
+        GroupTreeNode cursor = m_groupsRootHandle;
+        final int childIndex = m_pathToNode[m_pathToNode.length - 1];
+        // traverse path up to butlast element
+        for (int i = 0; i < m_pathToNode.length - 1; ++i)
+            cursor = (GroupTreeNode) cursor.getChildAt(m_pathToNode[i]);
+        if (undo) {
+            switch (m_editType) {
+            case ADD_NODE:
+                cursor.remove(childIndex);
+                break;
+            case REMOVE_NODE_KEEP_CHILDREN:
+                // move all children to newNode, then add newNode
+                GroupTreeNode newNode = m_subtreeBackup.deepCopy();
+                for (int i = childIndex; i < childIndex
+                        + m_subtreeRootChildCount; ++i) {
+                    newNode.add((GroupTreeNode) cursor.getChildAt(childIndex));
+                }
+                cursor.insert(newNode, childIndex);
+                break;
+            case REMOVE_NODE_AND_CHILDREN:
+                cursor.insert(m_subtreeBackup.deepCopy(), childIndex);
+                break;
+            }
+        } else { // redo
+            switch (m_editType) {
+            case ADD_NODE:
+                cursor.insert(m_subtreeBackup.deepCopy(), childIndex);
+                break;
+            case REMOVE_NODE_KEEP_CHILDREN:
+                // remove node, then insert all children
+                GroupTreeNode removedNode = (GroupTreeNode) cursor
+                        .getChildAt(childIndex);
+                cursor.remove(childIndex);
+                while (removedNode.getChildCount() > 0)
+                    cursor.insert((GroupTreeNode) removedNode.getFirstChild(),
+                            childIndex);
+                break;
+            case REMOVE_NODE_AND_CHILDREN:
+                cursor.remove(childIndex);
+                break;
+            }
+        }
+        if (m_revalidate)
+            m_groupSelector.revalidateGroups();
+    }
+
+    /**
+     * Call this method to decide if the group list should be immediately
+     * revalidated by this operation. Default is true.
+     * 
+     * @param val
+     *            a <code>boolean</code> value
+     */
+    public void setRevalidate(boolean val) {
+        m_revalidate = val;
+    }
+}
diff --git a/src/java/net/sf/jabref/groups/UndoableChangeAssignment.java b/src/java/net/sf/jabref/groups/UndoableChangeAssignment.java
new file mode 100644
index 0000000..c2de990
--- /dev/null
+++ b/src/java/net/sf/jabref/groups/UndoableChangeAssignment.java
@@ -0,0 +1,103 @@
+/*
+ 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.groups;
+
+import java.util.*;
+
+import javax.swing.undo.AbstractUndoableEdit;
+
+import net.sf.jabref.*;
+
+/**
+ * @author jzieren
+ * 
+ */
+public class UndoableChangeAssignment extends AbstractUndoableEdit {
+    private final Set m_previousAssignmentBackup;
+    private final Set m_newAssignmentBackup;
+    /** The path to the edited node */
+    private int[] m_pathToNode = null;
+    /** The root of the global groups tree */
+    private GroupTreeNode m_groupsRootHandle = null;
+
+    /**
+     * Constructor for use in a group itself, where the enclosing node is
+     * unknown. The node must be set using setEditedNode() before this instance
+     * may be used.
+     * 
+     * @param previousAssignment
+     * @param currentAssignment
+     */
+    public UndoableChangeAssignment(Set previousAssignment,
+            Set currentAssignment) {
+        m_previousAssignmentBackup = new HashSet(previousAssignment);
+        m_newAssignmentBackup = new HashSet(currentAssignment);
+    }
+
+    public UndoableChangeAssignment(Set previousAssignment,
+            Set currentAssignment, GroupTreeNode node) {
+        this(previousAssignment, currentAssignment);
+        setEditedNode(node);
+    }
+
+    /**
+     * Sets the node of the group that was edited. If this node was not
+     * specified at construction time, this method has to be called before this
+     * instance may be used.
+     * 
+     * @param node
+     *            The node whose assignments were edited.
+     */
+    public void setEditedNode(GroupTreeNode node) {
+        m_groupsRootHandle = (GroupTreeNode) node.getRoot();
+        m_pathToNode = node.getIndexedPath();
+    }
+
+    public String getUndoPresentationName() {
+        return Globals.lang("Undo") + ": "
+                + Globals.lang("change assignment of entries");
+    }
+
+    public String getRedoPresentationName() {
+        return Globals.lang("Redo") + ": "
+                + Globals.lang("change assignment of entries");
+    }
+
+    public void undo() {
+        super.undo();
+        ExplicitGroup group = (ExplicitGroup) m_groupsRootHandle.getChildAt(
+                m_pathToNode).getGroup();
+        group.clearAssignments();
+        for (Iterator it = m_previousAssignmentBackup.iterator(); it.hasNext();)
+            group.addEntry((BibtexEntry) it.next());
+    }
+
+    public void redo() {
+        super.redo();
+        ExplicitGroup group = (ExplicitGroup) m_groupsRootHandle.getChildAt(
+                m_pathToNode).getGroup();
+        group.clearAssignments();
+        for (Iterator it = m_newAssignmentBackup.iterator(); it.hasNext();)
+            group.addEntry((BibtexEntry) it.next());
+    }
+}
diff --git a/src/java/net/sf/jabref/groups/UndoableModifyGroup.java b/src/java/net/sf/jabref/groups/UndoableModifyGroup.java
new file mode 100644
index 0000000..b490ef0
--- /dev/null
+++ b/src/java/net/sf/jabref/groups/UndoableModifyGroup.java
@@ -0,0 +1,79 @@
+/*
+ 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.
+
+ 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.groups;
+
+import javax.swing.undo.AbstractUndoableEdit;
+
+import net.sf.jabref.Globals;
+
+public class UndoableModifyGroup extends AbstractUndoableEdit {
+    private final GroupSelector m_groupSelector;
+    private final AbstractGroup m_oldGroupBackup;
+    private final AbstractGroup m_newGroupBackup;
+    private final GroupTreeNode m_groupsRootHandle;
+    private final int[] m_pathToNode;
+
+    /**
+     * @param node
+     *            The node which still contains the old group.
+     * @param newGroup
+     *            The new group to replace the one currently stored in <b>node
+     *            </b>.
+     */
+    public UndoableModifyGroup(GroupSelector gs, GroupTreeNode groupsRoot,
+            GroupTreeNode node, AbstractGroup newGroup) {
+        m_groupSelector = gs;
+        m_oldGroupBackup = node.getGroup().deepCopy();
+        m_newGroupBackup = newGroup.deepCopy();
+        m_pathToNode = node.getIndexedPath();
+        m_groupsRootHandle = groupsRoot;
+    }
+
+    public String getUndoPresentationName() {
+        return Globals.lang("Undo") + ": " 
+            + Globals.lang("modify group");
+    }
+
+    public String getRedoPresentationName() {
+        return Globals.lang("Redo") + ": " 
+            + Globals.lang("modify group");
+    }
+
+    public void undo() {
+        super.undo();
+        m_groupsRootHandle.getDescendant(m_pathToNode).setGroup(
+                m_oldGroupBackup.deepCopy());
+        m_groupSelector.revalidateGroups();
+    }
+
+    public void redo() {
+        super.redo();
+        m_groupsRootHandle.getDescendant(m_pathToNode).setGroup(
+                m_newGroupBackup.deepCopy());
+        m_groupSelector.revalidateGroups();
+    }
+}
diff --git a/src/java/net/sf/jabref/groups/UndoableModifySubtree.java b/src/java/net/sf/jabref/groups/UndoableModifySubtree.java
new file mode 100644
index 0000000..3609cfb
--- /dev/null
+++ b/src/java/net/sf/jabref/groups/UndoableModifySubtree.java
@@ -0,0 +1,105 @@
+/*
+ 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.
+
+ 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.groups;
+
+import java.util.Vector;
+
+import javax.swing.undo.AbstractUndoableEdit;
+
+import net.sf.jabref.Globals;
+
+public class UndoableModifySubtree extends AbstractUndoableEdit {
+    /** A backup of the groups before the modification */
+    private final GroupTreeNode m_subtreeBackup;
+    /** The path to the global groups root node */
+    private final int[] m_subtreeRootPath;
+    private final GroupSelector m_groupSelector;
+    /** This holds the new subtree (the root's modified children) to allow redo. */
+    private Vector m_modifiedSubtree = new Vector();
+    private boolean m_revalidate = true;
+    private final String m_name;
+
+    /**
+     * 
+     * @param subtree
+     *            The root node of the subtree that was modified (this node may
+     *            not be modified, it is just used as a convenience handle).
+     */
+    public UndoableModifySubtree(GroupSelector groupSelector,
+            GroupTreeNode subtree, String name) {
+        m_subtreeBackup = subtree.deepCopy();
+        m_subtreeRootPath = subtree.getIndexedPath();
+        m_groupSelector = groupSelector;
+        m_name = name;
+    }
+
+    public String getUndoPresentationName() {
+        return Globals.lang("Undo") + ": " + m_name;
+        // JZTODO lyrics
+    }
+
+    public String getRedoPresentationName() {
+        return Globals.lang("Redo") + ": " + m_name;
+    }
+
+    public void undo() {
+        super.undo();
+        // remember modified children for redo
+        m_modifiedSubtree.clear();
+        // get node to edit
+        final GroupTreeNode subtreeRoot = m_groupSelector.getGroupTreeRoot()
+                .getNode(m_subtreeRootPath);
+        for (int i = 0; i < subtreeRoot.getChildCount(); ++i)
+            m_modifiedSubtree.add(subtreeRoot.getChildAt(i));
+        // keep subtree handle, but restore everything else from backup
+        subtreeRoot.removeAllChildren();
+        for (int i = 0; i < m_subtreeBackup.getChildCount(); ++i)
+            subtreeRoot.add(((GroupTreeNode) m_subtreeBackup.getChildAt(i))
+                    .deepCopy());
+        if (m_revalidate)
+            m_groupSelector.revalidateGroups();
+    }
+
+    public void redo() {
+        super.redo();
+        final GroupTreeNode subtreeRoot = m_groupSelector.getGroupTreeRoot()
+                .getNode(m_subtreeRootPath);
+        subtreeRoot.removeAllChildren();
+        for (int i = 0; i < m_modifiedSubtree.size(); ++i)
+            subtreeRoot.add((GroupTreeNode) m_modifiedSubtree.elementAt(i));
+        if (m_revalidate)
+            m_groupSelector.revalidateGroups();
+    }
+
+    /**
+     * Call this method to decide if the group list should be immediately
+     * revalidated by this operation. Default is true.
+     */
+    public void setRevalidate(boolean revalidate) {
+        m_revalidate = revalidate;
+    }
+}
diff --git a/src/java/net/sf/jabref/groups/UndoableMoveGroup.java b/src/java/net/sf/jabref/groups/UndoableMoveGroup.java
new file mode 100644
index 0000000..58bdcef
--- /dev/null
+++ b/src/java/net/sf/jabref/groups/UndoableMoveGroup.java
@@ -0,0 +1,93 @@
+/*
+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.groups;
+
+import javax.swing.undo.AbstractUndoableEdit;
+
+import net.sf.jabref.Globals;
+
+/**
+ * @author jzieren
+ * 
+ * TODO To change the template for this generated type comment go to Window -
+ * Preferences - Java - Code Style - Code Templates
+ */
+public class UndoableMoveGroup extends AbstractUndoableEdit {
+    private final GroupSelector m_groupSelector;
+    private final GroupTreeNode m_groupsRootHandle;
+    private final int[] m_pathToNewParent;
+    private final int m_newChildIndex;
+    private final int[] m_pathToOldParent;
+    private final int m_oldChildIndex;
+
+    /**
+     * @param moveNode
+     *            The node which is being moved. At the time of construction of
+     *            this object, it must not have moved yet.
+     * @param newParent
+     *            The new parent node to which <b>moveNode </b> will be moved.
+     * @param newChildIndex
+     *            The child index at <b>newParent </b> to which <b>moveNode </b>
+     *            will be moved.
+     */
+    public UndoableMoveGroup(GroupSelector gs, GroupTreeNode groupsRoot,
+            GroupTreeNode moveNode, GroupTreeNode newParent, int newChildIndex) {
+        m_groupSelector = gs;
+        m_groupsRootHandle = groupsRoot;
+        m_pathToNewParent = newParent.getIndexedPath();
+        m_newChildIndex = newChildIndex;
+        m_pathToOldParent = ((GroupTreeNode) moveNode.getParent())
+                .getIndexedPath();
+        m_oldChildIndex = moveNode.getParent().getIndex(moveNode);
+    }
+
+    public String getUndoPresentationName() {
+        return Globals.lang("Undo") + ": " 
+            + Globals.lang("move group");
+    }
+
+    public String getRedoPresentationName() {
+        return Globals.lang("Redo") + ": " 
+            + Globals.lang("move group");
+    }
+
+    public void undo() {
+        super.undo();
+        GroupTreeNode cursor = m_groupsRootHandle
+                .getDescendant(m_pathToNewParent);
+        cursor = (GroupTreeNode) cursor.getChildAt(m_newChildIndex);
+        m_groupsRootHandle.getDescendant(m_pathToOldParent).insert(cursor,
+                m_oldChildIndex);
+        m_groupSelector.revalidateGroups();
+    }
+
+    public void redo() {
+        super.redo();
+        GroupTreeNode cursor = m_groupsRootHandle
+                .getDescendant(m_pathToOldParent);
+        cursor = (GroupTreeNode) cursor.getChildAt(m_oldChildIndex);
+        m_groupsRootHandle.getDescendant(m_pathToNewParent).insert(cursor,
+                m_newChildIndex);
+        m_groupSelector.revalidateGroups();
+    }
+}
diff --git a/src/java/net/sf/jabref/groups/UndoableResetGroups.java b/src/java/net/sf/jabref/groups/UndoableResetGroups.java
new file mode 100644
index 0000000..b69cc9e
--- /dev/null
+++ b/src/java/net/sf/jabref/groups/UndoableResetGroups.java
@@ -0,0 +1,85 @@
+/*
+ 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.
+
+ 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.groups;
+
+import javax.swing.undo.AbstractUndoableEdit;
+
+import net.sf.jabref.Globals;
+
+class UndoableResetGroups extends AbstractUndoableEdit {
+    /** A backup of the groups before the modification */
+    private final GroupTreeNode m_groupsBackup;
+    /** A handle to the global groups root node */
+    private final GroupTreeNode m_groupsRootHandle;
+    private final GroupSelector m_groupSelector;
+    private boolean m_revalidate = true;
+
+    public UndoableResetGroups(GroupSelector groupSelector,
+            GroupTreeNode groupsRoot) {
+        this.m_groupsBackup = groupsRoot.deepCopy();
+        this.m_groupsRootHandle = groupsRoot;
+        this.m_groupSelector = groupSelector;
+    }
+
+    public String getUndoPresentationName() {
+        return Globals.lang("Undo") + ": " 
+            + Globals.lang("clear all groups");
+    }
+
+    public String getRedoPresentationName() {
+        return Globals.lang("Redo") + ": " 
+            + Globals.lang("clear all groups");
+    }
+
+    public void undo() {
+        super.undo();
+        // keep root handle, but restore everything else from backup
+        m_groupsRootHandle.removeAllChildren();
+        m_groupsRootHandle.setGroup(m_groupsBackup.getGroup().deepCopy());
+        for (int i = 0; i < m_groupsBackup.getChildCount(); ++i)
+            m_groupsRootHandle.add(((GroupTreeNode) m_groupsBackup
+                    .getChildAt(i)).deepCopy());
+        if (m_revalidate)
+            m_groupSelector.revalidateGroups();
+    }
+
+    public void redo() {
+        super.redo();
+        m_groupsRootHandle.removeAllChildren();
+        m_groupsRootHandle.setGroup(new AllEntriesGroup());
+        if (m_revalidate)
+            m_groupSelector.revalidateGroups();
+    }
+
+    /**
+     * Call this method to decide if the group list should be immediately
+     * revalidated by this operation. Default is true.
+     */
+    public void setRevalidate(boolean revalidate) {
+        m_revalidate = revalidate;
+    }
+}
diff --git a/src/java/net/sf/jabref/groups/UnsupportedVersionException.java b/src/java/net/sf/jabref/groups/UnsupportedVersionException.java
new file mode 100644
index 0000000..28a0e50
--- /dev/null
+++ b/src/java/net/sf/jabref/groups/UnsupportedVersionException.java
@@ -0,0 +1,32 @@
+/*
+ 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.groups;
+
+import net.sf.jabref.Globals;
+
+public class UnsupportedVersionException extends Exception {
+    public UnsupportedVersionException(String groupType, int version) {
+        super(Globals.lang("Unsupported version of class %0: %1", groupType, ""
+                + version));
+    }
+}
diff --git a/src/java/net/sf/jabref/groups/VersionHandling.java b/src/java/net/sf/jabref/groups/VersionHandling.java
new file mode 100644
index 0000000..57584a6
--- /dev/null
+++ b/src/java/net/sf/jabref/groups/VersionHandling.java
@@ -0,0 +1,208 @@
+/*
+ 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.groups;
+
+import java.util.Vector;
+
+import net.sf.jabref.*;
+
+/**
+ * Handles versioning of groups, e.g. automatic conversion from previous to
+ * current versions, or import of flat groups (JabRef <= 1.6) to tree.
+ * 
+ * @author jzieren (10.04.2005)
+ */
+public class VersionHandling {
+    public static final int CURRENT_VERSION = 3;
+
+    /**
+     * Imports old (flat) groups data and converts it to a 2-level tree with an
+     * AllEntriesGroup at the root.
+     * 
+     * @return the root of the generated tree.
+     */
+    public static GroupTreeNode importFlatGroups(Vector groups)
+            throws IllegalArgumentException {
+        GroupTreeNode root = new GroupTreeNode(new AllEntriesGroup());
+        final int number = groups.size() / 3;
+        String name, field, regexp;
+        for (int i = 0; i < number; ++i) {
+            field = (String) groups.elementAt(3 * i + 0);
+            name = (String) groups.elementAt(3 * i + 1);
+            regexp = (String) groups.elementAt(3 * i + 2);
+            root.add(new GroupTreeNode(new KeywordGroup(name, field, regexp,
+                    false, true, AbstractGroup.INDEPENDENT)));
+        }
+        return root;
+    }
+
+    public static GroupTreeNode importGroups(Vector orderedData,
+            BibtexDatabase db, int version) throws Exception {
+        switch (version) {
+        case 0:
+        case 1:
+            return Version0_1.fromString((String) orderedData.firstElement(),
+                    db, version);
+        case 2:
+        case 3:
+            return Version2_3.fromString(orderedData, db, version);
+        default:
+            throw new IllegalArgumentException(Globals.lang(
+                    "Failed to read groups data (unsupported version: %0)",
+                    "" + version));
+        }
+    }
+
+    /** Imports groups version 0 and 1. */
+    private static class Version0_1 {
+        /**
+         * Parses the textual representation obtained from
+         * GroupTreeNode.toString() and recreates that node and all of its
+         * children from it.
+         * 
+         * @throws Exception
+         *             When a group could not be recreated
+         */
+        private static GroupTreeNode fromString(String s, BibtexDatabase db,
+                int version) throws Exception {
+            GroupTreeNode root = null;
+            GroupTreeNode newNode;
+            int i;
+            String g;
+            while (s.length() > 0) {
+                if (s.startsWith("(")) {
+                    String subtree = getSubtree(s);
+                    newNode = fromString(subtree, db, version);
+                    // continue after this subtree by removing it
+                    // and the leading/trailing braces, and
+                    // the comma (that makes 3) that always trails it
+                    // unless it's at the end of s anyway.
+                    i = 3 + subtree.length();
+                    s = i >= s.length() ? "" : s.substring(i);
+                } else {
+                    i = indexOfUnquoted(s, ',');
+                    g = i < 0 ? s : s.substring(0, i);
+                    if (i >= 0)
+                        s = s.substring(i + 1);
+                    else
+                        s = "";
+                    newNode = new GroupTreeNode(AbstractGroup.fromString(Util
+                            .unquote(g, '\\'), db, version));
+                }
+                if (root == null) // first node will be root
+                    root = newNode;
+                else
+                    root.add(newNode);
+            }
+            return root;
+        }
+
+        /**
+         * Returns the substring delimited by a pair of matching braces, with
+         * the first brace at index 0. Quoted characters are skipped.
+         * 
+         * @return the matching substring, or "" if not found.
+         */
+        private static String getSubtree(String s) {
+            int i = 1;
+            int level = 1;
+            while (i < s.length()) {
+                switch (s.charAt(i)) {
+                case '\\':
+                    ++i;
+                    break;
+                case '(':
+                    ++level;
+                    break;
+                case ')':
+                    --level;
+                    if (level == 0)
+                        return s.substring(1, i);
+                    break;
+                }
+                ++i;
+            }
+            return "";
+        }
+
+        /**
+         * Returns the index of the first occurence of c, skipping quoted
+         * special characters (escape character: '\\').
+         * 
+         * @param s
+         *            The String to search in.
+         * @param c
+         *            The character to search
+         * @return The index of the first unescaped occurence of c in s, or -1
+         *         if not found.
+         */
+        private static int indexOfUnquoted(String s, char c) {
+            int i = 0;
+            while (i < s.length()) {
+                if (s.charAt(i) == '\\') {
+                    ++i; // skip quoted special
+                } else {
+                    if (s.charAt(i) == c)
+                        return i;
+                }
+                ++i;
+            }
+            return -1;
+        }
+    }
+    
+    private static class Version2_3 {
+        private static GroupTreeNode fromString(Vector data, BibtexDatabase db,
+                int version) throws Exception {
+            GroupTreeNode cursor = null;
+            GroupTreeNode root = null;
+            GroupTreeNode newNode;
+            AbstractGroup group;
+            int spaceIndex;
+            int level;
+            String s;
+            for (int i = 0; i < data.size(); ++i) {
+                s = data.elementAt(i).toString();
+                spaceIndex = s.indexOf(' ');
+                if (spaceIndex <= 0)
+                    throw new Exception("bad format"); // JZTODO lyrics
+                level = Integer.parseInt(s.substring(0, spaceIndex));
+                group = AbstractGroup.fromString(s.substring(spaceIndex + 1),
+                        db, version);
+                newNode = new GroupTreeNode(group);
+                if (cursor == null) {
+                    // create new root
+                    cursor = newNode;
+                    root = cursor;
+                } else {
+                    // insert at desired location
+                    while (level <= cursor.getLevel())
+                        cursor = (GroupTreeNode) cursor.getParent();
+                    cursor.add(newNode);
+                    cursor = newNode;
+                }
+            }
+            return root;
+        }
+    }
+}
diff --git a/src/java/net/sf/jabref/gui/AttachFileDialog.java b/src/java/net/sf/jabref/gui/AttachFileDialog.java
new file mode 100644
index 0000000..ff46ffa
--- /dev/null
+++ b/src/java/net/sf/jabref/gui/AttachFileDialog.java
@@ -0,0 +1,137 @@
+package net.sf.jabref.gui;
+
+import net.sf.jabref.*;
+import net.sf.jabref.external.ExternalFilePanel;
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.ActionListener;
+import java.awt.event.ActionEvent;
+
+import com.jgoodies.forms.layout.FormLayout;
+import com.jgoodies.forms.builder.DefaultFormBuilder;
+import com.jgoodies.forms.builder.ButtonBarBuilder;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: alver
+ * Date: May 18, 2005
+ * Time: 9:59:52 PM
+ * To change this template use File | Settings | File Templates.
+ */
+public class AttachFileDialog extends JDialog {
+
+    AttachFileDialog ths = this;
+    FieldEditor editor;
+    String fieldName;
+    JPanel main;
+    JButton browse = new JButton(Globals.lang("Browse")),
+        download = new JButton(Globals.lang("Download")),
+        auto = new JButton(Globals.lang("Auto")),
+        ok = new JButton(Globals.lang("Ok")),
+        cancel = new JButton(Globals.lang("Cancel"));
+    BibtexEntry entry;
+    private boolean cancelled = true; // Default to true, so a pure close operation implies Cancel.
+
+    public AttachFileDialog(Frame parent, BibtexEntry entry, String fieldName) {
+        super(parent, true);
+        this.entry = entry;
+        this.fieldName = fieldName;
+        this.editor = new FieldTextField(fieldName, (String)entry.getField(fieldName), false);
+
+        initGui();
+    }
+
+    public AttachFileDialog(Dialog parent, BibtexEntry entry, String fieldName) {
+        super(parent, true);
+        this.entry = entry;
+        this.fieldName = fieldName;
+        this.editor = new FieldTextField(fieldName, (String)entry.getField(fieldName), false);
+
+        initGui();
+    }
+
+    public boolean cancelled() {
+        return cancelled;
+    }
+
+    public String getValue() {
+        return editor.getText();
+    }
+
+    private void initGui() {
+
+        final ExternalFilePanel extPan = new ExternalFilePanel(fieldName, entry,
+                      Util.getFileFilterForField(fieldName));
+
+        browse.addActionListener(new ActionListener () {
+            public void actionPerformed(ActionEvent event) {
+                extPan.browseFile(fieldName, editor);
+            }
+        });
+
+        download.addActionListener(new ActionListener () {
+            public void actionPerformed(ActionEvent event) {
+                extPan.downLoadFile(fieldName, editor, ths);
+            }
+        });
+
+        auto.addActionListener(new ActionListener () {
+                    public void actionPerformed(ActionEvent event) {
+                        extPan.autoSetFile(fieldName, editor);
+                    }
+                });
+
+
+        ActionListener okListener = new ActionListener () {
+            public void actionPerformed(ActionEvent event) {
+                cancelled = false;
+                dispose();
+            }
+        };
+
+        ok.addActionListener(okListener);
+        ((JTextField)editor.getTextComponent()).addActionListener(okListener);
+
+        AbstractAction cancelListener = new AbstractAction () {
+            public void actionPerformed(ActionEvent event) {
+                cancelled = true;
+                dispose();
+            }
+        };
+
+        cancel.addActionListener(cancelListener);
+        editor.getTextComponent().getInputMap().put(Globals.prefs.getKey("Close dialog"), "close");
+	    editor.getTextComponent().getActionMap().put("close", cancelListener);
+
+        FormLayout layout = new FormLayout("fill:160dlu, 4dlu, fill:pref","");
+	    DefaultFormBuilder builder = new DefaultFormBuilder(layout);
+        //builder.append(Util.nCase(fieldName));//(editor.getLabel());
+        builder.appendSeparator(Util.nCase(fieldName));
+        builder.append(editor.getTextComponent());
+        builder.append(browse);
+
+        ButtonBarBuilder bb = new ButtonBarBuilder();
+        bb.addGridded(download);
+        bb.addGridded(auto);
+        builder.nextLine();
+        builder.append(bb.getPanel());
+        builder.nextLine();
+        builder.appendSeparator();
+
+        main = builder.getPanel();
+
+        main.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+
+        bb = new ButtonBarBuilder();
+        bb.addGlue();
+        bb.addGridded(ok);
+        bb.addGridded(cancel);
+        bb.addGlue();
+
+
+        getContentPane().add(main, BorderLayout.CENTER);
+        getContentPane().add(bb.getPanel(), BorderLayout.SOUTH);
+        pack();
+    }
+}
diff --git a/src/java/net/sf/jabref/gui/ColorSetupPanel.java b/src/java/net/sf/jabref/gui/ColorSetupPanel.java
new file mode 100644
index 0000000..521ee69
--- /dev/null
+++ b/src/java/net/sf/jabref/gui/ColorSetupPanel.java
@@ -0,0 +1,146 @@
+package net.sf.jabref.gui;
+
+import com.jgoodies.forms.layout.FormLayout;
+import com.jgoodies.forms.builder.DefaultFormBuilder;
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.ActionListener;
+import java.awt.event.ActionEvent;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import net.sf.jabref.Globals;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: alver
+ * Date: Oct 10, 2005
+ * Time: 4:29:35 PM
+ * To change this template use File | Settings | File Templates.
+ */
+public class ColorSetupPanel extends JPanel {
+
+    private final static int ICON_WIDTH=30, ICON_HEIGHT=20;
+    private ArrayList buttons = new ArrayList();
+
+    public ColorSetupPanel() {
+
+        FormLayout layout = new FormLayout
+                ("30dlu, 4dlu, fill:pref, 4dlu, fill:pref, 8dlu, 30dlu, 4dlu, fill:pref, 4dlu, fill:pref", "");
+        DefaultFormBuilder builder = new DefaultFormBuilder(layout);
+
+        buttons.add(new ColorButton("tableText", Globals.lang("Table text color")));
+        buttons.add(new ColorButton("tableBackground", Globals.lang("Table background color")));
+        buttons.add(new ColorButton("tableReqFieldBackground", Globals.lang("Background color for required fields")));
+        buttons.add(new ColorButton("tableOptFieldBackground", Globals.lang("Background color for optional fields")));
+        buttons.add(new ColorButton("markedEntryBackground", Globals.lang("Background color for marked entries")));
+        buttons.add(new ColorButton("incompleteEntryBackground", Globals.lang("Color for marking incomplete entries")));
+        buttons.add(new ColorButton("gridColor", Globals.lang("Table grid color")));
+
+
+
+        for (Iterator i=buttons.iterator(); i.hasNext();) {
+            ColorButton but = (ColorButton)i.next();
+            builder.append(but);
+            builder.append(but.getDefaultButton());
+            builder.append(but.getName());
+            but.addActionListener(new ColorButtonListener(but));
+
+        }
+
+        setLayout(new BorderLayout());
+        add(builder.getPanel(), BorderLayout.CENTER);
+
+        setValues();
+
+
+    }
+
+    public void setValues() {
+        for (Iterator i=buttons.iterator(); i.hasNext();) {
+            ColorButton but = (ColorButton)i.next();
+            but.setColor(Globals.prefs.getColor(but.getKey()));
+        }
+
+    }
+
+    public void storeSettings() {
+        for (Iterator i=buttons.iterator(); i.hasNext();) {
+            ColorButton but = (ColorButton)i.next();
+            Globals.prefs.putColor(but.getKey(), but.getColor());
+        }
+    }
+
+    class ColorButtonListener implements ActionListener {
+        private ColorButton button;
+
+        public ColorButtonListener(ColorButton button) {
+            this.button = button;
+        }
+        public void actionPerformed(ActionEvent e) {
+            Color chosen = JColorChooser.showDialog(null, button.getName(), button.getColor());
+            if (chosen != null)
+                button.setColor(chosen);
+        }
+    }
+
+    /**
+     * A button to display the chosen color, and hold key information about a color setting.
+     * Includes a method to produce a Default button for this setting.
+     */
+    class ColorButton extends JButton implements Icon {
+        private Color color = Color.white;
+        private String key, name;
+
+        public ColorButton(String key, String name) {
+            setIcon(this);
+            this.key = key;
+            this.name = name;
+            setBorder(BorderFactory.createRaisedBevelBorder());
+        }
+
+        public JButton getDefaultButton() {
+            JButton toDefault = new JButton(Globals.lang("Default"));
+            toDefault.addActionListener(new ActionListener() {
+                public void actionPerformed(ActionEvent e) {
+                    setColor(Globals.prefs.getDefaultColor(key));
+                    repaint();
+                }
+            });
+            return toDefault;
+        }
+
+
+        public String getKey() {
+            return key;
+        }
+
+        public String getName() {
+            return name;
+        }
+
+        public Color getColor() {
+            return color;
+        }
+
+        public void setColor(Color color) {
+            this.color = color;
+        }
+
+        public void paintIcon(Component c, Graphics g, int x, int y) {
+            Rectangle r = g.getClipBounds();
+            g.setColor(color);
+            g.fillRect(r.x, r.y, r.width, r.height);
+        }
+
+        public int getIconWidth() {
+            return ICON_WIDTH;
+        }
+
+        public int getIconHeight() {
+            return ICON_HEIGHT;
+        }
+    }
+
+}
diff --git a/src/java/net/sf/jabref/gui/DatabasePropertiesDialog.java b/src/java/net/sf/jabref/gui/DatabasePropertiesDialog.java
new file mode 100644
index 0000000..3b8aa1e
--- /dev/null
+++ b/src/java/net/sf/jabref/gui/DatabasePropertiesDialog.java
@@ -0,0 +1,87 @@
+package net.sf.jabref.gui;
+
+import net.sf.jabref.BasePanel;
+
+import net.sf.jabref.Globals;
+
+import javax.swing.*;
+
+import com.jgoodies.forms.builder.DefaultFormBuilder;
+import com.jgoodies.forms.builder.ButtonBarBuilder;
+import com.jgoodies.forms.layout.FormLayout;
+
+import java.awt.*;
+import java.awt.event.ActionListener;
+import java.awt.event.ActionEvent;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: alver
+ * Date: Oct 31, 2005
+ * Time: 10:46:03 PM
+ * To change this template use File | Settings | File Templates.
+ */
+public class DatabasePropertiesDialog extends JDialog {
+
+    BasePanel panel = null;
+
+    JComboBox encoding;
+    JButton ok, cancel;
+
+    public DatabasePropertiesDialog(JFrame parent) {
+        super(parent, Globals.lang("Database properties"), false);
+        encoding = new JComboBox(Globals.ENCODINGS);
+        ok = new JButton(Globals.lang("Ok"));
+        cancel = new JButton(Globals.lang("Cancel"));
+        init();
+    }
+
+    public void setPanel(BasePanel panel) {
+        this.panel = panel;
+    }
+
+    public final void init() {
+        DefaultFormBuilder builder = new DefaultFormBuilder(new FormLayout("left:pref, 4dlu, fill:pref", ""));
+        builder.getPanel().setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+        builder.append(Globals.lang("Database encoding"));
+        builder.append(encoding);
+
+        ButtonBarBuilder bb = new ButtonBarBuilder();
+        bb.addGlue();
+        bb.addGridded(ok);
+        bb.addGridded(cancel);
+        bb.addGlue();
+
+        getContentPane().add(builder.getPanel(), BorderLayout.CENTER);
+        getContentPane().add(bb.getPanel(), BorderLayout.SOUTH);
+        pack();
+
+        ok.addActionListener(new ActionListener() {
+            public void actionPerformed(ActionEvent e) {
+                storeSettings();
+                dispose();
+            }
+        });
+
+        cancel.addActionListener(new ActionListener() {
+            public void actionPerformed(ActionEvent e) {
+                dispose();
+            }
+        });
+
+    }
+
+    public void setVisible(boolean visible) {
+        if (visible)
+            setValues();
+        super.setVisible(visible);
+    }
+
+    public void setValues() {
+        encoding.setSelectedItem(panel.getEncoding());
+    }
+
+    public void storeSettings() {
+        panel.setEncoding((String)encoding.getSelectedItem());
+    }
+}
diff --git a/src/java/net/sf/jabref/gui/EntryCustomizationDialog2.java b/src/java/net/sf/jabref/gui/EntryCustomizationDialog2.java
new file mode 100644
index 0000000..496c280
--- /dev/null
+++ b/src/java/net/sf/jabref/gui/EntryCustomizationDialog2.java
@@ -0,0 +1,390 @@
+/*
+ * EntryCustomizationDialog2.java
+ *
+ * Created on February 10, 2005, 9:57 PM
+ */
+
+package net.sf.jabref.gui;
+
+import net.sf.jabref.*;
+import javax.swing.*;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
+import java.awt.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Iterator;
+import java.util.Set;
+import javax.swing.event.ListDataListener;
+
+/**
+ * NOTAT: 
+ *    * S?rg for at ting oppdateres riktig ved tillegg av ny type. (velge, unng? at det blir feil innhold i listene).
+ *    * 
+ *
+ *
+ * @author alver
+ */
+public class EntryCustomizationDialog2 extends JDialog implements ListSelectionListener, ActionListener {
+    
+    protected JabRefFrame frame;
+    protected GridBagLayout gbl = new GridBagLayout();
+    protected GridBagConstraints con = new GridBagConstraints();
+    protected FieldSetComponent reqComp, optComp;
+    protected EntryTypeList typeComp;
+    protected JButton ok, cancel, apply, helpButton, delete, importTypes, exportTypes;
+    protected final List preset = java.util.Arrays.asList(GUIGlobals.ALL_FIELDS);
+    protected String lastSelected = null;
+    protected Map reqLists = new HashMap(),
+            optLists = new HashMap();
+    protected Set defaulted = new HashSet(), changed = new HashSet();
+    
+    /** Creates a new instance of EntryCustomizationDialog2 */
+    public EntryCustomizationDialog2(JabRefFrame frame) {
+        super(frame, Globals.lang("Customize entry types"), false);
+        
+        this.frame = frame;
+        initGui();
+    }
+    
+    protected final void initGui() {
+        Container pane = getContentPane();
+        pane.setLayout(new BorderLayout());
+        
+        JPanel main = new JPanel(), buttons = new JPanel(),
+                right = new JPanel();
+        main.setLayout(new BorderLayout());
+        right.setLayout(new GridLayout(1, 2));
+        
+        java.util.List entryTypes = new ArrayList();
+        for (Iterator i=BibtexEntryType.ALL_TYPES.keySet().iterator(); i.hasNext();) {
+            entryTypes.add(i.next());
+        }
+        
+        typeComp = new EntryTypeList(entryTypes);
+        typeComp.addListSelectionListener(this);
+        typeComp.addAdditionActionListener(this);
+        typeComp.addDefaultActionListener(new DefaultListener());
+        typeComp.setListSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+        
+        //typeComp.setEnabled(false);
+        reqComp = new FieldSetComponent(Globals.lang("Required fields"), new ArrayList(), preset, true, true);
+        reqComp.setEnabled(false);
+        reqComp.setBorder(BorderFactory.createEmptyBorder(2,2,2,2));
+        ListDataListener dataListener = new DataListener();
+        reqComp.addListDataListener(dataListener);
+        optComp = new FieldSetComponent(Globals.lang("Optional fields"), new ArrayList(), preset, true, true);
+        optComp.setEnabled(false);
+        optComp.setBorder(BorderFactory.createEmptyBorder(2,2,2,2));
+        optComp.addListDataListener(dataListener);
+        right.add(reqComp);
+        right.add(optComp);
+        //right.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), Globals.lang("Fields")));
+        right.setBorder(BorderFactory.createEtchedBorder());
+        ok = new JButton("OK");
+        cancel = new JButton("Cancel");
+        apply = new JButton("Apply");
+        ok.addActionListener(this);
+        apply.addActionListener(this);
+        cancel.addActionListener(this);
+        buttons.add(ok);
+        buttons.add(apply);
+        buttons.add(cancel);
+        
+        
+        //con.fill = GridBagConstraints.BOTH;
+        //con.weightx = 0.3;
+        //con.weighty = 1;
+        //gbl.setConstraints(typeComp, con);
+        main.add(typeComp, BorderLayout.WEST);
+        main.add(right, BorderLayout.CENTER);
+        main.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+        pane.add(main, BorderLayout.CENTER);
+        pane.add(buttons, BorderLayout.SOUTH);
+        pack();
+    }
+    
+    public void valueChanged(ListSelectionEvent e) {
+        if (e.getValueIsAdjusting()) {
+            return;
+        }
+        
+        
+        if (lastSelected != null) {
+            // The entry type lastSelected is now unselected, so we store the current settings
+            // for that type in our two maps.
+            reqLists.put(lastSelected, reqComp.getFields());
+            optLists.put(lastSelected, optComp.getFields());
+        }
+        
+        String s = typeComp.getFirstSelected();
+        if (s == null)
+            return;
+        Object rl = reqLists.get(s);
+        if (rl == null) {
+            BibtexEntryType type = BibtexEntryType.getType(s);
+            if (type != null) {
+                String[] rf = type.getRequiredFields(),
+                        of = type.getOptionalFields();
+                List req, opt;
+                if (rf != null)
+                    req = java.util.Arrays.asList(rf);
+                else
+                    req = new ArrayList();
+                if (of != null)
+                    opt = java.util.Arrays.asList(of);
+                else
+                    opt = new ArrayList();
+                
+                reqComp.setFields(req);
+                reqComp.setEnabled(true);
+                optComp.setFields(opt);
+                optComp.setEnabled(true);
+            } else {
+                // New entry, veintle
+                reqComp.setFields(new ArrayList());
+                reqComp.setEnabled(true);
+                optComp.setFields(new ArrayList());
+                optComp.setEnabled(true);
+                new FocusRequester(reqComp);
+            }
+        } else {
+            reqComp.setFields((List)rl);
+            optComp.setFields((List)optLists.get(s));
+        }
+        
+        lastSelected = s;
+        typeComp.enable(s, changed.contains(lastSelected) && !defaulted.contains(lastSelected));
+    }
+    
+    protected void applyChanges() {
+        valueChanged(new ListSelectionEvent(new JList(), 0, 0, false));
+        // Iterate over our map of required fields, and list those types if necessary:
+        
+        List types = typeComp.getFields();
+        boolean globalChangesMade = false;
+        for (Iterator i=reqLists.keySet().iterator(); i.hasNext();) {
+            String typeName = (String)i.next();
+            if (!types.contains(typeName))
+                continue;
+           
+            List reqFields = (List)reqLists.get(typeName);
+            List optFields = (List)optLists.get(typeName);
+            String[] reqStr = new String[reqFields.size()];
+            reqFields.toArray(reqStr);
+            String[] optStr = new String[optFields.size()];
+            optFields.toArray(optStr);
+            
+            // If this type is already existing, check if any changes have
+            // been made
+            boolean changesMade = true;
+            
+            if (defaulted.contains(typeName)) {
+                // This type should be reverted to its default setup.
+                //System.out.println("Defaulting: "+typeName);
+                String nm = Util.nCase(typeName);
+                BibtexEntryType.removeType(nm);
+                
+                updateTypesForEntries(nm);
+                globalChangesMade = true;
+                continue;
+            }
+            
+            BibtexEntryType oldType = BibtexEntryType.getType(typeName);
+            if (oldType != null) {
+                String[] oldReq = oldType.getRequiredFields(),
+                        oldOpt = oldType.getOptionalFields();
+                if (equalArrays(oldReq, reqStr) && equalArrays(oldOpt, optStr))
+                    changesMade = false;
+            }
+            
+            if (changesMade) {
+                //System.out.println("Updating: "+typeName);
+                CustomEntryType typ = new CustomEntryType(Util.nCase(typeName), reqStr, optStr);
+                BibtexEntryType.ALL_TYPES.put(typeName.toLowerCase(), typ);
+                updateTypesForEntries(typ.getName());
+                globalChangesMade = true;
+            }
+        }
+        
+        
+        Set toRemove = new HashSet();
+        for (Iterator i=BibtexEntryType.ALL_TYPES.keySet().iterator(); i.hasNext();) {
+            Object o = i.next();
+            if (!types.contains(o)) {
+                //System.out.println("Deleted entry type (TODO): "+o);
+                toRemove.add(o);
+            }
+        }
+
+        // Remove those that should be removed:
+        if (toRemove.size() > 0) {
+            for (Iterator i=toRemove.iterator(); i.hasNext();)
+                typeDeletion((String)i.next());
+        }
+        
+        updateTables();
+    }
+    
+    protected void typeDeletion(String name) {
+        BibtexEntryType type = BibtexEntryType.getType(name);
+
+        if (type instanceof CustomEntryType) {
+            if (BibtexEntryType.getStandardType(name) == null) {
+                int reply = JOptionPane.showConfirmDialog
+                        (frame, Globals.lang("All entries of this "
+                        +"type will be declared "
+                        +"typeless. Continue?"),
+                        Globals.lang("Delete custom format")+
+                        " '"+Util.nCase(name)+"'", JOptionPane.YES_NO_OPTION,
+                        JOptionPane.WARNING_MESSAGE);
+                if (reply != JOptionPane.YES_OPTION)
+                    return;
+            }
+            BibtexEntryType.removeType(name);
+            updateTypesForEntries(Util.nCase(name));
+            changed.remove(name);
+            reqLists.remove(name);
+            optLists.remove(name);
+        }
+        //messageLabel.setText("'"+type.getName()+"' "+
+        //        Globals.lang("is a standard type."));
+
+    }
+
+
+protected boolean equalArrays(String[] one, String[] two) {
+    if ((one == null) && (two == null))
+        return true; // Both null.
+    if ((one == null) || (two == null))
+        return false; // One of them null, the other not.
+    if (one.length != two.length)
+        return false; // Different length.
+    // If we get here, we know that both are non-null, and that they have the same length.
+    for (int i=0; i<one.length; i++) {
+        if (!one[i].equals(two[i]))
+            return false;
+    }
+    // If we get here, all entries have matched.
+    return true;
+}
+
+public void actionPerformed(ActionEvent e) {
+    if (e.getSource() == ok) {
+        applyChanges();
+        setVisible(false);
+    } else if (e.getSource() == cancel) {
+        setVisible(false);
+    } else if (e.getSource() == apply) {
+        applyChanges();
+    } else if (e.getSource() == typeComp) {
+        //System.out.println("add: "+e.getActionCommand());
+        typeComp.selectField(e.getActionCommand());
+    }
+}
+
+/**
+ * Cycle through all databases, and make sure everything is updated with
+ * the new type customization. This includes making sure all entries have
+ * a valid type, that no obsolete entry editors are around, and that
+ * the right-click menus' change type menu is up-to-date.
+ */
+private void updateTypesForEntries(String typeName) {
+    if (frame.getTabbedPane().getTabCount() == 0)
+        return;
+    //messageLabel.setText(Globals.lang("Updating entries..."));
+    BibtexDatabase base;
+    Iterator iter;
+    for (int i=0; i<frame.getTabbedPane().getTabCount(); i++) {
+        BasePanel bp = (BasePanel)frame.getTabbedPane().getComponentAt(i);
+        boolean anyChanges = false;
+        
+        bp.entryEditors.remove(typeName);
+        
+        //bp.rcm.populateTypeMenu(); // Update type menu for change type.
+        base = bp.database();
+        iter = base.getKeySet().iterator();
+        while (iter.hasNext()) {
+            anyChanges = anyChanges |
+                    !(base.getEntryById((String)iter.next())).updateType();
+        }
+            /*if (anyChanges) {
+                bp.refreshTable();
+                bp.markBaseChanged();
+            }*/
+    }
+    
+}
+
+private void updateTables() {
+    if (frame.getTabbedPane().getTabCount() == 0)
+        return;
+    //messageLabel.setText(Globals.lang("Updating entries..."));
+    BibtexDatabase base;
+    Iterator iter;
+    for (int i=0; i<frame.getTabbedPane().getTabCount(); i++) {
+        BasePanel bp = (BasePanel)frame.getTabbedPane().getComponentAt(i);
+        //bp.markBaseChanged();
+    }
+    
+}
+
+// DEFAULT button pressed. Remember that this entry should be reset to default,
+// unless changes are made later.
+class DefaultListener implements ActionListener {
+    public void actionPerformed(ActionEvent e) {
+        if (lastSelected == null)
+            return;
+        defaulted.add(lastSelected);
+        
+        BibtexEntryType type = BibtexEntryType.getStandardType(lastSelected);
+        if (type != null) {
+            String[] rf = type.getRequiredFields(),
+                    of = type.getOptionalFields();
+            List req, opt;
+            if (rf != null)
+                req = java.util.Arrays.asList(rf);
+            else
+                req = new ArrayList();
+            if (of != null)
+                opt = java.util.Arrays.asList(of);
+            else
+                opt = new ArrayList();
+            
+            reqComp.setFields(req);
+            reqComp.setEnabled(true);
+            optComp.setFields(opt);
+        }
+    }
+} 
+
+class DataListener implements ListDataListener {
+    
+ 
+    public void intervalAdded(javax.swing.event.ListDataEvent e) {
+        record();
+    }
+
+    public void intervalRemoved(javax.swing.event.ListDataEvent e) {
+        record();
+    }
+
+    public void contentsChanged(javax.swing.event.ListDataEvent e) {
+        record();
+    }
+    
+    private void record() {
+        if (lastSelected == null)
+            return;
+        defaulted.remove(lastSelected);
+        changed.add(lastSelected);
+        typeComp.enable(lastSelected, true);
+    }
+    
+}
+}
diff --git a/src/java/net/sf/jabref/gui/EntryTypeList.java b/src/java/net/sf/jabref/gui/EntryTypeList.java
new file mode 100644
index 0000000..b0947f4
--- /dev/null
+++ b/src/java/net/sf/jabref/gui/EntryTypeList.java
@@ -0,0 +1,127 @@
+/*
+ * EntryTypeList.java
+ *
+ * Created on February 13, 2005, 2:07 PM
+ */
+
+package net.sf.jabref.gui;
+
+import net.sf.jabref.*;
+import java.util.List;
+import javax.swing.*;
+import javax.swing.event.*;
+import java.awt.event.*;
+
+/**
+ * This class extends FieldSetComponent to provide some required functionality for the
+ * list of entry types in EntryCustomizationDialog2.
+ * @author alver
+ */
+public class EntryTypeList extends FieldSetComponent implements ListSelectionListener, ActionListener {
+    
+    protected JButton def = new JButton(Globals.lang("Default"));
+    
+    /** Creates a new instance of EntryTypeList */
+    public EntryTypeList(List fields) {
+        super(Globals.lang("Entry types"), fields, false, true);
+        
+        con.gridx = 0;
+        con.gridy = 2;
+        con.fill = con.VERTICAL;
+        con.anchor = con.EAST;
+        gbl.setConstraints(def, con);
+        add(def);
+        list.addListSelectionListener(this);
+        def.addActionListener(this);
+        def.setEnabled(false);
+        remove.setEnabled(false);
+    }
+
+    protected void addField(String s) {
+        s = s.trim();
+        if (forceLowerCase)
+            s = s.toLowerCase();
+        if (s.equals("") || listModel.contains(s))
+            return;
+        
+        String testString = Util.checkLegalKey(s);
+        if (!testString.equals(s) || (s.indexOf('&') >= 0)) {
+            // Report error and exit.
+            JOptionPane.showMessageDialog(this, Globals.lang("Entry type names are not allowed to contain white space or the following "
+                    +"characters")+": # { } ~ , ^ &",
+                    Globals.lang("Error"), JOptionPane.ERROR_MESSAGE);
+            
+            return;
+        }
+        addFieldUncritically(s);
+    }
+    
+    protected void removeSelected() {
+        //super.removeSelected();
+        int[] selected = list.getSelectedIndices();
+        if (selected.length > 0)
+            changesMade = true;
+        for (int i=0; i<selected.length; i++) {
+            String typeName = (String)listModel.get(selected[selected.length-1-i]);
+            BibtexEntryType type = BibtexEntryType.getType(typeName);
+            // Check if there is a standard type for this name:
+            boolean standardTypeExists = (BibtexEntryType.getStandardType(typeName) != null);
+            
+            //System.out.println(typeName+"\t"+type.toString());
+            
+            // If it is a custom entry type, we can remove it. If type == null, it means
+            // the user must have added it and not yet applied it, so we can remove it
+            // in this case as well. If it is a standard type it cannot be removed.
+            if ((type != null) && (type instanceof CustomEntryType)) {
+                listModel.removeElementAt(selected[selected.length-1-i]);
+            }
+            else
+                // This shouldn't happen, since the Remove button should be disabled.
+                JOptionPane.showMessageDialog(null, Globals.lang("This entry type cannot be removed."),
+                        Globals.lang("Remove entry type"), JOptionPane.ERROR_MESSAGE);
+        }
+    }
+    
+    public void valueChanged(ListSelectionEvent e) {
+        if (e.getValueIsAdjusting()) {
+            return;
+        }
+        
+        
+        //
+        
+    }
+
+    public void enable(String typeName, boolean isChanged) {
+        //String s = (String)list.getSelectedValue();
+        
+        if (BibtexEntryType.getStandardType(typeName) != null) {
+            
+            if (isChanged || (BibtexEntryType.getType(typeName) instanceof CustomEntryType)) {
+                def.setEnabled(true);
+            } else
+                def.setEnabled(false);
+            
+            remove.setEnabled(false);
+        } else {
+            def.setEnabled(false);
+            remove.setEnabled(true);
+        }
+    }
+    
+    public void addDefaultActionListener(ActionListener l) {
+        def.addActionListener(l);
+    }
+    
+    public void actionPerformed(ActionEvent e) {
+        // Default button pressed.
+        if (e.getSource() == def)
+            def.setEnabled(false);
+        else super.actionPerformed(e);
+    }
+    
+    public void setEnabled(boolean en) {
+        super.setEnabled(en);
+        def.setEnabled(en);
+    }
+}
diff --git a/src/java/net/sf/jabref/gui/FieldSetComponent.java b/src/java/net/sf/jabref/gui/FieldSetComponent.java
new file mode 100644
index 0000000..3fb74f0
--- /dev/null
+++ b/src/java/net/sf/jabref/gui/FieldSetComponent.java
@@ -0,0 +1,344 @@
+/*
+ * FieldSetComponent.java
+ *
+ * Created on February 10, 2005, 8:32 PM
+ */
+
+package net.sf.jabref.gui;
+
+import net.sf.jabref.Util;
+import net.sf.jabref.Globals;
+import net.sf.jabref.GUIGlobals;
+import java.awt.*;
+import java.awt.event.*;
+import java.util.HashSet;
+import javax.swing.*;
+import javax.swing.event.ListSelectionListener;
+import java.util.List;
+import java.util.Iterator;
+import java.util.Set;
+import javax.swing.event.ListDataListener;
+
+/**
+ *
+ * @author alver
+ */
+public class FieldSetComponent extends JPanel implements ActionListener/*, ItemListener*/ {
+
+    protected Set additionListeners = new HashSet();
+    protected JList list;
+    protected JScrollPane sp = null;
+    protected DefaultListModel listModel;
+    protected JComboBox sel;
+    protected JTextField input;
+    protected JLabel title = null;
+    protected JButton add, remove, up=null, down=null;
+    protected GridBagLayout gbl = new GridBagLayout();
+    protected GridBagConstraints con = new GridBagConstraints();
+    protected boolean forceLowerCase, changesMade = false;
+    protected Set modelListeners = new HashSet();
+    
+    /** 
+     * Creates a new instance of FieldSetComponent, with preset selection
+     * values. These are put into a JComboBox.
+     */
+    public FieldSetComponent(String title, List fields, List preset, boolean arrows, boolean forceLowerCase) {
+        this(title, fields, preset, "Add", "Remove", arrows, forceLowerCase);
+    }
+    
+    /**
+     * Creates a new instance of FieldSetComponent without preset selection
+     * values. Replaces the JComboBox with a JTextField.
+     */
+    public FieldSetComponent(String title, List fields, boolean arrows, boolean forceLowerCase) {
+        this(title, fields, null, "Add", "Remove", arrows, forceLowerCase);
+    }
+    
+    public FieldSetComponent(String title, List fields, List preset, String addText, String removeText, 
+            boolean arrows, boolean forceLowerCase) {
+        this.forceLowerCase = forceLowerCase;                
+        add = new JButton(Globals.lang(addText));
+        remove = new JButton(Globals.lang(removeText));
+        listModel = new DefaultListModel();
+        if (title != null)
+            this.title = new JLabel(title);
+        
+        for (Iterator i=fields.iterator(); i.hasNext();)
+            listModel.addElement(i.next());
+        list = new JList(listModel);
+        list.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
+        // Set up GUI:
+        add.addActionListener(this);
+        remove.addActionListener(this);
+        
+        
+        setLayout(gbl);
+        con.insets = new Insets(1,1,1,1);
+        con.fill = GridBagConstraints.BOTH;
+        con.weightx = 1;
+        con.gridwidth = GridBagConstraints.REMAINDER;
+        if (this.title != null) {
+            gbl.setConstraints(this.title, con);
+            add(this.title);
+        }
+        
+        con.weighty = 1;
+        sp = new JScrollPane(list, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
+        gbl.setConstraints(sp, con);
+        add(sp);
+        con.weighty = 0;
+        con.gridwidth = 1;
+        if (arrows) {
+            con.weightx = 0;
+            up = new JButton(new ImageIcon(GUIGlobals.upIconFile));
+            down = new JButton(new ImageIcon(GUIGlobals.downIconFile));
+            up.addActionListener(this);
+            down.addActionListener(this);
+            up.setToolTipText(Globals.lang("Move up"));
+            down.setToolTipText(Globals.lang("Move down"));
+            gbl.setConstraints(up, con);
+            add(up);
+            gbl.setConstraints(down, con);
+            add(down);
+            con.weightx = 0;
+        }
+        
+        Component strut = Box.createHorizontalStrut(5);
+        gbl.setConstraints(strut, con);
+        add(strut);        
+        
+        con.weightx = 1;
+        con.gridwidth = GridBagConstraints.REMAINDER;
+        
+        //Component b = Box.createHorizontalGlue();
+        //gbl.setConstraints(b, con);
+        //add(b);
+        
+        //if (!arrows)
+        con.gridwidth = GridBagConstraints.REMAINDER;
+        gbl.setConstraints(remove, con);
+        add(remove);
+
+        con.gridwidth = 3;
+        con.weightx = 1;
+        if (preset != null) {
+            sel = new JComboBox(preset.toArray());
+            sel.setEditable(true);
+            //sel.addActionListener(this);
+            gbl.setConstraints(sel, con);
+            add(sel);
+        } else {
+            input = new JTextField(20);
+            input.addActionListener(this);
+            gbl.setConstraints(input, con);
+            add(input);
+        }
+        con.gridwidth = GridBagConstraints.REMAINDER;
+        con.weighty = 0;
+        con.weightx = 0.5;
+        con.gridwidth = 1;
+        gbl.setConstraints(add, con);
+        add(add);
+        
+    }
+    
+    public void setListSelectionMode(int mode) {
+        list.setSelectionMode(mode);
+    }
+    
+    public void selectField(String fieldName) {
+        int idx = listModel.indexOf(fieldName);
+        if (idx >= 0)
+            list.setSelectedIndex(idx);
+        
+        // Make sure it is visible:
+        JViewport viewport = sp.getViewport();
+        viewport.scrollRectToVisible(list.getCellBounds(idx, idx));
+        
+    }
+    
+    public String getFirstSelected() {
+        Object o = list.getSelectedValue();
+        if (o == null)
+            return null;
+        return (String)o;
+    }
+    
+    public void setEnabled(boolean en) {
+        if (input != null)
+            input.setEnabled(en);
+        if (sel != null)
+            sel.setEnabled(en);
+        if (up != null) {
+            up.setEnabled(en);
+            down.setEnabled(en);
+        }
+        add.setEnabled(en);
+        remove.setEnabled(en);
+    }
+    
+    public void setFields(List fields) {
+        DefaultListModel newListModel = new DefaultListModel();
+        for (Iterator i=fields.iterator(); i.hasNext();)
+            newListModel.addElement(i.next());
+        this.listModel = newListModel;
+        for (Iterator i=modelListeners.iterator(); i.hasNext();)
+            newListModel.addListDataListener((ListDataListener)i.next());
+        list.setModel(newListModel);
+    }
+    
+    /*public void itemStateChanged(ItemEvent e) {
+        if (e.getStateChange() == e.DESELECTED)
+            return;
+        //sel.is
+        if (sel.isPopupVisible())
+            return;
+        String s = sel.getSelectedItem().toString();
+        addField(s);
+        sel.getEditor().selectAll();
+    }*/
+
+    /**
+     * This method is called when a new field should be added to the list. Performs validation of the 
+     * field.
+     */
+    protected void addField(String s) {
+        s = s.trim();
+        if (forceLowerCase)
+            s = s.toLowerCase();
+        if (s.equals("") || listModel.contains(s))
+            return;
+        
+        String testString = Util.checkLegalKey(s);
+        if (!testString.equals(s) || (s.indexOf('&') >= 0)) {
+            // Report error and exit.
+            JOptionPane.showMessageDialog(this, Globals.lang("Field names are not allowed to contain white space or the following "
+                    +"characters")+": # { } ~ , ^ &",
+                    Globals.lang("Error"), JOptionPane.ERROR_MESSAGE);
+            
+            return;
+        }
+        addFieldUncritically(s);
+    }
+
+    /**
+     * This method adds a new field to the list, without any regard to validation. This method can be
+     * useful for classes that overrides addField(s) to provide different validation.
+     */
+    protected void addFieldUncritically(String s) {
+        listModel.addElement(s);
+        changesMade = true;
+        for (Iterator i=additionListeners.iterator(); i.hasNext();) {
+            ((ActionListener)i.next()).actionPerformed(new ActionEvent(this, 0, s));
+        }
+        
+    }
+    
+    protected void removeSelected() {
+        int[] selected = list.getSelectedIndices();
+        if (selected.length > 0)
+            changesMade = true;
+        for (int i=0; i<selected.length; i++)
+            listModel.removeElementAt(selected[selected.length-1-i]);
+
+    }
+    
+    public void activate() {
+        sel.requestFocus();
+    }
+    
+    /**
+     * Returns true if there have been changes to the field list. Reports true
+     * if changes have been made, regardless of whether the changes cancel each other.
+     */
+    public boolean changesMade() {
+        return changesMade;
+    }
+    
+    /**
+     * Return the current list.
+     */
+    public List getFields() {
+        Object[] o = listModel.toArray();
+        return java.util.Arrays.asList(o);
+    }
+    
+    /**
+     * Add a ListSelectionListener to the JList component displayed as part of this component.
+     */
+    public void addListSelectionListener(ListSelectionListener l) {
+        list.addListSelectionListener(l);
+    }
+    
+    /**
+     * Adds an ActionListener that will receive events each time a field is added. The ActionEvent
+     * will specify this component as source, and the added field as action command.
+     */
+    public void addAdditionActionListener(ActionListener l) {
+        additionListeners.add(l);
+    }
+    
+    public void removeAdditionActionListener(ActionListener l) {
+        additionListeners.remove(l);
+    }
+    
+    public void addListDataListener(ListDataListener l) {
+        listModel.addListDataListener(l);
+        modelListeners.add(l);
+     }
+    
+    /**
+     * If a field is selected in the list, move it dy positions.
+     */
+    public void move(int dy) {
+        int oldIdx = list.getSelectedIndex();
+        if  (oldIdx < 0)
+            return;
+        Object o = listModel.get(oldIdx);
+        // Compute the new index:
+        int newInd = Math.max(0, Math.min(listModel.size()-1, oldIdx+dy));
+        listModel.remove(oldIdx);
+        listModel.add(newInd, o);
+        list.setSelectedIndex(newInd);
+    }
+    
+    public void actionPerformed(ActionEvent e) {
+        Object src = e.getSource();
+        
+        if (src == add) {
+            // Selection has been made, or add button pressed:
+            if ((sel != null) && (sel.getSelectedItem() != null)) {
+                String s = sel.getSelectedItem().toString();
+                addField(s);
+            } else if ((input != null) && !input.getText().equals("")) {
+                addField(input.getText());
+            }
+        }
+        else if (src == input) {
+            addField(input.getText());
+        }
+        else if (src == remove) {
+            // Remove button pressed:
+            removeSelected();
+        }
+        else if (src == sel) {
+            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;
+            String s = sel.getSelectedItem().toString();
+            addField(s);
+            sel.getEditor().selectAll();
+        }
+        else if (src == up) {
+            move(-1);
+        }
+        else if (src == down) {
+            move(1);
+        }
+    }
+    
+              
+    
+}
diff --git a/src/java/net/sf/jabref/gui/FieldWeightDialog.java b/src/java/net/sf/jabref/gui/FieldWeightDialog.java
new file mode 100644
index 0000000..bdd78e2
--- /dev/null
+++ b/src/java/net/sf/jabref/gui/FieldWeightDialog.java
@@ -0,0 +1,128 @@
+package net.sf.jabref.gui;
+
+import com.jgoodies.forms.layout.FormLayout;
+import com.jgoodies.forms.builder.DefaultFormBuilder;
+import com.jgoodies.forms.builder.ButtonBarBuilder;
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.ActionListener;
+import java.awt.event.ActionEvent;
+import java.util.TreeSet;
+import java.util.HashMap;
+import java.util.Iterator;
+
+import net.sf.jabref.GUIGlobals;
+import net.sf.jabref.Globals;
+import net.sf.jabref.JabRefFrame;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: alver
+ * Date: Aug 23, 2005
+ * Time: 11:30:48 PM
+ * To change this template use File | Settings | File Templates.
+ */
+public class FieldWeightDialog extends JDialog {
+
+    JabRefFrame frame;
+    HashMap sliders = new HashMap();
+    JButton ok = new JButton(Globals.lang("OK")),
+        cancel = new JButton(Globals.lang("Cancel"));
+
+   public static void main(String[] args) {
+        new FieldWeightDialog(null).setVisible(true);
+    }
+
+    public FieldWeightDialog(JabRefFrame frame) {
+        this.frame = frame;
+        JPanel main = buildMainPanel();
+        main.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+        getContentPane().add(main, BorderLayout.CENTER);
+        getContentPane().add(buildButtonPanel(), BorderLayout.SOUTH);
+        pack();
+    }
+
+    public JPanel buildMainPanel() {
+        FormLayout layout = new FormLayout
+            ("right:pref, 4dlu, fill:pref, 8dlu, right:pref, 4dlu, fill:pref", // 4dlu, left:pref, 4dlu",
+             "");
+        DefaultFormBuilder builder = new DefaultFormBuilder(layout);
+
+        builder.appendSeparator(Globals.lang("Field sizes"));
+
+        // We use this list to build an alphabetical list of field names:
+        TreeSet fields = new TreeSet();
+        // We use this map to remember which slider represents which field name:
+        sliders.clear();
+        for (int i=0; i<GUIGlobals.ALL_FIELDS.length; i++) {
+            fields.add(GUIGlobals.ALL_FIELDS[i]);
+        }
+        fields.remove("bibtexkey"); // bibtex key doesn't need weight.
+        // Here is the place to add other fields:
+
+        // --------------
+
+        for (Iterator i=fields.iterator(); i.hasNext();) {
+            String field = (String)i.next();
+            builder.append(field);
+            int weight = (int)(100*GUIGlobals.getFieldWeight(field)/GUIGlobals.MAX_FIELD_WEIGHT) ;
+            //System.out.println(weight);
+            JSlider slider = new JSlider(0, 100, weight);//,);
+            sliders.put(slider, new SliderInfo(field, weight));
+            builder.append(slider);
+        }
+        builder.appendSeparator();
+
+        return builder.getPanel();
+
+    }
+
+    public JPanel buildButtonPanel() {
+
+        ok.addActionListener(new ActionListener() {
+            public void actionPerformed(ActionEvent actionEvent) {
+                storeSettings();
+                dispose();
+            }
+        });
+        cancel.addActionListener(new ActionListener() {
+            public void actionPerformed(ActionEvent actionEvent) {
+                dispose();
+            }
+        });
+
+        ButtonBarBuilder builder = new ButtonBarBuilder();
+        builder.addGlue();
+        builder.addGridded(ok);
+        builder.addGridded(cancel);
+        builder.addGlue();
+        return builder.getPanel();
+    }
+
+    public void storeSettings() {
+        for (Iterator i=sliders.keySet().iterator(); i.hasNext();) {
+            JSlider slider = (JSlider)i.next();
+            SliderInfo sInfo = (SliderInfo)sliders.get(slider);
+            // Only list the value if it has changed:
+            if (sInfo.originalValue != slider.getValue()) {
+                double weight = GUIGlobals.MAX_FIELD_WEIGHT*((double)slider.getValue())/100d;
+                GUIGlobals.setFieldWeight(sInfo.fieldName, weight);
+            }
+        }
+        frame.removeCachedEntryEditors();
+    }
+
+    /**
+     * "Struct" class to hold the necessary info about one of our JSliders:
+     * which field it represents, and what value it started out with.
+     */
+    static class SliderInfo {
+        String fieldName;
+        int originalValue;
+        public SliderInfo(String fieldName, int originalValue) {
+            this.fieldName = fieldName;
+            this.originalValue = originalValue;
+        }
+    }
+}
diff --git a/src/java/net/sf/jabref/gui/FirstColumnComparator.java b/src/java/net/sf/jabref/gui/FirstColumnComparator.java
new file mode 100644
index 0000000..817e30f
--- /dev/null
+++ b/src/java/net/sf/jabref/gui/FirstColumnComparator.java
@@ -0,0 +1,39 @@
+package net.sf.jabref.gui;
+
+import net.sf.jabref.BibtexEntry;
+import net.sf.jabref.Util;
+
+import java.util.Comparator;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: alver
+ * Date: Oct 14, 2005
+ * Time: 8:25:15 PM
+ * To change this template use File | Settings | File Templates.
+ */
+public class FirstColumnComparator implements Comparator {
+
+    public int compare(Object o1, Object o2) {
+
+        BibtexEntry e1 = (BibtexEntry)o1,
+                 e2 = (BibtexEntry)o2;
+
+        int score1=0, score2=0;
+
+        if (Util.isMarked(e1))
+            score1 -= 2;
+
+        if (Util.isMarked(e2))
+            score2 -= 2;
+
+        if (e1.hasAllRequiredFields())
+            score1++;
+
+        if (e2.hasAllRequiredFields())
+            score2++;
+
+        return score1-score2;
+    }
+
+}
diff --git a/src/java/net/sf/jabref/gui/GenFieldsCustomizer.java b/src/java/net/sf/jabref/gui/GenFieldsCustomizer.java
new file mode 100644
index 0000000..4af4e47
--- /dev/null
+++ b/src/java/net/sf/jabref/gui/GenFieldsCustomizer.java
@@ -0,0 +1,211 @@
+package net.sf.jabref.gui;
+
+import net.sf.jabref.*;
+import java.awt.*;
+import javax.swing.*;
+import javax.swing.border.*;
+import java.awt.event.*;
+
+/**
+ * <p>Title: </p>
+ * <p>Description: </p>
+ * <p>Copyright: Copyright (c) 2003</p>
+ * <p>Company: </p>
+ * @author not attributable
+ * @version 1.0
+ */
+
+public class GenFieldsCustomizer extends JDialog {
+  JPanel jPanel2 = new JPanel();
+  JButton ok = new JButton();
+  JButton cancel = new JButton();
+  JButton helpBut = new JButton();
+  TitledBorder titledBorder1;
+  TitledBorder titledBorder2;
+  JLabel jLabel1 = new JLabel();
+  JPanel jPanel3 = new JPanel();
+  JPanel jPanel4 = new JPanel();
+  GridBagLayout gridBagLayout1 = new GridBagLayout();
+  JScrollPane jScrollPane1 = new JScrollPane();
+  JLabel jLabel2 = new JLabel();
+  JTextArea fieldsArea = new JTextArea();
+  GridBagLayout gridBagLayout2 = new GridBagLayout();
+  JabRefFrame parent;
+  JButton revert = new JButton();
+  //EntryCustomizationDialog diag;
+  HelpAction help;
+  
+  public GenFieldsCustomizer(JabRefFrame frame/*, EntryCustomizationDialog diag*/) {
+    super(frame, Globals.lang("Set general fields"), false);
+    parent = frame;
+    //this.diag = diag;
+    help = new HelpAction(parent.helpDiag, GUIGlobals.generalFieldsHelp,
+	      "Help", GUIGlobals.helpSmallIconFile);
+    helpBut = new JButton(Globals.lang("Help"));
+    helpBut.addActionListener(help);
+    try {
+      jbInit();
+      setSize(new Dimension(400, 200));
+    }
+    catch(Exception ex) {
+      ex.printStackTrace();
+    }
+  }
+
+  private void jbInit() throws Exception {
+      ok.setText(Globals.lang("Ok"));
+    ok.addActionListener(new GenFieldsCustomizer_ok_actionAdapter(this));
+    cancel.setText(Globals.lang("Cancel"));
+    cancel.addActionListener(new GenFieldsCustomizer_cancel_actionAdapter(this));
+    //jPanel2.setBackground(GUIGlobals.lightGray);
+    jLabel1.setText(Globals.lang("Delimit fields with semicolon, ex.")+": url;pdf;note");
+    jPanel3.setLayout(gridBagLayout2);
+    jPanel4.setBorder(BorderFactory.createEtchedBorder());
+    jPanel4.setLayout(gridBagLayout1);
+    jLabel2.setText(Globals.lang("General fields"));
+
+    //    fieldsArea.setText(parent.prefs.get("generalFields"));
+    setFieldsText();
+
+    //jPanel3.setBackground(GUIGlobals.lightGray);
+    revert.setText(Globals.lang("Default"));
+    revert.addActionListener(new GenFieldsCustomizer_revert_actionAdapter(this));
+    this.getContentPane().add(jPanel2, BorderLayout.SOUTH);
+    jPanel2.add(ok, null);
+    jPanel2.add(revert, null);
+    jPanel2.add(cancel, null);
+    jPanel2.add(Box.createHorizontalStrut(10));
+    jPanel2.add(helpBut, null);
+    this.getContentPane().add(jPanel3, BorderLayout.CENTER);
+    jPanel3.add(jLabel1,    new GridBagConstraints(0, 1, 1, 1, 1.0, 0.0
+            ,GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0));
+    jPanel3.add(jPanel4,   new GridBagConstraints(0, 0, 1, 1, 1.0, 1.0
+            ,GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(5, 5, 5, 5), 318, 193));
+    jPanel4.add(jScrollPane1,    new GridBagConstraints(0, 1, 1, 1, 1.0, 1.0
+            ,GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(5, 5, 5, 5), 0, 0));
+    jScrollPane1.getViewport().add(fieldsArea, null);
+    jPanel4.add(jLabel2,    new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0
+            ,GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0));
+
+  // Key bindings:
+  ActionMap am = jPanel2.getActionMap();
+  InputMap im = jPanel2.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
+  im.put(Globals.prefs.getKey("Close dialog"), "close");
+  am.put("close", new AbstractAction() {
+    public void actionPerformed(ActionEvent e) {
+      dispose();
+      //diag.requestFocus();
+    }
+  });
+
+  }
+
+  void ok_actionPerformed(ActionEvent e) {
+      String[] lines = fieldsArea.getText().split("\n");
+      int i=0;
+      for (; i<lines.length; i++) {
+	  String[] parts = lines[i].split(":");
+          if (parts.length != 2) {
+              // Report error and exit.
+              String field = Globals.lang("field");
+              JOptionPane.showMessageDialog(this, Globals.lang("Each line must be on the following form")+" '"+
+                      Globals.lang("Tabname")+":"+field+"1;"+field+"2;...;"+field+"N'",
+                      Globals.lang("Error"), JOptionPane.ERROR_MESSAGE);
+              return;
+          }
+          String testString = Util.checkLegalKey(parts[1]);
+          if (!testString.equals(parts[1]) || (parts[1].indexOf('&') >= 0)) {
+              // Report error and exit.
+              JOptionPane.showMessageDialog(this, Globals.lang("Field names are not allowed to contain white space or the following "
+                      +"characters")+": # { } ~ , ^ &",
+                      Globals.lang("Error"), JOptionPane.ERROR_MESSAGE);
+              
+              return;
+          }
+          
+	  Globals.prefs.put((Globals.prefs.CUSTOM_TAB_NAME+i), parts[0]);
+	  Globals.prefs.put((Globals.prefs.CUSTOM_TAB_FIELDS+i), parts[1].toLowerCase());
+      }
+      Globals.prefs.purgeSeries(Globals.prefs.CUSTOM_TAB_NAME, i);
+      Globals.prefs.purgeSeries(Globals.prefs.CUSTOM_TAB_FIELDS, i);
+      Globals.prefs.updateEntryEditorTabList();
+      /*
+    String delimStr = fieldsArea.getText().replaceAll("\\s+","")
+        .replaceAll("\\n+","").trim();
+    parent.prefs.putStringArray("generalFields", Util.delimToStringArray(delimStr, ";"));
+      */
+
+      parent.removeCachedEntryEditors();
+      dispose();
+      //diag.requestFocus();
+  }
+
+  void cancel_actionPerformed(ActionEvent e) {
+    dispose();
+    //diag.requestFocus();
+  }
+
+    void setFieldsText() {
+	StringBuffer sb = new StringBuffer();
+	String name = null, fields = null;
+	int i=0;
+	while ((name = Globals.prefs.get(Globals.prefs.CUSTOM_TAB_NAME+i)) != null) {
+	    sb.append(name);
+	    fields = Globals.prefs.get(Globals.prefs.CUSTOM_TAB_FIELDS+i);
+	    sb.append(":");
+	    sb.append(fields);
+	    sb.append("\n");
+	    i++;
+	}
+	fieldsArea.setText(sb.toString());
+    }
+
+  void revert_actionPerformed(ActionEvent e) {
+      StringBuffer sb = new StringBuffer();
+      String name = null, fields = null;
+      int i=0;
+      while ((name = (String)Globals.prefs.defaults.get(Globals.prefs.CUSTOM_TAB_NAME+i)) != null) {
+	  sb.append(name);
+	  fields = (String)Globals.prefs.defaults.get(Globals.prefs.CUSTOM_TAB_FIELDS+i);
+	  sb.append(":");
+	  sb.append(fields);
+	  sb.append("\n");
+	  i++;
+      }
+      fieldsArea.setText(sb.toString());
+      //    fieldsArea.setText((String)parent.prefs.defaults.get("generalFields"));
+  }
+}
+
+class GenFieldsCustomizer_ok_actionAdapter implements java.awt.event.ActionListener {
+  GenFieldsCustomizer adaptee;
+
+  GenFieldsCustomizer_ok_actionAdapter(GenFieldsCustomizer adaptee) {
+    this.adaptee = adaptee;
+  }
+  public void actionPerformed(ActionEvent e) {
+    adaptee.ok_actionPerformed(e);
+  }
+}
+
+class GenFieldsCustomizer_cancel_actionAdapter implements java.awt.event.ActionListener {
+  GenFieldsCustomizer adaptee;
+
+  GenFieldsCustomizer_cancel_actionAdapter(GenFieldsCustomizer adaptee) {
+    this.adaptee = adaptee;
+  }
+  public void actionPerformed(ActionEvent e) {
+    adaptee.cancel_actionPerformed(e);
+  }
+}
+
+class GenFieldsCustomizer_revert_actionAdapter implements java.awt.event.ActionListener {
+  GenFieldsCustomizer adaptee;
+
+  GenFieldsCustomizer_revert_actionAdapter(GenFieldsCustomizer adaptee) {
+    this.adaptee = adaptee;
+  }
+  public void actionPerformed(ActionEvent e) {
+    adaptee.revert_actionPerformed(e);
+  }
+}
diff --git a/src/java/net/sf/jabref/gui/GlazedEntrySorter.java b/src/java/net/sf/jabref/gui/GlazedEntrySorter.java
new file mode 100644
index 0000000..f8cc5d3
--- /dev/null
+++ b/src/java/net/sf/jabref/gui/GlazedEntrySorter.java
@@ -0,0 +1,98 @@
+package net.sf.jabref.gui;
+
+import net.sf.jabref.*;
+import ca.odell.glazedlists.BasicEventList;
+import ca.odell.glazedlists.SortedList;
+import ca.odell.glazedlists.EventList;
+import ca.odell.glazedlists.event.ListEventAssembler;
+import ca.odell.glazedlists.event.ListEvent;
+import ca.odell.glazedlists.event.ListEventListener;
+
+import java.util.*;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: alver
+ * Date: Oct 12, 2005
+ * Time: 8:54:36 PM
+ * To change this template use File | Settings | File Templates.
+ */
+public class GlazedEntrySorter implements DatabaseChangeListener {
+/*
+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
+
+*/
+
+    //TreeSet list;
+    EventList list;
+
+    Comparator comp;
+    String[] idArray;
+    BibtexEntry[] entryArray;
+    //static BibtexEntry[] DUMMY = new BibtexEntry[0];
+    private boolean outdated = false;
+    private boolean changed = false;
+
+    public GlazedEntrySorter(Map entries, Comparator comp) {
+        //list = new TreeSet(comp);
+        list = new BasicEventList();
+        //list2 = new SortedList(list, new FieldComparator(Globals.KEY_FIELD));
+        this.comp = comp;
+        list.getReadWriteLock().writeLock().lock();
+        Set keySet = entries.keySet();
+        if (keySet != null) {
+            Iterator i = keySet.iterator();
+            while (i.hasNext()) {
+                list.add(entries.get(i.next()));
+            }
+        }
+        list.getReadWriteLock().writeLock().unlock();
+    }
+
+    public EventList getTheList() {
+        return list;
+    }
+
+    public void databaseChanged(DatabaseChangeEvent e) {
+        list.getReadWriteLock().writeLock().lock();
+        if (e.getType() == DatabaseChangeEvent.ADDED_ENTRY) {
+            //int pos = -Collections.binarySearch(list, e.getEntry(), comp) - 1;
+            list.add(e.getEntry());
+            //System.out.println("Added. Size: " + list.size());
+
+        } else if (e.getType() == DatabaseChangeEvent.REMOVED_ENTRY) {
+            list.remove(e.getEntry());
+            //System.out.println("Removed. Size: " + list.size());
+        } else if (e.getType() == DatabaseChangeEvent.CHANGED_ENTRY) {
+            int index = list.indexOf(e.getEntry());
+            list.set(index, e.getEntry());
+        }
+        list.getReadWriteLock().writeLock().unlock();
+
+
+    }
+
+
+}
diff --git a/src/java/net/sf/jabref/gui/IconComparator.java b/src/java/net/sf/jabref/gui/IconComparator.java
new file mode 100644
index 0000000..9d7a43a
--- /dev/null
+++ b/src/java/net/sf/jabref/gui/IconComparator.java
@@ -0,0 +1,35 @@
+package net.sf.jabref.gui;
+
+import net.sf.jabref.BibtexEntry;
+
+import java.util.Comparator;
+
+/**
+ * Comparator that handles icon columns.
+ */
+public class IconComparator implements Comparator {
+
+    private String[] fields;
+
+    public IconComparator(String[] fields) {
+        this.fields = fields;
+    }
+
+    public int compare(Object o1, Object o2) {
+         BibtexEntry e1 = (BibtexEntry)o1,
+                 e2 = (BibtexEntry)o2;
+
+        for (int i=0; i<fields.length; i++) {
+            Object val1 = e1.getField(fields[i]),
+                    val2 = e2.getField(fields[i]);
+            if (val1 == null) {
+                if (val2 != null)
+                    return 1;
+            } else {
+                if (val2 == null)
+                    return -1;
+            }
+        }
+        return 0;
+    }
+}
diff --git a/src/java/net/sf/jabref/gui/ImportInspectionDialog.java b/src/java/net/sf/jabref/gui/ImportInspectionDialog.java
new file mode 100644
index 0000000..0e0315c
--- /dev/null
+++ b/src/java/net/sf/jabref/gui/ImportInspectionDialog.java
@@ -0,0 +1,831 @@
+package net.sf.jabref.gui;
+
+import net.sf.jabref.*;
+import net.sf.jabref.groups.GroupTreeNode;
+import net.sf.jabref.groups.AllEntriesGroup;
+import net.sf.jabref.groups.AbstractGroup;
+import net.sf.jabref.groups.UndoableChangeAssignment;
+import net.sf.jabref.labelPattern.LabelPatternUtil;
+import net.sf.jabref.undo.NamedCompound;
+import net.sf.jabref.undo.UndoableInsertEntry;
+import net.sf.jabref.undo.UndoableRemoveEntry;
+
+import javax.swing.*;
+import javax.swing.undo.AbstractUndoableEdit;
+import javax.swing.event.ListSelectionListener;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.table.DefaultTableModel;
+import javax.swing.table.TableModel;
+import javax.swing.table.TableColumnModel;
+import java.util.*;
+import java.util.List;
+import java.awt.*;
+import java.awt.event.ActionListener;
+import java.awt.event.ActionEvent;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+
+import com.jgoodies.forms.builder.ButtonBarBuilder;
+import com.jgoodies.forms.builder.ButtonStackBuilder;
+import com.jgoodies.uif_lite.component.UIFSplitPane;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: alver
+ * Date: 20.mar.2005
+ * Time: 22:02:35
+ * To change this template use File | Settings | File Templates.
+ */
+public class ImportInspectionDialog extends JDialog {
+    private ImportInspectionDialog ths = this;
+    private BasePanel panel;
+    private JabRefFrame frame;
+    private UIFSplitPane contentPane = new UIFSplitPane(UIFSplitPane.VERTICAL_SPLIT);
+    private MyTableModel tableModel = new MyTableModel();
+    private JTable table = new MyTable(tableModel);
+    private String[] fields;
+    private JProgressBar progressBar = new JProgressBar(JProgressBar.HORIZONTAL);
+    private JButton ok = new JButton(Globals.lang("Ok")),
+        cancel = new JButton(Globals.lang("Cancel")),
+        generate = new JButton(Globals.lang("Generate now"));
+    private List entries = new ArrayList(),
+            entriesToDelete = new ArrayList(); // Duplicate resolving may require deletion of old entries.
+    private String undoName;
+    private ArrayList callBacks = new ArrayList();
+    private boolean newDatabase;
+    private JMenu groupsAdd = new JMenu(Globals.lang("Add to group"));
+    private JPopupMenu popup = new JPopupMenu();
+    private JButton selectAll = new JButton(Globals.lang("Select all"));
+    private JButton deselectAll = new JButton(Globals.lang("Deselect all"));
+    private JButton stop = new JButton(Globals.lang("Stop"));
+    private JButton delete = new JButton(Globals.lang("Delete"));
+    private JButton help = new JButton(Globals.lang("Help"));
+    private PreviewPanel preview = new PreviewPanel(Globals.prefs.get("preview1"));
+    private ListSelectionListener previewListener = null;
+    private boolean generatedKeys = false; // Set to true after keys have been generated.
+    private boolean defaultSelected = true;
+    private Rectangle toRect = new Rectangle(0, 0, 1, 1);
+    private Map groupAdditions = new HashMap();
+    private Icon pdfIcon = new ImageIcon(GUIGlobals.pdfIcon);
+    private Icon psIcon = new ImageIcon(GUIGlobals.psIcon);
+    private JCheckBox autoGenerate = new JCheckBox(Globals.lang("Generate keys"), Globals.prefs.getBoolean("generateKeysAfterInspection"));
+    private final int
+        DUPL_COL = 1,    
+        PDF_COL = 2,
+        PS_COL = 3,
+        URL_COL = 4,
+        PAD = 5;
+
+
+    /**
+     * The "defaultSelected" boolean value determines if new entries added are selected for import or not.
+     * This value is true by default.
+     * @param defaultSelected The desired value.
+     */
+    public void setDefaultSelected(boolean defaultSelected) {
+        this.defaultSelected = defaultSelected;
+    }
+
+    /**
+     * Creates a dialog that displays the given list of fields in the table.
+     * The dialog allows another process to add entries dynamically while the dialog
+     * is shown.
+     *
+     * @param frame
+     * @param panel
+     * @param fields
+     */
+    public ImportInspectionDialog(JabRefFrame frame, BasePanel panel, String[] fields,
+                                  String undoName, boolean newDatabase) {
+        this.frame = frame;
+        this.panel = panel;
+        this.fields = fields;
+        this.undoName = undoName;
+        this.newDatabase = newDatabase;
+
+        tableModel.addColumn(Globals.lang("Keep"));
+        tableModel.addColumn("");
+        tableModel.addColumn("");
+        tableModel.addColumn("");
+        tableModel.addColumn("");
+        DeleteListener deleteListener = new DeleteListener();
+
+
+        for (int i = 0; i < fields.length; i++) {
+            tableModel.addColumn(Util.nCase(fields[i]));
+        }
+
+        setWidths();
+        table.setRowSelectionAllowed(true);
+        table.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
+        GeneralRenderer renderer = new GeneralRenderer(Color.white, true);
+        table.setDefaultRenderer(JLabel.class, renderer);
+        table.setDefaultRenderer(String.class, renderer);
+        //table.setCellSelectionEnabled(false);
+        previewListener = new TableSelectionListener();
+        table.getSelectionModel().addListSelectionListener(previewListener);
+        table.addMouseListener(new TableClickListener());
+        getContentPane().setLayout(new BorderLayout());
+        progressBar.setIndeterminate(true);
+        JPanel centerPan = new JPanel();
+        centerPan.setLayout(new BorderLayout());
+        contentPane.setTopComponent(new JScrollPane(table));
+        contentPane.setBottomComponent(new JScrollPane(preview));
+
+        centerPan.add(contentPane, BorderLayout.CENTER);
+        centerPan.add(progressBar, BorderLayout.SOUTH);
+
+        popup.add(deleteListener);
+        popup.addSeparator();
+        if (!newDatabase) {
+            GroupTreeNode node = panel.metaData().getGroups();
+            groupsAdd.setEnabled(false); // Will get enabled if there are groups that can be added to.
+            insertNodes(groupsAdd, node, true);
+            popup.add(groupsAdd);
+        }
+
+        // Add "Attach file" menu choices to right click menu:
+        popup.add(new AttachFile("pdf"));
+        popup.add(new AttachFile("ps"));
+        popup.add(new AttachUrl());
+        getContentPane().add(centerPan, BorderLayout.CENTER);
+
+
+        ButtonBarBuilder bb = new ButtonBarBuilder();
+        bb.addGlue();
+        bb.addGridded(ok);
+        bb.addGridded(stop);
+        bb.addGridded(cancel);
+        bb.addRelatedGap();
+        bb.addGridded(help);
+        bb.addGlue();
+        bb.getPanel().setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));
+
+        ButtonStackBuilder builder = new ButtonStackBuilder();
+        builder.addGridded(selectAll);
+        builder.addGridded(deselectAll);
+        builder.addRelatedGap();
+        builder.addGridded(delete);
+        builder.addRelatedGap();
+        builder.addGridded(autoGenerate);
+        builder.addGridded(generate);
+        builder.getPanel().setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));
+        centerPan.add(builder.getPanel(), BorderLayout.WEST);
+
+        ok.setEnabled(false);
+        generate.setEnabled(false);
+        ok.addActionListener(new OkListener());
+        cancel.addActionListener(new CancelListener());
+        generate.addActionListener(new GenerateListener());
+        stop.addActionListener(new StopListener());
+        selectAll.addActionListener(new SelectionButton(true));
+        deselectAll.addActionListener(new SelectionButton(false));
+        delete.addActionListener(deleteListener);
+        help.addActionListener(new HelpAction(frame.helpDiag, GUIGlobals.importInspectionHelp));
+        getContentPane().add(bb.getPanel(), BorderLayout.SOUTH);
+        setSize(new Dimension(650, 650));
+        //contentPane.setDividerLocation(0.6f);
+    }
+
+    public void setProgress(int current, int max) {
+        progressBar.setIndeterminate(false);
+        progressBar.setMinimum(0);
+        progressBar.setMaximum(max);
+        progressBar.setValue(current);
+    }
+
+    /**
+     * Wrapper for addEntries(List) that takes a single entry.
+     *
+     * @param entry The entry to add.
+     */
+    public void addEntry(BibtexEntry entry) {
+        List list = new ArrayList();
+        list.add(entry);
+        addEntries(list);
+    }
+
+    /**
+     * Add a List of entries to the table view. The table will update to show the
+     * added entries. Synchronizes on this.entries to avoid conflict with the delete button
+     * which removes entries.
+     *
+     * @param entries
+     */
+    public void addEntries(List entries) {
+        synchronized (this.entries) {
+            for (Iterator i = entries.iterator(); i.hasNext();) {
+                BibtexEntry entry = (BibtexEntry) i.next();
+                this.entries.add(entry);
+                Object[] values = new Object[tableModel.getColumnCount()];
+                values[0] = Boolean.valueOf(defaultSelected);
+                // Add an icon for it if this entry is a duplicate of an existing entry:
+                if ((panel != null) && (Util.containsDuplicate(panel.database(), entry) != null)) {
+                    JLabel lab = new JLabel(new ImageIcon(GUIGlobals.duplicateIcon));
+                    lab.setToolTipText(Globals.lang("Possible duplicate of existing entry. Click to resolve."));
+                    values[DUPL_COL] = lab;
+                }
+                // pdf:
+                if (entry.getField("pdf") != null) {
+                    JLabel lab = new JLabel(new ImageIcon(GUIGlobals.pdfIcon));
+                    lab.setToolTipText((String) entry.getField("pdf"));
+                    values[PDF_COL] = lab;
+                } else
+                    values[PDF_COL] = null;
+                // ps:
+                if (entry.getField("ps") != null) {
+                    JLabel lab = new JLabel(new ImageIcon(GUIGlobals.psIcon));
+                    lab.setToolTipText((String) entry.getField("ps"));
+                    values[PS_COL] = lab;
+                } else
+                    values[PS_COL] = null;
+                // url:
+                if (entry.getField("url") != null) {
+                    JLabel lab = new JLabel(new ImageIcon(GUIGlobals.wwwIcon));
+                    lab.setToolTipText((String) entry.getField("url"));
+                    values[URL_COL] = lab;
+                } else
+                    values[URL_COL] = null;
+
+                for (int j = 0; j < fields.length; j++)
+                    values[PAD + j] = entry.getField(fields[j]);
+                tableModel.addRow(values);
+            }
+        }
+    }
+
+    /**
+     * Removes all selected entries from the table. Synchronizes on this.entries to prevent
+     * conflict with addition of new entries.
+     */
+    public void removeSelectedEntries() {
+        synchronized (this.entries) {
+            int[] rows = table.getSelectedRows();
+            if (rows.length > 0) {
+                for (int i = rows.length - 1; i >= 0; i--) {
+                    tableModel.removeRow(rows[i]);
+                    this.entries.remove(rows[i]);
+
+                }
+            }
+        }
+    }
+
+    /**
+     * When this method is called, the dialog will visually change to indicate
+     * that all entries are in place.
+     */
+    public void entryListComplete() {
+        progressBar.setIndeterminate(false);
+        progressBar.setVisible(false);
+        ok.setEnabled(true);
+        if (!generatedKeys)
+            generate.setEnabled(true);
+        stop.setEnabled(false);
+    }
+
+
+    /**
+     * This method returns a List containing all entries that are selected
+     * (checkbox checked).
+     *
+     * @return a List containing the selected entries.
+     */
+    public List getSelectedEntries() {
+        List selected = new ArrayList();
+        for (int i = 0; i < table.getRowCount(); i++) {
+            Boolean sel = (Boolean) table.getValueAt(i, 0);
+            if (sel.booleanValue()) {
+                selected.add(entries.get(i));
+            }
+        }
+        return selected;
+    }
+
+    /**
+     * Generate keys for all entries. All keys will be unique with respect to one another,
+     * and, if they are destined for an existing database, with respect to existing keys in
+     * the database.
+     */
+    public void generateKeys(boolean addColumn) {
+        BibtexDatabase database = null;
+        // Relate to the existing database, if any:
+        if (panel != null)
+            database = panel.database();
+        // ... or create a temporary one:
+        else
+            database = new BibtexDatabase();
+        List keys = new ArrayList(entries.size());
+        // Iterate over the entries, add them to the database we are working with,
+        // and generate unique keys:
+        for (Iterator i = entries.iterator(); i.hasNext();) {
+            BibtexEntry entry = (BibtexEntry) i.next();
+            //if (newDatabase) {
+            try {
+                entry.setId(Util.createNeutralId());
+                database.insertEntry(entry);
+            } catch (KeyCollisionException ex) {
+                ex.printStackTrace();
+            }
+            //}
+            LabelPatternUtil.makeLabel(Globals.prefs.getKeyPattern(), database, entry);
+            // Add the generated key to our list:
+            keys.add(entry.getCiteKey());
+        }
+        // Remove the entries from the database again, since they are not supposed to
+        // added yet. They only needed to be in it while we generated the keys, to keep
+        // control over key uniqueness.
+        for (Iterator i = entries.iterator(); i.hasNext();) {
+            BibtexEntry entry = (BibtexEntry) i.next();
+            database.removeEntry(entry.getId());
+        }
+
+        if (addColumn) {
+            // Add a column to the table for displaying the generated keys:
+            tableModel.addColumn("Bibtexkey", keys.toArray());
+            setWidths();
+        }
+    }
+
+    /*public void removeKeys() {
+        for (Iterator i = entries.iterator(); i.hasNext();) {
+            BibtexEntry entry = (BibtexEntry) i.next();
+            entry.setField(Globals.KEY_FIELD, null);
+        }
+        tableModel. // AAAAAAAAAAHHH no removeColumn()?????????
+    } */
+
+    public void insertNodes(JMenu menu, GroupTreeNode node, boolean add) {
+        final AbstractAction action = getAction(node, add);
+
+        if (node.getChildCount() == 0) {
+            menu.add(action);
+            if (action.isEnabled())
+                menu.setEnabled(true);
+            return;
+        }
+
+        JMenu submenu = null;
+        if (node.getGroup() instanceof AllEntriesGroup) {
+            for (int i = 0; i < node.getChildCount(); ++i) {
+                insertNodes(menu, (GroupTreeNode) node.getChildAt(i), add);
+            }
+        } else {
+            submenu = new JMenu("[" + node.getGroup().getName() + "]");
+            // setEnabled(true) is done above/below if at least one menu
+            // entry (item or submenu) is enabled
+            submenu.setEnabled(action.isEnabled());
+            submenu.add(action);
+            submenu.add(new JPopupMenu.Separator());
+            for (int i = 0; i < node.getChildCount(); ++i)
+                insertNodes(submenu, (GroupTreeNode) node.getChildAt(i), add);
+            menu.add(submenu);
+            if (submenu.isEnabled())
+                menu.setEnabled(true);
+        }
+    }
+
+    private AbstractAction getAction(GroupTreeNode node, boolean add) {
+        AbstractAction action = add ? (AbstractAction) new AddToGroupAction(node)
+                : (AbstractAction) new RemoveFromGroupAction(node);
+        AbstractGroup group = node.getGroup();
+        action.setEnabled(/*add ? */group.supportsAdd());// && !group.containsAll(selection)
+        //        : group.supportsRemove() && group.containsAny(selection));
+        return action;
+    }
+
+    /**
+     * Stores the information about the selected entries being scheduled for addition
+     * to this group. The entries are *not* added to the group at this time.
+     * <p/>
+     * Synchronizes on this.entries to prevent
+     * conflict with threads that modify the entry list.
+     */
+    class AddToGroupAction extends AbstractAction {
+        private GroupTreeNode node;
+
+        public AddToGroupAction(GroupTreeNode node) {
+            super(node.getGroup().getName());
+            this.node = node;
+        }
+
+        public void actionPerformed(ActionEvent event) {
+            synchronized (entries) {
+                int[] rows = table.getSelectedRows();
+                if (rows.length == 0)
+                    return;
+
+                for (int i = 0; i < rows.length; i++) {
+                    BibtexEntry entry = (BibtexEntry) entries.get(rows[i]);
+                    // We store the groups this entry should be added to in a Set in the Map:
+                    Set groups = (Set) groupAdditions.get(entry);
+                    if (groups == null) {
+                        // No previous definitions, so we create the Set now:
+                        groups = new HashSet();
+                        groupAdditions.put(entry, groups);
+                    }
+                    // Add the group:
+                    groups.add(node);
+                }
+            }
+        }
+    }
+
+    class RemoveFromGroupAction extends AbstractAction {
+        private GroupTreeNode node;
+
+        public RemoveFromGroupAction(GroupTreeNode node) {
+            this.node = node;
+        }
+
+        public void actionPerformed(ActionEvent event) {
+        }
+    }
+
+    public void addCallBack(CallBack cb) {
+        callBacks.add(cb);
+    }
+
+    class OkListener implements ActionListener {
+        public void actionPerformed(ActionEvent event) {
+
+            // First check if we are supposed to warn about duplicates. If so, see if there
+            // are unresolved duplicates, and warn if yes.
+            if (Globals.prefs.getBoolean("warnAboutDuplicatesInInspection")) {
+                for (int i=0; i<tableModel.getRowCount(); i++) {
+                    // Only check entries that are to be imported:
+                    Boolean sel = (Boolean) table.getValueAt(i, 0);
+                    if (!sel.booleanValue())
+                        continue;
+
+                    if (tableModel.getValueAt(i, DUPL_COL) != null) {
+                        CheckBoxMessage cbm = new CheckBoxMessage(
+                                Globals.lang("There are possible duplicates (marked with a 'D' icon) that haven't been resolved. Continue?"),
+                                Globals.lang("Disable this confirmation dialog"), false);
+                        int answer = JOptionPane.showConfirmDialog(ImportInspectionDialog.this, cbm, Globals.lang("Duplicates found"),
+                                    JOptionPane.YES_NO_OPTION);
+                        if (cbm.isSelected())
+                            Globals.prefs.putBoolean("warnAboutDuplicatesInInspection", false);
+                        if (answer == JOptionPane.NO_OPTION)
+                            return;
+                        break;
+                    }
+                }
+            }
+
+            // The compund undo action used to contain all changes made by this dialog.
+            NamedCompound ce = new NamedCompound(undoName);
+
+            // See if we should remove any old entries for duplicate resolving:
+            if (entriesToDelete.size() > 0) {
+                for (Iterator i=entriesToDelete.iterator(); i.hasNext();) {
+                    BibtexEntry entry = (BibtexEntry)i.next();
+                    ce.addEdit(new UndoableRemoveEntry(panel.database(), entry, panel));
+                    panel.database().removeEntry(entry.getId());
+                }
+            }
+            /*panel.undoManager.addEdit(undo);
+            panel.refreshTable();
+            panel.markBaseChanged();*/
+
+
+            // If "Generate keys" is checked, generate keys unless it's already been done:
+            if (autoGenerate.isSelected() && !generatedKeys) {
+                generateKeys(false);
+            }
+            // Remember the choice until next time:
+            Globals.prefs.putBoolean("generateKeysAfterInspection", autoGenerate.isSelected());
+
+            final List selected = getSelectedEntries();
+
+            if (selected.size() > 0) {
+
+                if (newDatabase) {
+                    // Create a new BasePanel for the entries:
+                    BibtexDatabase base = new BibtexDatabase();
+                    panel = new BasePanel(frame, base, null, new HashMap(), Globals.prefs.get("defaultEncoding"));
+                }
+
+                boolean groupingCanceled = false;
+
+                // Set owner/timestamp if options are enabled:
+                Util.setAutomaticFields(selected);
+
+
+                for (Iterator i = selected.iterator(); i.hasNext();) {
+                    BibtexEntry entry = (BibtexEntry) i.next();
+                    //entry.clone();
+
+                    // If this entry should be added to any groups, do it now:
+                    Set groups = (Set) groupAdditions.get(entry);
+                    if (!groupingCanceled && (groups != null)) {
+                        if (entry.getField(Globals.KEY_FIELD) == null) {
+                            // The entry has no key, so it can't be added to the group.
+                            // The best course of ation is probably to ask the user if a key should be generated
+                            // immediately.
+                           int answer = JOptionPane.showConfirmDialog(ImportInspectionDialog.this,
+                                   Globals.lang("Cannot add entries to group without generating keys. Generate keys now?"),
+                                    Globals.lang("Add to group"), JOptionPane.YES_NO_OPTION);
+                            if (answer == JOptionPane.YES_OPTION) {
+                                generateKeys(false);
+                            } else
+                                groupingCanceled = true;
+                        }
+
+                        // If the key was list, or has been list now, go ahead:
+                        if (entry.getField(Globals.KEY_FIELD) != null) {
+                            for (Iterator i2 = groups.iterator(); i2.hasNext();) {
+                                GroupTreeNode node = (GroupTreeNode) i2.next();
+                                if (node.getGroup().supportsAdd()) {
+                                    // Add the entry:
+                                    AbstractUndoableEdit undo = node.getGroup().add(new BibtexEntry[]{entry});
+                                    if (undo instanceof UndoableChangeAssignment)
+                                        ((UndoableChangeAssignment) undo).setEditedNode(node);
+                                    ce.addEdit(undo);
+
+                                } else {
+                                    // Shouldn't happen...
+                                }
+                            }
+                        }
+                    }
+
+                    try {
+                        entry.setId(Util.createNeutralId());
+                        panel.database().insertEntry(entry);
+                        ce.addEdit(new UndoableInsertEntry(panel.database(), entry, panel));
+                    } catch (KeyCollisionException e) {
+                        e.printStackTrace();
+                    }
+                }
+
+                ce.end();
+                panel.undoManager.addEdit(ce);
+            }
+            
+            dispose();
+            SwingUtilities.invokeLater(new Thread() {
+                public void run() {
+                    if (newDatabase) {
+                        frame.addTab(panel, null, true);
+                    }
+                    panel.markBaseChanged();
+                    for (Iterator i = callBacks.iterator(); i.hasNext();) {
+                        ((CallBack) i.next()).done(selected.size());
+                    }
+                }
+            });
+
+        }
+
+    }
+
+    private void signalStopFetching() {
+        for (Iterator i = callBacks.iterator(); i.hasNext();) {
+            ((CallBack) i.next()).stopFetching();
+        }
+    }
+
+    private void setWidths() {
+        DeleteListener deleteListener = new DeleteListener();
+        TableColumnModel cm = table.getColumnModel();
+        cm.getColumn(0).setPreferredWidth(55);
+        cm.getColumn(0).setMinWidth(55);
+        cm.getColumn(0).setMaxWidth(55);
+        for (int i = 1; i < PAD; i++) {
+            // Lock the width of icon columns.
+            cm.getColumn(i).setPreferredWidth(GUIGlobals.WIDTH_ICON_COL);
+            cm.getColumn(i).setMinWidth(GUIGlobals.WIDTH_ICON_COL);
+            cm.getColumn(i).setMaxWidth(GUIGlobals.WIDTH_ICON_COL);
+        }
+
+        for (int i = 0; i < fields.length; i++) {
+            Object o = GUIGlobals.fieldLength.get(fields[i]);
+            int width = o == null ? GUIGlobals.DEFAULT_FIELD_LENGTH :
+                    ((Integer) o).intValue();
+            table.getColumnModel().getColumn(i + PAD).setPreferredWidth(width);
+        }
+    }
+
+
+
+    class StopListener implements ActionListener {
+        public void actionPerformed(ActionEvent event) {
+            signalStopFetching();
+            entryListComplete();
+        }
+    }
+
+    class CancelListener implements ActionListener {
+        public void actionPerformed(ActionEvent event) {
+            signalStopFetching();
+            dispose();
+            for (Iterator i = callBacks.iterator(); i.hasNext();) {
+                ((CallBack) i.next()).cancelled();
+            }
+        }
+    }
+
+    class GenerateListener implements ActionListener {
+        public void actionPerformed(ActionEvent event) {
+            generate.setEnabled(false);
+            generatedKeys = true; // To prevent the button from getting enabled again.
+            generateKeys(true); // Generate the keys.
+        }
+    }
+
+    class DeleteListener extends JMenuItem implements ActionListener {
+        public DeleteListener() {
+            super(Globals.lang("Delete"));
+            addActionListener(this);
+        }
+
+        public void actionPerformed(ActionEvent event) {
+            removeSelectedEntries();
+        }
+    }
+
+    class MyTable extends JTable {
+        public MyTable(TableModel model) {
+            super(model);
+            //setDefaultRenderer(Boolean.class, );
+        }
+
+        public boolean isCellEditable(int row, int col) {
+            return col == 0;
+        }
+    }
+
+    class MyTableModel extends DefaultTableModel {
+
+
+        public Class getColumnClass(int i) {
+            if (i == 0)
+                return Boolean.class;
+            else
+                return String.class;
+        }
+
+    }
+
+    class SelectionButton implements ActionListener {
+        private Boolean enable;
+
+        public SelectionButton(boolean enable) {
+            this.enable = Boolean.valueOf(enable);
+        }
+
+        public void actionPerformed(ActionEvent event) {
+            for (int i = 0; i < table.getRowCount(); i++) {
+                table.setValueAt(enable, i, 0);
+            }
+        }
+    }
+
+    class TableSelectionListener implements ListSelectionListener {
+        public void valueChanged(ListSelectionEvent event) {
+            if (event.getValueIsAdjusting())
+                return;
+            if (table.getSelectedRowCount() > 1)
+                return; // No soup for you!
+            int row = table.getSelectedRow();
+            if (row < 0)
+                return;
+            preview.setEntry((BibtexEntry) entries.get(row));
+            contentPane.setDividerLocation(0.5f);
+            SwingUtilities.invokeLater(new Runnable() {
+                public void run() {
+                    preview.scrollRectToVisible(toRect);
+                }
+            });
+
+        }
+
+    }
+
+    /**
+     * This class handles clicks on the table that should trigger specific
+     * events, like opening the popup menu.
+     */
+    class TableClickListener extends MouseAdapter {
+        public void mousePressed(MouseEvent e) {
+
+            // Check if the user has right-clicked. If so, open the right-click menu.
+            if (e.isPopupTrigger()) {
+                //if ( (e.getButton() == MouseEvent.BUTTON3) ||
+                //     (ctrlClick && (e.getButton() == MouseEvent.BUTTON1) && e.isControlDown())) {
+                int[] rows = table.getSelectedRows();
+                popup.show(table, e.getX(), e.getY());
+                return;
+            }
+
+            // Check if any other action should be taken:
+            final int col = table.columnAtPoint(e.getPoint()),
+              row = table.rowAtPoint(e.getPoint());
+            // Is this the duplicate icon column, and is there an icon?
+            if ((col == DUPL_COL) && (tableModel.getValueAt(row, col) != null)) {
+                BibtexEntry first = (BibtexEntry)entries.get(row);
+                BibtexEntry other = Util.containsDuplicate(panel.database(), first);
+                if (other != null) { // This should be true since the icon is displayed...
+                    DuplicateResolverDialog diag = new DuplicateResolverDialog(frame, other, first, DuplicateResolverDialog.INSPECTION);
+                    Util.placeDialog(diag, ImportInspectionDialog.this);
+                    diag.setVisible(true);
+                    ImportInspectionDialog.this.toFront();
+                    if (diag.getSelected() == DuplicateResolverDialog.KEEP_UPPER) {
+                        // Remove old entry. Or... add it to a list of entries to be deleted. We only delete
+                        // it after Ok is clicked.
+                        entriesToDelete.add(other);
+                        tableModel.setValueAt(null, row, col); // Clear duplicate icon.
+                    } else if (diag.getSelected() == DuplicateResolverDialog.KEEP_LOWER) {
+                        // Remove the entry from the import inspection dialog.
+                        synchronized (entries) {
+                            tableModel.removeRow(row);
+                            entries.remove(row);
+                        }
+                    } else if (diag.getSelected() == DuplicateResolverDialog.KEEP_BOTH) {
+                        // Do nothing.
+                        tableModel.setValueAt(null, row, col); // Clear duplicate icon.
+                    }
+                }
+            }
+        }
+    }
+
+    class AttachUrl extends JMenuItem implements ActionListener {
+        public AttachUrl() {
+            super(Globals.lang("Attach URL"));
+            addActionListener(this);
+        }
+
+        public void actionPerformed(ActionEvent event) {
+            int[] rows = table.getSelectedRows();
+            if (rows.length != 1)
+                return;
+            BibtexEntry entry = (BibtexEntry) entries.get(rows[0]);
+            String result = JOptionPane.showInputDialog(ths, Globals.lang("Enter URL"), entry.getField("url"));
+            if (result != null) {
+                if (result.equals("")) {
+                    entry.clearField("url");
+                    tableModel.setValueAt(null, rows[0], 3);
+                } else {
+                    entry.setField("url", result);
+                    JLabel lab = new JLabel(new ImageIcon(GUIGlobals.wwwIcon));
+                    lab.setToolTipText(result);
+                    tableModel.setValueAt(lab, rows[0], 3);
+                }
+            }
+
+        }
+    }
+
+
+    class AttachFile extends JMenuItem implements ActionListener {
+        String fileType;
+
+        public AttachFile(String fileType) {
+            super(Globals.lang("Attach %0 file", new String[]{fileType.toUpperCase()}));
+            this.fileType = fileType;
+            addActionListener(this);
+        }
+
+        public void actionPerformed(ActionEvent event) {
+            int[] rows = table.getSelectedRows();
+            if (rows.length != 1)
+                return;
+            BibtexEntry entry = (BibtexEntry) entries.get(rows[0]);
+            // Call up a dialog box that provides Browse, Download and auto buttons:
+            AttachFileDialog diag = new AttachFileDialog(ths, entry, fileType);
+            Util.placeDialog(diag, ths);
+            diag.setVisible(true);
+            // After the dialog has closed, if it wasn't cancelled, list the field:
+            if (!diag.cancelled()) {
+                entry.setField(fileType, diag.getValue());
+                // Add a marker to the table:
+                int column = (fileType.equals("pdf") ? PDF_COL : PS_COL);
+                JLabel lab = new JLabel(new ImageIcon((column == PDF_COL ? GUIGlobals.pdfIcon
+                        : GUIGlobals.psIcon)));
+                lab.setToolTipText((String) entry.getField(fileType));
+                tableModel.setValueAt(lab, rows[0], column);
+                //tableModel.setValueAt((fileType.equals("pdf") ? pdfIcon : psIcon), rows[0], 1);
+
+                //tableModel.setValueAt(entry.getField(fileType), rows[0], column);
+            }
+
+        }
+    }
+
+    public static interface CallBack {
+        // This method is called by the dialog when the user has selected the
+        // wanted entries, and clicked Ok. The callback object can update status
+        // line etc.
+        public void done(int entriesImported);
+
+        // This method is called by the dialog when the user has cancelled the import.
+        public void cancelled();
+
+        // This method is called by the dialog when the user has cancelled or
+        // signalled a stop. It is expected that any long-running fetch operations
+        // will stop after this method is called.
+        public void stopFetching();
+    }
+}
diff --git a/src/java/net/sf/jabref/gui/MainTable.java b/src/java/net/sf/jabref/gui/MainTable.java
new file mode 100644
index 0000000..2b7561b
--- /dev/null
+++ b/src/java/net/sf/jabref/gui/MainTable.java
@@ -0,0 +1,497 @@
+package net.sf.jabref.gui;
+
+import net.sf.jabref.*;
+import net.sf.jabref.search.SearchMatcher;
+import net.sf.jabref.search.HitOrMissComparator;
+import net.sf.jabref.groups.EntryTableTransferHandler;
+
+import javax.swing.*;
+import javax.swing.table.TableCellRenderer;
+import javax.swing.table.TableModel;
+import javax.swing.table.TableColumnModel;
+
+import ca.odell.glazedlists.SortedList;
+import ca.odell.glazedlists.EventList;
+import ca.odell.glazedlists.gui.AbstractTableComparatorChooser;
+import ca.odell.glazedlists.matchers.Matcher;
+import ca.odell.glazedlists.event.ListEventListener;
+import ca.odell.glazedlists.swing.EventSelectionModel;
+import ca.odell.glazedlists.swing.TableComparatorChooser;
+import ca.odell.glazedlists.swing.EventTableModel;
+
+import java.awt.*;
+import java.awt.event.ActionListener;
+import java.awt.event.ActionEvent;
+import java.util.Comparator;
+
+/**
+ * Created by IntelliJ IDEA.
+ * 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 sortedForTable, sortedForSearch, sortedForGrouping;
+    private boolean tableColorCodes, showingFloatSearch=false, showingFloatGrouping=false;
+    private EventSelectionModel selectionModel;
+    private TableComparatorChooser comparatorChooser;
+    private JScrollPane pane;
+    private Comparator searchComparator, groupComparator;
+    private Matcher searchMatcher, groupMatcher;
+    public static final int REQUIRED = 1
+    ,
+    OPTIONAL = 2
+    ,
+    OTHER = 3;
+
+    static {
+        updateRenderers();
+    }
+
+    public MainTable(MainTableFormat tableFormat, EventList list) {
+        super();
+        this.tableFormat = tableFormat;
+        // This SortedList has a Comparator controlled by the TableComparatorChooser
+        // we are going to install, which responds to user sorting selctions:
+        sortedForTable = new SortedList(list, null);
+        // This SortedList applies afterwards, and can float search hits:
+        sortedForSearch = new SortedList(sortedForTable, null);
+        // This SortedList applies afterwards, and can float grouping hits:
+        sortedForGrouping = new SortedList(sortedForSearch, null);
+
+
+        searchMatcher = null;
+        groupMatcher = null;
+        searchComparator = null;//new HitOrMissComparator(searchMatcher);
+        groupComparator = null;//new HitOrMissComparator(groupMatcher);
+
+        EventTableModel tableModel = new EventTableModel(sortedForGrouping, tableFormat);
+        setModel(tableModel);
+
+        tableColorCodes = Globals.prefs.getBoolean("tableColorCodesOn");
+        selectionModel = new EventSelectionModel(sortedForGrouping);
+        setSelectionModel(selectionModel);
+        pane = new JScrollPane(this);
+        pane.getViewport().setBackground(Globals.prefs.getColor("tableBackground"));
+        setGridColor(Globals.prefs.getColor("gridColor"));
+        comparatorChooser = new MyTableComparatorChooser(this, sortedForTable,
+                TableComparatorChooser.MULTIPLE_COLUMN_KEYBOARD);
+
+        final EventList selected = getSelected();
+
+        // enable DnD
+        setDragEnabled(true);
+        setTransferHandler(new EntryTableTransferHandler(this));
+
+        setupComparatorChooser();
+        refreshSorting();
+        setWidths();
+
+    }
+
+    public void refreshSorting() {
+        sortedForSearch.getReadWriteLock().writeLock().lock();
+        sortedForSearch.setComparator(searchComparator);
+        sortedForSearch.getReadWriteLock().writeLock().unlock();
+        sortedForGrouping.getReadWriteLock().writeLock().lock();
+        sortedForGrouping.setComparator(groupComparator);
+        sortedForGrouping.getReadWriteLock().writeLock().unlock();
+    }
+
+    /**
+     * Adds a sorting rule that floats hits to the top, and causes non-hits to be grayed out:
+     * @param m The Matcher that determines if an entry is a hit or not.
+     */
+    public void showFloatSearch(Matcher m) {
+        showingFloatSearch = true;
+        searchMatcher = m;
+        searchComparator = new HitOrMissComparator(m);
+        refreshSorting();
+    }
+
+    /**
+     * Removes sorting by search results, and graying out of non-hits.
+     */
+    public void stopShowingFloatSearch() {
+        showingFloatSearch = false;
+        searchMatcher = null;
+        searchComparator = null;
+        refreshSorting();
+    }
+
+    /**
+     * Adds a sorting rule that floats group hits to the top, and causes non-hits to be grayed out:
+     * @param m The Matcher that determines if an entry is a in the current group selection or not.
+     */
+    public void showFloatGrouping(Matcher m) {
+        showingFloatGrouping = true;
+        groupMatcher = m;
+        groupComparator = new HitOrMissComparator(m);
+        refreshSorting();
+    }
+
+    /**
+     * Removes sorting by group, and graying out of non-hits.
+     */
+    public void stopShowingFloatGrouping() {
+        showingFloatGrouping = false;
+        groupMatcher = null;
+        groupComparator = null;
+        refreshSorting();
+    }
+
+    public EventList getTableRows() {
+        return sortedForGrouping;
+    }
+    public void addSelectionListener(ListEventListener listener) {
+        getSelected().addListEventListener(listener);
+    }
+
+    public JScrollPane getPane() {
+        return pane;
+    }
+
+    public TableCellRenderer getCellRenderer(int row, int column) {
+
+        int score = -3;
+        TableCellRenderer renderer = defRenderer;
+
+        int status = getCellStatus(row, column);
+
+        if (!showingFloatSearch || matches(row, searchMatcher))
+            score++;
+        if (!showingFloatGrouping || matches(row, groupMatcher))
+            score += 2;
+
+        // Now, a grayed out renderer is for entries with -1, and
+        // a very grayed out one for entries with -2
+        if (score < -1) {
+            if (column == 0) {
+                veryGrayedOutNumberRenderer.setNumber(row);
+                renderer = veryGrayedOutNumberRenderer;
+            } else renderer = veryGrayedOutRenderer;
+        }
+        else if (score == -1) {
+            if (column == 0) {
+                grayedOutNumberRenderer.setNumber(row);
+                renderer = grayedOutNumberRenderer;
+            } else renderer = grayedOutRenderer;
+        }
+        
+        else if (column == 0) {
+            // Return a renderer with red background if the entry is incomplete.
+            if (!isComplete(row)) {
+                incRenderer.setNumber(row);
+                renderer = incRenderer;
+            } else {
+                compRenderer.setNumber(row);
+                if (isMarked(row)) {
+                    renderer = markedNumberRenderer;
+                    markedNumberRenderer.setNumber(row);
+                } else
+                    renderer = compRenderer;
+            }
+        }
+        else if (tableColorCodes) {
+            if (status == EntryTableModel.REQUIRED)
+                renderer = reqRenderer;
+            else if (status == EntryTableModel.OPTIONAL)
+                renderer = optRenderer;
+            else if (status == EntryTableModel.BOOLEAN)
+                renderer = getDefaultRenderer(Boolean.class);
+        }
+
+        // For MARKED feature:
+        if ((column != 0) && isMarked(row)) {
+            renderer = markedRenderer;
+        }
+
+        return renderer;
+
+    }
+
+    public void setWidths() {
+        // Setting column widths:
+        int ncWidth = Globals.prefs.getInt("numberColWidth");
+        String[] widths = Globals.prefs.getStringArray("columnWidths");
+        TableColumnModel cm = getColumnModel();
+        cm.getColumn(0).setPreferredWidth(ncWidth);
+        for (int i = 1; i < tableFormat.padleft; i++) {
+            // Lock the width of icon columns.
+            cm.getColumn(i).setPreferredWidth(GUIGlobals.WIDTH_ICON_COL);
+            cm.getColumn(i).setMinWidth(GUIGlobals.WIDTH_ICON_COL);
+            cm.getColumn(i).setMaxWidth(GUIGlobals.WIDTH_ICON_COL);
+        }
+        for (int i = tableFormat.padleft; i < getModel().getColumnCount(); i++) {
+            try {
+                cm.getColumn(i).setPreferredWidth(Integer.parseInt(widths[i - tableFormat.padleft]));
+            } catch (Throwable ex) {
+                Globals.logger("Exception while setting column widths. Choosing default.");
+                cm.getColumn(i).setPreferredWidth(GUIGlobals.DEFAULT_FIELD_LENGTH);
+            }
+
+        }
+    }
+
+    public BibtexEntry getEntryAt(int row) {
+        return (BibtexEntry)sortedForGrouping.get(row);
+    }
+
+    public BibtexEntry[] getSelectedEntries() {
+        final BibtexEntry[] BE_ARRAY = new BibtexEntry[0];
+        return (BibtexEntry[]) getSelected().toArray(BE_ARRAY);
+    }
+
+    private void setupComparatorChooser() {
+        // First column:
+        java.util.List comparators = comparatorChooser.getComparatorsForColumn(0);
+        comparators.clear();
+        comparators.add(new FirstColumnComparator());
+
+        // Icon columns:
+        for (int i = 1; i < tableFormat.padleft; i++) {
+            comparators = comparatorChooser.getComparatorsForColumn(i);
+            comparators.clear();
+            String[] iconField = tableFormat.getIconTypeForColumn(i);
+            comparators.add(new IconComparator(iconField));
+        }
+        // Remaining columns:
+        for (int i = tableFormat.padleft; i < tableFormat.getColumnCount(); i++) {
+            comparators = comparatorChooser.getComparatorsForColumn(i);
+            comparators.clear();
+            comparators.add(new FieldComparator(tableFormat.getColumnName(i).toLowerCase()));
+        }
+
+        // Set initial sort columns:
+
+        // Default sort order:
+        String[] sortFields = new String[] {Globals.prefs.get("priSort"), Globals.prefs.get("secSort"),
+            Globals.prefs.get("terSort")};
+        boolean[] sortDirections = new boolean[] {Globals.prefs.getBoolean("priDescending"),
+            Globals.prefs.getBoolean("secDescending"), Globals.prefs.getBoolean("terDescending")}; // descending
+
+        sortedForTable.getReadWriteLock().writeLock().lock();
+        for (int i=0; i<sortFields.length; i++) {
+            int index = tableFormat.getColumnIndex(sortFields[i]);
+            if (index >= 0) {
+                comparatorChooser.appendComparator(index, 0, sortDirections[i]);
+            }
+        }
+        sortedForTable.getReadWriteLock().writeLock().unlock();
+
+    }
+
+    public int getCellStatus(int row, int col) {
+        try {
+            BibtexEntry be = (BibtexEntry)sortedForGrouping.get(row);
+            BibtexEntryType type = be.getType();
+            String columnName = tableFormat.getColumnName(col).toLowerCase();
+            if (columnName.equals(GUIGlobals.KEY_FIELD) || type.isRequired(columnName)) {
+                return REQUIRED;
+            }
+            if (type.isOptional(columnName)) {
+                return OPTIONAL;
+            }
+            return OTHER;
+        } catch (NullPointerException ex) {
+            //System.out.println("Exception: getCellStatus");
+            return OTHER;
+        }
+    }
+
+    public EventList getSelected() {
+        return selectionModel.getSelected();
+    }
+
+    public int findEntry(BibtexEntry entry) {
+        //System.out.println(sortedForGrouping.indexOf(entry));
+        return sortedForGrouping.indexOf(entry);
+    }
+
+    public String[] getIconTypeForColumn(int column) {
+        return tableFormat.getIconTypeForColumn(column);
+    }
+
+    private boolean nonZeroField(int row, String field) {
+        BibtexEntry be = (BibtexEntry)sortedForGrouping.get(row);
+        Object o = be.getField(field);
+        return ((o == null) || !o.equals("0"));
+    }
+
+    private boolean matches(int row, Matcher m) {
+        Object o = sortedForGrouping.get(row);
+        return m.matches(o);
+    }
+
+    private boolean isComplete(int row) {
+        try {
+            BibtexEntry be = (BibtexEntry)sortedForGrouping.get(row);
+            return be.hasAllRequiredFields();
+        } catch (NullPointerException ex) {
+            //System.out.println("Exception: isComplete");
+            return true;
+        }
+    }
+
+    private boolean isMarked(int row) {
+        try {
+            BibtexEntry be = (BibtexEntry)sortedForGrouping.get(row);
+            return Util.isMarked(be);
+        } catch (NullPointerException ex) {
+            //System.out.println("Exception: isMarked");
+            return false;
+        }
+    }
+
+
+    public void scrollTo(int y) {
+        JScrollBar scb = pane.getVerticalScrollBar();
+        scb.setValue(y * scb.getUnitIncrement(1));
+    }
+
+    /**
+     * updateFont
+     */
+    public void updateFont() {
+        setFont(GUIGlobals.CURRENTFONT);
+        setRowHeight(GUIGlobals.TABLE_ROW_PADDING + GUIGlobals.CURRENTFONT.getSize());
+    }
+
+    public void ensureVisible(int row) {
+        JScrollBar vert = pane.getVerticalScrollBar();
+        int y = row * getRowHeight();
+        if ((y < vert.getValue()) || (y > vert.getValue() + vert.getVisibleAmount()))
+            scrollToCenter(row, 1);
+    }
+
+    public void scrollToCenter(int rowIndex, int vColIndex) {
+        if (!(this.getParent() instanceof JViewport)) {
+            return;
+        }
+
+        JViewport viewport = (JViewport) this.getParent();
+
+        // This rectangle is relative to the table where the
+        // northwest corner of cell (0,0) is always (0,0).
+        Rectangle rect = this.getCellRect(rowIndex, vColIndex, true);
+
+        // The location of the view relative to the table
+        Rectangle viewRect = viewport.getViewRect();
+
+        // Translate the cell location so that it is relative
+        // to the view, assuming the northwest corner of the
+        // view is (0,0).
+        rect.setLocation(rect.x - viewRect.x, rect.y - viewRect.y);
+
+        // Calculate location of rect if it were at the center of view
+        int centerX = (viewRect.width - rect.width) / 2;
+        int centerY = (viewRect.height - rect.height) / 2;
+
+        // Fake the location of the cell so that scrollRectToVisible
+        // will move the cell to the center
+        if (rect.x < centerX) {
+            centerX = -centerX;
+        }
+        if (rect.y < centerY) {
+            centerY = -centerY;
+        }
+        rect.translate(centerX, centerY);
+
+        // Scroll the area into view.
+        viewport.scrollRectToVisible(rect);
+
+        revalidate();
+        repaint();
+    }
+
+
+    private static GeneralRenderer defRenderer
+    ,
+    reqRenderer
+    ,
+    optRenderer
+    ,
+    grayedOutRenderer,
+    veryGrayedOutRenderer
+    ,
+    markedRenderer;
+
+    private static IncompleteRenderer incRenderer;
+    private static CompleteRenderer
+            compRenderer,
+            grayedOutNumberRenderer,
+            veryGrayedOutNumberRenderer,
+            markedNumberRenderer;
+
+    public static void updateRenderers() {
+
+        boolean antialiasing = Globals.prefs.getBoolean("antialias");
+        defRenderer = new GeneralRenderer(Globals.prefs.getColor("tableBackground"),
+                Globals.prefs.getColor("tableText"), antialiasing);
+        reqRenderer = new GeneralRenderer(Globals.prefs.getColor("tableReqFieldBackground"), Globals.prefs.getColor("tableText"), antialiasing);
+        optRenderer = new GeneralRenderer(Globals.prefs.getColor("tableOptFieldBackground"), Globals.prefs.getColor("tableText"), antialiasing);
+        incRenderer = new IncompleteRenderer(antialiasing);
+        compRenderer = new CompleteRenderer(Globals.prefs.getColor("tableBackground"), antialiasing);
+        markedNumberRenderer = new CompleteRenderer(Globals.prefs.getColor("markedEntryBackground"), antialiasing);
+        grayedOutNumberRenderer = new CompleteRenderer(Globals.prefs.getColor("grayedOutBackground"), antialiasing);
+        veryGrayedOutNumberRenderer = new CompleteRenderer(Globals.prefs.getColor("veryGrayedOutBackground"), antialiasing);
+        grayedOutRenderer = new GeneralRenderer(Globals.prefs.getColor("grayedOutBackground"),
+            Globals.prefs.getColor("grayedOutText"), antialiasing);
+        veryGrayedOutRenderer = new GeneralRenderer(Globals.prefs.getColor("veryGrayedOutBackground"),
+                Globals.prefs.getColor("veryGrayedOutText"), antialiasing);
+        markedRenderer = new GeneralRenderer(Globals.prefs.getColor("markedEntryBackground"),
+                Globals.prefs.getColor("tableText"), antialiasing);
+    }
+
+    static class IncompleteRenderer extends GeneralRenderer {
+        public IncompleteRenderer(boolean antialiasing) {
+            super(Globals.prefs.getColor("incompleteEntryBackground"), antialiasing);
+            super.setToolTipText(Globals.lang("This entry is incomplete"));
+        }
+
+        protected void setNumber(int number) {
+            super.setValue(String.valueOf(number + 1));
+        }
+
+        protected void setValue(Object value) {
+
+        }
+    }
+
+    static class CompleteRenderer extends GeneralRenderer {
+        public CompleteRenderer(Color color, boolean antialiasing) {
+            super(color, antialiasing);
+        }
+
+        protected void setNumber(int number) {
+            super.setValue(String.valueOf(number + 1));
+        }
+
+        protected void setValue(Object value) {
+
+        }
+    }
+
+    class MyTableComparatorChooser extends TableComparatorChooser {
+        public MyTableComparatorChooser(JTable table, SortedList list,
+                                        Object sortingStrategy) {
+            super(table, list, sortingStrategy);
+            // We need to reset the stack of sorted list each time sorting order
+            // changes, or the sorting breaks down:
+            addSortActionListener(new ActionListener() {
+                public void actionPerformed(ActionEvent e) {
+                    //System.out.println("...");
+                    refreshSorting();
+                }
+            });
+        }
+/*
+        protected void columnClicked(int i, int i1) {
+
+            super.columnClicked(i, i1);
+            refreshSorting();
+        }*/
+    }
+}
diff --git a/src/java/net/sf/jabref/gui/MainTableFormat.java b/src/java/net/sf/jabref/gui/MainTableFormat.java
new file mode 100644
index 0000000..66828f6
--- /dev/null
+++ b/src/java/net/sf/jabref/gui/MainTableFormat.java
@@ -0,0 +1,210 @@
+package net.sf.jabref.gui;
+
+import ca.odell.glazedlists.gui.TableFormat;
+import ca.odell.glazedlists.SortedList;
+import ca.odell.glazedlists.FilterList;
+import ca.odell.glazedlists.matchers.Matcher;
+import ca.odell.glazedlists.swing.EventTableModel;
+import ca.odell.glazedlists.swing.EventSelectionModel;
+import ca.odell.glazedlists.swing.TableComparatorChooser;
+import net.sf.jabref.*;
+import net.sf.jabref.imports.ImportFormatReader;
+
+import javax.swing.*;
+import java.util.*;
+import java.awt.*;
+import java.awt.event.ActionListener;
+import java.awt.event.ActionEvent;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: alver
+ * Date: Oct 12, 2005
+ * Time: 7:37:48 PM
+ * To change this template use File | Settings | File Templates.
+ */
+public class MainTableFormat implements TableFormat {
+
+    public static final String[]
+            PDF = {"pdf", "ps"}
+    ,
+    URL_ = {"url", "doi"}
+    ,
+    CITESEER = {"citeseerurl"};
+
+    BasePanel panel;
+
+    String[] columns; // Contains the current column names.
+    public int padleft = -1; // padleft indicates how many columns (starting from left) are
+    // special columns (number column or icon column).
+    private HashMap iconCols = new HashMap();
+    int[] nameCols = null;
+    boolean namesAsIs, abbr_names, namesNatbib, namesFf, namesLf, namesLastOnly, showShort;
+
+    public MainTableFormat(BasePanel panel) {
+        this.panel = panel;
+    }
+
+    public int getColumnCount() {
+        return padleft + columns.length;
+    }
+
+    public String getColumnName(int col) {
+        if (col == 0) {
+            return GUIGlobals.NUMBER_COL;
+        } else if (getIconTypeForColumn(col) != null) {
+            return "";
+        } else if (GUIGlobals.FIELD_DISPLAYS.get(columns[col - padleft]) != null) {
+            return ((String) GUIGlobals.FIELD_DISPLAYS.get(columns[col - padleft]));
+        }
+        return Util.nCase(columns[col - padleft]);
+    }
+
+    /**
+     * This method returns a string array indicating the types of icons to be displayed in the given column.
+     * It returns null if the column is not an icon column, and thereby also serves to identify icon
+     * columns.
+     */
+    public String[] getIconTypeForColumn(int col) {
+        Object o = iconCols.get(new Integer(col));
+        if (o != null)
+            return (String[]) o;
+        else
+            return null;
+    }
+
+    /**
+     * Finds the column index for the given column name.
+     * @param colName The column name
+     * @return The column index if any, or -1 if no column has that name. 
+     */
+    public int getColumnIndex(String colName) {
+        for (int i=0; i<columns.length; i++) {
+            if (columns[i].equalsIgnoreCase(colName))
+                return i+padleft;
+        }
+        return -1;
+    }
+
+    public Object getColumnValue(Object object, int col) {
+        Object o;
+        BibtexEntry be = (BibtexEntry) object;
+        String[] iconType = getIconTypeForColumn(col); // If non-null, indicates an icon column's type.
+        if (col == 0) {
+            o = "#";// + (row + 1);
+        }
+
+        else if (iconType != null) {
+            int hasField = -1;
+            for (int i = iconType.length - 1; i >= 0; i--)
+                if (hasField(be, iconType[i]))
+                    hasField = i;
+            if (hasField < 0)
+                return null;
+
+            // Ok, so we are going to display an icon. Find out which one, and return it:
+            o = GUIGlobals.getTableIcon(iconType[hasField]);
+        } else if (columns[col - padleft].equals(GUIGlobals.TYPE_HEADER)) {
+            o = be.getType().getName();
+        } else {
+
+            o = be.getField(columns[col - padleft]);
+            for (int i = 0; i < nameCols.length; i++) {
+                if (col - padleft == nameCols[i]) {
+                    if (o == null) {
+                        return null;
+                    }
+                    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);
+
+                    return o;
+                }
+            }
+
+
+        }
+
+        return o;
+    }
+
+    public boolean hasField(BibtexEntry be, String field) {
+        // Returns true iff the entry has a nonzero value in its
+        // 'search' field.
+        return ((be != null) && (be.getField(field) != null));
+    }
+
+    public void updateTableFormat() {
+
+        // Read table columns from prefs:
+        columns = Globals.prefs.getStringArray("columnNames");
+
+        // Read name format options:
+        showShort = Globals.prefs.getBoolean("showShort");        //MK:
+        namesNatbib = Globals.prefs.getBoolean("namesNatbib");    //MK:
+        namesLastOnly = Globals.prefs.getBoolean("namesLastOnly");
+        namesAsIs = Globals.prefs.getBoolean("namesAsIs");
+        abbr_names = Globals.prefs.getBoolean("abbrAuthorNames"); //MK:
+        namesFf = Globals.prefs.getBoolean("namesFf");
+        namesLf = !(namesAsIs || namesFf || namesNatbib || namesLastOnly); // None of the above.
+
+        // Set the icon columns, indicating the number of special columns to the left.
+        // We add those that are enabled in preferences.
+        iconCols.clear();
+        int coln = 1;
+        if (Globals.prefs.getBoolean("pdfColumn"))
+            iconCols.put(new Integer(coln++), PDF);
+        if (Globals.prefs.getBoolean("urlColumn"))
+            iconCols.put(new Integer(coln++), URL_);
+        if (Globals.prefs.getBoolean("citeseerColumn"))
+            iconCols.put(new Integer(coln++), CITESEER);
+
+        // Add 1 to the number of icon columns to get padleft.
+        padleft = 1 + iconCols.size();
+
+        // Set up the int[] nameCols, to mark which columns should be
+        // treated as lists of names. This is to provide a correct presentation
+        // of names as efficiently as possible.
+        Vector tmp = new Vector(2, 1);
+        for (int i = 0; i < columns.length; i++) {
+            if (columns[i].equals("author")
+                    || columns[i].equals("editor")) {
+                tmp.add(new Integer(i));
+            }
+        }
+        nameCols = new int[tmp.size()];
+        for (int i = 0; i < nameCols.length; i++) {
+            nameCols[i] = ((Integer) tmp.elementAt(i)).intValue();
+        }
+    }
+
+    public boolean isIconColumn(int col) {
+        return (getIconTypeForColumn(col) != null);
+    }
+
+
+
+    static class NoSearchMatcher implements Matcher {
+        public boolean matches(Object object) {
+            return true;
+        }
+    }
+
+    static class SearchMatcher implements Matcher {
+        private String field = Globals.SEARCH;
+        private SearchRuleSet ruleSet;
+        private Hashtable searchOptions;
+
+        public SearchMatcher(SearchRuleSet ruleSet, Hashtable searchOptions) {
+            this.ruleSet = ruleSet;
+            this.searchOptions = searchOptions;
+        }
+        public boolean matches(Object object) {
+            BibtexEntry entry = (BibtexEntry)object;
+            int result = ruleSet.applyRule(searchOptions, entry);
+            return result > 0;
+        }
+    }
+}
diff --git a/src/java/net/sf/jabref/gui/MainTableSelectionListener. b/src/java/net/sf/jabref/gui/MainTableSelectionListener.
new file mode 100644
index 0000000..326c49f
--- /dev/null
+++ b/src/java/net/sf/jabref/gui/MainTableSelectionListener.
@@ -0,0 +1,268 @@
+package net.sf.jabref.gui;
+
+import ca.odell.glazedlists.event.ListEventListener;
+import ca.odell.glazedlists.event.ListEvent;
+import ca.odell.glazedlists.EventList;
+import net.sf.jabref.*;
+
+import javax.swing.*;
+import java.awt.event.MouseListener;
+import java.awt.event.MouseEvent;
+import java.io.IOException;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: alver
+ * Date: Oct 15, 2005
+ * Time: 3:02:52 AM
+ * To change this template use File | Settings | File Templates.
+ */
+public class MainTableSelectionListener implements ListEventListener, MouseListener {
+
+    PreviewPanel[] previewPanel = null;
+    int activePreview = 1;
+    PreviewPanel preview;
+    MainTable table;
+    BasePanel panel;
+    EventList tableRows;
+    private boolean previewActive = Globals.prefs.getBoolean("previewEnabled");
+    private boolean workingOnPreview = false;
+
+    public MainTableSelectionListener(BasePanel panel, MainTable table) {
+        this.table = table;
+        this.panel = panel;
+        this.tableRows = table.getTableRows();
+        instantiatePreviews();
+        this.preview = previewPanel[activePreview];
+    }
+
+    private void instantiatePreviews() {
+        previewPanel = new PreviewPanel[]
+                {new PreviewPanel(panel.database(), Globals.prefs.get("preview0")),
+                        new PreviewPanel(panel.database(), Globals.prefs.get("preview1"))};
+        BibtexEntry testEntry = PreviewPrefsTab.getTestEntry();
+        previewPanel[0].setEntry(testEntry);
+        previewPanel[1].setEntry(testEntry);
+    }
+
+    public void updatePreviews() {
+        try {
+            previewPanel[0].readLayout(Globals.prefs.get("preview0"));
+            previewPanel[1].readLayout(Globals.prefs.get("preview1"));
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    public void listChanged(ListEvent e) {
+        //System.out.println(e);
+        EventList selected = e.getSourceList();
+        Object newSelected = null;
+        while (e.next()) {
+            if (e.getType() == ListEvent.INSERT) {
+                if (newSelected != null)
+                    return; // More than one new selected. Do nothing.
+                else {
+                    if (e.getIndex() < selected.size())
+                        newSelected = selected.get(e.getIndex());
+                }
+
+            }
+        }
+
+
+        if (newSelected != null) {
+
+            // Ok, we have a single new entry that has been selected. Now decide what to do with it:
+            final BibtexEntry toShow = (BibtexEntry) newSelected;
+            final int mode = panel.getMode(); // What is the panel already showing?
+            if ((mode == BasePanel.WILL_SHOW_EDITOR) || (mode == BasePanel.SHOWING_EDITOR)) {
+                // An entry is currently being edited.
+                EntryEditor oldEditor = panel.getCurrentEditor();
+                // Get an old or new editor for the entry to edit:
+                EntryEditor newEditor = panel.getEntryEditor(toShow);
+                // Show the new editor unless it was already visible:
+                if ((newEditor != oldEditor) || (mode != BasePanel.SHOWING_EDITOR)) {
+                    panel.showEntryEditor(newEditor);
+                }
+            } else {
+                // Either nothing or a preview was shown. Update the preview.
+                if (previewActive) {
+                    updatePreview(toShow, false);
+                }
+
+            }
+        }
+
+    }
+
+    private void updatePreview(final BibtexEntry toShow, final boolean changedPreview) {
+        if (workingOnPreview)
+            return;
+        final int mode = panel.getMode();
+        workingOnPreview = true;
+        final Runnable update = new Runnable() {
+            public void run() {
+                // If nothing was already shown, set the preview and move the separator:
+                if (changedPreview || (mode == BasePanel.SHOWING_NOTHING)) {
+                    panel.showPreview(preview);
+                    panel.adjustSplitter();
+                }
+                workingOnPreview = false;
+            }
+        };
+        final Runnable worker = new Runnable() {
+            public void run() {
+                preview.setEntry(toShow);
+                SwingUtilities.invokeLater(update);
+            }
+        };
+        (new Thread(worker)).start();
+    }
+
+    public void editSignalled() {
+        if (table.getSelected().size() == 1) {
+            editSignalled((BibtexEntry) table.getSelected().get(0));
+        }
+    }
+
+    public void editSignalled(BibtexEntry entry) {
+        final int mode = panel.getMode();
+        EntryEditor editor = panel.getEntryEditor(entry);
+        if (mode != BasePanel.SHOWING_EDITOR) {
+            panel.showEntryEditor(editor);
+            panel.adjustSplitter();
+        }
+        new FocusRequester(editor);
+    }
+
+    public void mouseReleased(MouseEvent e) {
+        // First find the column on which the user has clicked.
+        final int col = table.columnAtPoint(e.getPoint()),
+                row = table.rowAtPoint(e.getPoint());
+        // Check if the user has right-clicked. If so, open the right-click menu.
+        if (e.isPopupTrigger()) {
+            processPopupTrigger(e, row, col);
+            return;
+        }
+    }
+
+    protected void processPopupTrigger(MouseEvent e, int row, int col) {
+        int selRow = table.getSelectedRow();
+        if (selRow == -1 ||// (getSelectedRowCount() == 0))
+                !table.isRowSelected(table.rowAtPoint(e.getPoint()))) {
+            table.setRowSelectionInterval(row, row);
+            //panel.updateViewToSelected();
+        }
+        RightClickMenu rightClickMenu = new RightClickMenu(panel, panel.metaData());
+        rightClickMenu.show(table, e.getX(), e.getY());
+    }
+
+    public void mousePressed(MouseEvent e) {
+
+        // First find the column on which the user has clicked.
+        final int col = table.columnAtPoint(e.getPoint()),
+                row = table.rowAtPoint(e.getPoint());
+
+        // A double click on an entry should open the entry's editor.
+        if (e.getClickCount() == 2) {
+
+            BibtexEntry toShow = (BibtexEntry) tableRows.get(row);
+            editSignalled(toShow);
+        }
+
+        // Check if the user has right-clicked. If so, open the right-click menu.
+        if (e.isPopupTrigger()) {
+            processPopupTrigger(e, row, col);
+            return;
+        }
+
+        // Check if the user has clicked on an icon cell to open url or pdf.
+        final String[] iconType = table.getIconTypeForColumn(col);
+        if (iconType != null) {
+
+            Object value = table.getValueAt(row, col);
+            if (value == null) return; // No icon here, so we do nothing.
+
+            final BibtexEntry entry = (BibtexEntry) tableRows.get(row);
+
+            // Get the icon type. Corresponds to the field name.
+            int hasField = -1;
+            for (int i = iconType.length - 1; i >= 0; i--)
+                if (entry.getField(iconType[i]) != null)
+                    hasField = i;
+            if (hasField == -1)
+                return;
+            final String fieldName = iconType[hasField];
+
+            // Open it now. We do this in a thread, so the program won't freeze during the wait.
+            (new Thread() {
+                public void run() {
+                    panel.output(Globals.lang("External viewer called") + ".");
+
+                    Object link = entry.getField(fieldName);
+                    if (iconType == null) {
+                        Globals.logger("Error: no link to " + fieldName + ".");
+                        return; // There is an icon, but the field is not set.
+                    }
+
+                    try {
+                        Util.openExternalViewer((String) link, fieldName, Globals.prefs);
+                    }
+                    catch (IOException ex) {
+                        panel.output(Globals.lang("Error") + ": " + ex.getMessage());
+                    }
+                }
+
+            }).start();
+        }
+    }
+
+    public void entryEditorClosing(EntryEditor editor) {
+        preview.setEntry(editor.getEntry());
+        if (previewActive)
+            panel.showPreview(preview);
+        else
+            panel.hideBottomComponent();
+        panel.adjustSplitter();
+        new FocusRequester(table);
+    }
+
+
+    public void mouseClicked(MouseEvent e) {
+
+    }
+
+    public void mouseEntered(MouseEvent e) {
+
+    }
+
+    public void mouseExited(MouseEvent e) {
+
+    }
+
+    public void setPreviewActive(boolean enabled) {
+        previewActive = enabled;
+        if (!previewActive) {
+            panel.hideBottomComponent();
+        } else {
+            if (table.getSelected().size() > 0 ) {
+                updatePreview((BibtexEntry) table.getSelected().get(0), false);
+            }
+        }
+    }
+
+    public void switchPreview() {
+        if (activePreview < previewPanel.length - 1)
+            activePreview++;
+        else
+            activePreview = 0;
+        if (previewActive) {
+            this.preview = previewPanel[activePreview];
+
+            if (table.getSelected().size() > 0) {
+                updatePreview((BibtexEntry) table.getSelected().get(0), true);
+            }
+        }
+    }
+}
diff --git a/src/java/net/sf/jabref/gui/MainTableSelectionListener.java b/src/java/net/sf/jabref/gui/MainTableSelectionListener.java
new file mode 100644
index 0000000..326c49f
--- /dev/null
+++ b/src/java/net/sf/jabref/gui/MainTableSelectionListener.java
@@ -0,0 +1,268 @@
+package net.sf.jabref.gui;
+
+import ca.odell.glazedlists.event.ListEventListener;
+import ca.odell.glazedlists.event.ListEvent;
+import ca.odell.glazedlists.EventList;
+import net.sf.jabref.*;
+
+import javax.swing.*;
+import java.awt.event.MouseListener;
+import java.awt.event.MouseEvent;
+import java.io.IOException;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: alver
+ * Date: Oct 15, 2005
+ * Time: 3:02:52 AM
+ * To change this template use File | Settings | File Templates.
+ */
+public class MainTableSelectionListener implements ListEventListener, MouseListener {
+
+    PreviewPanel[] previewPanel = null;
+    int activePreview = 1;
+    PreviewPanel preview;
+    MainTable table;
+    BasePanel panel;
+    EventList tableRows;
+    private boolean previewActive = Globals.prefs.getBoolean("previewEnabled");
+    private boolean workingOnPreview = false;
+
+    public MainTableSelectionListener(BasePanel panel, MainTable table) {
+        this.table = table;
+        this.panel = panel;
+        this.tableRows = table.getTableRows();
+        instantiatePreviews();
+        this.preview = previewPanel[activePreview];
+    }
+
+    private void instantiatePreviews() {
+        previewPanel = new PreviewPanel[]
+                {new PreviewPanel(panel.database(), Globals.prefs.get("preview0")),
+                        new PreviewPanel(panel.database(), Globals.prefs.get("preview1"))};
+        BibtexEntry testEntry = PreviewPrefsTab.getTestEntry();
+        previewPanel[0].setEntry(testEntry);
+        previewPanel[1].setEntry(testEntry);
+    }
+
+    public void updatePreviews() {
+        try {
+            previewPanel[0].readLayout(Globals.prefs.get("preview0"));
+            previewPanel[1].readLayout(Globals.prefs.get("preview1"));
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    public void listChanged(ListEvent e) {
+        //System.out.println(e);
+        EventList selected = e.getSourceList();
+        Object newSelected = null;
+        while (e.next()) {
+            if (e.getType() == ListEvent.INSERT) {
+                if (newSelected != null)
+                    return; // More than one new selected. Do nothing.
+                else {
+                    if (e.getIndex() < selected.size())
+                        newSelected = selected.get(e.getIndex());
+                }
+
+            }
+        }
+
+
+        if (newSelected != null) {
+
+            // Ok, we have a single new entry that has been selected. Now decide what to do with it:
+            final BibtexEntry toShow = (BibtexEntry) newSelected;
+            final int mode = panel.getMode(); // What is the panel already showing?
+            if ((mode == BasePanel.WILL_SHOW_EDITOR) || (mode == BasePanel.SHOWING_EDITOR)) {
+                // An entry is currently being edited.
+                EntryEditor oldEditor = panel.getCurrentEditor();
+                // Get an old or new editor for the entry to edit:
+                EntryEditor newEditor = panel.getEntryEditor(toShow);
+                // Show the new editor unless it was already visible:
+                if ((newEditor != oldEditor) || (mode != BasePanel.SHOWING_EDITOR)) {
+                    panel.showEntryEditor(newEditor);
+                }
+            } else {
+                // Either nothing or a preview was shown. Update the preview.
+                if (previewActive) {
+                    updatePreview(toShow, false);
+                }
+
+            }
+        }
+
+    }
+
+    private void updatePreview(final BibtexEntry toShow, final boolean changedPreview) {
+        if (workingOnPreview)
+            return;
+        final int mode = panel.getMode();
+        workingOnPreview = true;
+        final Runnable update = new Runnable() {
+            public void run() {
+                // If nothing was already shown, set the preview and move the separator:
+                if (changedPreview || (mode == BasePanel.SHOWING_NOTHING)) {
+                    panel.showPreview(preview);
+                    panel.adjustSplitter();
+                }
+                workingOnPreview = false;
+            }
+        };
+        final Runnable worker = new Runnable() {
+            public void run() {
+                preview.setEntry(toShow);
+                SwingUtilities.invokeLater(update);
+            }
+        };
+        (new Thread(worker)).start();
+    }
+
+    public void editSignalled() {
+        if (table.getSelected().size() == 1) {
+            editSignalled((BibtexEntry) table.getSelected().get(0));
+        }
+    }
+
+    public void editSignalled(BibtexEntry entry) {
+        final int mode = panel.getMode();
+        EntryEditor editor = panel.getEntryEditor(entry);
+        if (mode != BasePanel.SHOWING_EDITOR) {
+            panel.showEntryEditor(editor);
+            panel.adjustSplitter();
+        }
+        new FocusRequester(editor);
+    }
+
+    public void mouseReleased(MouseEvent e) {
+        // First find the column on which the user has clicked.
+        final int col = table.columnAtPoint(e.getPoint()),
+                row = table.rowAtPoint(e.getPoint());
+        // Check if the user has right-clicked. If so, open the right-click menu.
+        if (e.isPopupTrigger()) {
+            processPopupTrigger(e, row, col);
+            return;
+        }
+    }
+
+    protected void processPopupTrigger(MouseEvent e, int row, int col) {
+        int selRow = table.getSelectedRow();
+        if (selRow == -1 ||// (getSelectedRowCount() == 0))
+                !table.isRowSelected(table.rowAtPoint(e.getPoint()))) {
+            table.setRowSelectionInterval(row, row);
+            //panel.updateViewToSelected();
+        }
+        RightClickMenu rightClickMenu = new RightClickMenu(panel, panel.metaData());
+        rightClickMenu.show(table, e.getX(), e.getY());
+    }
+
+    public void mousePressed(MouseEvent e) {
+
+        // First find the column on which the user has clicked.
+        final int col = table.columnAtPoint(e.getPoint()),
+                row = table.rowAtPoint(e.getPoint());
+
+        // A double click on an entry should open the entry's editor.
+        if (e.getClickCount() == 2) {
+
+            BibtexEntry toShow = (BibtexEntry) tableRows.get(row);
+            editSignalled(toShow);
+        }
+
+        // Check if the user has right-clicked. If so, open the right-click menu.
+        if (e.isPopupTrigger()) {
+            processPopupTrigger(e, row, col);
+            return;
+        }
+
+        // Check if the user has clicked on an icon cell to open url or pdf.
+        final String[] iconType = table.getIconTypeForColumn(col);
+        if (iconType != null) {
+
+            Object value = table.getValueAt(row, col);
+            if (value == null) return; // No icon here, so we do nothing.
+
+            final BibtexEntry entry = (BibtexEntry) tableRows.get(row);
+
+            // Get the icon type. Corresponds to the field name.
+            int hasField = -1;
+            for (int i = iconType.length - 1; i >= 0; i--)
+                if (entry.getField(iconType[i]) != null)
+                    hasField = i;
+            if (hasField == -1)
+                return;
+            final String fieldName = iconType[hasField];
+
+            // Open it now. We do this in a thread, so the program won't freeze during the wait.
+            (new Thread() {
+                public void run() {
+                    panel.output(Globals.lang("External viewer called") + ".");
+
+                    Object link = entry.getField(fieldName);
+                    if (iconType == null) {
+                        Globals.logger("Error: no link to " + fieldName + ".");
+                        return; // There is an icon, but the field is not set.
+                    }
+
+                    try {
+                        Util.openExternalViewer((String) link, fieldName, Globals.prefs);
+                    }
+                    catch (IOException ex) {
+                        panel.output(Globals.lang("Error") + ": " + ex.getMessage());
+                    }
+                }
+
+            }).start();
+        }
+    }
+
+    public void entryEditorClosing(EntryEditor editor) {
+        preview.setEntry(editor.getEntry());
+        if (previewActive)
+            panel.showPreview(preview);
+        else
+            panel.hideBottomComponent();
+        panel.adjustSplitter();
+        new FocusRequester(table);
+    }
+
+
+    public void mouseClicked(MouseEvent e) {
+
+    }
+
+    public void mouseEntered(MouseEvent e) {
+
+    }
+
+    public void mouseExited(MouseEvent e) {
+
+    }
+
+    public void setPreviewActive(boolean enabled) {
+        previewActive = enabled;
+        if (!previewActive) {
+            panel.hideBottomComponent();
+        } else {
+            if (table.getSelected().size() > 0 ) {
+                updatePreview((BibtexEntry) table.getSelected().get(0), false);
+            }
+        }
+    }
+
+    public void switchPreview() {
+        if (activePreview < previewPanel.length - 1)
+            activePreview++;
+        else
+            activePreview = 0;
+        if (previewActive) {
+            this.preview = previewPanel[activePreview];
+
+            if (table.getSelected().size() > 0) {
+                updatePreview((BibtexEntry) table.getSelected().get(0), true);
+            }
+        }
+    }
+}
diff --git a/src/java/net/sf/jabref/gui/components/JPanelXBox.java b/src/java/net/sf/jabref/gui/components/JPanelXBox.java
new file mode 100644
index 0000000..b63ea02
--- /dev/null
+++ b/src/java/net/sf/jabref/gui/components/JPanelXBox.java
@@ -0,0 +1,21 @@
+package net.sf.jabref.gui.components;
+
+import java.awt.Component;
+import javax.swing.BoxLayout;
+import javax.swing.JPanel;
+
+/**
+ * A JPanel that by default uses a BoxLayout.X_AXIS
+ */
+public class JPanelXBox extends JPanel {
+	/** Create the panel and set BoxLayout.X_AXIS */
+	public JPanelXBox() {
+		super();
+		setLayout(new BoxLayout(this,BoxLayout.X_AXIS));
+	}
+	public JPanelXBox(Component comp) {
+		this();
+		add(comp);
+	}
+}
+
diff --git a/src/java/net/sf/jabref/gui/components/JPanelXBoxLeftJustify.java b/src/java/net/sf/jabref/gui/components/JPanelXBoxLeftJustify.java
new file mode 100644
index 0000000..d161f79
--- /dev/null
+++ b/src/java/net/sf/jabref/gui/components/JPanelXBoxLeftJustify.java
@@ -0,0 +1,19 @@
+package net.sf.jabref.gui.components;
+
+import java.awt.Component;
+import javax.swing.JPanel;
+
+public class JPanelXBoxLeftJustify extends JPanelXBox {
+	public JPanelXBoxLeftJustify() {
+		super();
+		add(new JPanel()); // padding
+	}
+	public JPanelXBoxLeftJustify(Component c) {
+		this();
+		add(c);
+	}
+	public Component add(Component c) {
+		return super.add(c,Math.max(0,getComponentCount()-1));
+	}
+}
+
diff --git a/src/java/net/sf/jabref/gui/components/JPanelXBoxPreferredHeight.java b/src/java/net/sf/jabref/gui/components/JPanelXBoxPreferredHeight.java
new file mode 100644
index 0000000..cdf5c7d
--- /dev/null
+++ b/src/java/net/sf/jabref/gui/components/JPanelXBoxPreferredHeight.java
@@ -0,0 +1,18 @@
+package net.sf.jabref.gui.components;
+
+import java.awt.*;
+
+public class JPanelXBoxPreferredHeight extends JPanelXBox {
+	public JPanelXBoxPreferredHeight() {
+		// nothing special
+	}
+	public JPanelXBoxPreferredHeight(Component c) {
+		add(c);
+	}
+	public Dimension getMaximumSize() {
+		Dimension pref = getPreferredSize();
+		pref.width = super.getMaximumSize().width;
+		return pref;				
+	}
+}
+
diff --git a/src/java/net/sf/jabref/gui/components/JPanelXBoxPreferredSize.java b/src/java/net/sf/jabref/gui/components/JPanelXBoxPreferredSize.java
new file mode 100644
index 0000000..0fecca4
--- /dev/null
+++ b/src/java/net/sf/jabref/gui/components/JPanelXBoxPreferredSize.java
@@ -0,0 +1,16 @@
+package net.sf.jabref.gui.components;
+
+import java.awt.*;
+
+public class JPanelXBoxPreferredSize extends JPanelXBox {
+	public JPanelXBoxPreferredSize() {
+		// nothing special
+	}
+	public JPanelXBoxPreferredSize(Component c) {
+		add(c);
+	}
+	public Dimension getMaximumSize() {
+		return getPreferredSize();
+	}
+}
+
diff --git a/src/java/net/sf/jabref/gui/components/JPanelYBox.java b/src/java/net/sf/jabref/gui/components/JPanelYBox.java
new file mode 100644
index 0000000..f25f17c
--- /dev/null
+++ b/src/java/net/sf/jabref/gui/components/JPanelYBox.java
@@ -0,0 +1,14 @@
+package net.sf.jabref.gui.components;
+
+import javax.swing.*;
+
+/**
+ * A JPanel that by default uses a BoxLayout.Y_AXIS
+ */
+public class JPanelYBox extends JPanel {
+	/** Create the panel and set BoxLayout.Y_AXIS */
+	public JPanelYBox() {
+		setLayout(new BoxLayout(this,BoxLayout.Y_AXIS));
+	}
+}
+
diff --git a/src/java/net/sf/jabref/gui/components/JPanelYBoxPreferredHeight.java b/src/java/net/sf/jabref/gui/components/JPanelYBoxPreferredHeight.java
new file mode 100644
index 0000000..d74e5cf
--- /dev/null
+++ b/src/java/net/sf/jabref/gui/components/JPanelYBoxPreferredHeight.java
@@ -0,0 +1,12 @@
+package net.sf.jabref.gui.components;
+
+import java.awt.Dimension;
+
+public class JPanelYBoxPreferredHeight extends JPanelYBox {
+	public Dimension getMaximumSize() {
+		Dimension pref = getPreferredSize();
+		pref.width = super.getMaximumSize().width;
+		return pref;				
+	}
+}
+
diff --git a/src/java/net/sf/jabref/gui/components/JPanelYBoxPreferredSize.java b/src/java/net/sf/jabref/gui/components/JPanelYBoxPreferredSize.java
new file mode 100644
index 0000000..1fb0551
--- /dev/null
+++ b/src/java/net/sf/jabref/gui/components/JPanelYBoxPreferredSize.java
@@ -0,0 +1,16 @@
+package net.sf.jabref.gui.components;
+
+import java.awt.*;
+
+public class JPanelYBoxPreferredSize extends JPanelYBox {
+	public JPanelYBoxPreferredSize() {
+		// nothing special
+	}
+	public JPanelYBoxPreferredSize(Component c) {
+		add(c);
+	}
+	public Dimension getMaximumSize() {
+		return getPreferredSize();
+	}
+}
+
diff --git a/src/java/net/sf/jabref/gui/components/JPanelYBoxPreferredWidth.java b/src/java/net/sf/jabref/gui/components/JPanelYBoxPreferredWidth.java
new file mode 100644
index 0000000..6ef327a
--- /dev/null
+++ b/src/java/net/sf/jabref/gui/components/JPanelYBoxPreferredWidth.java
@@ -0,0 +1,12 @@
+package net.sf.jabref.gui.components;
+
+import java.awt.Dimension;
+
+public class JPanelYBoxPreferredWidth extends JPanelYBox {
+	public Dimension getMaximumSize() {
+		Dimension pref = getPreferredSize();
+		pref.height = super.getMaximumSize().height;
+		return pref;				
+	}
+}
+
diff --git a/src/java/net/sf/jabref/imports/AuthorDialog.java b/src/java/net/sf/jabref/imports/AuthorDialog.java
new file mode 100644
index 0000000..a5cb4ba
--- /dev/null
+++ b/src/java/net/sf/jabref/imports/AuthorDialog.java
@@ -0,0 +1,28 @@
+package net.sf.jabref.imports;
+
+import net.sf.jabref.*;
+import javax.swing.*;
+import java.beans.*;
+
+public class AuthorDialog extends JDialog {
+
+    boolean[] checked;
+    JCheckBox[] checkBox;
+    JOptionPane optionPane;
+    int count, piv = 0;
+
+
+    public AuthorDialog(JFrame frame, MedlineFetcher mf, String ids[]) {
+	super(frame, Globals.lang("Pick titles"),true);
+
+	count = ids.length;
+	checked=new boolean[count];
+    }
+
+    public boolean[] showDialog(){
+	pack();
+	setVisible(true);
+	return checked;
+    }
+
+}
diff --git a/src/java/net/sf/jabref/imports/BibTeXMLHandler.java b/src/java/net/sf/jabref/imports/BibTeXMLHandler.java
new file mode 100644
index 0000000..0250892
--- /dev/null
+++ b/src/java/net/sf/jabref/imports/BibTeXMLHandler.java
@@ -0,0 +1,113 @@
+package net.sf.jabref.imports;
+
+import org.xml.sax.*;
+import org.xml.sax.helpers.*;
+import java.util.*;
+import net.sf.jabref.*;
+/*
+  Copyright (C) 2000-2004 E.L. Willighagen <egonw at sci.kun.nl>
+
+  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
+
+*/
+
+/**
+ * Reader for the BibTeXML format. See
+ * <a href="http://bibtexml.sourceforge.net/">bibtexml.sf.net</a>.
+ *
+ * @author Egon Willighagen
+ */
+public class BibTeXMLHandler extends DefaultHandler {
+
+    private ArrayList bibitems;
+
+    private BibtexEntry b; // the entry being read
+
+    // XML parsing stuff
+    private String name; // the current element name
+    private String currentChars;
+
+    public BibTeXMLHandler() {
+        super();
+    }
+
+    public ArrayList getItems(){ return bibitems;}
+
+    // SAX parsing methods
+
+    public void doctypeDecl(String name, String publicId,
+        String systemId) {}
+
+    public void startDocument() {
+        bibitems = new ArrayList();
+    }
+
+    public void endDocument() {
+    }
+
+    public void characters(char ch[], int start, int length) {
+        String s = new String(ch, start, length).trim();
+        currentChars += s;
+    }
+
+    public void startElement(String uri, String local, String raw, Attributes atts) {
+        String name = raw;
+        this.name = name;
+        if (name.equals("bibtex:entry")) {
+            String articleID = null;
+            for (int i = 0; i < atts.getLength(); i++) {
+                if (atts.getQName(i).equals("bibtex:id") ||
+                    atts.getQName(i).equals("id")) {
+                    articleID = atts.getValue(i);
+                }
+            }
+            b = new BibtexEntry(Util.createNeutralId());
+	    b.setField(Globals.KEY_FIELD, articleID);
+        } else if (
+            name.equals("bibtex:article") ||
+            name.equals("bibtex:inbook") ||
+            name.equals("bibtex:book") ||
+            name.equals("bibtex:booklet") ||
+            name.equals("bibtex:incollection") ||
+            name.equals("bibtex:inproceedings") ||
+            name.equals("bibtex:proceedings") ||
+            name.equals("bibtex:manual") ||
+            name.equals("bibtex:mastersthesis") ||
+            name.equals("bibtex:phdthesis") ||
+            name.equals("bibtex:techreport") ||
+            name.equals("bibtex:unpublished") ||
+            name.equals("bibtex:misc") ||
+            name.equals("bibtex:other")) {
+            BibtexEntryType tp = BibtexEntryType.getType(local);
+            b.setType(tp);
+        }
+        currentChars = "";
+    }
+
+    public void endElement(String uri, String local, String raw) {
+        String name = raw;
+        if (name.equals("bibtex:entry")) {
+            bibitems.add( b  );
+        } else if (name.startsWith("bibtex:")) {
+            b.setField(local, currentChars);
+            // Util.pr(local+ " "+currentChars);
+        }
+        currentChars = "";
+    }
+
+}
+
+
diff --git a/src/java/net/sf/jabref/imports/BiblioscapeImporter.java b/src/java/net/sf/jabref/imports/BiblioscapeImporter.java
new file mode 100644
index 0000000..2729fb2
--- /dev/null
+++ b/src/java/net/sf/jabref/imports/BiblioscapeImporter.java
@@ -0,0 +1,266 @@
+package net.sf.jabref.imports;
+
+import java.io.InputStream;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.util.List;
+import java.util.Vector;
+import java.util.Map;
+import java.util.ArrayList;
+import java.util.HashMap;
+import net.sf.jabref.BibtexEntry;
+import net.sf.jabref.Globals;
+
+/**
+ * Imports a Biblioscape Tag File. The format is described on
+ * http://www.biblioscape.com/manual_bsp/Biblioscape_Tag_File.htm Several
+ * Biblioscape field types are ignored. Others are only included in the BibTeX
+ * field "comment".
+ */
+public class BiblioscapeImporter extends ImportFormat {
+
+    /**
+     * Return the name of this import format.
+     */
+    public String getFormatName() {
+	return "Biblioscape";
+    }
+
+    /*
+     *  (non-Javadoc)
+     * @see net.sf.jabref.imports.ImportFormat#getCLIId()
+     */
+    public String getCLIId() {
+      return "biblioscape";
+    }
+    
+    /**
+     * Check whether the source is in the correct format for this importer.
+     */
+    public boolean isRecognizedFormat(InputStream in) throws IOException {
+	return true;
+    }
+
+    /**
+     * Parse the entries in the source, and return a List of BibtexEntry
+     * objects.
+     */
+    public List importEntries(InputStream stream) throws IOException {
+
+	ArrayList bibItems = new ArrayList();
+	BufferedReader in = new BufferedReader(ImportFormatReader.getReaderDefaultEncoding(stream));
+	String line;
+	HashMap hm = new HashMap();
+	HashMap lines = new HashMap();
+	StringBuffer previousLine = null;
+	while ((line = in.readLine()) != null){
+	    if (line.length() == 0) continue; // ignore empty lines, e.g. at file
+                                          // end
+        // entry delimiter -> item complete
+        if (line.equals("------")){
+          String[] type = new String[2];
+          String[] pages = new String[2];
+          String country = null;
+          String address = null;
+          String titleST = null;
+          String titleTI = null;
+          Vector comments = new Vector();
+          // add item
+          Object[] l = lines.entrySet().toArray();
+          for (int i = 0; i < l.length; ++i){
+            Map.Entry entry = (Map.Entry) l[i];
+            if (entry.getKey().equals("AU")) hm.put("author", entry.getValue()
+                .toString());
+            else if (entry.getKey().equals("TI")) titleTI = entry.getValue()
+                .toString();
+            else if (entry.getKey().equals("ST")) titleST = entry.getValue()
+                .toString();
+            else if (entry.getKey().equals("YP")) hm.put("year", entry
+                .getValue().toString());
+            else if (entry.getKey().equals("VL")) hm.put("volume", entry
+                .getValue().toString());
+            else if (entry.getKey().equals("NB")) hm.put("number", entry
+                .getValue().toString());
+            else if (entry.getKey().equals("PS")) pages[0] = entry.getValue()
+                .toString();
+            else if (entry.getKey().equals("PE")) pages[1] = entry.getValue()
+                .toString();
+            else if (entry.getKey().equals("KW")) hm.put("keywords", entry
+                .getValue().toString());
+            //else if (entry.getKey().equals("RM"))
+            // hm.put("",entry.getValue().toString());
+            //else if (entry.getKey().equals("RU"))
+            // hm.put("",entry.getValue().toString());
+            else if (entry.getKey().equals("RT")) type[0] = entry.getValue()
+                .toString();
+            else if (entry.getKey().equals("SB")) comments.add("Subject: "
+                + entry.getValue().toString());
+            else if (entry.getKey().equals("SA")) comments
+                .add("Secondary Authors: " + entry.getValue().toString());
+            else if (entry.getKey().equals("NT")) hm.put("note", entry
+                .getValue().toString());
+            //else if (entry.getKey().equals("PP"))
+            // hm.put("",entry.getValue().toString());
+            else if (entry.getKey().equals("PB")) hm.put("publisher", entry
+                .getValue().toString());
+            else if (entry.getKey().equals("TA")) comments
+                .add("Tertiary Authors: " + entry.getValue().toString());
+            else if (entry.getKey().equals("TT")) comments
+                .add("Tertiary Title: " + entry.getValue().toString());
+            else if (entry.getKey().equals("ED")) hm.put("edition", entry
+                .getValue().toString());
+            //else if (entry.getKey().equals("DP"))
+            // hm.put("",entry.getValue().toString());
+            else if (entry.getKey().equals("TW")) type[1] = entry.getValue()
+                .toString();
+            else if (entry.getKey().equals("QA")) comments
+                .add("Quaternary Authors: " + entry.getValue().toString());
+            else if (entry.getKey().equals("QT")) comments
+                .add("Quaternary Title: " + entry.getValue().toString());
+            else if (entry.getKey().equals("IS")) hm.put("isbn", entry
+                .getValue().toString());
+            //else if (entry.getKey().equals("LA"))
+            // hm.put("",entry.getValue().toString());
+            else if (entry.getKey().equals("AB")) hm.put("abstract", entry
+                .getValue().toString());
+            //else if (entry.getKey().equals("DI"))
+            // hm.put("",entry.getValue().toString());
+            //else if (entry.getKey().equals("DM"))
+            // hm.put("",entry.getValue().toString());
+            //else if (entry.getKey().equals("AV"))
+            // hm.put("",entry.getValue().toString());
+            //else if (entry.getKey().equals("PR"))
+            // hm.put("",entry.getValue().toString());
+            //else if (entry.getKey().equals("LO"))
+            // hm.put("",entry.getValue().toString());
+            else if (entry.getKey().equals("AD")) address = entry.getValue()
+                .toString();
+            else if (entry.getKey().equals("LG")) hm.put("language", entry
+                .getValue().toString());
+            else if (entry.getKey().equals("CO")) country = entry.getValue()
+                .toString();
+            else if (entry.getKey().equals("UR") || entry.getKey().equals("AT")){
+              String s = entry.getValue().toString().trim();
+              hm.put(s.startsWith("http://") || s.startsWith("ftp://") ? "url"
+                  : "pdf", entry.getValue().toString());
+            }else if (entry.getKey().equals("C1")) comments.add("Custom1: "
+                + entry.getValue().toString());
+            else if (entry.getKey().equals("C2")) comments.add("Custom2: "
+                + entry.getValue().toString());
+            else if (entry.getKey().equals("C3")) comments.add("Custom3: "
+                + entry.getValue().toString());
+            else if (entry.getKey().equals("C4")) comments.add("Custom4: "
+                + entry.getValue().toString());
+            //else if (entry.getKey().equals("RD"))
+            // hm.put("",entry.getValue().toString());
+            //else if (entry.getKey().equals("MB"))
+            // hm.put("",entry.getValue().toString());
+            else if (entry.getKey().equals("C5")) comments.add("Custom5: "
+                + entry.getValue().toString());
+            else if (entry.getKey().equals("C6")) comments.add("Custom6: "
+                + entry.getValue().toString());
+            //else if (entry.getKey().equals("FA"))
+            // hm.put("",entry.getValue().toString());
+            //else if (entry.getKey().equals("CN"))
+            // hm.put("",entry.getValue().toString());
+            else if (entry.getKey().equals("DE")) hm.put("annote", entry
+                .getValue().toString());
+            //else if (entry.getKey().equals("RP"))
+            // hm.put("",entry.getValue().toString());
+            //else if (entry.getKey().equals("DF"))
+            // hm.put("",entry.getValue().toString());
+            //else if (entry.getKey().equals("RS"))
+            // hm.put("",entry.getValue().toString());
+            else if (entry.getKey().equals("CA")) comments.add("Categories: "
+                + entry.getValue().toString());
+            //else if (entry.getKey().equals("WP"))
+            // hm.put("",entry.getValue().toString());
+            else if (entry.getKey().equals("TH")) comments.add("Short Title: "
+                + entry.getValue().toString());
+            //else if (entry.getKey().equals("WR"))
+            // hm.put("",entry.getValue().toString());
+            //else if (entry.getKey().equals("EW"))
+            // hm.put("",entry.getValue().toString());
+            else if (entry.getKey().equals("SE")) hm.put("chapter", entry
+                .getValue().toString());
+            //else if (entry.getKey().equals("AC"))
+            // hm.put("",entry.getValue().toString());
+            //else if (entry.getKey().equals("LP"))
+            // hm.put("",entry.getValue().toString());
+          }
+
+          String bibtexType = "misc";
+          // to find type, first check TW, then RT
+          for (int i = 1; i >= 0 && bibtexType.equals("misc"); --i){
+            if (type[i] == null) continue;
+            type[i] = type[i].toLowerCase();
+            if (type[i].indexOf("article") >= 0) bibtexType = "article";
+            else if (type[i].indexOf("journal") >= 0) bibtexType = "article";
+            else if (type[i].indexOf("book section") >= 0) bibtexType = "inbook";
+            else if (type[i].indexOf("book") >= 0) bibtexType = "book";
+            else if (type[i].indexOf("conference") >= 0) bibtexType = "inproceedings";
+            else if (type[i].indexOf("proceedings") >= 0) bibtexType = "inproceedings";
+            else if (type[i].indexOf("report") >= 0) bibtexType = "techreport";
+            else if (type[i].indexOf("thesis") >= 0
+                && type[i].indexOf("master") >= 0) bibtexType = "mastersthesis";
+            else if (type[i].indexOf("thesis") >= 0) bibtexType = "phdthesis";
+          }
+
+          // depending on bibtexType, decide where to place the titleRT and
+          // titleTI
+          if (bibtexType.equals("article")){
+            if (titleST != null) hm.put("journal", titleST);
+            if (titleTI != null) hm.put("title", titleTI);
+          }else if (bibtexType.equals("inbook")){
+            if (titleST != null) hm.put("booktitle", titleST);
+            if (titleTI != null) hm.put("title", titleTI);
+          }else{
+            if (titleST != null) hm.put("booktitle", titleST); // should not
+                                                               // happen, I
+                                                               // think
+            if (titleTI != null) hm.put("title", titleTI);
+          }
+
+          // concatenate pages
+          if (pages[0] != null || pages[1] != null) hm.put("pages",
+              (pages[0] != null ? pages[0] : "")
+                  + (pages[1] != null ? "--" + pages[1] : ""));
+
+          // concatenate address and country
+          if (address != null) hm.put("address", address
+              + (country != null ? ", " + country : ""));
+
+          if (comments.size() > 0){ // set comment if present
+            StringBuffer s = new StringBuffer();
+            for (int i = 0; i < comments.size(); ++i)
+                s.append(i > 0 ? "; " : "").append(comments.elementAt(i).toString());
+            hm.put("comment", s.toString());
+          }
+          BibtexEntry b = new BibtexEntry(Globals.DEFAULT_BIBTEXENTRY_ID,
+              Globals.getEntryType(bibtexType));
+          b.setField(hm);
+          bibItems.add(b);
+
+          hm.clear();
+          lines.clear();
+          previousLine = null;
+
+          continue;
+        }
+        // new key
+        if (line.startsWith("--") && line.length() >= 7
+            && line.substring(4, 7).equals("-- ")){
+          lines.put(line.substring(2, 4), previousLine = new StringBuffer(line
+              .substring(7)));
+          continue;
+        }
+        // continuation (folding) of previous line
+        if (previousLine == null) // sanity check; should never happen
+        return null;
+        previousLine.append(line.trim());
+      }
+	
+	return bibItems;
+    }
+    
+}
diff --git a/src/java/net/sf/jabref/imports/BibteXMLImporter.java b/src/java/net/sf/jabref/imports/BibteXMLImporter.java
new file mode 100644
index 0000000..e3fdc15
--- /dev/null
+++ b/src/java/net/sf/jabref/imports/BibteXMLImporter.java
@@ -0,0 +1,89 @@
+package net.sf.jabref.imports;
+
+import java.util.regex.Pattern;
+import java.io.BufferedReader;
+import java.io.InputStream;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+import java.io.IOException;
+import java.util.List;
+import java.util.ArrayList;
+
+/**
+ * Importer for the Refer/Endnote format.
+ *
+ * check here for details on the format
+ * http://www.ecst.csuchico.edu/~jacobsd/bib/formats/endnote.html
+ */
+public class BibteXMLImporter extends ImportFormat {
+
+    /**
+     * Return the name of this import format.
+     */
+    public String getFormatName() {
+	return "BibTeXML";
+    }
+
+    /*
+     *  (non-Javadoc)
+     * @see net.sf.jabref.imports.ImportFormat#getCLIId()
+     */
+    public String getCLIId() {
+      return "bibtexml";
+    }
+    
+
+    /**
+     * 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 "<bibtex:file *" line.
+	BufferedReader in = new BufferedReader(ImportFormatReader.getReaderDefaultEncoding(stream));
+	Pattern pat1 = Pattern
+	    .compile("<bibtex:file .*");
+	String str;
+	while ((str = in.readLine()) != null){
+	    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();
+
+	// Obtain a factory object for creating SAX parsers
+	SAXParserFactory parserFactory = SAXParserFactory.newInstance();
+	// Configure the factory object to specify attributes of the parsers it
+	// creates
+	// parserFactory.setValidating(true);
+	parserFactory.setNamespaceAware(true);	
+	// Now create a SAXParser object
+
+
+	try{
+	    SAXParser parser = parserFactory.newSAXParser(); //May throw exceptions
+	    BibTeXMLHandler handler = new BibTeXMLHandler();
+	    // Start the parser. It reads the file and calls methods of the handler.
+	    parser.parse(stream, handler);
+	    // When you're done, report the results stored by your handler object
+	    bibItems = handler.getItems();
+	    
+	}catch (javax.xml.parsers.ParserConfigurationException e1){
+	    e1.printStackTrace();
+	}catch (org.xml.sax.SAXException e2){
+	    e2.printStackTrace();
+	}catch (java.io.IOException e3){
+	    e3.printStackTrace();
+	}
+	return bibItems;
+	
+    }
+    
+}
diff --git a/src/java/net/sf/jabref/imports/BibtexParser.java b/src/java/net/sf/jabref/imports/BibtexParser.java
new file mode 100644
index 0000000..3d60af6
--- /dev/null
+++ b/src/java/net/sf/jabref/imports/BibtexParser.java
@@ -0,0 +1,776 @@
+/*
+Copyright (C) 2003 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.
+
+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.imports;
+
+import java.io.*;
+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()
+                              + " (" + "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)
+                                + " (" + "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(GUIGlobals.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 == '"')
+	    {
+		// 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)))
+        {
+
+	    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/BiomailImporter.java b/src/java/net/sf/jabref/imports/BiomailImporter.java
new file mode 100644
index 0000000..8cab79f
--- /dev/null
+++ b/src/java/net/sf/jabref/imports/BiomailImporter.java
@@ -0,0 +1,191 @@
+package net.sf.jabref.imports;
+
+import net.sf.jabref.BibtexEntry;
+import net.sf.jabref.Globals;
+
+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.regex.Pattern;
+
+
+/**
+ * Importer for the ISI Web of Science format.
+ */
+public class BiomailImporter extends ImportFormat {
+    /**
+     * Return the name of this import format.
+     */
+    public String getFormatName() {
+        return "Biomail";
+    }
+
+    /*
+     *  (non-Javadoc)
+     * @see net.sf.jabref.imports.ImportFormat#getCLIId()
+     */
+    public String getCLIId() {
+      return "biomail";
+    }
+    
+    /**
+     * 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 "BioMail" line.
+        BufferedReader in =
+                new BufferedReader(ImportFormatReader.getReaderDefaultEncoding(stream));
+        Pattern pat1 = Pattern.compile("BioMail");
+
+        String str;
+
+        while ((str = in.readLine()) != null) {
+
+            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));
+
+        String str;
+
+        while ((str = in.readLine()) != null) {
+            if (str.length() < 3)
+                continue;
+
+            // begining of a new item
+            if (str.substring(0, 6).equals("PMID- "))
+                sb.append("::").append(str);
+            else {
+                String beg = str.substring(0, 6);
+
+                if (beg.indexOf(" ") > 0) {
+                    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());
+                }
+            }
+        }
+
+        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 = "";
+            String shortauthor = "";
+            String fullauthor = "";
+            hm.clear();
+
+            for (int j = 0; j < fields.length; j++) {
+                System.out.println(">>>"+fields[j]+"<<<");
+
+                //empty field don't do anything
+                if (fields[j].length() <= 2)
+                    continue;
+
+                String beg = fields[j].substring(0, 6);
+                String value = fields[j].substring(6);
+                value = value.trim();
+
+                if (beg.equals("PT  - ")) {
+                    PT = value.replaceAll("JOURNAL ARTICLE", "article").replaceAll("Journal Article", "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("FAU - ")) {
+                    String tmpauthor = value.replaceAll("EOLEOL", " and ");
+
+                    // if there is already someone there then append with "and"
+                    if (!"".equals(fullauthor))
+                        fullauthor = fullauthor + " and " + tmpauthor;
+                    else
+                        fullauthor = tmpauthor;
+                } else if (beg.equals("AU  - ")) {
+                    String tmpauthor = value.replaceAll("EOLEOL", " and ").replaceAll(" ", ", ");
+
+                    // if there is already someone there then append with "and"
+                    if (!"".equals(shortauthor))
+                        shortauthor = shortauthor + " and " + tmpauthor;
+                    else
+                        shortauthor = tmpauthor;
+                } else if (beg.equals("TI  - "))
+                    hm.put("title", value.replaceAll("EOLEOL", " "));
+                else if (beg.equals("TA  - "))
+                    hm.put("journal", value.replaceAll("EOLEOL", " "));
+                else if (beg.equals("AB  - "))
+                    hm.put("abstract", value.replaceAll("EOLEOL", " "));
+                else if (beg.equals("PG  - "))
+                    pages = value.replaceAll("-", "--");
+                else if (beg.equals("IP  - "))
+                    hm.put("number", value);
+                else if (beg.equals("DP  - ")) {
+                    String[] parts = value.split(" "); // sometimes this is just year, sometimes full date
+                    hm.put("year", parts[0]);
+                } else if (beg.equals("VI  - "))
+                    hm.put("volume", value);
+                else if (beg.equals("AID - ")) {
+                    String[] parts = value.split(" ");
+                    if ("[doi]".equals(parts[1])) {
+                        hm.put("doi", parts[0]);
+                        hm.put("url", "http://dx.doi.org/" + parts[0]);
+                    }
+                }
+            }
+
+            if (!"".equals(pages))
+                hm.put("pages", pages);
+            if (!"".equals(fullauthor))
+                hm.put("author", fullauthor);
+            else if (!"".equals(shortauthor))
+                hm.put("author", shortauthor);
+
+            BibtexEntry b =
+                    new BibtexEntry(Globals.DEFAULT_BIBTEXENTRY_ID, Globals.getEntryType(Type)); // id assumes an existing database so don't
+
+            // create one here
+            b.setField(hm);
+
+            // the first bibitem is always empty, presumably as a result of trying
+            // to parse header informaion. So add only if we have at least author or
+            // title fields.
+            if (hm.get("author") != null || hm.get("title") != null)
+                bibitems.add(b);
+        }
+
+        return bibitems;
+    }
+
+
+}
diff --git a/src/java/net/sf/jabref/imports/BooleanAssign.java b/src/java/net/sf/jabref/imports/BooleanAssign.java
new file mode 100644
index 0000000..fd24d16
--- /dev/null
+++ b/src/java/net/sf/jabref/imports/BooleanAssign.java
@@ -0,0 +1,31 @@
+/*
+ * Package package net.sf.jabref.imports;
+ * Created on Jul 12, 2004
+ * Author mspiegel
+ *
+ */
+package net.sf.jabref.imports;
+
+/**
+ * @author mspiegel
+ *
+ */
+public class BooleanAssign {
+    
+    boolean value;
+    
+    /**
+	 * @param b
+	 */
+	public BooleanAssign(boolean b) {
+		setValue(b);		
+	}
+
+	public void setValue(boolean value) {
+        this.value = value;
+    }
+    
+    public boolean getValue() {
+        return(value);
+    }
+}
diff --git a/src/java/net/sf/jabref/imports/CiteSeerCitationHandler.java b/src/java/net/sf/jabref/imports/CiteSeerCitationHandler.java
new file mode 100644
index 0000000..3507e6b
--- /dev/null
+++ b/src/java/net/sf/jabref/imports/CiteSeerCitationHandler.java
@@ -0,0 +1,69 @@
+package net.sf.jabref.imports;
+
+
+
+import java.util.Hashtable;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+/*
+ * Created on Jun 13, 2004
+ *
+ * To change the template for this generated file go to
+ * Window>Preferences>Java>Code Generation>Code and Comments
+ */
+
+/**
+ * @author mspiegel
+ *
+ * To change the template for this generated type comment go to
+ * Window>Preferences>Java>Code Generation>Code and Comments
+ */
+public class CiteSeerCitationHandler extends DefaultHandler {
+
+	protected boolean correctDirection;
+	protected boolean getCitation;
+	protected Hashtable citationList;
+
+	/**
+	 * @param identifierVector
+	 */
+	public CiteSeerCitationHandler(Hashtable citationHashTable) {
+		citationList = citationHashTable;		
+	}
+
+	public void characters(char[] ch, int start, int length) {
+		if (getCitation == true) {
+			String target = new String(ch, start, length);
+			if (citationList.get(target) == null) {
+				citationList.put(target, Boolean.TRUE);
+			}
+			getCitation = false;
+		}
+	}
+	
+	public void startDocument() throws SAXException {
+		correctDirection = false;
+		getCitation = false;
+	}
+
+
+	public void startElement(String name, String localName, String qName, Attributes attrs)
+			throws SAXException {
+		if (qName.equals("oai_citeseer:relation")) {
+			for (int i = 0; i < attrs.getLength(); i++) {
+			   String attrName = attrs.getQName(i);
+			   String attrValue = attrs.getValue(i);	   
+			   if (attrName.equals("type") && attrValue.equals("Is Referenced By")) {
+			   		correctDirection = true;
+			   } else if (attrName.equals("type") && attrValue.equals("References")) {
+			   		correctDirection = false;
+			   }
+			 }
+		} else if (qName.equals("oai_citeseer:uri") && correctDirection) {
+			getCitation = true;
+		}
+	}
+}
\ No newline at end of file
diff --git a/src/java/net/sf/jabref/imports/CiteSeerFetcher.java b/src/java/net/sf/jabref/imports/CiteSeerFetcher.java
new file mode 100644
index 0000000..da20310
--- /dev/null
+++ b/src/java/net/sf/jabref/imports/CiteSeerFetcher.java
@@ -0,0 +1,604 @@
+/*
+ * Created on Jun 13, 2004
+ *
+ * To change the template for this generated file go to
+ * Window>Preferences>Java>Code Generation>Code and Comments
+ */
+package net.sf.jabref.imports;
+
+import java.awt.BorderLayout;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.TreeSet;
+import java.util.Vector;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import javax.swing.BorderFactory;
+import javax.swing.JPanel;
+import javax.swing.JLabel;
+import javax.swing.JOptionPane;
+import javax.swing.JProgressBar;
+import javax.swing.SwingUtilities;
+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.undo.NamedCompound;
+
+/**
+ * @author mspiegel
+ *
+ * To change the template for this generated type comment go to
+ * Window>Preferences>Java>Code Generation>Code and Comments
+ */
+public class CiteSeerFetcher extends SidePaneComponent {
+
+    final static String CITESEER_HOST = "citeseer.ist.psu.edu";
+	final static String PREFIX_URL = "http://" + CITESEER_HOST + "/";
+	final static String PREFIX_IDENTIFIER = "oai:CiteSeerPSU:";
+	final static String OAI_HOST = "http://cs1.ist.psu.edu/";
+	final static String OAI_URL = OAI_HOST + "cgi-bin/oai.cgi?";
+	final static String OAI_ACTION = "verb=GetRecord";
+	final static String OAI_METADATAPREFIX ="metadataPrefix=oai_citeseer";
+	protected SAXParserFactory parserFactory;
+	protected SAXParser saxParser;
+	
+	boolean citationFetcherActive;
+	boolean importFetcherActive;
+
+	JProgressBar progressBar, progressBar2;
+	JLabel citeSeerProgress;
+	GridBagLayout gbl = new GridBagLayout();
+	GridBagConstraints con = new GridBagConstraints();
+	SidePaneManager sidePaneManager;
+
+
+	public CiteSeerFetcher(SidePaneManager p0)  {
+		super(p0, GUIGlobals.wwwCiteSeerIcon, Globals.lang("CiteSeer Transfer"));
+
+		sidePaneManager = p0;
+		progressBar = new JProgressBar();
+		progressBar2 = new JProgressBar();
+		citeSeerProgress = new JLabel();
+		progressBar.setValue(0);
+		progressBar.setMinimum(0);
+		progressBar.setMaximum(100);
+		progressBar.setStringPainted(true);
+		progressBar2.setValue(0);
+		progressBar2.setMinimum(0);
+		progressBar2.setMaximum(100);
+		progressBar2.setStringPainted(true);
+                JPanel main = new JPanel();
+		main.setLayout(gbl);
+		//SidePaneHeader header = new SidePaneHeader
+		//	("CiteSeer Transfer", GUIGlobals.wwwCiteSeerIcon, this);
+		con.gridwidth = GridBagConstraints.REMAINDER;			
+		con.fill = GridBagConstraints.BOTH;
+		con.weightx = 1;
+		con.insets = new Insets(0, 0, 2,  0);
+		//gbl.setConstraints(header, con);
+		//add(header);
+		con.insets = new Insets(0, 0, 0,  0);
+		con.fill = GridBagConstraints.HORIZONTAL;		
+		gbl.setConstraints(progressBar, con);
+		main.add(progressBar);		
+		gbl.setConstraints(progressBar2, con);
+		main.add(progressBar2);
+		gbl.setConstraints(citeSeerProgress, con);
+		main.add(citeSeerProgress);		
+                main.setBorder(BorderFactory.createEmptyBorder(1,1,1,1));
+                add(main, BorderLayout.CENTER);
+		try {
+			citationFetcherActive = false;
+			importFetcherActive = false;
+			parserFactory = SAXParserFactory.newInstance();
+			saxParser = parserFactory.newSAXParser();
+
+		} catch (ParserConfigurationException e) {
+			e.printStackTrace();
+		} catch (SAXException e) {
+			e.printStackTrace();
+		}
+	}
+
+	/***********************************/
+	/* Begin Inner Class Declarations */
+	/* The inner classes are used to modify components, when not in the
+	 * event-dispatching thread.  These are used to follow the "single-threaded
+	 * rule", as defined here: http://java.sun.com/products/jfc/tsc/articles/threads/threads1.html
+	 *
+	 *
+	 * I'm pretty sure the Dialog box invokers should remain as inner classes,
+	 * but I can't decide whether or not to break the one-thread rule for the
+	 * progress bar classes.  Because the search contains a locking-mechanism,
+	 * activateFetcher() and deactivateFetcher(), there should only be at-most-one
+	 * thread accessing the progress bar at any time.
+	 */
+
+	class ShowEmptyFetchSetDialog implements Runnable {
+	
+		public void run() {
+			JOptionPane.showMessageDialog(panel.frame(),
+				Globals.lang("The CiteSeer fetch operation returned zero results" 
+						+ "."),
+				"CiteSeer",
+				JOptionPane.INFORMATION_MESSAGE);
+			deactivateCitationFetcher();
+		}		
+	}
+
+	public ShowEmptyFetchSetDialog getEmptyFetchSetDialog() {
+		return(new ShowEmptyFetchSetDialog());
+	}
+	
+	class ShowNoConnectionDialog implements Runnable {
+		protected String targetURL = "";
+		ShowNoConnectionDialog(String URL) {
+				targetURL = URL;
+		}
+		public void run() {
+				JOptionPane.showMessageDialog(panel.frame(),
+				Globals.lang("Could not connect to host") + " " + targetURL + ".  " +
+				Globals.lang("Please check your network connection to this machine" + "."),
+				Globals.lang("CiteSeer Error"),
+				JOptionPane.ERROR_MESSAGE);
+		}
+	}
+
+	class ShowBadIdentifiersDialog implements Runnable {
+
+	    Hashtable rejectedEntries;
+	    
+	    ShowBadIdentifiersDialog(Hashtable entries) {
+	        rejectedEntries = entries;
+	    }
+	    
+        /* (non-Javadoc)
+         * @see java.lang.Runnable#run()
+         */
+        public void run() {
+            if (rejectedEntries.size() == 1) {
+                
+            } else if (rejectedEntries.size() > 1) {
+            	int i;
+                String rowNumbers = "";
+                String oneRowOfNumbers = "";
+                TreeSet rowSet = new TreeSet(rejectedEntries.keySet());
+                int rowSize = rowSet.size();
+                for(i=0; (i < rowSize - 1) && (i < 100); i++) {
+                    Integer next = (Integer) rowSet.first();
+                    if (oneRowOfNumbers.equals(""))
+                        oneRowOfNumbers = next.toString();
+                    else {
+                        oneRowOfNumbers = oneRowOfNumbers + ", ";
+                        if (oneRowOfNumbers.length() > 50) {
+                        	oneRowOfNumbers = oneRowOfNumbers + "\n";
+                        	rowNumbers = rowNumbers + oneRowOfNumbers;
+                        	oneRowOfNumbers = "";
+                        }
+                        oneRowOfNumbers = oneRowOfNumbers + next.toString();
+                    }
+                    rowSet.remove(next);
+                }
+            	rowNumbers = rowNumbers + oneRowOfNumbers;
+            	if (i == 100) {
+            		rowNumbers = rowNumbers + "..";
+            	} else {
+            		rowNumbers = rowNumbers + " "+Globals.lang("and")+" " + ((Integer)rowSet.first()).toString();
+            	}
+                JOptionPane.showMessageDialog(panel.frame(),
+                        Globals.lang("Couldn't parse the 'citeseerurl' field of the following entries") + ':' + '\n' + 
+                        rowNumbers + ".\n" + 
+                        Globals.lang("Please refer to the JabRef help manual on using the CiteSeer tools" + '.'),
+                        Globals.lang("Warning"),
+                        JOptionPane.WARNING_MESSAGE);
+            }
+        }
+	}	
+	
+	class ShowBadIdentifierDialog implements Runnable {
+		protected String badURL = "";
+		protected int rowNumber;
+
+		ShowBadIdentifierDialog(String URL, int row) {
+			badURL = URL;
+			rowNumber = row;
+		}
+		public void run() {
+			JOptionPane.showMessageDialog(panel.frame(),
+			Globals.lang("Couldn't find an entry associated with this URL") + ": \"" + badURL + '\"' +
+			Globals.lang(" on entry number ") + (rowNumber + 1) + ".  " +
+			Globals.lang("Please refer to the JabRef help manual on using the CiteSeer tools."),
+			Globals.lang("CiteSeer Error"),
+			JOptionPane.ERROR_MESSAGE);
+		}
+	}
+	
+	class ShowBadURLDialog implements Runnable {
+		protected String badURL = "";
+		protected int rowNumber;
+
+		ShowBadURLDialog(String URL, int row) {
+			badURL = URL;
+			rowNumber = row;
+		}
+		public void run() {
+			JOptionPane.showMessageDialog(panel.frame(),
+			Globals.lang("Unable to parse the following URL") + ": \"" + badURL + '\"' +
+			Globals.lang(" on entry number ") + (rowNumber + 1) + ".  " +
+			Globals.lang("Please refer to the JabRef help manual on using the CiteSeer tools."),
+			Globals.lang("CiteSeer Error"),
+			JOptionPane.ERROR_MESSAGE);
+		}
+	}
+
+	class ShowMissingURLDialog implements Runnable {
+		protected int rowNumber;
+
+		ShowMissingURLDialog(int row) {
+			rowNumber = row;
+		}
+		public void run() {
+			JOptionPane.showMessageDialog(panel.frame(),
+			Globals.lang("The URL field appears to be empty on entry number ") + (rowNumber + 1) + ".  " +
+			Globals.lang("Please refer to the JabRef help manual on using the CiteSeer tools."),
+			Globals.lang("CiteSeer Error"),
+			JOptionPane.ERROR_MESSAGE);
+		}
+	}
+	
+	class UpdateProgressBarMaximum implements Runnable {
+		protected int maximum;
+		UpdateProgressBarMaximum(int newValue) {
+			maximum = newValue;
+		}
+		public void run() {
+			progressBar.setMaximum(maximum);
+		}
+	}
+
+	class UpdateProgressBarTwoMaximum implements Runnable {
+		protected int maximum;
+		UpdateProgressBarTwoMaximum(int newValue) {
+			maximum = newValue;
+		}
+		public void run() {
+			progressBar2.setMaximum(maximum);
+		}
+	}
+
+	class InitializeProgressBar implements Runnable {
+	    public void run() {
+			progressBar.setValue(0);
+	        progressBar.setMinimum(0);
+			progressBar.setMaximum(100);
+		    progressBar.setString(null);
+	    }
+	}
+
+	class InitializeProgressBarTwo implements Runnable {
+
+		public void run() {
+			progressBar2.setValue(0);
+	        progressBar2.setMinimum(0);
+			progressBar2.setMaximum(100);
+		    progressBar2.setString(null);
+	    }
+	}
+		
+	class UpdateProgressBarValue implements Runnable {
+		protected int counter;
+		UpdateProgressBarValue(int newValue) {
+			counter = newValue;
+		}
+		public void run() {
+			progressBar.setValue(counter);
+		}
+	}
+
+	class UpdateProgressBarTwoValue implements Runnable {
+		protected int counter;
+		UpdateProgressBarTwoValue(int newValue) {
+			counter = newValue;
+		}
+		public void run() {
+			progressBar2.setValue(counter);
+		}		
+	}
+
+	class UpdateProgressStatus implements Runnable {
+		protected String status;
+		UpdateProgressStatus(String newStatus) {
+			status = newStatus;
+		}
+		public void run() {
+			citeSeerProgress.setText(status);
+		}
+	}
+	
+	/* End Inner Class Declarations */
+
+
+	/***********************************/
+
+	synchronized public boolean activateCitationFetcher() {
+		if (citationFetcherActive == true) {
+			return(false);
+		}	else {
+			citationFetcherActive = true;
+			return(true);
+		}
+	}
+	synchronized public void deactivateCitationFetcher() {
+		citationFetcherActive = false;
+	}
+
+	synchronized public boolean activateImportFetcher() {
+		if (importFetcherActive == true) {
+			return(false);
+		}	else {
+			importFetcherActive = true;
+			return(true);
+		}
+	}
+	synchronized public void deactivateImportFetcher() {
+		importFetcherActive = false;
+	}
+
+	public void beginImportCiteSeerProgress() {
+	    progressBar.setIndeterminate(true);
+	    progressBar.setString("");
+	    progressBar2.setVisible(false);
+	    citeSeerProgress.setText("");
+	    sidePaneManager.ensureVisible("CiteSeerProgress");
+	}
+	public void endImportCiteSeerProgress() {
+	    progressBar.setIndeterminate(false);
+		progressBar.setMinimum(0);
+		progressBar.setMaximum(100);
+		progressBar.setValue(100);
+//	    progressBar.setString(null);
+	}
+
+
+	/**
+	 * @param newDatabase
+	 * @param targetDatabase
+	 */
+	public int populate(BibtexDatabase newDatabase, BibtexDatabase targetDatabase) {
+		int errorCode = 0;
+		Iterator targetIterator = targetDatabase.getKeySet().iterator();
+		boolean abortOperation = false;
+		String currentKey;
+		BibtexEntry currentEntry;
+		Enumeration newEntryEnum;
+		Hashtable citationHashTable = new Hashtable();
+		Hashtable rejectedEntries = new Hashtable();
+		InitializeProgressBar initializeProgressBar = new InitializeProgressBar();
+		InitializeProgressBarTwo initializeProgressBarTwo = new InitializeProgressBarTwo();
+		UpdateProgressBarMaximum updateMaximum = new UpdateProgressBarMaximum(targetDatabase.getEntryCount());		
+	    progressBar2.setVisible(true);		
+		SwingUtilities.invokeLater(initializeProgressBar);
+		SwingUtilities.invokeLater(initializeProgressBarTwo);
+		SwingUtilities.invokeLater(updateMaximum);		
+		int identifierCounter = 0;
+		UpdateProgressStatus progressStatus = new UpdateProgressStatus(Globals.lang("Fetching Identifiers"));
+		SwingUtilities.invokeLater(progressStatus);
+		while (targetIterator.hasNext() && !abortOperation) {
+			currentKey = (String) targetIterator.next();
+			currentEntry = targetDatabase.getEntryById(currentKey);
+			abortOperation = generateIdentifierList(currentEntry, citationHashTable, rejectedEntries);
+			UpdateProgressBarValue updateValue = new UpdateProgressBarValue(++identifierCounter);			
+			SwingUtilities.invokeLater(updateValue);
+		}
+		if (rejectedEntries.size() > 0) {
+			errorCode = -1;
+		    ShowBadIdentifiersDialog badIdentifiersDialog = new ShowBadIdentifiersDialog(rejectedEntries);
+		    SwingUtilities.invokeLater(badIdentifiersDialog);
+		}
+		if (citationHashTable.size() > 0) {
+			UpdateProgressBarTwoMaximum update2Maximum = new UpdateProgressBarTwoMaximum(citationHashTable.size());
+			SwingUtilities.invokeLater(update2Maximum);
+		}
+		progressStatus = new UpdateProgressStatus(Globals.lang("Fetching Citations"));
+		SwingUtilities.invokeLater(progressStatus);		
+		generateCitationList(citationHashTable, newDatabase);
+		newEntryEnum = citationHashTable.elements();
+		progressStatus = new UpdateProgressStatus(Globals.lang("Done"));
+		SwingUtilities.invokeLater(progressStatus);
+		if (abortOperation)
+			errorCode = -2;
+		return(errorCode);
+	}
+
+
+	private Hashtable generateCitationList(Hashtable citationHashTable, BibtexDatabase database)
+	 {
+		try {
+			NamedCompound dummyNamedCompound = new NamedCompound(Globals.lang("Import Data from CiteSeer Database"));
+			BooleanAssign dummyBoolean = new BooleanAssign(false);
+			if ((citationHashTable != null) && (citationHashTable.size() > 0)) {
+			    int citationCounter=0;
+			    for (Enumeration e = citationHashTable.keys() ; e.hasMoreElements() ;) {
+			        String key = (String) e.nextElement();
+					String id = Util.createNeutralId();
+					BibtexEntry newEntry = new BibtexEntry(id);
+					StringBuffer citeseerURLString = new StringBuffer();
+					citeseerURLString.append(OAI_URL);
+					citeseerURLString.append(OAI_ACTION);
+					citeseerURLString.append("&" + OAI_METADATAPREFIX);
+                    citeseerURLString.append("&" + "identifier=").append(key);
+					URL citeseerUrl = new URL( citeseerURLString.toString());
+					HttpURLConnection citeseerConnection = (HttpURLConnection)citeseerUrl.openConnection();				
+					saxParser.parse(citeseerConnection.getInputStream(), new CiteSeerUndoHandler(dummyNamedCompound, newEntry, panel, dummyBoolean));
+					database.insertEntry(newEntry);
+					citationCounter++;
+					UpdateProgressBarTwoValue updateValue = new UpdateProgressBarTwoValue(citationCounter);
+					SwingUtilities.invokeLater(updateValue);
+			    }
+			}
+		} catch (SAXException e) {
+				System.out.println("SAXException: " + e.getLocalizedMessage());
+				e.printStackTrace();
+		} catch (IOException e) {
+				ShowNoConnectionDialog dialog = new ShowNoConnectionDialog(OAI_HOST);
+				SwingUtilities.invokeLater(dialog);
+		} catch (KeyCollisionException e) {
+		    	System.out.println("KeyCollisionException: " + e.getLocalizedMessage());
+                e.printStackTrace();
+        }
+		return citationHashTable;
+	}
+
+	public static String generateCanonicalNumber(BibtexEntry be) {
+	    return(generateCanonicalNumber((String) be.getField("citeseerurl")));
+	}
+	
+    public static String generateCanonicalNumber(String link) {
+        String IDnumber = null;
+	    if (link != null) {
+	        Pattern pattern = Pattern.compile("[0-9]+");
+	        Matcher matcher = pattern.matcher(link);
+	        if (matcher.find()) {
+	            IDnumber = matcher.group();
+	        }
+	    }
+        return IDnumber;
+    }
+	
+	public String generateCanonicalIdentifier(BibtexEntry be) {
+	    String canonID = null;
+	    String IDnumber = generateCanonicalNumber(be);
+	    if (IDnumber != null) {
+	        canonID = PREFIX_IDENTIFIER + IDnumber;
+	    }
+	    return(canonID);
+	}
+	
+	public static String generateCanonicalURL(String link) {
+	    String canonURL = null;
+	    String IDnumber = generateCanonicalNumber(link);
+	    if (IDnumber != null) {
+	        canonURL = PREFIX_URL + IDnumber + ".html";
+	    }
+	    return(canonURL);
+	}	
+
+    public static String generateCanonicalURL(BibtexEntry be) {
+        return(generateCanonicalURL((String) be.getField("citeseerurl")));
+	}
+	
+	private boolean generateIdentifierList(BibtexEntry currentEntry, Hashtable citationHashTable, Hashtable rejectedEntries)
+		{
+                  boolean abortOperation = false;
+                  String identifier = generateCanonicalIdentifier(currentEntry);                  
+                  try {
+                    if (identifier != null) {
+                      StringBuffer citeseerURLString = new StringBuffer();
+                      citeseerURLString.append(OAI_URL);
+                      citeseerURLString.append(OAI_ACTION);
+                      citeseerURLString.append("&" + OAI_METADATAPREFIX);
+                        citeseerURLString.append("&" + "identifier=").append(identifier);
+                      URL citeseerUrl = new URL( citeseerURLString.toString());
+                      HttpURLConnection citeseerConnection = (HttpURLConnection)citeseerUrl.openConnection();				
+                      saxParser.parse(citeseerConnection.getInputStream(), new CiteSeerCitationHandler(citationHashTable));
+                    } else {
+                      int row = panel.mainTable.findEntry(currentEntry);
+                      rejectedEntries.put(new Integer(row+1),currentEntry);                     
+                    }
+		} catch (SAXException e) {
+			System.out.println("SAXException: " + e.getLocalizedMessage());
+			e.printStackTrace();
+		} catch (IOException e) {
+			System.out.println("IOException: " + e.getLocalizedMessage());
+		    ShowNoConnectionDialog dialog = new ShowNoConnectionDialog(OAI_HOST);
+			abortOperation = true;
+			SwingUtilities.invokeLater(dialog);
+		}
+		return(abortOperation);
+	}
+
+	public boolean importCiteSeerEntries(int[] clickedOn, NamedCompound citeseerNamedCompound) {
+	  	boolean newValues = false;
+	  	boolean abortOperation = false;
+	  	Vector clickedVector = new Vector();
+		Hashtable rejectedEntries = new Hashtable();		
+		for(int i=0; i < clickedOn.length; i++)
+			clickedVector.add(new Integer(clickedOn[i]));
+		Iterator clickedIterator = clickedVector.iterator();
+		BooleanAssign overwriteAll = new BooleanAssign(false);
+		BooleanAssign overwriteNone = new BooleanAssign(false);
+
+		while (clickedIterator.hasNext() && !abortOperation) {
+			int currentIndex = ((Integer) clickedIterator.next()).intValue();
+			BooleanAssign newValue = new BooleanAssign(false);
+			BibtexEntry be = panel.mainTable.getEntryAt(currentIndex);
+			abortOperation = importCiteSeerEntry(be, citeseerNamedCompound, overwriteAll, overwriteNone, newValue, rejectedEntries);
+			if (newValue.getValue())
+				newValues = true;
+		}
+		if (rejectedEntries.size() > 0) {
+		    ShowBadIdentifiersDialog badIdentifiersDialog = new ShowBadIdentifiersDialog(rejectedEntries);
+		    SwingUtilities.invokeLater(badIdentifiersDialog);
+		}
+		return newValues;
+	}
+	
+	
+	
+	/**
+	 * @param be
+	 * @param overwriteNone
+	 * @param overwriteAll
+	 * @param rejectedEntries
+	 *
+	 */
+	public boolean importCiteSeerEntry(BibtexEntry be, NamedCompound citeseerNC, BooleanAssign overwriteAll, 
+			BooleanAssign overwriteNone, BooleanAssign newValue, Hashtable rejectedEntries) {
+	    boolean abortOperation = false;
+		SAXParserFactory factory = SAXParserFactory.newInstance();
+    	String identifier = generateCanonicalIdentifier(be);			 
+		try {
+			if (identifier != null) {
+					StringBuffer citeseerURLString = new StringBuffer();
+					citeseerURLString.append(OAI_URL);
+					citeseerURLString.append(OAI_ACTION);
+					citeseerURLString.append("&" + OAI_METADATAPREFIX);
+                citeseerURLString.append("&" + "identifier=").append(identifier);
+                    URL citeseerUrl = new URL( citeseerURLString.toString());
+                    HttpURLConnection citeseerConnection = (HttpURLConnection)citeseerUrl.openConnection();									
+					InputStream inputStream  = citeseerConnection.getInputStream();
+					DefaultHandler handlerBase = new CiteSeerUndoHandler(citeseerNC, be, panel, newValue, overwriteAll, overwriteNone);
+
+					saxParser.parse(inputStream, handlerBase);
+				} else {
+                    int row = panel.mainTable.findEntry(be);
+                    rejectedEntries.put(new Integer(row+1), be);                
+				}
+			} catch (IOException e) {
+					ShowNoConnectionDialog dialog = new ShowNoConnectionDialog(OAI_HOST);
+					SwingUtilities.invokeLater(dialog);
+					abortOperation = true;
+			} catch (SAXException e) {
+				System.out.println("SAXException: " + e.getLocalizedMessage());
+				e.printStackTrace();
+				abortOperation = true;				
+			}
+			return abortOperation;
+		}
+
+
+
+}
diff --git a/src/java/net/sf/jabref/imports/CiteSeerFetcherPanel.java b/src/java/net/sf/jabref/imports/CiteSeerFetcherPanel.java
new file mode 100644
index 0000000..364a2d9
--- /dev/null
+++ b/src/java/net/sf/jabref/imports/CiteSeerFetcherPanel.java
@@ -0,0 +1,199 @@
+package net.sf.jabref.imports;
+
+import java.net.*;
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.ActionListener;
+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 net.sf.jabref.HelpAction;
+import net.sf.jabref.gui.ImportInspectionDialog;
+
+/**
+ * <p>Title: </p>
+ * <p>Description: </p>
+ * <p>Copyright: Copyright (c) 2003</p>
+ * <p>Company: </p>
+ *
+ * @author not attributable
+ * @version 1.0
+ */
+
+public class CiteSeerFetcherPanel extends SidePaneComponent implements ActionListener {
+
+
+    String idList;
+    JTextField tf = new JTextField();
+    JPanel pan = new JPanel();
+    GridBagLayout gbl = new GridBagLayout();
+    GridBagConstraints con = new GridBagConstraints();
+    CiteSeerFetcher citeSeerFetcher;
+    AuthorDialog authorDialog;
+    JFrame jFrame; // invisible dialog holder
+    JButton go = new JButton(Globals.lang("Fetch")),
+    helpBut = new JButton(new ImageIcon(GUIGlobals.helpIconFile));
+    HelpAction help;
+    CiteSeerFetcherPanel ths = this;
+
+    public CiteSeerFetcherPanel(SidePaneManager p0, final CiteSeerFetcher fetcher) {
+        super(p0, GUIGlobals.wwwCiteSeerIcon, Globals.lang("Fetch CiteSeer"));
+
+        help = new HelpAction(Globals.helpDiag, GUIGlobals.citeSeerHelp, "Help");
+
+        this.citeSeerFetcher = fetcher;
+        helpBut.addActionListener(help);
+        helpBut.setMargin(new Insets(0, 0, 0, 0));
+        //tf.setMinimumSize(new Dimension(1,1));
+        //add(hd, BorderLayout.NORTH);
+        //ok.setToolTipText(Globals.lang("Fetch Medline"));
+        JPanel main = new JPanel();
+        main.setLayout(gbl);
+        con.fill = GridBagConstraints.BOTH;
+        con.insets = new Insets(0, 0, 2, 0);
+        con.gridwidth = GridBagConstraints.REMAINDER;
+        con.weightx = 1;
+        con.weighty = 0;
+        //gbl.setConstraints(header, con);
+        //add(header);
+        con.weighty = 1;
+        con.insets = new Insets(0, 0, 0, 0);
+        //    pan.setLayout(gbl);
+        con.fill = GridBagConstraints.BOTH;
+        gbl.setConstraints(tf, con);
+        main.add(tf);
+        con.weighty = 0;
+        con.gridwidth = 1;
+        gbl.setConstraints(go, con);
+        main.add(go);
+        con.gridwidth = GridBagConstraints.REMAINDER;
+        gbl.setConstraints(helpBut, con);
+        main.add(helpBut);
+        main.setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1));
+        add(main, BorderLayout.CENTER);
+        go.addActionListener(this);
+        tf.addActionListener(this);
+    }
+
+    public JTextField getTextField() {
+        return tf;
+    }
+
+    public void actionPerformed(ActionEvent e) {
+        if (citeSeerFetcher.activateImportFetcher()) {
+            (new Thread() {
+
+                BibtexEntry entry;
+
+                class Update implements ImportInspectionDialog.CallBack {
+
+                    // This method is called by the dialog when the user has selected the
+                    // wanted entries, and clicked Ok. The callback object can update status
+                    // line etc.
+                    public void done(int entriesImported) {
+                        if (entriesImported > 0)
+                            panel.output(Globals.lang("Completed import from CiteSeer."));
+                        else
+                            panel.output(Globals.lang("No entries imported."));
+                    }
+
+                    public void cancelled() {
+                        panel.output(Globals.lang("%0 import cancelled.", "CiteSeer"));
+                    }
+                    
+                    public void stopFetching() {
+                    }
+
+                    /*public void run() {
+                        citeSeerFetcher.endImportCiteSeerProgress();
+                        if (addedEntries != null)
+                            panel.markBaseChanged();
+                        panel.refreshTable();
+// Select the entries that were added:
+                        if (addedEntries.size() > 0) {
+                            BibtexEntry[] toSelect = new BibtexEntry[addedEntries.size()];
+                            toSelect = (BibtexEntry[]) addedEntries.toArray(toSelect);
+
+                            panel.selectEntries(toSelect, 0);
+                            if (toSelect.length == 1)
+                                panel.showEntry(toSelect[0]);
+//else
+//    panel.updateViewToSelected();
+                        }
+                        panel.output(Globals.lang("Completed Import Fields from CiteSeer."));
+                    } */
+
+                }
+
+                public void run() {
+
+                    // Open the inspection dialog... we will fill it as the entries come in:
+                    ImportInspectionDialog diag = null;
+                    if (Globals.prefs.getBoolean("useImportInspectionDialog")) {
+                        diag = new ImportInspectionDialog(panel.frame(), panel,
+                            GUIGlobals.DEFAULT_INSPECTION_FIELDS, Globals.lang("Fetch CiteSeer"), false);
+                        diag.addCallBack(new Update());
+                        Util.placeDialog(diag, panel.frame());
+                        diag.setVisible(true);
+                        diag.setProgress(0, 1);
+                    }
+                    NamedCompound undoEdit =
+                            new NamedCompound(Globals.lang("CiteSeer import entries")),
+                            // Use a dummy UndoEdit to avoid storing the information on
+                            // every field change, since we are importing new entries:
+                            dummyCompound = new NamedCompound(Globals.lang("Ok"));
+                    BooleanAssign overwriteAll = new BooleanAssign(true),
+                            overwriteNone = new BooleanAssign(false),
+                            newValue = new BooleanAssign(false);
+                    Hashtable rejectedEntries = new Hashtable();
+                    String text = tf.getText().replaceAll(",", ";");
+                    String[] ids = text.split(";");
+                    BibtexEntry[] entries = new BibtexEntry[ids.length];
+                    citeSeerFetcher.activateImportFetcher();
+
+                    for (int i = 0; i < entries.length; i++) {
+                        // Create the entry:
+                        entries[i] = new BibtexEntry(Util.createNeutralId(), BibtexEntryType.getType("article"));
+                        // Set its citeseerurl field:
+                        entries[i].setField("citeseerurl", ids[i].trim());
+                        // Try to import based on the id:
+                        boolean newValues = citeSeerFetcher.importCiteSeerEntry
+                                (entries[i], dummyCompound, overwriteAll, overwriteNone,
+                                        newValue, rejectedEntries);
+
+                        // What we do with the entry depends on whether we are using the inspection window:
+                        if (diag != null) {
+                            diag.addEntry(entries[i]);
+                            diag.setProgress(i+1, entries.length);
+                        } else {
+                            // Do nothing. We will add the entries afterwards (?)
+                        }
+                    }
+                    citeSeerFetcher.deactivateImportFetcher();
+
+                    if (diag != null) {
+                        // Signal that we are done. The ImportInspectionDialog will add the entries for us.
+                        diag.entryListComplete();
+                    } else {
+                        panel.frame().addBibEntries(Arrays.asList(entries), null, false);
+                        (new Update()).done(entries.length);
+                    }
+                }
+            }).start();
+        } else {
+            JOptionPane.showMessageDialog(panel.frame(),
+                    Globals.lang("A CiteSeer import operation is currently in progress.") + "  " +
+                    Globals.lang("Please wait until it has finished."),
+                    Globals.lang("CiteSeer Import Error"),
+                    JOptionPane.WARNING_MESSAGE);
+        }
+    }
+}
+
diff --git a/src/java/net/sf/jabref/imports/CiteSeerUndoHandler.java b/src/java/net/sf/jabref/imports/CiteSeerUndoHandler.java
new file mode 100644
index 0000000..e4ebf87
--- /dev/null
+++ b/src/java/net/sf/jabref/imports/CiteSeerUndoHandler.java
@@ -0,0 +1,230 @@
+/*
+ * Created on Jun 29, 2004
+ *
+ * To change the template for this generated file go to
+ * Window>Preferences>Java>Code Generation>Code and Comments
+ */
+package net.sf.jabref.imports;
+
+
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+
+import javax.swing.JDialog;
+import javax.swing.JOptionPane;
+
+import net.sf.jabref.BasePanel;
+import net.sf.jabref.BibtexEntry;
+import net.sf.jabref.undo.NamedCompound;
+import net.sf.jabref.undo.UndoableFieldChange;
+
+
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+/**
+ * @author mspiegel
+ * 
+ * To change the template for this generated type comment go to
+ * Window>Preferences>Java>Code Generation>Code and Comments
+ */
+public class CiteSeerUndoHandler extends DefaultHandler {
+
+    NamedCompound citeseerNamedCompound = null;
+
+    BibtexEntry bibEntry = null;
+
+    String nextField = null;
+
+    boolean nextAssign = false;
+
+    BasePanel panel = null;
+
+    BooleanAssign overwriteAll;
+    BooleanAssign overwriteNone;
+    BooleanAssign recordFound;
+    
+    String newAuthors = null;
+
+    int citeseerCitationCount = 0;
+    
+    /*
+     * Woe unto those who call this function from anywhere but
+     * makeOverwriteChoice(). You will seriously f*&k things up.
+     */
+    private boolean overwriteDialog(String oldValue, String newValue,
+            String fieldName) {
+        boolean retval = false;
+        Object[] possibilities = { "Yes", "Yes to All", "No", "No to All" };
+
+        final JOptionPane optionPane = new JOptionPane(
+                "Do you want to overwrite the value '" + oldValue
+                        + "' \nwith the value '" + newValue + "' \nfor the "
+                        + fieldName + " field?", JOptionPane.QUESTION_MESSAGE,
+                JOptionPane.DEFAULT_OPTION, null, possibilities, "No");
+
+        final JDialog dialog = new JDialog(panel.frame(), "Overwrite Value",
+                true);
+        dialog.setContentPane(optionPane);
+        dialog.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
+
+        optionPane.addPropertyChangeListener(new PropertyChangeListener() {
+            public void propertyChange(PropertyChangeEvent e) {
+                String prop = e.getPropertyName();
+
+                if (dialog.isVisible() && (e.getSource() == optionPane)
+                        && (prop.equals(JOptionPane.VALUE_PROPERTY))) {
+                    //If you were going to check something
+                    //before closing the window, you'd do
+                    //it here.
+                    dialog.setVisible(false);
+                }
+            }
+        });
+        dialog.pack();
+        dialog.setVisible(true);
+
+        String userChoice = (String) optionPane.getValue();
+        if (userChoice.equals("Yes to All")) {
+            overwriteAll.setValue(true);
+            retval = true;
+        } else if (userChoice.equals("Yes")) {
+            retval = true;
+        } else if (userChoice.equals("No to All")) {
+            overwriteNone.setValue(true);
+        }
+        return (retval);
+    }
+
+    public CiteSeerUndoHandler(NamedCompound newCompound, BibtexEntry be,
+            BasePanel basePanel, BooleanAssign assignment, BooleanAssign overwriteAll, BooleanAssign overwriteNone) {
+        citeseerNamedCompound = newCompound;
+        bibEntry = be;
+        panel = basePanel;
+        recordFound = assignment;
+        recordFound.setValue(false);
+        this.overwriteAll = overwriteAll;
+        this.overwriteNone = overwriteNone;    	
+    }
+
+    public CiteSeerUndoHandler(NamedCompound newCompound, BibtexEntry be,
+            BasePanel basePanel, BooleanAssign assignment) {
+    	this(newCompound, be, basePanel, assignment, new BooleanAssign(false), new BooleanAssign(false));
+    }
+       
+	public void characters(char[] ch, int start, int length) {
+        if (nextAssign == true) {
+            String target = new String(ch, start, length);        
+            if (nextField.equals("title")) {
+                if (makeOverwriteChoice((String) bibEntry.getField(nextField),
+                        target, nextField)) {
+                    UndoableFieldChange fieldChange = new UndoableFieldChange(
+                            bibEntry, nextField, bibEntry.getField(nextField),
+                            target);
+                    citeseerNamedCompound.addEdit(fieldChange);
+                    bibEntry.setField(nextField, target);
+                }
+            } else if (nextField.equals("year")) {
+                if (makeOverwriteChoice((String) bibEntry.getField(nextField),
+                        String.valueOf(target.substring(0, 4)), nextField)) {
+                    UndoableFieldChange fieldChange = new UndoableFieldChange(
+                            bibEntry, nextField, bibEntry.getField(nextField),
+                            String.valueOf(target.substring(0, 4)));
+                    citeseerNamedCompound.addEdit(fieldChange);
+                    bibEntry.setField(nextField, String.valueOf(target
+                            .substring(0, 4)));
+                }
+            } else if (nextField.equals("citeseerurl")) {
+                if (makeOverwriteChoice((String) bibEntry.getField(nextField),
+                        target, nextField)) {
+                    UndoableFieldChange fieldChange = new UndoableFieldChange(
+                            bibEntry, nextField, bibEntry.getField(nextField),
+                            target);
+                    citeseerNamedCompound.addEdit(fieldChange);
+                    bibEntry.setField(nextField, target);
+                }
+            }
+            nextAssign = false;
+        }
+    }
+
+    /**
+     * @param oldValue
+     * @param newValue
+     * @param fieldName
+     * @return overwrite
+     */
+    private boolean makeOverwriteChoice(String oldValue, String newValue,
+            String fieldName) {
+        boolean overwrite;
+        if ((oldValue == null) || (oldValue.equals("")))
+            overwrite = true;
+        else if (oldValue.equals(newValue))
+            overwrite = false;
+        else if (overwriteAll.getValue() == true)
+            overwrite = true;
+        else if (overwriteNone.getValue() == true)
+            overwrite = false;
+        else
+            overwrite = overwriteDialog(oldValue, newValue, fieldName);
+        if (overwrite)
+            recordFound.setValue(true);
+        return overwrite;
+    }
+
+    public void startElement(String name, String localName, String qName, Attributes attrs)
+            throws SAXException {
+        if (qName.equals("oai_citeseer:relation")) {
+    			for (int i = 0; i < attrs.getLength(); i++) {
+    			   String attrName = attrs.getQName(i);
+    			   String attrValue = attrs.getValue(i);	   
+    			   if (attrName.equals("type") && attrValue.equals("Is Referenced By")) {  	
+    			   	citeseerCitationCount++;
+    			   }
+    			}
+        } else if (qName.equals("oai_citeseer:author")) {        	
+            addAuthor(attrs.getValue("name"));
+        } else if (qName.equals("dc:title")) {
+            nextField = "title";
+            nextAssign = true;
+        } else if (qName.equals("dc:date")) {
+            nextField = "year";
+            nextAssign = true;
+        } else if (qName.equals("dc:identifier")) {
+            nextField = "citeseerurl";
+            nextAssign = true;
+        }
+    }
+
+    public void endDocument() {
+        if (newAuthors != null) {
+            if (makeOverwriteChoice((String) bibEntry.getField("author"),
+                    newAuthors, "author")) {
+                UndoableFieldChange fieldChange = new UndoableFieldChange(
+                        bibEntry, "author", bibEntry.getField("author"), newAuthors);
+                citeseerNamedCompound.addEdit(fieldChange);
+                bibEntry.setField("author", newAuthors);
+            }
+        }
+        Integer newCount = new Integer(citeseerCitationCount);
+        UndoableFieldChange fieldChange = new UndoableFieldChange(
+                bibEntry, "citeseercitationcount", 
+				bibEntry.getField("citeseercitationcount"), 
+				newCount);
+        citeseerNamedCompound.addEdit(fieldChange);
+        bibEntry.setField("citeseercitationcount", newCount);
+    }
+
+    /**
+     * @param string
+     */
+    private void addAuthor(String newAuthor) {
+        if (newAuthors == null) {
+            newAuthors = newAuthor;
+        } else {
+            newAuthors = newAuthors + " and " + newAuthor;
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/src/java/net/sf/jabref/imports/CsaImporter.java b/src/java/net/sf/jabref/imports/CsaImporter.java
new file mode 100644
index 0000000..8b9a8cd
--- /dev/null
+++ b/src/java/net/sf/jabref/imports/CsaImporter.java
@@ -0,0 +1,450 @@
+package net.sf.jabref.imports;
+
+import net.sf.jabref.BibtexEntry;
+import net.sf.jabref.Globals;
+
+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.regex.Pattern;
+import java.util.regex.Matcher;
+
+
+/**
+ * Importer for records downloaded from CSA: Cambridge Scientific Abstracts
+ * in full text format.  Although the same basic format is used by all CSA
+ * databases, this importer has been tailored and tested to handle
+ * ASFA: Aquatic Sciences and Fisheries records.
+ *
+ * @author John Relph
+ */
+public class CsaImporter extends ImportFormat {
+
+    // local fields
+    private int line;
+
+    // pre-compiled patterns
+    private final static Pattern FIELD_PATTERN =
+	Pattern.compile("^([A-Z][A-Z]): ([A-Z].*)$");
+    private final static Pattern VOLNOPP_PATTERN =
+	Pattern.compile("[;,\\.]\\s+(\\d+[A-Za-z]?)\\((\\d+(?:-\\d+)?)\\)(?:,\\s+|:)(\\d+-\\d+)");
+    private final static Pattern PAGES_PATTERN =
+	Pattern.compile("[;,\\.]\\s+(?:(\\[?[vn]\\.?p\\.?\\]?)|(?:pp?\\.?\\s+)(\\d+[A-Z]?(?:-\\d+[A-Z]?)?)|(\\d+[A-Z]?(?:-\\d+[A-Z]?)?)(?:\\s+pp?))");
+    private final static Pattern VOLUME_PATTERN =
+	Pattern.compile("[;,\\.]?\\s+[vV][oO][lL]\\.?\\s+(\\d+[A-Z]?(?:-\\d+[A-Z]?)?)");
+    private final static Pattern NUMBER_PATTERN =
+	Pattern.compile("[;,\\.]\\s+(?:No|no|Part|part|NUMB)\\.?\\s+([A-Z]?\\d+(?:[/-]\\d+)?)");
+    private final static Pattern DATE_PATTERN =
+	Pattern.compile("[;,\\.]\\s+(?:(\\d+)\\s)?(?:([A-Z][a-z][a-z])[\\.,]*\\s)?\\(?(\\d\\d\\d\\d)\\)?(?:\\s([A-Z][a-z][a-z]))?(?:\\s+(\\d+))?");
+    private final static Pattern LT_PATTERN =
+	Pattern.compile("\\[Lt\\]");
+
+    // other constants
+    private static final String MONS =
+	"jan feb mar apr may jun jul aug sep oct nov dec";
+    private static final String[] MONTHS =
+	{ "January", "February", "March", "April", "May", "June",
+	  "July", "August", "September", "October", "November", "December" };
+
+    /**
+     * Return the name of this import format.
+     */
+    public String getFormatName() {
+	return "CSA";
+    }
+
+    /*
+     *  (non-Javadoc)
+     * @see net.sf.jabref.imports.ImportFormat#getCLIId()
+     */
+    public String getCLIId() {
+      return "csa";
+    }
+    
+    // read a line
+    private String readLine(BufferedReader file) throws IOException {
+	String str = file.readLine();
+	if (str != null)
+	    line++;
+	return str;
+    }
+
+    // append to the "note" field
+    private void addNote(HashMap hm, String note) {
+	
+	StringBuffer notebuf = new StringBuffer();
+	if (hm.get("note") != null) {
+	    notebuf.append((String)hm.get("note"));
+	    notebuf.append("\n");
+	}
+	notebuf.append(note);
+	hm.put("note", notebuf.toString());
+    }
+
+    // parse the date from the Source field
+    private String parseDate(HashMap hm, String fstr) {
+
+	// find LAST matching date in string
+	int match = -1;
+	Matcher pm = DATE_PATTERN.matcher(fstr);
+	while (pm.find()) {
+	    match = pm.start();
+//	    System.out.println("MATCH: " + match + ": " + pm.group(0));
+	}
+
+	if (match == -1) {
+//	    System.out.println("NO MATCH: \"" + fstr + "\"");
+	    return fstr;
+	}
+	
+	if (!pm.find(match)) {
+//	    System.out.println("MATCH FAILED: \"" + fstr + "\"");
+	    return fstr;
+	}
+	
+	StringBuffer date = new StringBuffer();
+
+	String day = pm.group(1);
+	if (day == null)
+	    day = pm.group(5);
+	else if (pm.group(5) != null)
+	    return fstr;	// possible day found in two places
+
+	if (day != null && !day.equals("0")) {
+	    date.append(day);
+	    date.append(" ");
+	} else
+	    day = null;
+
+	String mon = pm.group(2);
+	if (mon == null)
+	    mon = pm.group(4);
+	else if (pm.group(4) != null)
+	    return fstr;	// possible month found in two places
+
+	int idx = -1;
+	if (mon != null) {
+	    String lmon = mon.toLowerCase();
+	    idx = MONS.indexOf(lmon);
+	    if (idx == -1)  // not legal month, error
+		return fstr;
+	    date.append(mon);
+	    date.append(" ");
+	    idx = idx / 4;
+	    hm.put("month", MONTHS[idx]);
+
+	} else if (day != null) // day found but not month, error
+	    return fstr;
+
+	String year = pm.group(3);
+	date.append(year);
+
+	StringBuffer note = new StringBuffer();
+	if (day != null && !day.equals("0")) {
+	    note.append("Source Date: ");
+	    note.append(date);
+	    note.append(".");
+	    addNote(hm, note.toString());
+	}
+
+	// check if journal year matches PY field
+	if (hm.get("year") != null) {
+	    String oyear = (String)hm.get("year");
+	    if (!year.equals(oyear)) {
+		note.setLength(0);
+		note.append("Source Year: ");
+		note.append(year);
+		note.append(".");
+		addNote(hm, note.toString());
+//		System.out.println(year + " != " + oyear);
+	    }
+	} else
+	    hm.put("year", year);
+	    
+	int len = fstr.length();
+	StringBuffer newf = new StringBuffer();
+	if (pm.start() > 0)
+	    newf.append(fstr.substring(0, pm.start()));
+	if (pm.end() < len)
+	    newf.append(fstr.substring(pm.end(), len));
+	return newf.toString();
+    }
+
+    /**
+     * Check whether the source is in the correct format for this importer.
+     */
+    public boolean isRecognizedFormat(InputStream stream) throws IOException {
+	// CSA records start with "DN: Database Name"
+	BufferedReader in =
+	    new BufferedReader(ImportFormatReader.getReaderDefaultEncoding(stream));
+	String str;
+	while ((str = in.readLine()) != null) {
+	    if (str.equals("DN: Database Name"))
+		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();
+	HashMap hm = new HashMap();
+
+	BufferedReader in =
+	    new BufferedReader(ImportFormatReader.getReaderDefaultEncoding(stream));
+
+	String Type = null;
+	String str;
+	boolean first = true;
+	int rline = 1;
+	line = 1;
+	str = readLine(in);
+	while (true) {
+	    if (str == null || str.length() == 0) {	// end of record
+		if (!hm.isEmpty()) { // have a record
+		    if (Type == null) {
+			addNote(hm, "Publication Type: [NOT SPECIFIED]");
+			addNote(hm, "[PERHAPS NOT FULL FORMAT]");
+			Type = "article";
+		    }
+
+		    // post-process Journal article
+		    if (Type.equals("article") &&
+			hm.get("booktitle") != null) {
+			String booktitle = (String)hm.get("booktitle");
+			hm.remove("booktitle");
+			hm.put("journal", booktitle);
+		    }
+
+		    BibtexEntry b =
+			new BibtexEntry(Globals.DEFAULT_BIBTEXENTRY_ID,
+					Globals.getEntryType(Type));
+
+		    // create one here
+		    b.setField(hm);
+
+		    bibitems.add(b);
+		}
+		hm.clear();	// ready for next record
+		first = true;
+		if (str == null)
+		    break;	// end of file
+		str = readLine(in);
+		rline = line;
+		continue;
+	    }
+
+	    int fline = line;	// save this before reading field contents
+	    Matcher fm = FIELD_PATTERN.matcher(str);
+	    if (fm.find()) {
+
+		// save the field name (long and short)
+		String fabbr = fm.group(1);
+		String fname = fm.group(2);
+
+		// read the contents of the field
+		sb.setLength(0); // clear the buffer
+		while ((str = readLine(in)) != null) {
+		    if (! str.startsWith("    ")) // field contents?
+			break;	// nope
+		    if (sb.length() > 0) {
+			sb.append(" ");
+		    }
+		    sb.append(str.substring(4)); // skip spaces
+		}
+		String fstr = sb.toString();
+		if (fstr == null || fstr.length() == 0) {
+		    int line1 = line - 1;
+		    throw new IOException("illegal empty field at line " +
+					  line1);
+		}
+		// replace [Lt] with <
+		fm = LT_PATTERN.matcher(fstr);
+		if (fm.find())
+		    fstr = fm.replaceAll("<");
+
+		// check for start of new record
+		if (fabbr.equals("DN") &&
+		    fname.equalsIgnoreCase("Database Name")) {
+		    if (first == false) {
+			throw new IOException("format error at line " + fline +
+					      ": DN out of order");
+		    }
+		    first = false;
+		    rline = fline; // save start of record
+		} else if (first == true) {
+		    throw new IOException("format error at line " + fline +
+					      ": missing DN");
+		}
+
+		if (fabbr.equals("PT")) {
+		    Type = null;
+		    String flow = fstr.toLowerCase();
+		    String[] types = flow.split("; ");
+		    if (types[0].equals("article") ||
+			types[0].equals("journal article")) {
+			Type = "article";
+		    } else if (types[0].equals("dissertation")) {
+			Type = "phdthesis";
+		    } else {
+			for (int ii = 0; ii < types.length; ++ii) {
+			    if (types[ii].equals("conference")) {
+				Type = "inproceedings";
+				break;
+			    } else if (types[ii].equals("book monograph") &&
+				       Type == null) {
+				Type = "book";
+			    } else if (types[ii].equals("report") &&
+				       Type == null) {
+				Type = "techreport";
+			    }
+			}
+			if (Type == null) {
+			    Type = "misc";
+			}
+		    }
+		}
+
+		String ftype = null;
+		if (fabbr.equals("AB"))
+		    ftype = "abstract";
+		else if (fabbr.equals("AF"))
+		    ftype = "affiliation";
+		else if (fabbr.equals("AU"))
+		    ftype = "author";
+		else if (fabbr.equals("CA"))
+		    ftype = "organization";
+		else if (fabbr.equals("DE"))
+		    ftype = "keywords";
+		else if (fabbr.equals("DO"))
+		    ftype = "doi";
+		else if (fabbr.equals("ED"))
+		    ftype = "editor";
+		else if (fabbr.equals("IB"))
+		    ftype = "ISBN";
+		else if (fabbr.equals("IS"))
+		    ftype = "ISSN";
+		else if (fabbr.equals("JN"))
+		    ftype = "journal";
+		else if (fabbr.equals("LA"))
+		    ftype = "language";
+		else if (fabbr.equals("PB"))
+		    ftype = "publisher";
+		else if (fabbr.equals("PY")) {
+		    ftype = "year";
+		    if (hm.get("year") != null) {
+			String oyear = (String)hm.get("year");
+			if (!fstr.equals(oyear)) {
+			    StringBuffer note = new StringBuffer();
+			    note.append("Source Year: ");
+			    note.append(oyear);
+			    note.append(".");
+			    addNote(hm, note.toString());
+//			    System.out.println(fstr + " != " + oyear);
+			}
+		    } 
+		} else if (fabbr.equals("RL")) {
+		    ftype = "url";
+		    String[] lines = fstr.split(" ");
+		    StringBuffer urls = new StringBuffer();
+		    for (int ii = 0; ii < lines.length; ++ii) {
+			if (lines[ii].startsWith("[URL:"))
+			    urls.append(lines[ii].substring(5));
+			else if (lines[ii].endsWith("]")) {
+			    int len = lines[ii].length();
+			    urls.append(lines[ii].substring(0, len - 1));
+			    if (ii < lines.length - 1)
+				urls.append("\n");
+			} else
+			    urls.append(lines[ii]);
+		    }
+		    fstr = urls.toString();
+		} else if (fabbr.equals("SO")) {
+		    ftype = "booktitle";
+
+		    // see if we can extract journal information
+
+		    // compact vol(no):page-page:
+		    Matcher pm = VOLNOPP_PATTERN.matcher(fstr);
+		    if (pm.find()) {
+			hm.put("volume", pm.group(1));
+			hm.put("number", pm.group(2));
+			hm.put("pages", pm.group(3));
+			fstr = pm.replaceFirst("");
+		    }
+
+		    // pages
+		    pm = PAGES_PATTERN.matcher(fstr);
+		    StringBuffer pages = new StringBuffer();
+		    while (pm.find()) {
+			if (pages.length() > 0)
+			    pages.append(",");
+			String pp = pm.group(1);
+			if (pp == null)
+			    pp = pm.group(2);
+			if (pp == null)
+			    pp = pm.group(3);
+			pages.append(pp);
+			fstr = pm.replaceFirst("");
+			pm = PAGES_PATTERN.matcher(fstr);
+		    }
+		    if (pages.length() > 0)
+			hm.put("pages", pages.toString());
+
+		    // volume:
+		    pm = VOLUME_PATTERN.matcher(fstr);
+		    if (pm.find()) {
+			hm.put("volume", pm.group(1));
+			fstr = pm.replaceFirst("");
+		    }
+
+		    // number:
+		    pm = NUMBER_PATTERN.matcher(fstr);
+		    if (pm.find()) {
+			hm.put("number", pm.group(1));
+			fstr = pm.replaceFirst("");
+		    }
+
+		    // journal date:
+		    fstr = parseDate(hm, fstr);
+
+		    // strip trailing whitespace
+		    Pattern pp = Pattern.compile(",?\\s*$");
+		    pm = pp.matcher(fstr);
+		    if (pm.find())
+			fstr = pm.replaceFirst("");
+
+		    if (fstr.equals(""))
+			continue;
+//		    System.out.println("SOURCE: \"" + fstr + "\"");
+		} else if (fabbr.equals("TI"))
+		    ftype = "title";
+		else if (fabbr.equals("RE"))
+		    continue;	// throw away References
+
+		if (ftype != null) {
+		    hm.put(ftype, fstr);
+		} else {
+		    StringBuffer val = new StringBuffer();
+		    val.append(fname);
+		    val.append(": ");
+		    val.append(fstr);
+		    val.append(".");
+		    addNote(hm, val.toString());
+		}
+	    } else
+		str = readLine(in);
+	}
+
+	return bibitems;
+    }
+}
diff --git a/src/java/net/sf/jabref/imports/CustomImportList.java b/src/java/net/sf/jabref/imports/CustomImportList.java
new file mode 100644
index 0000000..fdc7708
--- /dev/null
+++ b/src/java/net/sf/jabref/imports/CustomImportList.java
@@ -0,0 +1,189 @@
+/*
+ Copyright (C) 2005 Andreas Rudert, based on CustomExportList by ??
+
+ 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.imports;
+
+import java.io.File;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.TreeSet;
+import net.sf.jabref.Globals;
+import net.sf.jabref.JabRefPreferences;
+
+/**
+ * Collection of user defined custom import formats. 
+ * 
+ * <p>The collection can be stored and retrieved from Preferences. It is sorted by the default
+ * order of {@link ImportFormat}.</p>
+ */
+public class CustomImportList extends TreeSet {
+
+  /**
+   * Object with data for a custom importer.
+   * 
+   * <p>Is also responsible for instantiating the class loader.</p>
+   */
+  public class Importer implements Comparable {
+    
+    private String name;
+    private String cliId;
+    private String className;
+    private String basePath;
+    
+    public Importer() {
+      super();
+    }
+    
+    public Importer(String[] data) {
+      super();
+      this.name = data[0];
+      this.cliId = data[1];
+      this.className = data[2];
+      this.basePath = data[3];
+    }
+    
+    public String getName() {
+      return this.name;
+    }
+    
+    public void setName(String name) {
+      this.name = name;
+    }
+    
+    public String getClidId() {
+      return this.cliId;
+    }
+    
+    public void setCliId(String cliId) {
+      this.cliId = cliId;
+    }
+    
+    public String getClassName() {
+      return this.className;
+    }
+    
+    public void setClassName(String className) {
+      this.className = className;
+    }
+    
+    public void setBasePath(String basePath) {
+      this.basePath = basePath;
+    }
+    
+    public File getBasePath() {
+      return new File(basePath);
+    }
+    
+    public URL getBasePathUrl() throws MalformedURLException {
+      return getBasePath().toURL();
+    }
+    
+    public String[] getAsStringArray() {
+      return new String[] {name, cliId, className, basePath};
+    }
+    
+    public boolean equals(Object o) {
+      return o != null && o instanceof Importer && this.getName().equals(((Importer)o).getName());
+    }
+    
+    public int hashCode() {
+      return name.hashCode();
+    }
+    
+    public int compareTo(Object o) {
+      return this.getName().compareTo( ((Importer)o).getName() );
+    }
+    
+    public String toString() {
+      return this.name;
+    }
+    
+    public ImportFormat getInstance() throws MalformedURLException, ClassNotFoundException, InstantiationException, IllegalAccessException {
+      URLClassLoader cl = new URLClassLoader(new URL[] {getBasePathUrl()});
+      Class clazz = Class.forName(className, true, cl);
+      ImportFormat importFormat = (ImportFormat)clazz.newInstance();
+      importFormat.setIsCustomImporter(true);
+      return importFormat;
+    }
+  }
+  
+  private JabRefPreferences prefs;
+
+  public CustomImportList(JabRefPreferences prefs) {
+    super();
+    this.prefs = prefs;
+    readPrefs();
+  }
+
+
+  private void readPrefs() {
+    int i=0;
+    String[] s = null;
+    while ((s = prefs.getStringArray("customImportFormat"+i)) != null) {
+      try {
+        super.add(new Importer(s));
+      } catch (Exception e) {
+        System.err.println("Warning! Could not load " + s[0] + " from preferences. Will ignore.");
+        // Globals.prefs.remove("customImportFormat"+i);
+      }
+      i++;
+    }
+  }
+
+  public void addImporter(Importer customImporter) {
+    super.add(customImporter);
+  }
+  
+  /**
+   * Adds an importer.
+   * 
+   * <p>If an old one equal to the new one was contained, the old
+   * one is replaced.</p>
+   * 
+   * @param customImporter new (version of an) importer
+   * @return  if the importer was contained
+   */
+  public boolean replaceImporter(Importer customImporter) {
+    boolean wasContained = this.remove(customImporter);
+    this.addImporter(customImporter);
+    return wasContained;
+  }
+
+  public void store() {
+    purgeAll();
+    Importer[] importers = (Importer[])this.toArray(new Importer[]{});
+    for (int i = 0; i < importers.length; i++) {
+      Globals.prefs.putStringArray("customImportFormat"+i, importers[i].getAsStringArray());
+    }
+  }
+
+  private void purgeAll() {
+    for (int i = 0; Globals.prefs.getStringArray("customImportFormat"+i) != null; i++) {
+      Globals.prefs.remove("customImportFormat"+i);
+    }
+  }
+
+}
diff --git a/src/java/net/sf/jabref/imports/EndnoteImporter.java b/src/java/net/sf/jabref/imports/EndnoteImporter.java
new file mode 100644
index 0000000..aa6bf7e
--- /dev/null
+++ b/src/java/net/sf/jabref/imports/EndnoteImporter.java
@@ -0,0 +1,194 @@
+package net.sf.jabref.imports;
+
+import java.util.regex.Pattern;
+import java.io.InputStream;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.HashMap;
+import net.sf.jabref.BibtexEntry;
+import net.sf.jabref.Globals;
+import net.sf.jabref.Util;
+import net.sf.jabref.AuthorList;
+
+/**
+ * Importer for the Refer/Endnote format.
+ *
+ * check here for details on the format
+ * http://www.ecst.csuchico.edu/~jacobsd/bib/formats/endnote.html
+ */
+public class EndnoteImporter extends ImportFormat {
+
+    /**
+     * Return the name of this import format.
+     */
+    public String getFormatName() {
+    return "Refer/Endnote";
+    }
+
+    /*
+     *  (non-Javadoc)
+     * @see net.sf.jabref.imports.ImportFormat#getCLIId()
+     */
+    public String getCLIId() {
+      return "refer";
+    }
+    
+    /**
+     * 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 "%A *" line.
+    BufferedReader in = new BufferedReader(ImportFormatReader.getReaderDefaultEncoding(stream));
+    Pattern pat1 = Pattern
+        .compile("%A .*");
+    String str;
+    while ((str = in.readLine()) != null){
+        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));
+    String ENDOFRECORD = "__EOREOR__";
+
+    String str;
+    boolean first = true;
+    while ((str = in.readLine()) != null){
+        str = str.trim();
+        // if(str.equals("")) continue;
+        if (str.indexOf("%0") == 0){
+        if (first){
+            first = false;
+        }else{
+            sb.append(ENDOFRECORD);
+        }
+        sb.append(str);
+        }else sb.append(str);
+        sb.append("\n");
+    }
+
+    String[] entries = sb.toString().split(ENDOFRECORD);
+    HashMap hm = new HashMap();
+    String Author = "", Type = "", Editor = "";
+    for (int i = 0; i < entries.length; i++){
+        hm.clear();
+        Author = "";
+        Type = "";
+        Editor = "";
+	boolean IsEditedBook = false;
+        String[] fields = entries[i].substring(1).split("\n%");
+        //String lastPrefix = "";
+        for (int j = 0; j < fields.length; j++){
+        if (fields[j].length() < 3) continue;
+
+        /*
+           * Details of Refer format for Journal Article and Book:
+           *
+           * Generic Ref Journal Article Book Code Author %A Author Author Year %D
+           * Year Year Title %T Title Title Secondary Author %E Series Editor
+           * Secondary Title %B Journal Series Title Place Published %C City
+           * Publisher %I Publisher Volume %V Volume Volume Number of Volumes %6
+           * Number of Volumes Number %N Issue Pages %P Pages Number of Pages
+           * Edition %7 Edition Subsidiary Author %? Translator Alternate Title %J
+           * Alternate Journal Label %F Label Label Keywords %K Keywords Keywords
+           * Abstract %X Abstract Abstract Notes %O Notes Notes
+           */
+
+        String prefix = fields[j].substring(0, 1);
+        String val = fields[j].substring(2);
+        if (prefix.equals("A")){
+            if (Author.equals("")) Author = val;
+            else Author += " and " + val;
+        }else if (prefix.equals("E")){
+            if (Editor.equals("")) Editor = val;
+            else Editor += " and " + val;
+        }else if (prefix.equals("T")) hm.put("title", Util
+                             .putBracesAroundCapitals(val));
+        else if (prefix.equals("0")){
+            if (val.indexOf("Journal") == 0) Type = "article";
+            else if ((val.indexOf("Book Section") == 0)) Type = "incollection";
+            else if ((val.indexOf("Book") == 0)) Type = "book";
+            else if (val.indexOf("Edited Book") == 0) {
+                Type = "book";
+                IsEditedBook = true;
+            }else if (val.indexOf("Conference") == 0) // Proceedings
+            Type = "inproceedings";
+            else if (val.indexOf("Report") == 0) // Techreport
+            Type = "techreport";
+            else if (val.indexOf("Review") == 0)
+                Type = "article";
+            else if (val.indexOf("Thesis") == 0)
+                Type = "phdthesis";
+            else Type = "misc"; //
+        }else if (prefix.equals("7")) hm.put("edition", val);
+        else if (prefix.equals("C")) hm.put("address", val);
+        else if (prefix.equals("D")) hm.put("year", val);
+        else if (prefix.equals("8")) hm.put("date", val);
+        else if (prefix.equals("J")){
+            // "Alternate journal. Let's set it only if no journal
+            // has been set with %B.
+            if (hm.get("journal") == null) hm.put("journal", val);
+        }else if (prefix.equals("B")){
+            // This prefix stands for "journal" in a journal entry, and
+            // "series" in a book entry.
+            if (Type.equals("article")) hm.put("journal", val);
+            else if (Type.equals("book") || Type.equals("inbook")) hm.put(
+                                          "series", val);
+            else /* if (Type.equals("inproceedings")) */
+            hm.put("booktitle", val);
+        }else if (prefix.equals("I")) {
+            if (Type.equals("phdthesis"))
+                hm.put("school", val);
+            else
+                 hm.put("publisher", val);
+        }
+            // replace single dash page ranges (23-45) with double dashes (23--45):
+        else if (prefix.equals("P")) hm.put("pages", val.replaceAll("([0-9]) *- *([0-9])","$1--$2"));
+        else if (prefix.equals("V")) hm.put("volume", val);
+        else if (prefix.equals("N")) hm.put("number", val);
+        else if (prefix.equals("U")) hm.put("url", val);
+        else if (prefix.equals("O")) hm.put("note", val);
+        else if (prefix.equals("K")) hm.put("keywords", val);
+        else if (prefix.equals("X")) hm.put("abstract", val);
+        else if (prefix.equals("9")){
+            //Util.pr(val);
+            if (val.indexOf("Ph.D.") == 0) Type = "phdthesis";
+            if (val.indexOf("Masters") == 0) Type = "mastersthesis";
+        }else if (prefix.equals("F")) hm.put(Globals.KEY_FIELD, Util
+                             .checkLegalKey(val));
+        }
+
+        // For Edited Book, EndNote puts the editors in the author field.
+        // We want them in the editor field so that bibtex knows it's an edited book
+        if (IsEditedBook && Editor.equals("")) {
+           Editor = Author;
+           Author = "";
+        }
+
+        //fixauthorscomma
+        if (!Author.equals("")) hm.put("author", AuthorList.fixAuthor_lastNameFirst(Author));
+        if (!Editor.equals("")) hm.put("editor", AuthorList.fixAuthor_lastNameFirst(Editor));
+        BibtexEntry b = new BibtexEntry(Globals.DEFAULT_BIBTEXENTRY_ID, Globals
+                        .getEntryType(Type)); // id assumes an existing database so don't
+        // create one here
+        b.setField(hm);
+        //if (hm.isEmpty())
+        if (b.getAllFields().length > 0) bibitems.add(b);
+
+    }
+    return bibitems;
+
+    }
+
+}
diff --git a/src/java/net/sf/jabref/imports/FieldContentParser.java b/src/java/net/sf/jabref/imports/FieldContentParser.java
new file mode 100644
index 0000000..db582a2
--- /dev/null
+++ b/src/java/net/sf/jabref/imports/FieldContentParser.java
@@ -0,0 +1,174 @@
+package net.sf.jabref.imports;
+
+import net.sf.jabref.Globals;
+
+
+/**
+ * This class provides the reformatting needed when reading BibTeX fields formatted
+ * in JabRef style. The reformatting must undo all formatting done by JabRef when
+ * writing the same fields.
+ */
+public class FieldContentParser {
+
+    /**
+     * Performs the reformatting
+     * @param content StringBuffer containing the field to format.
+     * @return The formatted field content. NOTE: the StringBuffer returned may
+     * or may not be the same as the argument given.
+     */
+    public StringBuffer format(StringBuffer content) {
+
+        //boolean rep = false;
+
+        int i=0;
+
+        // Remove windows newlines and insert unix ones:
+        // TODO: 2005.12.3: Added replace from \r to \n, to work around a reported problem of words stiched together.
+        // But: we need to find out why these lone \r characters appear in his file.
+        content = new StringBuffer(content.toString().replaceAll("\r\n","\n").replaceAll("\r", "\n"));
+        //if (rep) System.out.println(content.toString());
+        /*while (i<content.length()) {
+            if (content.charAt(i) == '\r')
+                content.deleteCharAt(i);
+            else i++;
+        }
+
+        i=0;*/
+        while (i<content.length()) {
+
+            int c = content.charAt(i);
+            if (c == '\n') {
+                if ((content.length()>i+2) && (content.charAt(i+1)=='\t')
+                    && !Character.isWhitespace(content.charAt(i+2))) {
+                    // We have \n\t followed by non-whitespace, which indicates
+                    // a wrap made by JabRef. Remove and insert space if necessary.
+
+                    content.deleteCharAt(i); // \n
+                    content.deleteCharAt(i); // \t
+                    // Add space only if necessary:
+                    if ((i>0) && !Character.isWhitespace(content.charAt(i-1))) {
+                        content.insert(i, ' ');
+                        // Increment i because of the inserted character:
+                        i++;
+                    }
+                }
+                else if ((content.length()>i+3) && (content.charAt(i+1)=='\t')
+                    && (content.charAt(i+2)==' ')
+                    && !Character.isWhitespace(content.charAt(i+3))) {
+                    // We have \n\t followed by ' ' followed by non-whitespace, which indicates
+                    // a wrap made by JabRef <= 1.7.1. Remove:
+
+                    content.deleteCharAt(i); // \n
+                    content.deleteCharAt(i); // \t
+                    // Remove space only if necessary:
+                    if ((i>0) && Character.isWhitespace(content.charAt(i-1))) {
+                        content.deleteCharAt(i);
+                    }
+                }
+                else if ((content.length()>i+3) && (content.charAt(i+1)=='\t')
+                        && (content.charAt(i+2)=='\n') && (content.charAt(i+3)=='\t')) {
+                    // We have \n\t\n\t, which looks like a JabRef-formatted empty line.
+                    // Remove the tabs and keep one of the line breaks:
+                    content.deleteCharAt(i+1); // \t
+                    content.deleteCharAt(i+1); // \n
+                    content.deleteCharAt(i+1); // \t
+                    // Skip past the line breaks:
+                    i++;
+
+                    // Now, if more \n\t pairs are following, keep each line break. This
+                    // preserves several line breaks properly. Repeat until done:
+                    while ((content.length()>i+1) && (content.charAt(i)=='\n')
+                        && (content.charAt(i+1)=='\t')) {
+
+                        content.deleteCharAt(i+1);
+                        i++;
+                    }
+                }
+                else if ((content.length()>i+1) && (content.charAt(i+1)!='\n')) {
+                    // We have a line break not followed by another line break. This is probably a normal
+                    // line break made by whatever other editor, so we will remove the line break.
+                    content.deleteCharAt(i);
+                    // If the line break is not accompanied by other whitespace we must add a space:
+                    if (!Character.isWhitespace(content.charAt(i)) &&  // No whitespace after?
+                            (i>0) && !Character.isWhitespace(content.charAt(i-1))) // No whitespace before?
+                        content.insert(i, ' ');
+                }
+
+                //else if ((content.length()>i+1) && (content.charAt(i+1)=='\n'))
+                else
+                    i++;
+                //content.deleteCharAt(i);
+            }
+            else if (c == ' ') {
+                //if ((content.length()>i+2) && (content.charAt(i+1)==' ')) {
+                if ((i>0) && (content.charAt(i-1)==' ')) {
+                    // We have two spaces in a row. Don't include this one.
+                    content.deleteCharAt(i);
+                }
+                else
+                    i++;
+            } else if (c == '\t')
+                // Remove all tab characters that aren't associated with a line break.
+                content.deleteCharAt(i);
+            else
+                i++;
+
+        }
+
+        return content;
+    }
+
+    /**
+     * Formats field contents for output. Must be "symmetric" with the parse method above,
+     * so stored and reloaded fields are not mangled.
+     * @param in
+     * @param wrapAmount
+     * @return the wrapped String.
+     */
+    public static String wrap(String in, int wrapAmount){
+        // JZ: due to the formatting/wrapping bug, I temporarily disabled
+        // the below code to prevent JabRef from modifying .bib files in
+        // a way that may require manual correction.
+        //return in;
+
+        String[] lines = in.split("\n");
+        StringBuffer res = new StringBuffer();
+        addWrappedLine(res, lines[0], wrapAmount);
+        for (int i=1; i<lines.length; i++) {
+
+            if (!lines[i].trim().equals("")) {
+                res.append(Globals.NEWLINE);
+                res.append('\t');
+                res.append(Globals.NEWLINE);
+                res.append('\t');
+                addWrappedLine(res, lines[i], wrapAmount);
+            } else {
+                res.append(Globals.NEWLINE);
+                res.append('\t');
+            }
+        }
+        return res.toString();
+    }
+
+    private static void addWrappedLine(StringBuffer res, String line, int wrapAmount) {
+        // Set our pointer to the beginning of the new line in the StringBuffer:
+        int p = res.length();
+        // Add the line, unmodified:
+        res.append(line);
+
+        while (p < res.length()){
+            int q = res.indexOf(" ", p+wrapAmount);
+            if ((q < 0) || (q >= res.length()))
+                break;
+
+            res.deleteCharAt(q);
+            res.insert(q, Globals.NEWLINE+"\t");
+            p = q+1;
+
+        }
+    }
+
+    static class Indents {
+        //int hyp
+    }
+}
diff --git a/src/java/net/sf/jabref/imports/ImportCustomizationDialog.java b/src/java/net/sf/jabref/imports/ImportCustomizationDialog.java
new file mode 100644
index 0000000..b4f4f79
--- /dev/null
+++ b/src/java/net/sf/jabref/imports/ImportCustomizationDialog.java
@@ -0,0 +1,299 @@
+/*
+ Copyright (C) 2005 Andreas Rudert, based on ExportCustomizationDialog by ??
+
+ 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.imports;
+
+import javax.swing.JDialog;
+import java.awt.*;
+import net.sf.jabref.*;
+import javax.swing.*;
+import java.awt.event.ActionListener;
+import java.awt.event.ActionEvent;
+import java.io.File;
+import java.io.IOException;
+import java.util.zip.ZipFile;
+
+import javax.swing.table.AbstractTableModel;
+import javax.swing.table.TableColumnModel;
+
+/**
+ * Dialog to manage custom importers.
+ */
+public class ImportCustomizationDialog extends JDialog {
+
+  private final JabRefFrame frame;
+  private JButton addFromFolderButton = new JButton(Globals.lang("Add from folder"));
+  private JButton addFromJarButton = new JButton(Globals.lang("Add from jar"));
+  private JButton showDescButton = new JButton(Globals.lang("Show description"));
+  private JButton removeButton = new JButton(Globals.lang("Remove"));
+  private JButton closeButton = new JButton(Globals.lang("Close"));
+  private JButton helpButton = new JButton(Globals.lang("Help"));
+
+  private JPanel optionsPanel = new JPanel();
+  private JPanel mainPanel = new JPanel();
+  private JTable customImporterTable;
+  private JabRefPreferences prefs = Globals.prefs;
+  private ImportCustomizationDialog importCustomizationDialog;
+  
+  /*
+   *  (non-Javadoc)
+   * @see java.awt.Component#getSize()
+   */
+  public Dimension getSize() {
+    int width = GUIGlobals.IMPORT_DIALOG_COL_0_WIDTH
+              + GUIGlobals.IMPORT_DIALOG_COL_1_WIDTH
+              + GUIGlobals.IMPORT_DIALOG_COL_2_WIDTH
+              + GUIGlobals.IMPORT_DIALOG_COL_3_WIDTH;
+    return new Dimension(width, width/2);
+  }
+  
+  /**
+   * Converts a path relative to a base-path into a class name.
+   * 
+   * @param basePath  base path
+   * @param path  path that includes base-path as a prefix
+   * @return  class name
+   */
+  private String pathToClass(File basePath, File path) {
+    String className = null;
+    // remove leading basepath from path
+    while (!path.equals(basePath)) {
+      className = path.getName() + (className != null ? "." + className : "");
+      path = path.getParentFile();
+    }
+    className = className.substring(0, className.lastIndexOf('.'));
+    return className;    
+  }
+  
+  /**
+   * Adds an importer to the model that underlies the custom importers.
+   * 
+   * @param importer  importer
+   */
+  void addOrReplaceImporter(CustomImportList.Importer importer) {
+    prefs.customImports.replaceImporter(importer);
+    Globals.importFormatReader.resetImportFormats();
+    ((ImportTableModel)customImporterTable.getModel()).fireTableDataChanged();
+  }
+  
+  /**
+   * 
+   * @param frame_
+   * @throws HeadlessException
+   */
+  public ImportCustomizationDialog(JabRefFrame frame_) throws HeadlessException {
+    super(frame_, Globals.lang("Manage custom imports"), false);
+    this.importCustomizationDialog = this;
+    frame = frame_;
+    
+    addFromFolderButton.addActionListener(new ActionListener() {
+     public void actionPerformed(ActionEvent e) {
+       CustomImportList.Importer importer = prefs.customImports.new Importer();  
+       importer.setBasePath( Globals.getNewDir(frame, prefs, new File(prefs.get("workingDirectory")), "",
+           Globals.lang("Select Classpath of New Importer"), JFileChooser.CUSTOM_DIALOG, false) );
+       String chosenFileStr = Globals.getNewFile(frame, prefs, importer.getBasePath(), ".class",
+           Globals.lang("Select new ImportFormat Subclass"), JFileChooser.CUSTOM_DIALOG, false);
+       if (chosenFileStr != null) {
+         try {
+           importer.setClassName( pathToClass(importer.getBasePath(), new File(chosenFileStr)) );
+           importer.setName( importer.getInstance().getFormatName() );
+           importer.setCliId( importer.getInstance().getCLIId() );
+         } catch (Exception exc) {           
+           exc.printStackTrace();
+           JOptionPane.showMessageDialog(frame, Globals.lang("Could not instantiate %0 %1", chosenFileStr + ":\n", exc.getMessage()));
+         } catch (NoClassDefFoundError exc) {
+           exc.printStackTrace();
+           JOptionPane.showMessageDialog(frame, Globals.lang("Could not instantiate %0 %1. Have you chosen the correct package path?", chosenFileStr + ":\n", exc.getMessage()));           
+         }
+
+         addOrReplaceImporter(importer);
+         customImporterTable.revalidate();
+         customImporterTable.repaint();
+         frame.setUpImportMenus();
+       }
+      }
+    });
+    addFromFolderButton.setToolTipText(Globals.lang("Add a (compiled) custom ImportFormat class from a class path. \nThe path need not be on the classpath of JabRef."));
+
+    addFromJarButton.addActionListener(new ActionListener() {
+     public void actionPerformed(ActionEvent e) {
+       String basePath = Globals.getNewFile(frame, prefs, new File(prefs.get("workingDirectory")), ".zip,.jar",
+           Globals.lang("Select a Zip-archive"), JFileChooser.CUSTOM_DIALOG, false);
+       ZipFile zipFile = null;
+       if (basePath != null) {
+         try {
+           zipFile = new ZipFile(new File(basePath), ZipFile.OPEN_READ);
+         } catch (IOException exc) {
+           exc.printStackTrace();
+           JOptionPane.showMessageDialog(frame, Globals.lang("Could not open %0 %1", basePath + ":\n", exc.getMessage()) 
+                                              + "\n" + Globals.lang("Have you chosen the correct package path?"));
+           return;         
+         } catch (NoClassDefFoundError exc) {
+           exc.printStackTrace();
+           JOptionPane.showMessageDialog(frame, Globals.lang("Could not instantiate %0 %1", basePath + ":\n", exc.getMessage())
+                                              + "\n" + Globals.lang("Have you chosen the correct package path?"));           
+         }
+       }
+         
+       if (zipFile != null) {
+         ZipFileChooser zipFileChooser = new ZipFileChooser(importCustomizationDialog, zipFile);
+         zipFileChooser.setVisible(true);
+       }
+       customImporterTable.revalidate();
+       customImporterTable.repaint(10);
+       frame.setUpImportMenus();
+      }
+    });
+    addFromJarButton.setToolTipText(Globals.lang("Add a (compiled) custom ImportFormat class from a Zip-archive.\nThe Zip-archive need not be on the classpath of JabRef."));
+    
+    showDescButton.addActionListener(new ActionListener() {
+     public void actionPerformed(ActionEvent e) {
+       int row = customImporterTable.getSelectedRow();
+       if (row != -1) {
+         CustomImportList.Importer importer = ((ImportTableModel)customImporterTable.getModel()).getImporter(row);
+         try {
+           ImportFormat importFormat = importer.getInstance();
+           JOptionPane.showMessageDialog(frame, importFormat.getDescription());
+         } catch (Exception exc) {           
+           exc.printStackTrace();
+           JOptionPane.showMessageDialog(frame, Globals.lang("Could not instantiate %0 %1", importer.getName() + ":\n", exc.getMessage()));
+         }
+       } else {
+         JOptionPane.showMessageDialog(frame, Globals.lang("Please select an importer"));
+       }
+     }
+    });
+    
+    removeButton.addActionListener(new ActionListener() {
+      public void actionPerformed(ActionEvent e) {
+        int row = customImporterTable.getSelectedRow();
+        if (row != -1) {
+          customImporterTable.removeRowSelectionInterval(row,row);
+          prefs.customImports.remove(((ImportTableModel)customImporterTable.getModel()).getImporter(row));
+          Globals.importFormatReader.resetImportFormats();
+          customImporterTable.revalidate();
+          customImporterTable.repaint();
+          frame.setUpImportMenus();
+        }  else {
+          JOptionPane.showMessageDialog(frame, Globals.lang("Please select an importer."));
+        }
+      }
+    });
+
+    AbstractAction closeAction = new AbstractAction() {
+      public void actionPerformed(ActionEvent e) {
+        dispose();
+      }
+    };
+
+    closeButton.addActionListener(closeAction);
+
+    helpButton.addActionListener(new HelpAction(frame.helpDiag, GUIGlobals.importCustomizationHelp,
+                                          "Help"));
+
+    ImportTableModel tableModel = new ImportTableModel();
+    customImporterTable = new JTable(tableModel);
+    TableColumnModel cm = customImporterTable.getColumnModel();
+    cm.getColumn(0).setPreferredWidth(GUIGlobals.IMPORT_DIALOG_COL_0_WIDTH);
+    cm.getColumn(1).setPreferredWidth(GUIGlobals.IMPORT_DIALOG_COL_1_WIDTH);
+    cm.getColumn(2).setPreferredWidth(GUIGlobals.IMPORT_DIALOG_COL_2_WIDTH);
+    cm.getColumn(3).setPreferredWidth(GUIGlobals.IMPORT_DIALOG_COL_3_WIDTH);
+    JScrollPane sp = new JScrollPane(customImporterTable, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
+                                     JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
+    customImporterTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+    customImporterTable.setPreferredScrollableViewportSize(getSize());
+    if (customImporterTable.getRowCount() > 0) {
+      customImporterTable.setRowSelectionInterval(0, 0);
+    }
+
+    // Key bindings:
+    ActionMap am = mainPanel.getActionMap();
+    InputMap im = mainPanel.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
+    im.put(frame.prefs().getKey("Close dialog"), "close");
+    am.put("close", closeAction);
+    mainPanel.setLayout(new BorderLayout());
+    mainPanel.add(sp, BorderLayout.CENTER);
+    optionsPanel.add(addFromFolderButton);
+    optionsPanel.add(addFromJarButton);
+    optionsPanel.add(showDescButton);
+    optionsPanel.add(removeButton);
+    optionsPanel.add(closeButton);
+    optionsPanel.add(Box.createHorizontalStrut(5));
+    optionsPanel.add(helpButton);
+
+    getContentPane().add(mainPanel, BorderLayout.CENTER);
+    getContentPane().add(optionsPanel, BorderLayout.SOUTH);
+    this.setSize(getSize());
+    pack();
+    Util.placeDialog(this, frame);
+    new FocusRequester(customImporterTable);
+  }
+
+  /**
+   * Table model for the custom importer table.
+   */
+  class ImportTableModel extends AbstractTableModel {
+    private String[] columnNames = new String[] {
+      Globals.lang("Import name"), 
+      Globals.lang("Command line id"),
+      Globals.lang("ImportFormat class"),
+      Globals.lang("Contained in")
+    };
+    
+    public Object getValueAt(int rowIndex, int columnIndex) {
+      Object value = null;
+      CustomImportList.Importer importer = getImporter(rowIndex);
+      if (columnIndex == 0) {
+        value = importer.getName();
+      } else if (columnIndex == 1) {
+        value = importer.getClidId();
+      } else if (columnIndex == 2) {
+        value = importer.getClassName();
+      } else if (columnIndex == 3) {
+        value = importer.getBasePath();
+      }
+      return value;
+    }
+    
+    public int getColumnCount() {
+      return columnNames.length;
+    }
+
+    public int getRowCount() {
+      return Globals.prefs.customImports.size();
+    }
+
+    public String getColumnName(int col) {
+      return columnNames[col];
+    }
+
+    public CustomImportList.Importer getImporter(int rowIndex) {
+      CustomImportList.Importer[] importers = (CustomImportList.Importer[])Globals.prefs.customImports.toArray(new CustomImportList.Importer[] {});
+      return importers[rowIndex];
+    }    
+  }
+
+}
diff --git a/src/java/net/sf/jabref/imports/ImportFormat.java b/src/java/net/sf/jabref/imports/ImportFormat.java
new file mode 100644
index 0000000..b6d4267
--- /dev/null
+++ b/src/java/net/sf/jabref/imports/ImportFormat.java
@@ -0,0 +1,156 @@
+package net.sf.jabref.imports;
+
+import java.io.InputStream;
+import java.io.IOException;
+import java.util.List;
+
+/**
+ * Role of an importer for JabRef.
+ * 
+ * <p>Importers are sorted according to following criteria
+ * <ol><li>
+ *   custom importers come first, then importers shipped with JabRef
+ * </li><li>
+ *   then importers are sorted by name.
+ * </li></ol>
+ * </p>
+ */
+public abstract class ImportFormat implements Comparable {
+
+    private boolean isCustomImporter;
+    
+    /**
+     * Constructor for custom importers.
+     */
+    public ImportFormat() {
+      this.isCustomImporter = false;
+    }
+
+    /**
+     * Check whether the source is in the correct format for this importer.
+     */
+    public abstract boolean isRecognizedFormat(InputStream in) throws IOException;
+
+    /**
+     * Parse the entries in the source, and return a List of BibtexEntry
+     * objects.
+     */
+    public abstract List importEntries(InputStream in) throws IOException;
+
+
+    /**
+     * Name of this import format.
+     * 
+     * <p>The name must be unique.</p>
+     * 
+     * @return format name, must be unique and not <code>null</code>
+     */
+    public abstract String getFormatName();
+    
+    /**
+     * Extensions that this importer can read.
+     * 
+     * @return comma separated list of extensions or <code>null</code> for the default
+     */
+    public String getExtensions() {
+      return null;
+    }
+    
+    /**
+     * Short, one token ID to identify the format from the command line.
+     * 
+     * @return command line ID
+     */
+    public String getCLIId() {
+      String id = getFormatName();
+      StringBuffer result = new StringBuffer(id.length());
+      for (int i = 0; i < id.length(); i++) {
+        char c = id.charAt(i);
+        if (Character.isLetterOrDigit(c)) {
+          result.append(Character.toLowerCase(c));
+        }
+      }
+      return result.toString();
+    }
+    
+    /**
+     * Description  of the ImportFormat.
+     * 
+     * <p>Implementors of ImportFormats should override this. Ideally, it should specify
+     * <ul><li>
+     *   what kind of entries from what sources and based on what specification it is able to import
+     * </li><li>
+     *   by what criteria it {@link #isRecognizedFormat(InputStream) recognizes} an import format
+     * </li></ul>
+     * 
+     * @return description of the import format
+     */
+    public String getDescription() {
+      return "No description available for " + getFormatName() + ".";
+    }
+    
+    /**
+     * Sets if this is a custom importer.
+     * 
+     * <p>For custom importers added dynamically to JabRef, this will be
+     * set automatically by JabRef.</p>
+     * 
+     * @param isCustomImporter if this is a custom importer
+     */
+    public final void setIsCustomImporter(boolean isCustomImporter) {
+      this.isCustomImporter = isCustomImporter;
+    }
+    
+    /**
+     * Wether this importer is a custom importer.
+     * 
+     * <p>Custom importers will have precedence over built-in importers.</p>
+     * 
+     * @return  wether this is a custom importer
+     */
+    public final boolean getIsCustomImporter() {
+      return this.isCustomImporter; 
+    }
+        
+    /*
+     *  (non-Javadoc)
+     * @see java.lang.Object#hashCode()
+     */
+    public int hashCode() {
+      return getFormatName().hashCode();
+    }
+    
+    /*
+     *  (non-Javadoc)
+     * @see java.lang.Object#equals(java.lang.Object)
+     */
+    public boolean equals(Object o) {
+      return o != null 
+          && o instanceof ImportFormat
+          && ((ImportFormat)o).getIsCustomImporter() == getIsCustomImporter() 
+          && ((ImportFormat)o).getFormatName().equals(getFormatName());
+    }
+    
+    /*
+     *  (non-Javadoc)
+     * @see java.lang.Object#toString()
+     */
+    public String toString() {
+      return getFormatName();
+    }
+    
+    /*
+     *  (non-Javadoc)
+     * @see java.lang.Comparable#compareTo(java.lang.Object)
+     */
+    public int compareTo(Object o) {
+      int result = 0;
+      ImportFormat importer = (ImportFormat)o;
+      if (getIsCustomImporter() == importer.getIsCustomImporter()) {
+        result = getFormatName().compareTo(importer.getFormatName());
+      } else {
+        result = getIsCustomImporter() ? 1 : -1;
+      }
+      return result;
+    }
+}
diff --git a/src/java/net/sf/jabref/imports/ImportFormatReader.java b/src/java/net/sf/jabref/imports/ImportFormatReader.java
new file mode 100644
index 0000000..fee48c8
--- /dev/null
+++ b/src/java/net/sf/jabref/imports/ImportFormatReader.java
@@ -0,0 +1,487 @@
+/*
+ * Copyright (C) 2003 Morten O. Alver and 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.imports;
+
+import net.sf.jabref.*;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+
+import java.util.SortedSet;
+import java.util.TreeSet;
+import java.util.Iterator;
+import java.util.List;
+
+import java.util.regex.*;
+
+
+/*
+ * // int jabrefframe BibtexDatabase database=new BibtexDatabase(); String
+ * filename=Globals.getNewFile(); ArrayList bibitems=readISI(filename); // is
+ * there a getFileName(); Iterator it = bibitems.iterator();
+ * while(it.hasNext()){ BibtexEntry entry = (BibtexEntry)it.next();
+ * entry.setId(Util.createId(entry.getType(), database); try {
+ * database.insertEntry(entry); } catch (KeyCollisionException ex) {
+ *  } }
+ */
+public class ImportFormatReader {
+
+    public static String BIBTEX_FORMAT = "BibTeX";
+    private final static String SPACE_MARKER = "__SPC__";
+    private final static Pattern bracketsPattern = Pattern.compile("\\{.*\\}"),
+	spaceMarkerPattern = Pattern.compile(SPACE_MARKER);
+
+  /** all import formats, in the defalt order of import formats */
+  private SortedSet formats = new TreeSet();
+
+  public ImportFormatReader() {
+    super();
+  }
+
+  public void resetImportFormats() {
+    formats.clear();
+    
+    // Add all our importers to the TreeMap. The map is used to build the import
+    // menus, and .
+    formats.add(new CsaImporter());   
+    formats.add(new IsiImporter());
+    formats.add(new EndnoteImporter());
+    formats.add(new MedlineImporter());
+    formats.add(new BibteXMLImporter());
+    formats.add(new BiblioscapeImporter());
+    formats.add(new SixpackImporter());
+    formats.add(new InspecImporter());
+    formats.add(new ScifinderImporter());
+    formats.add(new OvidImporter());
+    formats.add(new RisImporter());
+    formats.add(new JstorImporter());
+    formats.add(new SilverPlatterImporter());
+    formats.add(new BiomailImporter());
+    formats.add(new RepecNepImporter());    
+    
+    // add all custom importers
+    for (Iterator i = Globals.prefs.customImports.iterator(); i.hasNext(); ) {
+      CustomImportList.Importer importer = (CustomImportList.Importer)i.next();
+
+      try {
+        ImportFormat imFo = importer.getInstance();
+        formats.add(imFo);
+      } catch(Exception e) {
+        System.err.println("Could not instantiate " + importer.getName() + " importer, will ignore it. Please check if the class is still available.");
+        e.printStackTrace();
+      }      
+    }
+  }
+  
+  /**
+   * Format for a given CLI-ID.
+   * 
+   * <p>Will return the first format according to the default-order of
+   * format that matches the given ID.</p>
+   * 
+   * @param cliId  CLI-Id
+   * @return  Import Format or <code>null</code> if none matches
+   */
+  public ImportFormat getByCliId(String cliId) {
+    ImportFormat result = null;
+    for (Iterator i = formats.iterator(); i.hasNext() && result == null; ) {
+      ImportFormat format = (ImportFormat)i.next();
+      if (format.getCLIId().equals(cliId)) {
+        result = format;
+      }
+    }
+    return result;
+  }
+  
+  public List importFromStream(String format, InputStream in)
+    throws IOException {
+    ImportFormat importer = getByCliId(format);
+
+    if (importer == null)
+      throw new IllegalArgumentException("Unknown import format: " + format);
+
+    List res = importer.importEntries(in);
+
+    // Remove all empty entries
+    if (res != null)
+      purgeEmptyEntries(res);
+
+    return res;
+  }
+
+  public List importFromFile(String format, String filename)
+    throws IOException {
+    ImportFormat importer = getByCliId(format);
+
+    if (importer == null)
+      throw new IllegalArgumentException("Unknown import format: " + format);
+
+    return importFromFile(importer, filename);
+  }
+
+  public List importFromFile(ImportFormat importer, String filename)
+    throws IOException {
+    File file = new File(filename);
+    InputStream stream = new FileInputStream(file);
+
+    if (!importer.isRecognizedFormat(stream))
+      throw new IOException(Globals.lang("Wrong file format"));
+
+    stream = new FileInputStream(file);
+
+    return importer.importEntries(stream);
+  }
+
+  public static BibtexDatabase createDatabase(List bibentries) {
+    purgeEmptyEntries(bibentries);
+
+    BibtexDatabase database = new BibtexDatabase();
+
+    for (Iterator i = bibentries.iterator(); i.hasNext();) {
+      BibtexEntry entry = (BibtexEntry) i.next();
+
+      try {
+        entry.setId(Util.createNeutralId());
+        database.insertEntry(entry);
+      } catch (KeyCollisionException ex) {
+        //ignore
+        System.err.println("KeyCollisionException [ addBibEntries(...) ]");
+      }
+    }
+
+    return database;
+  }
+
+  /**
+   * All custom importers.
+   * 
+   * <p>Elements are in default order.</p>
+   * 
+   * @return all custom importers, elements are of type {@link InputFormat}
+   */
+  public SortedSet getCustomImportFormats() {
+    SortedSet result = new TreeSet();
+    for (Iterator i = this.formats.iterator(); i.hasNext(); ) {
+      ImportFormat format = (ImportFormat)i.next();
+      if (format.getIsCustomImporter()) {
+        result.add(format);  
+      }
+    }
+    return result;
+  }
+  
+  /**
+   * All built-in importers.
+   * 
+   * <p>Elements are in default order.</p>
+   * 
+   * @return all custom importers, elements are of type {@link InputFormat}
+   */
+  public SortedSet getBuiltInInputFormats() {
+    SortedSet result = new TreeSet();
+    for (Iterator i = this.formats.iterator(); i.hasNext(); ) {
+      ImportFormat format = (ImportFormat)i.next();
+      if (!format.getIsCustomImporter()) {
+        result.add(format);  
+      }
+    }
+    return result;    
+  }
+  
+  /**
+   * All importers.
+   * 
+   * <p>Elements are in default order.</p>
+   * 
+   * @return all custom importers, elements are of type {@link InputFormat}
+   */
+  public SortedSet getImportFormats() {
+    return this.formats;
+  }
+
+  /**
+   * Human readable list of all known import formats (name and CLI Id).
+   * 
+   * <p>List is in default-order.</p>
+   * 
+   * @return  human readable list of all known import formats
+   */
+  public String getImportFormatList() {
+    StringBuffer sb = new StringBuffer();
+
+    for (Iterator i = this.formats.iterator(); i.hasNext();) {
+      ImportFormat imFo = (ImportFormat)i.next();
+      int pad = Math.max(0, 14 - imFo.getFormatName().length());
+      sb.append("  ");
+      sb.append(imFo.getFormatName());
+
+      for (int j = 0; j < pad; j++)
+        sb.append(" ");
+
+      sb.append(" : ");
+      sb.append(imFo.getCLIId());
+      sb.append("\n");
+    }
+
+    String res = sb.toString();
+
+    return res; //.substring(0, res.length()-1);
+  }
+
+
+    /**
+     * Expand initials, e.g. EH Wissler -> E. H. Wissler or Wissler, EH -> Wissler, E. H.
+     * @param name
+     * @return The name after expanding initials.
+     */
+    public static String expandAuthorInitials(String name) {
+      String[] authors = name.split(" and ");
+      StringBuffer sb = new StringBuffer();
+      for (int i=0; i<authors.length; i++) {
+          if (authors[i].indexOf(", ") >= 0) {
+              String[] names = authors[i].split(", ");
+              if (names.length > 0) {
+                  sb.append(names[0]);
+                  if (names.length > 1)
+                    sb.append(", ");
+              }
+              for (int j=1; j<names.length; j++) {
+                  sb.append(expandAll(names[j]));
+              }
+
+          } else {
+              String[] names = authors[i].split(" ");
+              if (names.length > 0) {
+                  sb.append(expandAll(names[0]));
+              }
+              for (int j=1; j<names.length; j++) {
+                  sb.append(" ");
+                  sb.append(names[j]);
+              }
+          }
+          if (i < authors.length-1)
+              sb.append(" and ");
+      }
+
+      return sb.toString().trim();
+  }
+  
+//------------------------------------------------------------------------------
+
+
+    public static String expandAll(String s) {
+        //System.out.println("'"+s+"'");
+        // Avoid arrayindexoutof.... :
+        if (s.length() == 0)
+          return s;
+        // If only one character (uppercase letter), add a dot and return immediately:
+        if ((s.length() == 1) && (Character.isLetter(s.charAt(0)) &&
+                Character.isUpperCase(s.charAt(0))))
+          return s+".";
+        StringBuffer sb = new StringBuffer();
+        char c = s.charAt(0), d = 0;
+        for (int i=1; i<s.length(); i++) {
+            d = s.charAt(i);
+            if (Character.isLetter(c) && Character.isUpperCase(c) &&
+                    Character.isLetter(d) && Character.isUpperCase(d)) {
+                sb.append(c);
+                sb.append(". ");
+            }
+            else {
+                sb.append(c);
+            }
+            c = d;
+        }
+        if (Character.isLetter(c) && Character.isUpperCase(c) &&
+              Character.isLetter(d) && Character.isUpperCase(d)) {
+            sb.append(c);
+            sb.append(". ");
+        }
+        else {
+            sb.append(c);
+        }
+        return sb.toString().trim();
+    }
+
+
+  static File checkAndCreateFile(String filename) {
+    File f = new File(filename);
+
+    if (!f.exists() && !f.canRead() && !f.isFile()) {
+      System.err.println("Error " + filename
+        + " is not a valid file and|or is not readable.");
+      Globals.logger("Error " + filename + " is not a valid file and|or is not readable.");
+
+      return null;
+    } else
+
+      return f;
+  }
+
+  //==================================================
+  // Set a field, unless the string to set is empty.
+  //==================================================
+  public static void setIfNecessary(BibtexEntry be, String field, String content) {
+    if (!content.equals(""))
+      be.setField(field, content);
+  }
+
+
+
+    public static Reader getReader(File f, String encoding)
+      throws IOException {
+      InputStreamReader reader;
+      reader = new InputStreamReader(new FileInputStream(f), encoding);
+
+      return reader;
+    }
+
+  public static Reader getReaderDefaultEncoding(InputStream in)
+    throws IOException {
+    InputStreamReader reader;
+    reader = new InputStreamReader(in, Globals.prefs.get("defaultEncoding"));
+
+    return reader;
+  }
+
+  public static BibtexDatabase import_File(String format, String filename)
+    throws IOException {
+    BibtexDatabase database = null;
+    List bibentries = null;
+    File f = new File(filename);
+
+    if (!f.exists())
+      throw new IOException(Globals.lang("File not found") + ": " + filename);
+
+    try {
+      bibentries = Globals.importFormatReader.importFromFile(format, filename);
+    } catch (IllegalArgumentException ex) {
+      throw new IOException(Globals.lang("Could not resolve import format") + " '"
+        + format + "'");
+    }
+
+    if (bibentries == null)
+      throw new IOException(Globals.lang("Import failed"));
+
+    // Remove all empty entries:
+    purgeEmptyEntries(bibentries);
+
+    // Add entries to database.
+    database = new BibtexDatabase();
+
+    Iterator it = bibentries.iterator();
+
+    while (it.hasNext()) {
+      BibtexEntry entry = (BibtexEntry) it.next();
+
+      try {
+        entry.setId(Util.createNeutralId());
+        database.insertEntry(entry);
+      } catch (KeyCollisionException ex) {
+        //ignore
+        System.err.println("KeyCollisionException [ addBibEntries(...) ]");
+      }
+    }
+
+    return database;
+  }
+
+  /**
+   * Receives an ArrayList of BibtexEntry instances, iterates through them, and
+   * removes all entries that have no fields set. This is useful for rooting out
+   * an unsucessful import (wrong format) that returns a number of empty entries.
+   */
+  public static void purgeEmptyEntries(List entries) {
+    for (Iterator i = entries.iterator(); i.hasNext();) {
+      BibtexEntry entry = (BibtexEntry) i.next();
+
+      // Get all fields of the entry:
+      Object[] o = entry.getAllFields();
+
+      // If there are no fields, remove the entry:
+      if (o.length == 0)
+        i.remove();
+    }
+  }
+
+  /**
+   * Tries to import a file by iterating through the available import filters,
+   * and keeping the import that seems most promising. Returns an Object array
+   * with two elements, 0: the name of the format used, 1: a List of entries.
+   */
+  public Object[] importUnknownFormat(String filename) {
+    Object entryList = null;
+    String usedFormat = null;
+    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;
+        }
+      } catch (IOException ex) {
+	  //ex.printStackTrace();
+        //System.out.println("Import failed");
+      }
+    }
+
+    // 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"));
+	    if ((pr.getDatabase().getEntryCount() > 0)
+		|| (pr.getDatabase().getStringCount() > 0)) {
+		entryList = pr;
+        pr.setFile(new File(filename));
+		usedFormat = BIBTEX_FORMAT;
+	    }
+	} catch (Throwable ex) {
+	    //ex.printStackTrace();
+	}
+	
+    }
+
+    return new Object[] { usedFormat, entryList };
+  }
+}
diff --git a/src/java/net/sf/jabref/imports/ImportMenuItem.java b/src/java/net/sf/jabref/imports/ImportMenuItem.java
new file mode 100644
index 0000000..d841eb1
--- /dev/null
+++ b/src/java/net/sf/jabref/imports/ImportMenuItem.java
@@ -0,0 +1,105 @@
+package net.sf.jabref.imports;
+
+import javax.swing.*;
+import java.awt.event.*;
+import java.io.IOException;
+import java.io.File;
+
+import net.sf.jabref.*;
+import net.sf.jabref.gui.ImportInspectionDialog;
+
+
+public class ImportMenuItem extends JMenuItem implements ActionListener,
+        ImportInspectionDialog.CallBack {
+    
+    ImportFormat importer;
+    JabRefFrame frame;
+    boolean openInNew;
+
+    public ImportMenuItem(JabRefFrame frame, ImportFormat importer, boolean openInNew) {
+    	super(importer.getFormatName());
+    	this.frame = frame;
+    	this.importer = importer;
+    	this.openInNew = openInNew;
+      this.setToolTipText( importer.getDescription() );
+    	addActionListener(this);
+    }
+
+    public void actionPerformed(ActionEvent e) {
+    	MyWorker worker = new MyWorker();
+    	worker.init();
+    	worker.getWorker().run();
+    	worker.getCallBack().update();
+    }
+
+    class MyWorker extends AbstractWorker {
+    	String filename = null, formatName = null;
+    	java.util.List entries = null;
+    	boolean fileOk = false;
+    	public void init() {
+  	    filename = Globals.getNewFile(frame, Globals.prefs, new File(Globals.prefs.get("workingDirectory")),
+          importer.getExtensions(), JFileChooser.OPEN_DIALOG, false);
+  	    if ((filename != null) && !(new File(filename)).exists()) {
+      		JOptionPane.showMessageDialog(frame, Globals.lang("File not found")+": '"+filename+"'",
+					      Globals.lang("Import failed"), JOptionPane.ERROR_MESSAGE);
+	    }
+	    else if (filename != null) {
+    		frame.block();
+    		frame.output(Globals.lang("Importing file")+": '"+filename+"'");
+    		fileOk = true;
+            Globals.prefs.put("workingDirectory", filename);
+        }
+	    
+	}
+	public void run() {
+	    if (!fileOk)
+		return;
+	    
+	    try {
+		entries = Globals.importFormatReader.importFromFile(importer, filename);
+		if (entries != null)
+		    ImportFormatReader.purgeEmptyEntries(entries);
+	    } catch (IOException ex) {
+		ex.printStackTrace();
+	    }
+	}
+	public void update() {
+	    if (!fileOk)
+		return;
+
+	    if (entries != null) {
+            BasePanel panel = null;
+            if (!openInNew) {
+                panel = (BasePanel)frame.getTabbedPane().getSelectedComponent();
+            }
+
+            frame.addImportedEntries(panel, entries, filename, openInNew, ImportMenuItem.this);
+            
+
+	    } else {
+		JOptionPane.showMessageDialog(frame, Globals.lang("No entries found. Please make sure you are "
+								  +"using the correct import filter."), Globals.lang("Import failed"),
+					      JOptionPane.ERROR_MESSAGE);
+		frame.output("");
+	    }
+	    frame.unblock();
+	    
+	}
+    }
+
+    public void done(int entriesImported) {
+        frame.output(Globals.lang("Imported entries")+": "+entriesImported);
+    }
+
+    public void cancelled() {
+        frame.output(Globals.lang("%0 import cancelled.", importer.getFormatName()));
+    }
+
+
+    // This method is called by the dialog when the user has cancelled or
+    // signalled a stop. It is expected that any long-running fetch operations
+    // will stop after this method is called.
+    public void stopFetching() {
+        // No process to stop.
+    }
+}
diff --git a/src/java/net/sf/jabref/imports/ImportUnknownMenuItem.java b/src/java/net/sf/jabref/imports/ImportUnknownMenuItem.java
new file mode 100644
index 0000000..ff33adb
--- /dev/null
+++ b/src/java/net/sf/jabref/imports/ImportUnknownMenuItem.java
@@ -0,0 +1,126 @@
+package net.sf.jabref.imports;
+
+import net.sf.jabref.*;
+import net.sf.jabref.gui.ImportInspectionDialog;
+
+import javax.swing.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.File;
+
+public class ImportUnknownMenuItem extends JMenuItem implements ActionListener,
+        ImportInspectionDialog.CallBack {
+    
+    JabRefFrame frame;
+    boolean openInNew;
+    MyWorker worker = null;
+
+    public ImportUnknownMenuItem(JabRefFrame frame, boolean openInNew) {
+	super(Globals.lang("Autodetect format"));
+	this.frame = frame;
+	this.openInNew = openInNew;
+	addActionListener(this);
+    }
+
+    public void actionPerformed(ActionEvent e) {
+	worker = new MyWorker();
+	worker.init();
+	worker.getWorker().run();
+	worker.getCallBack().update();
+    }
+
+    class MyWorker extends AbstractWorker {
+	String filename = null, formatName = null;
+	java.util.List entries = null;
+	ParserResult bibtexResult = null; // Used for a parsed Bibtex database, if that is the
+	// correct format. Must be handled differently, because it can contain metadata and strings.
+	boolean fileOk = false;
+	public void init() {
+	    filename = frame.getNewFile();
+	    if ((filename != null) && !(new File(filename)).exists()) {
+		JOptionPane.showMessageDialog(frame, Globals.lang("File not found")+": '"+filename+"'",
+					      Globals.lang("Error"), JOptionPane.ERROR_MESSAGE);
+	    }
+	    else if (filename != null) {
+		frame.block();
+		frame.output(Globals.lang("Importing file")+": '"+filename+"'");
+		fileOk = true;
+        Globals.prefs.put("workingDirectory", filename);
+        }
+	    
+	}
+	public void run() {
+	    if (!fileOk)
+		return;
+	    
+	    //try {
+		Object[] o = Globals.importFormatReader.importUnknownFormat(filename);
+		formatName = (String)o[0];
+		if (o[1] instanceof java.util.List)
+		    entries = (java.util.List)o[1];
+		else if (o[1] instanceof ParserResult)
+		    bibtexResult = (ParserResult)o[1];
+	    //} catch (IOException ex) {
+		//ex.printStackTrace();
+	    //}
+	}
+	public void update() {
+	    if (!fileOk)
+		return;
+	    
+	    if (entries != null) {
+            BasePanel panel = null;
+            if (!openInNew) {
+                panel = (BasePanel)frame.getTabbedPane().getSelectedComponent();
+            }
+            frame.addImportedEntries(panel, entries, filename, openInNew, ImportUnknownMenuItem.this);
+            
+
+	    }
+	    else if (bibtexResult != null) {
+            if (!openInNew) {
+                BasePanel panel = (BasePanel)frame.getTabbedPane().getSelectedComponent();
+                try {
+                    panel.mergeFromBibtex(bibtexResult, true, true, false, false);
+                    frame.output(Globals.lang("Imported from database")+" '"+filename+"'");
+                } catch (KeyCollisionException e) {
+                    e.printStackTrace();
+                }
+
+            } else {
+		        frame.addTab(bibtexResult.getDatabase(), bibtexResult.getFile(),
+			        bibtexResult.getMetaData(), Globals.prefs.get("defaultEncoding"), true);
+		        frame.output(Globals.lang("Opened database") + " '" + filename +
+			        "' " + Globals.lang("with") + " " +
+			        bibtexResult.getDatabase() .getEntryCount() + " " +
+			        Globals.lang("entries") + ".");
+            }
+
+	    }
+	    else
+		frame.output(Globals.lang("Could not find a suitable import format."));
+	    frame.unblock();
+	}
+    }
+
+    public void done(int entriesImported) {
+        if (worker.entries != null) {
+            frame.output(Globals.lang("Imported entries")+": "+entriesImported
+    			     +"  "+Globals.lang("Format used")+": "+worker.formatName);
+        }
+    }
+
+    public void cancelled() {
+        frame.output(Globals.lang("Import cancelled."));
+    }
+
+
+    // This method is called by the dialog when the user has cancelled or
+    // signalled a stop. It is expected that any long-running fetch operations
+    // will stop after this method is called.
+    public void stopFetching() {
+        // No process to stop.
+    }
+
+
+}
diff --git a/src/java/net/sf/jabref/imports/InspecImporter.java b/src/java/net/sf/jabref/imports/InspecImporter.java
new file mode 100644
index 0000000..876dd59
--- /dev/null
+++ b/src/java/net/sf/jabref/imports/InspecImporter.java
@@ -0,0 +1,138 @@
+package net.sf.jabref.imports;
+
+import java.io.InputStream;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.HashMap;
+import net.sf.jabref.BibtexEntry;
+import net.sf.jabref.Globals;
+import net.sf.jabref.AuthorList;
+
+import java.util.regex.Pattern;
+
+/**
+ * INSPEC format importer.
+ */
+public class InspecImporter extends ImportFormat {
+
+    /**
+     * Return the name of this import format.
+     */
+    public String getFormatName() {
+	return "INSPEC";
+    }
+
+  /*
+   *  (non-Javadoc)
+   * @see net.sf.jabref.imports.ImportFormat#getCLIId()
+   */
+  public String getCLIId() {
+    return "inspec";
+  }
+    
+  /**
+   * 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}");
+    Pattern pat1 = Pattern.compile("Record.*INSPEC.*");
+
+    //was PY \\\\d{4}? before
+    String str;
+
+    while ((str = in.readLine()) != null) {
+      //Inspec and IEEE seem to have these strange " - " between key and value
+      //str = str.replace(" - ", "");
+      //System.out.println(str);
+
+      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));
+	String str;
+	while ((str = in.readLine()) != null){
+	    if (str.length() < 2) continue;
+	    if (str.indexOf("Record") == 0) sb.append("__::__").append(str);
+	    else
+            sb.append("__NEWFIELD__").append(str);
+	}
+	in.close();
+	String[] entries = sb.toString().split("__::__");
+	String Type = "";
+	HashMap h = new HashMap();
+	for (int i = 0; i < entries.length; i++){
+	    if (entries[i].indexOf("Record") != 0) continue;
+	    h.clear();
+	    
+	    String[] fields = entries[i].split("__NEWFIELD__");
+	    for (int j = 0; j < fields.length; j++){
+		//System.out.println(fields[j]);
+		String s = fields[j];
+		String f3 = s.substring(0, 2);
+		String frest = s.substring(5);
+		if (f3.equals("TI")) h.put("title", frest);
+		else if (f3.equals("PY")) h.put("year", frest);
+		else if (f3.equals("AU")) h.put("author",
+						AuthorList.fixAuthor_lastNameFirst(frest.replaceAll(",-", ", ").replaceAll(
+                                                        ";", " and ")));
+		else if (f3.equals("AB")) h.put("abstract", frest);
+		else if (f3.equals("ID")) h.put("keywords", frest);
+		else if (f3.equals("SO")){
+		    int m = frest.indexOf(".");
+		    if (m >= 0){
+			String jr = frest.substring(0, m);
+			h.put("journal", jr.replaceAll("-", " "));
+			frest = frest.substring(m);
+			m = frest.indexOf(";");
+			if (m >= 5){
+			    String yr = frest.substring(m - 5, m);
+			    h.put("year", yr);
+			    frest = frest.substring(m);
+			    m = frest.indexOf(":");
+			    if (m >= 0){
+				String pg = frest.substring(m + 1).trim();
+				h.put("pages", pg);
+				h.put("volume", frest.substring(1, m));
+			    }
+			}
+		    }
+		    
+		}else if (f3.equals("RT")){
+		    frest = frest.trim();
+		    if (frest.equals("Journal-Paper")) Type = "article";
+		    else if (frest.equals("Conference-Paper")
+			     || frest.equals("Conference-Paper; Journal-Paper")) Type = "inproceedings";
+		    else Type = frest.replaceAll(" ", "");
+		}
+	    }
+	    BibtexEntry b = new BibtexEntry(Globals.DEFAULT_BIBTEXENTRY_ID, Globals
+					    .getEntryType(Type)); // id assumes an existing database so don't
+	    // create one here
+	    b.setField(h);
+	    
+	    bibitems.add(b);
+	    
+	}
+    
+	return bibitems;
+    }
+}
+
+
diff --git a/src/java/net/sf/jabref/imports/IsiImporter.java b/src/java/net/sf/jabref/imports/IsiImporter.java
new file mode 100644
index 0000000..3b502a6
--- /dev/null
+++ b/src/java/net/sf/jabref/imports/IsiImporter.java
@@ -0,0 +1,235 @@
+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.regex.Pattern;
+
+
+/**
+ * Importer for the ISI Web of Science format.
+ */
+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(Globals.DEFAULT_BIBTEXENTRY_ID, Globals.getEntryType(Type)); // id assumes an existing database so don't
+
+      // create one here
+      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();
+    }
+
+}
diff --git a/src/java/net/sf/jabref/imports/JstorImporter.java b/src/java/net/sf/jabref/imports/JstorImporter.java
new file mode 100644
index 0000000..7bf1ae7
--- /dev/null
+++ b/src/java/net/sf/jabref/imports/JstorImporter.java
@@ -0,0 +1,92 @@
+package net.sf.jabref.imports;
+
+import java.io.InputStream;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.util.List;
+import java.util.ArrayList;
+import net.sf.jabref.BibtexEntry;
+import net.sf.jabref.BibtexEntryType;
+import net.sf.jabref.Util;
+import net.sf.jabref.AuthorList;
+
+/**
+ * Imports a Biblioscape Tag File. The format is described on
+ * http://www.biblioscape.com/manual_bsp/Biblioscape_Tag_File.htm Several
+ * Biblioscape field types are ignored. Others are only included in the BibTeX
+ * field "comment".
+ */
+public class JstorImporter extends ImportFormat {
+
+    /**
+     * Return the name of this import format.
+     */
+    public String getFormatName() {
+    return "JStor (tab delimited)";
+    }
+
+    /*
+     *  (non-Javadoc)
+     * @see net.sf.jabref.imports.ImportFormat#getCLIId()
+     */
+    public String getCLIId() {
+      return "jstor";
+    }
+    
+    /**
+     * Check whether the source is in the correct format for this importer.
+     */
+    public boolean isRecognizedFormat(InputStream in) throws IOException {
+    return true;
+    }
+
+    /**
+     * Parse the entries in the source, and return a List of BibtexEntry
+     * objects.
+     */
+    public List importEntries(InputStream stream) throws IOException {
+    ArrayList bibitems = new ArrayList();
+    String s = "";
+    BufferedReader in = new BufferedReader(ImportFormatReader.getReaderDefaultEncoding(stream));
+    while ((s != null) && !s.startsWith("Item Type"))
+        s = in.readLine();
+
+    mainloop: while ((s = in.readLine()) != null){
+        if (s.equals("")) continue;
+        if (s.startsWith("-----------------------------")) break mainloop;
+        String[] fields = s.split("\t");
+        BibtexEntry be = new BibtexEntry(Util.createNeutralId());
+        try{
+        if (fields[0].equals("FLA")) be.setType(BibtexEntryType
+                            .getType("article"));
+        ImportFormatReader.setIfNecessary(be, "title", fields[2]);
+        ImportFormatReader.setIfNecessary(be, "author", AuthorList.fixAuthor_lastNameFirst(fields[4].replaceAll("; ", " and ")));
+        ImportFormatReader.setIfNecessary(be, "journal", fields[7]);
+        ImportFormatReader.setIfNecessary(be, "volume", fields[9]);
+        ImportFormatReader.setIfNecessary(be, "number", fields[10]);
+        String[] datefield = fields[12].split(" ");
+        ImportFormatReader.setIfNecessary(be, "year", datefield[datefield.length - 1]);
+        if (datefield.length > 1) {
+            if (datefield[0].endsWith(","))
+                datefield[0] = datefield[0].substring(0, datefield[0].length()-1);
+            ImportFormatReader.setIfNecessary(be, "month", datefield[0]);
+        }
+        //for (int i=0; i<fields.length; i++)
+        //  Util.pr(i+": "+fields[i]);
+        ImportFormatReader.setIfNecessary(be, "pages", fields[13].replaceAll("-", "--"));
+        ImportFormatReader.setIfNecessary(be, "url", fields[14]);
+        ImportFormatReader.setIfNecessary(be, "issn", fields[15]);
+        ImportFormatReader.setIfNecessary(be, "abstract", fields[16]);
+        ImportFormatReader.setIfNecessary(be, "keywords", fields[17]);
+        ImportFormatReader.setIfNecessary(be, "copyright", fields[21]);
+        }catch (ArrayIndexOutOfBoundsException ex){
+        }
+        bibitems.add(be);
+    }
+
+    return bibitems;
+
+    }
+}
+
+
diff --git a/src/java/net/sf/jabref/imports/MedlineFetcher.java b/src/java/net/sf/jabref/imports/MedlineFetcher.java
new file mode 100644
index 0000000..a3c56e4
--- /dev/null
+++ b/src/java/net/sf/jabref/imports/MedlineFetcher.java
@@ -0,0 +1,484 @@
+package net.sf.jabref.imports;
+
+import java.util.ArrayList;
+import java.net.*;
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.ActionListener;
+import javax.xml.parsers.SAXParserFactory;
+import javax.xml.parsers.SAXParser;
+import java.awt.event.ActionEvent;
+import java.awt.event.FocusAdapter;
+import java.awt.event.FocusEvent;
+import java.util.Iterator;
+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 net.sf.jabref.HelpAction;
+import net.sf.jabref.gui.ImportInspectionDialog;
+
+/**
+ * <p>Title: </p>
+ * <p>Description: </p>
+ * <p>Copyright: Copyright (c) 2003</p>
+ * <p>Company: </p>
+ * @author not attributable
+ * @version 1.0
+ */
+
+public class MedlineFetcher extends SidePaneComponent implements Runnable,
+        ImportInspectionDialog.CallBack {
+
+    /**@class SearchResult
+     *        nested class.
+     */
+    public class SearchResult {
+	public int count;
+	public int retmax;
+	public int retstart;
+	public String ids = "";
+    public ArrayList idList = new ArrayList();
+	public SearchResult()
+	    {
+		count = 0;
+		retmax = 0;
+		retstart = 0;
+	    }
+
+	public void addID(String id)
+        {
+
+        idList.add(id);
+		if(!ids.equals(""))
+		    ids += ","+id;
+		else
+		    ids = id;
+	    }
+    }
+    final int PACING = 20;
+    final int MAX_TO_FETCH = 10;
+    boolean keepOn = true;
+    String idList;
+    JTextField tf = new JTextField();
+    JPanel pan = new JPanel();
+    GridBagLayout gbl = new GridBagLayout();
+    GridBagConstraints con = new GridBagConstraints();
+    MedlineFetcher ths = this;
+    AuthorDialog authorDialog;
+    JFrame jFrame; // invisible dialog holder
+    JButton go = new JButton(Globals.lang("Fetch")),
+	helpBut = new JButton(new ImageIcon(GUIGlobals.helpIconFile));
+    HelpAction help;
+    
+    public MedlineFetcher(SidePaneManager p0) {
+	super(p0, GUIGlobals.fetchMedlineIcon, Globals.lang("Fetch Medline"));
+
+	help = new HelpAction(Globals.helpDiag, GUIGlobals.medlineHelp, "Help");
+	helpBut.addActionListener(help);
+	helpBut.setMargin(new Insets(0,0,0,0));        
+	//tf.setMinimumSize(new Dimension(1,1));
+	//add(hd, BorderLayout.NORTH);
+	//ok.setToolTipText(Globals.lang("Fetch Medline"));
+        JPanel main = new JPanel();
+    	main.setLayout(gbl);
+	con.fill = GridBagConstraints.BOTH;
+	//con.insets = new Insets(0, 0, 2,  0);
+	con.gridwidth = GridBagConstraints.REMAINDER;
+	con.weightx = 1;
+	con.weighty = 1;
+	con.fill = GridBagConstraints.BOTH;
+	gbl.setConstraints(tf, con);
+	main.add(tf);
+	con.weighty = 0;
+	con.gridwidth = 1;
+	gbl.setConstraints(go, con);
+	main.add(go);
+	con.gridwidth = GridBagConstraints.REMAINDER;
+	gbl.setConstraints(helpBut, con);
+	main.add(helpBut);
+	ActionListener listener = new ActionListener() {
+		public void actionPerformed(ActionEvent e) {
+		    (new Thread(ths)).start(); // Run fetch in thread.
+		}
+	    };
+        main.setBorder(BorderFactory.createEmptyBorder(1,1,1,1));
+	add(main, BorderLayout.CENTER);
+	go.addActionListener(listener);
+	tf.addActionListener(listener);
+        tf.addFocusListener(new FocusAdapter() {
+            public void focusGained(FocusEvent event) {
+                if (!event.isTemporary() && (tf.getText().length()>0)) {
+                    tf.selectAll();
+                }
+            }
+        });
+    }
+    
+    public JTextField getTextField() {
+        return tf;
+    }
+    
+    public void fetchById() {
+	//if(idList==null || idList.trim().equals(""))//if user pressed cancel
+	//  return;
+	Pattern p = Pattern.compile("\\d+[,\\d+]*");
+	//System.out.println(""+p+"\t"+idList);
+	Matcher m = p.matcher( idList );
+	if ( m.matches() ) {
+	    panel.frame().output(Globals.lang("Fetching Medline by ID..."));
+	    
+	    ArrayList bibs = fetchMedline(idList);
+	    if ((bibs != null) && (bibs.size() > 0)) {
+		//if (panel.prefs().getBoolean("useOwner")) {
+		//    Util.setDefaultOwner(bibs, panel.prefs().get("defaultOwner"));
+		//}
+		tf.setText("");
+		/*NamedCompound ce = new NamedCompound("fetch Medline");
+		Iterator i = bibs.iterator();
+		while (i.hasNext()) {
+		    try {
+			BibtexEntry be = (BibtexEntry) i.next();
+			String id = Util.createId(be.getType(), panel.database());
+			be.setId(id);
+			entries.add(be);
+			//panel.database().insertEntry(be);
+			//ce.addEdit(new UndoableInsertEntry(panel.database(), be, panel));
+		    }
+		    catch (KeyCollisionException ex) {
+		    }
+		    }*/
+		//ce.end();
+
+        panel.frame().addImportedEntries(panel, bibs, null, false, this);
+
+        /*
+		int importedEntries = panel.frame().addBibEntries(bibs, null, false);
+        if (importedEntries == 0) {
+            return; // Nothing to refresh!
+        }
+        panel.markBaseChanged();
+		panel.refreshTable();
+        if (bibs.size() > 0) {
+            BibtexEntry[] entries = (BibtexEntry[])bibs.toArray(new BibtexEntry[0]);
+            panel.selectEntries(entries, 0);
+            if (entries.length == 1)
+                panel.showEntry(entries[0]);
+            //else
+            //    panel.updateViewToSelected();
+        }*/
+
+		//panel.undoManager.addEdit(ce);
+	    } else
+		panel.output(Globals.lang("No Medline entries found."));
+	} else {
+	    JOptionPane.showMessageDialog(panel.frame(),Globals.lang("Please enter a semicolon or comma separated list of Medline IDs (numbers)."),Globals.lang("Input error"),JOptionPane.ERROR_MESSAGE);
+	}
+    }
+    
+    
+
+//==================================================
+//
+//==================================================
+  public static ArrayList fetchMedline(String id)
+  {
+    ArrayList bibItems=null;
+    try {
+
+      String baseUrl = "http://eutils.ncbi.nlm.nih.gov/entrez/eutils/efetch.fcgi?db=pubmed&retmode=xml&rettype=citation&id=" + id;
+
+      URL url = new URL( baseUrl );
+      HttpURLConnection data = (HttpURLConnection)url.openConnection();
+
+
+       /* Reader un = new InputStreamReader(data.getInputStream());
+        int c;
+        while ((c=un.read()) != -1) {
+          System.out.print((char)c);
+        }*/
+        
+        
+        // Obtain a factory object for creating SAX parsers
+        SAXParserFactory parserFactory = SAXParserFactory.newInstance();
+        // Configure the factory object to specify attributes of the parsers it creates
+        parserFactory.setValidating(true);
+        parserFactory.setNamespaceAware(true);
+
+        // Now create a SAXParser object
+        SAXParser parser = parserFactory.newSAXParser();   //May throw exceptions
+        MedlineHandler handler = new MedlineHandler();
+        // Start the parser. It reads the file and calls methods of the handler.
+
+        parser.parse( data.getInputStream(), handler);
+	/*FileOutputStream out = new FileOutputStream(new File("/home/alver/ut.txt"));
+	System.out.println("#####");
+	InputStream is = data.getInputStream();
+	int c;
+	while ((c = is.read()) != -1) {
+	    out.write((char)c);
+	}
+	System.out.println("#####");
+	out.close();*/
+        // When you're done, report the results stored by your handler object
+        bibItems = handler.getItems();
+
+    }
+    catch(javax.xml.parsers.ParserConfigurationException e1){}
+    catch(org.xml.sax.SAXException e2){}
+    catch(java.io.IOException e3){}
+    return bibItems;
+}
+
+   public void run() {
+
+	idList = tf.getText().replace(';', ',');
+
+	//if(idList==null || idList.trim().equals(""))//if user pressed cancel
+	//    return;
+        Pattern p1 = Pattern.compile("\\d+[,\\d+]*"),
+            p2 = Pattern.compile(".+[,.+]*");
+
+         Matcher m1 = p1.matcher( idList ),
+             m2 = p2.matcher( idList );
+         if ( m1.matches() ) {
+	     panel.frame().output(Globals.lang("Fetching Medline by id ..."));
+	     idList = tf.getText().replace(';', ',');
+	     fetchById();
+	     //System.out.println("Fetch by id");
+         }
+         else if ( m2.matches() ) {
+	    panel.frame().output(Globals.lang("Fetching Medline by term ..."));
+
+	    // my stuff
+	    //---------------------------
+	    String searchTerm = setupTerm(idList); // fix the syntax
+	    SearchResult result = getIds(searchTerm ,0,1); // get the ids from entrez
+	    // prompt the user to number articles to retrieve
+            if (result.count == 0) {
+                JOptionPane.showMessageDialog(panel.frame(), Globals.lang("No references found"));
+                return;
+            }
+	    String question = 
+		Globals.lang("References found")+": "
+		+ Integer.toString(result.count)+"  "
+		+ Globals.lang("Number of references to fetch?");
+	    String strCount = 
+		JOptionPane.showInputDialog(question, 
+					    Integer.toString(result.count));
+	    
+	    // for strCount ...
+	    if(strCount.equals(""))
+		    return;
+	    int count;
+        try {
+            count = Integer.parseInt(strCount);
+        } catch (NumberFormatException ex) {
+            panel.output("");
+            return;
+        }
+
+        ImportInspectionDialog diag = new ImportInspectionDialog(panel.frame(), panel,
+                GUIGlobals.DEFAULT_INSPECTION_FIELDS, Globals.lang("Fetch Medline"), false);
+        Util.placeDialog(diag, panel.frame());
+         diag.setDefaultSelected(false); // Make sure new entries are not selected by default.
+
+             // diag.setProgress(0, count);
+        diag.setVisible(true);
+        keepOn = true;
+         diag.addCallBack(new ImportInspectionDialog.CallBack() {
+             public void done(int entriesImported) {
+                 if (entriesImported > 0) {
+                 panel.output(Globals.lang("Medline entries fetched")+": "+entriesImported);
+                 panel.markBaseChanged();
+             } else
+                 panel.output(Globals.lang("No Medline entries found."));
+            }
+
+             public void cancelled() {
+                 panel.output(Globals.lang("%0 import cancelled.", "Medline"));
+             }
+
+
+             public void stopFetching() {
+                // Make sure the fetch loop exits at next iteration.
+                keepOn = false;
+             }
+         });
+	    for (int jj = 0; jj < count; jj+=PACING) {
+            if (!keepOn)
+                break;
+		    // get the ids from entrez
+		    result = getIds(searchTerm,jj,PACING);
+
+            /*String[] test = getTitles((String[])result.idList.toArray(new String[0]));
+            for (int pelle=0; pelle<test.length; pelle++) {
+                System.out.println(": "+test[pelle]);
+            } */
+
+            final ArrayList bibs = fetchMedline(result.ids);
+            if (!keepOn)
+                break;
+            diag.addEntries(bibs);
+            diag.setProgress(jj+PACING, count);
+	    }
+         diag.entryListComplete();
+	 }
+   }
+    public String setupTerm(String in){
+        Pattern part1=Pattern.compile(", ");
+        Pattern part2=Pattern.compile(",");
+        Pattern part3=Pattern.compile(" ");
+        Matcher matcher;
+        matcher=part1.matcher(in);
+        in=matcher.replaceAll("\\+AND\\+");
+        matcher=part2.matcher(in);
+        in=matcher.replaceAll("\\+AND\\+");
+        matcher=part3.matcher(in);
+        in=matcher.replaceAll("+");
+
+        return in;
+    }
+
+    // this gets the initial list of ids
+    public SearchResult getIds(String term, int start,int pacing){
+        String baseUrl="http://eutils.ncbi.nlm.nih.gov/entrez/eutils";
+        String medlineUrl = baseUrl
+	    +"/esearch.fcgi?db=pubmed&retmax="
+	    +Integer.toString(pacing)
+	    +"&retstart="+Integer.toString(start)
+	    +"&term=";
+        Pattern idPattern=Pattern.compile("<Id>(\\d+)</Id>");
+        Pattern countPattern=Pattern.compile("<Count>(\\d+)<\\/Count>");
+	Pattern retMaxPattern=Pattern.compile("<RetMax>(\\d+)<\\/RetMax>");
+	Pattern retStartPattern=Pattern.compile("<RetStart>(\\d+)<\\/RetStart>");
+        Matcher idMatcher;
+        Matcher countMatcher;
+        Matcher retMaxMatcher;
+        Matcher retStartMatcher;
+	boolean doCount = true;
+	SearchResult result = new SearchResult();
+	//System.out.println(medlineUrl+term);
+        try{
+            URL ncbi = new URL(medlineUrl+term);
+            // get the ids
+            HttpURLConnection ncbiCon=(HttpURLConnection)ncbi.openConnection();
+            BufferedReader in =
+                new BufferedReader
+                (new InputStreamReader
+                 ( ncbi.openStream()));
+            String inLine;
+            while ((inLine=in.readLine())!=null){
+
+		// get the count
+		idMatcher=idPattern.matcher(inLine);
+		if (idMatcher.find()){
+		    result.addID(idMatcher.group(1));
+		}
+		retMaxMatcher=retMaxPattern.matcher(inLine);
+		if (idMatcher.find()){
+		    result.retmax=Integer.parseInt(retMaxMatcher.group(1));
+		}
+		retStartMatcher=retStartPattern.matcher(inLine);
+		if (retStartMatcher.find()){
+		    result.retstart=Integer.parseInt(retStartMatcher.group(1));
+		}
+		countMatcher=countPattern.matcher(inLine);
+		if (doCount && countMatcher.find()){
+		    result.count=Integer.parseInt(countMatcher.group(1));
+		    doCount = false;
+		}
+            }
+
+        }
+        catch (MalformedURLException e) {     // new URL() failed
+            System.out.println("bad url");
+            e.printStackTrace();
+        }
+        catch (IOException e) {               // openConnection() failed
+            System.out.println("connection failed");
+            e.printStackTrace();
+
+        }
+        return result;
+    }
+
+    public String[] getTitles(String[] idArrayList) {
+      String[] titles = new String[Math.min(MAX_TO_FETCH, idArrayList.length)];
+        String temp;
+        for (int i=0; i<Math.min(MAX_TO_FETCH, idArrayList.length); i++){
+            temp=getOneCitation(idArrayList[i]);
+            titles[i]=getVitalData(temp);
+        }
+        return titles;
+    }
+
+        // get the xml for an entry
+    public String getOneCitation(String id){
+	String baseUrl="http://eutils.ncbi.nlm.nih.gov/entrez/eutils";
+	String retrieveUrl = baseUrl+"/efetch.fcgi?db=pubmed&retmode=xml&rettype=citation&id=";
+	StringBuffer sb=new StringBuffer();
+	try{
+	    URL ncbi = new URL(retrieveUrl+id);
+	    HttpURLConnection ncbiCon=(HttpURLConnection)ncbi.openConnection();
+	    BufferedReader in =
+		new BufferedReader
+		(new InputStreamReader
+		 ( ncbi.openStream()));
+	    String inLine;
+	    while ((inLine=in.readLine())!=null){
+
+		sb.append(inLine);
+	    }
+
+	}
+	catch (MalformedURLException e) {     // new URL() failed
+	    System.out.println("bad url");
+	    e.printStackTrace();
+	}
+	catch (IOException e) {               // openConnection() failed
+	    System.out.println("connection failed");
+	    e.printStackTrace();
+
+	}
+	return sb.toString();
+    }
+
+        // parse out the titles from the xml
+    public String getVitalData(String sb){
+	StringBuffer result=new StringBuffer();
+	Pattern articleTitle=Pattern.compile("<ArticleTitle>(.+)</ArticleTitle>");
+	Pattern authorName=Pattern.compile("<Author>(.+)</Author>");
+	Matcher matcher;
+	matcher=articleTitle.matcher(sb);
+	if (matcher.find())
+        result.append("Title: ").append(matcher.group(1));
+
+	//matcher=authorName.matcher(sb);
+	//while (matcher.find())
+	//   result.append("\tAuthor: "+matcher.group(1));
+	return result.toString();
+    }
+
+    // This method is called by the dialog when the user has selected the
+    // wanted entries, and clicked Ok. The callback object can update status
+    // line etc.
+    public void done(int entriesImported) {
+        panel.output(Globals.lang("Medline entries fetched")+": "+entriesImported);
+    }
+
+    public void cancelled() {
+        panel.output(Globals.lang("%0 import cancelled.", "Medline"));
+    }
+
+
+    // This method is called by the dialog when the user has cancelled or
+    // signalled a stop. It is expected that any long-running fetch operations
+    // will stop after this method is called.
+    public void stopFetching() {
+        //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+}
diff --git a/src/java/net/sf/jabref/imports/MedlineHandler.java b/src/java/net/sf/jabref/imports/MedlineHandler.java
new file mode 100644
index 0000000..f8d7759
--- /dev/null
+++ b/src/java/net/sf/jabref/imports/MedlineHandler.java
@@ -0,0 +1,292 @@
+package net.sf.jabref.imports;
+import java.util.regex.*;
+import javax.xml.parsers.*;
+import java.util.ArrayList;
+import org.xml.sax.*;
+import org.xml.sax.helpers.*;
+import net.sf.jabref.*;
+
+
+/*
+  Copyright (C) 2002-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
+
+*/
+
+public class MedlineHandler extends DefaultHandler
+{
+    ArrayList bibitems= new ArrayList();
+    boolean inTitle=false,			inYear = false,
+		inJournal = false,			inMonth = false,
+		inVolume = false,			inAuthorList = false,
+		inAuthor =false,			inLastName = false,
+		inInitials = false,			inMedlinePgn = false,
+		inMedlineID = false,		inURL=false,
+		inIssue = false,			inPubDate = false,
+		inUrl=false, inForename=false, inAbstractText=false, inMedlineDate=false,
+		inPubMedID=false, inDescriptorName=false,inDoi=false,inPii=false;
+    String title="", journal="", keyword="",author="",
+		lastName="",year="",forename="", abstractText="";
+    String month="",volume="",lastname="",initials="",number="",page="",medlineID="",url="",MedlineDate="";
+    String series="",editor="",booktitle="",type="article",key="",address="",
+		pubmedid="", descriptorName="",doi="",pii="";
+    ArrayList authors=new ArrayList();
+    int rowNum=0;
+    public ArrayList getItems(){ return bibitems;}
+
+    public MedlineHandler(){
+		super();
+
+    }
+    public void startElement(String uri, String localName, String qName,  Attributes atts)
+    {
+		//		public void startElement(String localName, Attributes atts) {
+		// Get the number of attribute
+		if(localName.equals("PubmedArticle")){}
+		else if(localName.equals("ArticleTitle")){ inTitle=true; title="";}
+		else if(localName.equals("PubDate")){inPubDate=true;}
+		else if(localName.equals("Year") && inPubDate==true){inYear=true;}
+		else if( localName.equals("MedlineDate") && inPubDate==true){inMedlineDate=true;} // medline date does not have 4 digit dates instead it has multiyear etc
+		else if(localName.equals("MedlineTA")){inJournal=true;journal="";} //journal name
+		else if(localName.equals("Month") && inPubDate==true){inMonth=true;}
+		else if(localName.equals("Volume")){inVolume=true;}
+		else if(localName.equals("AuthorList")){
+			inAuthorList=true;
+			authors.clear();}
+		else if(localName.equals("DescriptorName")){
+			//keyword="";
+			inDescriptorName=true;
+			//descriptorName="";
+		}
+                else if(localName.equals("Author")){inAuthor=true;author="";}
+                else if(localName.equals("CollectiveName")){inForename=true;forename="";} // Morten A. 20040513.
+		else if(localName.equals("PMID")){inPubMedID=true;pubmedid="";}
+		else if(localName.equals("LastName")){inLastName=true; lastName="";}
+		else if(localName.equals("ForeName") || localName.equals("FirstName")) {
+			inForename=true; forename="";
+		}
+		else if(localName.equals("Issue")){inIssue=true;}
+		else if(localName.equals("MedlinePgn")){inMedlinePgn=true;
+		}//pagenumber
+		else if(localName.equals("URL")){inUrl=true;}
+		else if(localName.equals("Initials")){inInitials=true;}
+		else if(localName.equals("AbstractText")){ inAbstractText=true;}
+		else if(localName.equals("ArticleId")){
+			for (int i = 0; i < atts.getLength(); i++) {
+				String name = atts.getQName(i);
+				String type = atts.getType(i);
+				String value = atts.getValue(i);
+				//System.out.println("name:" + name + " type: " + type + " value: " + value);
+				if(value.equals("doi"))
+					inDoi=true;
+				else if(value.equals("pii"))
+					inPii=true;
+
+			}
+		}
+
+
+
+		return;
+    }
+    String join(Object[] sa,String delim){
+		StringBuffer sb=new StringBuffer();
+		sb.append( sa[0].toString() );
+		for(int i=1; i<sa.length; i++)
+	    {
+			sb.append( delim );
+			sb.append( sa[i].toString() );
+	    }
+		return sb.toString();
+    }
+    String makeBibtexString(){
+		String out  = "";
+                // PENDING jeffrey.kuhn at yale.edu 2005-05-27 : added call to fixPageRange
+		out= "article{,\n" + " author = { " + author + " },\n title = { " + title + "},\n journal ={ " + journal + "},\n year = " + year +
+			"},\n volume = { " + volume + "},\n number = { "+ number + "},\n pages = { " + fixPageRange(page) + "},\n abstract = { " + abstractText + "},\n}";
+		return out;
+    }
+    public void endElement( String uri, String localName, String qName ) {
+		if(localName.equals("PubmedArticle")){
+			//bibitems.add( new Bibitem(null, makeBibtexString(), Globals.nextKey(),"-1" )	 );
+			// check if year ="" then give medline date instead
+			if(year.equals("")){
+				if(!MedlineDate.equals("")) {
+					// multi-year date format
+					//System.out.println(MedlineDate);
+					year = MedlineDate.substring(0,4);
+					//Matcher m = Pattern.compile("\\b[0-9]{4}\\b").matcher(MedlineDate);
+					//if(m.matches())
+					//year = m.group();
+				}
+			}
+			//################################## 09/23/03  put {} around capitals
+
+			title=Util.putBracesAroundCapitals(title);
+			//##############################
+			// Sort keywords and remove duplicates. Add pubmedid as keyword (user request)
+            StringBuffer sb = new StringBuffer(Util.sortWordsAndRemoveDuplicates(descriptorName));
+            if (sb.length()>0)
+                sb.append(", ");
+            sb.append(pubmedid);
+            keyword = sb.toString();
+            
+			BibtexEntry b=new BibtexEntry(Util.createNeutralId(),//Globals.DEFAULT_BIBTEXENTRY_ID,
+										  Globals.getEntryType("article")); // id assumes an existing database so don't create one here
+			if (!author.equals("")) { 
+			    b.setField("author",ImportFormatReader.expandAuthorInitials(author));
+			    author = "";
+			}
+			if (!title.equals("")) b.setField("title",title);
+			if (!journal.equals("")) b.setField("journal",journal);
+			if (!year.equals("")) b.setField("year",year);
+                        // PENDING jeffrey.kuhn at yale.edu 2005-05-27 : added call to fixPageRange
+			if (!page.equals("")) b.setField("pages",fixPageRange(page));
+			if (!volume.equals("")) b.setField("volume",volume);
+			if (!abstractText.equals("")) b.setField("abstract",abstractText.replaceAll("%","\\\\%"));
+			if (!keyword.equals("")) b.setField("keywords",keyword);
+			if (!month.equals("")) b.setField("month",month);
+			//if (!url.equals("")) b.setField("url",url);
+			if (!number.equals("")) b.setField("number",number);
+
+			if(!doi.equals("")){
+			    b.setField("doi",doi);
+			    b.setField("url","http://dx.doi.org/"+doi);
+			}
+			if(!pii.equals(""))
+			    b.setField("pii",pii);
+
+                        // PENDING jeffrey.kuhn at yale.edu 2005-05-27 : added "pmid" bibtex field
+                        // Older references do not have doi entries, but every
+                        // medline entry has a unique pubmed ID (aka primary ID).
+                        // Add a bibtex field for the pubmed ID for future use.
+                        if (!pubmedid.equals(""))
+                            b.setField("pmid",pubmedid);
+                        
+			bibitems.add( b  );
+
+			abstractText = "";
+			author = "";
+			title="";
+			journal="";
+			keyword="";
+			doi=""; pii="";
+			year="";
+			forename="";
+			lastName="";
+			abstractText="";
+			pubmedid="";
+			month="";volume="";lastname="";initials="";number="";page="";medlineID="";url="";
+			MedlineDate="";
+		}
+
+		else if(localName.equals("ArticleTitle")){inTitle=false;}
+		else if(localName.equals("PubDate")){inPubDate=false;}
+		else if(localName.equals("Year")){inYear=false;}
+		else if(localName.equals("PMID")){inPubMedID=false;}
+		else if(localName.equals("MedlineDate")){inMedlineDate=false;}
+		else if(localName.equals("MedlineTA")){inJournal=false;} //journal name
+		else if(localName.equals("Month")){inMonth=false;}
+		else if(localName.equals("Volume")){inVolume=false;}
+		else if(localName.equals("AuthorList")){
+			author = join( authors.toArray(), " and " );
+			inAuthorList = false;
+		}
+		else if(localName.equals("Author")){
+			// forename sometimes has initials with " " in middle: is pattern [A-Z] [A-Z]
+			// when above is the case replace it with initials
+			if(forename.length()==3 && forename.charAt(1)==' '){
+				forename=initials;
+			}
+			author = forename + " " + lastname;
+			//author = initials + " " + lastname;
+			authors.add(author);
+			inAuthor=false;
+			forename = "";
+			initials = "";
+			lastname = "";
+		}
+		else if(localName.equals("DescriptorName")) inDescriptorName=false;
+		else if(localName.equals("LastName")){inLastName=false;}
+		else if(localName.equals("ForeName")||localName.equals("FirstName")){ inForename=false;}
+		else if(localName.equals("Issue")){ inIssue = false;}
+		else if(localName.equals("MedlinePgn")){inMedlinePgn=false;}//pagenumber
+		else if(localName.equals("URL")){ inUrl=false;}
+		else if(localName.equals("Initials")){
+			//initials= '.' + initials + '.';
+			inInitials=false;
+		}
+		else if(localName.equals("AbstractText")){ inAbstractText=false;}
+		else if(localName.equals("ArticleId")){
+			if(inDoi)
+				inDoi=false;
+			else if(inPii)
+				inPii=false;}
+    }
+
+    public void characters( char[] data, int start, int length ) {
+
+		// if stack is not ready, data is not content of recognized element
+		if( inTitle ){ title += new String( data, start, length);}
+		else if(inYear){ year+=new String(data,start,length);}
+		else if(inJournal){journal += new String(data,start,length);}
+		else if(inMonth){month += new String(data,start,length);}
+		else if(inVolume){volume += new String(data,start,length);}
+		else if(inLastName){lastname += new String(data,start,length);}
+		else if(inInitials){initials += new String(data,start,length);}
+		else if(inIssue){number += new String(data,start,length);}
+		else if(inMedlinePgn){ page += new String(data,start,length);}
+		else if(inMedlineID){medlineID += new String(data,start,length);}
+		else if(inURL){url += new String(data,start,length);}
+		else if(inPubMedID){pubmedid = new String(data,start,length);}
+		else if(inDescriptorName) descriptorName += new String(data,start,length) + ", ";
+		else if(inForename){
+			forename += new String(data,start,length);
+			//System.out.println("IN FORENAME: " + forename);
+		}
+		else if(inAbstractText){ abstractText += new String(data,start,length);}
+		else if(inMedlineDate){ MedlineDate += new String(data,start,length);}
+		else if(inDoi){ doi=new String(data,start,length);}
+		else if(inPii){ pii=new String(data,start,length);}
+    }
+
+    // PENDING jeffrey.kuhn at yale.edu 2005-05-27 : added fixPageRange method
+    //   Convert medline page ranges from short form to full form.
+    //   Medline reports page ranges in a shorthand format. 
+    //   The last page is reported using only the digits which
+    //   differ from the first page. 
+    //      i.e. 12345-51 refers to the actual range 12345-12351
+    public String fixPageRange(String pageRange) {
+        int minusPos = pageRange.indexOf('-');
+        if (minusPos < 0) {
+            return pageRange;
+        }
+        String first = pageRange.substring(0, minusPos).trim();
+        String last = pageRange.substring(minusPos+1).trim();
+        int llast = last.length(), lfirst = first.length();
+        if (llast < lfirst) {
+            last = first.substring(0, lfirst-llast) + last;
+        }
+        return first + "--" + last;
+    }
+}
diff --git a/src/java/net/sf/jabref/imports/MedlineImporter.java b/src/java/net/sf/jabref/imports/MedlineImporter.java
new file mode 100644
index 0000000..293af92
--- /dev/null
+++ b/src/java/net/sf/jabref/imports/MedlineImporter.java
@@ -0,0 +1,73 @@
+package net.sf.jabref.imports;
+
+import java.io.InputStream;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+import java.io.IOException;
+import java.util.List;
+import java.util.ArrayList;
+
+/**
+ * Importer for the Refer/Endnote format.
+ *
+ * check here for details on the format
+ * http://www.ecst.csuchico.edu/~jacobsd/bib/formats/endnote.html
+ */
+public class MedlineImporter extends ImportFormat {
+
+    /**
+     * Return the name of this import format.
+     */
+    public String getFormatName() {
+	return "Medline";
+    }
+
+    /*
+     *  (non-Javadoc)
+     * @see net.sf.jabref.imports.ImportFormat#getCLIId()
+     */
+    public String getCLIId() {
+      return "medline";
+    }
+    
+    /**
+     * Check whether the source is in the correct format for this importer.
+     */
+    public boolean isRecognizedFormat(InputStream in) throws IOException {
+	return true;
+    }
+
+    /**
+     * Parse the entries in the source, and return a List of BibtexEntry
+     * objects.
+     */
+    public List importEntries(InputStream stream) throws IOException {
+
+	// Obtain a factory object for creating SAX parsers
+	SAXParserFactory parserFactory = SAXParserFactory.newInstance();
+
+	// Configure the factory object to specify attributes of the parsers it
+	// creates
+	parserFactory.setValidating(true);
+	parserFactory.setNamespaceAware(true);
+	
+	// Now create a SAXParser object
+	ArrayList bibItems = null;
+	try{
+	    SAXParser parser = parserFactory.newSAXParser(); //May throw exceptions
+	    MedlineHandler handler = new MedlineHandler();
+	    // Start the parser. It reads the file and calls methods of the handler.
+	    parser.parse(stream, handler);
+	    
+	    // When you're done, report the results stored by your handler object
+	    bibItems = handler.getItems();
+	}catch (javax.xml.parsers.ParserConfigurationException e1){
+	}catch (org.xml.sax.SAXException e2){
+	}catch (java.io.IOException e3){
+	}
+	
+	return bibItems;
+	
+    }
+    
+}
diff --git a/src/java/net/sf/jabref/imports/OpenDatabaseAction.java b/src/java/net/sf/jabref/imports/OpenDatabaseAction.java
new file mode 100644
index 0000000..6e9188f
--- /dev/null
+++ b/src/java/net/sf/jabref/imports/OpenDatabaseAction.java
@@ -0,0 +1,274 @@
+package net.sf.jabref.imports;
+
+import net.sf.jabref.*;
+
+import javax.swing.*;
+import java.io.*;
+import java.awt.event.*;
+import java.util.*;
+
+// The action concerned with opening an existing database.
+
+public class OpenDatabaseAction extends MnemonicAwareAction {
+    boolean showDialog;
+
+    private JabRefFrame frame;
+
+    public OpenDatabaseAction(JabRefFrame frame, boolean showDialog) {
+        super(new ImageIcon(GUIGlobals.openIconFile));
+        this.frame = frame;
+        this.showDialog = showDialog;
+        putValue(NAME, "Open database");
+        putValue(ACCELERATOR_KEY, Globals.prefs.getKey("Open database"));
+        putValue(SHORT_DESCRIPTION, Globals.lang("Open BibTeX database"));
+    }
+
+    public void actionPerformed(ActionEvent e) {
+        File fileToOpen = null;
+
+        if (showDialog) {
+
+            String chosenFile = Globals.getNewFile(frame, Globals.prefs, new File(Globals.prefs.get("workingDirectory")), ".bib",
+                    JFileChooser.OPEN_DIALOG, true);
+
+            if (chosenFile != null) {
+                fileToOpen = new File(chosenFile);
+            }
+        } else {
+            Util.pr(NAME);
+            Util.pr(e.getActionCommand());
+            fileToOpen = new File(Util.checkName(e.getActionCommand()));
+        }
+
+        // Run the actual open in a thread to prevent the program
+        // locking until the file is loaded.
+        if (fileToOpen != null) {
+            final File theFile = fileToOpen;
+            (new Thread() {
+                public void run() {
+                    openIt(theFile, true);
+                }
+            }).start();
+            frame.getFileHistory().newFile(fileToOpen.getPath());
+        }
+    }
+
+    class OpenItSwingHelper implements Runnable {
+        BasePanel bp;
+        boolean raisePanel;
+        File file;
+
+        OpenItSwingHelper(BasePanel bp, File file, boolean raisePanel) {
+            this.bp = bp;
+            this.raisePanel = raisePanel;
+            this.file = file;
+        }
+
+        public void run() {
+            frame.addTab(bp, file, raisePanel);
+        }
+    }
+
+    public void openIt(File file, boolean raisePanel) {
+        if ((file != null) && (file.exists())) {
+            frame.output(Globals.lang("Opening") + ": '" + file.getPath() + "'");
+            try {
+                String fileName = file.getPath();
+                Globals.prefs.put("workingDirectory", file.getPath());
+                // Should this be done _after_ we know it was successfully opened?
+                String encoding = Globals.prefs.get("defaultEncoding");
+                ParserResult pr = loadDatabase(file, encoding);
+		if ((pr == null) || (pr == ParserResult.INVALID_FORMAT)) {
+		    JOptionPane.showMessageDialog(null, Globals.lang("Error opening file"+" '"+fileName+"'"),
+						  Globals.lang("Error"),
+						  JOptionPane.ERROR_MESSAGE);
+
+		    return;
+		}
+		 
+                BibtexDatabase db = pr.getDatabase();
+                HashMap meta = pr.getMetaData();
+
+                if (pr.hasWarnings()) {
+                    final String[] wrns = pr.warnings();
+                    (new Thread() {
+                        public void run() {
+                            StringBuffer wrn = new StringBuffer();
+                            for (int i = 0; i < wrns.length; i++)
+                                wrn.append(i + 1).append(". ").append(wrns[i]).append("\n");
+
+                            if (wrn.length() > 0)
+                                wrn.deleteCharAt(wrn.length() - 1);
+                            // Note to self or to someone else: The following line causes an
+                            // ArrayIndexOutOfBoundsException in situations with a large number of
+                            // warnings; approx. 5000 for the database I opened when I observed the problem
+                            // (duplicate key warnings). I don't think this is a big problem for normal situations,
+                            // and it may possibly be a bug in the Swing code.
+                            JOptionPane.showMessageDialog(frame, wrn.toString(),
+                                    Globals.lang("Warnings"),
+                                    JOptionPane.WARNING_MESSAGE);
+                        }
+                    }).start();
+                }
+
+                BasePanel bp = new BasePanel(frame, db, file, meta, pr.getEncoding());
+
+                /*
+                 if (Globals.prefs.getBoolean("autoComplete")) {
+                 db.setCompleters(autoCompleters);
+                 }
+                */
+
+                // file is set to null inside the EventDispatcherThread
+                SwingUtilities.invokeLater(new OpenItSwingHelper(bp, file, raisePanel));
+
+                // See if any custom entry types were imported, but disregard those we already know:
+                for (Iterator i = pr.getEntryTypes().keySet().iterator(); i.hasNext();) {
+                    String typeName = ((String) i.next()).toLowerCase();
+                    if (BibtexEntryType.ALL_TYPES.get(typeName) != null)
+                        i.remove();
+                }
+                if (pr.getEntryTypes().size() > 0) {
+
+
+                    StringBuffer sb = new StringBuffer(Globals.lang("Custom entry types found in file") + ": ");
+                    Object[] types = pr.getEntryTypes().keySet().toArray();
+                    Arrays.sort(types);
+                    for (int i = 0; i < types.length; i++) {
+                        sb.append(types[i].toString()).append(", ");
+                    }
+                    String s = sb.toString();
+                    int answer = JOptionPane.showConfirmDialog(frame,
+                            s.substring(0, s.length() - 2) + ".\n"
+                            + Globals.lang("Remember these entry types?"),
+                            Globals.lang("Custom entry types"),
+                            JOptionPane.YES_NO_OPTION,
+                            JOptionPane.QUESTION_MESSAGE);
+                    if (answer == JOptionPane.YES_OPTION) {
+                        // Import
+                        HashMap et = pr.getEntryTypes();
+                        for (Iterator i = et.keySet().iterator(); i.hasNext();) {
+                            BibtexEntryType typ = (BibtexEntryType) et.get(i.next());
+                            //System.out.println(":"+typ.getName()+"\n"+typ.toString());
+                            BibtexEntryType.ALL_TYPES.put(typ.getName().toLowerCase(), typ);
+                        }
+
+                    }
+                }
+
+                frame.output(Globals.lang("Opened database") + " '" + fileName +
+                        "' " + Globals.lang("with") + " " +
+                        db.getEntryCount() + " " + Globals.lang("entries") + ".");
+
+            } catch (Exception ex) {
+                //ex.printStackTrace();
+                Util.showQuickErrorDialog(frame, Globals.lang("Open database"), ex);
+                /*
+                JOptionPane.showMessageDialog
+                        (frame, ex.getMessage(),
+                                Globals.lang("Open database"), JOptionPane.ERROR_MESSAGE);
+                                */
+            }
+        }
+    }
+
+    public static ParserResult loadDatabase(File fileToOpen, String encoding)
+            throws IOException {
+
+        // First we make a quick check to see if this looks like a BibTeX file:
+        Reader reader;// = ImportFormatReader.getReader(fileToOpen, encoding);
+        //if (!BibtexParser.isRecognizedFormat(reader))
+        //    return null;
+
+        // The file looks promising. Reinitialize the reader and go on:
+        //reader = getReader(fileToOpen, encoding);
+
+        // We want to check if there is a JabRef signature in the file, because that would tell us
+        // which character encoding is used. However, to read the signature we must be using a compatible
+        // encoding in the first place. Since the signature doesn't contain any fancy characters, we can
+        // read it regardless of encoding, with either UTF8 or UTF-16. That's the hypothesis, at any rate.
+        // 8 bit is most likely, so we try that first:
+        Reader utf8Reader = ImportFormatReader.getReader(fileToOpen, "UTF8");
+        String suppliedEncoding = checkForEncoding(utf8Reader);
+        utf8Reader.close();
+        // Now if that didn't get us anywhere, we check with the 16 bit encoding:
+        if (suppliedEncoding == null) {
+            Reader utf16Reader = ImportFormatReader.getReader(fileToOpen, "UTF-16");
+            suppliedEncoding = checkForEncoding(utf16Reader);
+            utf16Reader.close();
+            //System.out.println("Result of UTF-16 test: "+suppliedEncoding);
+        }
+
+        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.
+            }
+        } else {
+            // We couldn't find a header with info about encoding. Use default:
+            reader = ImportFormatReader.getReader(fileToOpen, encoding);
+        }
+
+        BibtexParser bp = new BibtexParser(reader);
+
+        ParserResult pr = bp.parse();
+        pr.setEncoding(encoding);
+
+        return pr;
+    }
+
+    private static String checkForEncoding(Reader reader) {
+        String suppliedEncoding = null;
+        StringBuffer headerText = new StringBuffer();
+        try {
+            boolean keepon = true;
+            int piv = 0;
+            int c;
+
+            while (keepon) {
+                c = reader.read();
+                headerText.append((char) c);
+                if (((piv == 0) && Character.isWhitespace((char) c))
+                        || (c == GUIGlobals.SIGNATURE.charAt(piv)))
+                    piv++;
+                else //if (((char)c) == '@')
+                    keepon = false;
+                //System.out.println(headerText.toString());
+                found:
+                if (piv == GUIGlobals.SIGNATURE.length()) {
+                    keepon = false;
+
+                    //if (headerText.length() > GUIGlobals.SIGNATURE.length())
+                    //    System.out.println("'"+headerText.toString().substring(0, headerText.length()-GUIGlobals.SIGNATURE.length())+"'");
+                    // Found the signature. The rest of the line is unknown, so we skip
+                    // it:
+                    while (reader.read() != '\n') ;
+
+                    // Then we must skip the "Encoding: "
+                    for (int i = 0; i < GUIGlobals.encPrefix.length(); i++) {
+                        if (reader.read() != GUIGlobals.encPrefix.charAt(i))
+                            break found; // No,
+                        // it
+                        // doesn't
+                        // seem
+                        // to
+                        // match.
+                    }
+
+                    // If ok, then read the rest of the line, which should contain the
+                    // name
+                    // of the encoding:
+                    StringBuffer sb = new StringBuffer();
+
+                    while ((c = reader.read()) != '\n') sb.append((char) c);
+
+                    suppliedEncoding = sb.toString();
+                }
+            }
+        } catch (IOException ex) {
+        }
+        return suppliedEncoding;
+    }
+}
diff --git a/src/java/net/sf/jabref/imports/OvidImporter.java b/src/java/net/sf/jabref/imports/OvidImporter.java
new file mode 100644
index 0000000..cd8690e
--- /dev/null
+++ b/src/java/net/sf/jabref/imports/OvidImporter.java
@@ -0,0 +1,243 @@
+package net.sf.jabref.imports;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.io.InputStream;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.HashMap;
+import net.sf.jabref.BibtexEntry;
+import net.sf.jabref.Globals;
+import net.sf.jabref.Util;
+import net.sf.jabref.AuthorList;
+
+/**
+ * Imports an Ovid file.
+ */
+public class OvidImporter extends ImportFormat {
+
+    public static Pattern ovid_src_pat = Pattern
+    .compile("Source ([ \\w&\\-,:]+)\\.[ ]+([0-9]+)\\(([\\w\\-]+)\\):([0-9]+\\-?[0-9]+?)\\,.*([0-9][0-9][0-9][0-9])");
+
+    public static Pattern ovid_src_pat_no_issue = Pattern
+    .compile("Source ([ \\w&\\-,:]+)\\.[ ]+([0-9]+):([0-9]+\\-?[0-9]+?)\\,.*([0-9][0-9][0-9][0-9])");
+
+    public static Pattern ovid_src_pat_2 = Pattern.compile(
+            "([ \\w&\\-,]+)\\. Vol ([0-9]+)\\(([\\w\\-]+)\\) ([A-Za-z]+) ([0-9][0-9][0-9][0-9]), ([0-9]+\\-?[0-9]+)");
+
+    public static Pattern incollection_pat = Pattern.compile(
+            "(.+)\\(([0-9][0-9][0-9][0-9])\\)\\. ([ \\w&\\-,:]+)\\.[ ]+\\(pp. ([0-9]+\\-?[0-9]+?)\\).[A-Za-z0-9, ]+pp\\. "
+            +"([\\w, ]+): ([\\w, ]+)");
+    public static Pattern book_pat = Pattern.compile(
+                "\\(([0-9][0-9][0-9][0-9])\\)\\. [A-Za-z, ]+([0-9]+) pp\\. ([\\w, ]+): ([\\w, ]+)");
+
+    //   public static Pattern ovid_pat_inspec= Pattern.compile("Source ([
+    // \\w&\\-]+)");
+
+
+    /**
+     * Return the name of this import format.
+     */
+    public String getFormatName() {
+    return "Ovid";
+    }
+
+    /*
+     *  (non-Javadoc)
+     * @see net.sf.jabref.imports.ImportFormat#getCLIId()
+     */
+    public String getCLIId() {
+      return "ovid";
+    }
+    
+    /**
+     * Check whether the source is in the correct format for this importer.
+     */
+    public boolean isRecognizedFormat(InputStream in) throws IOException {
+    return true;
+    }
+
+    /**
+     * 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));
+    String line;
+    while ((line = in.readLine()) != null){
+        if (line.length() > 0 && line.charAt(0) != ' '){
+        sb.append("__NEWFIELD__");
+        }
+        sb.append(line);
+        sb.append('\n');
+    }
+
+    String items[] = sb.toString().split("<[0-9]+>");
+
+    for (int i = 1; i < items.length; i++){
+        HashMap h = new HashMap();
+        String[] fields = items[i].split("__NEWFIELD__");
+        for (int j = 0; j < fields.length; j++){
+            int linebreak = fields[j].indexOf('\n');
+            String fieldName = fields[j].substring(0, linebreak).trim();
+            String content = fields[j].substring(linebreak).trim();
+            // Remove unnecessary dots at the end of lines:
+            if (content.endsWith("."))
+                    content = content.substring(0, content.length()-1);
+            //fields[j] = fields[j].trim();
+            if (fieldName.indexOf("Author") == 0
+                && fieldName.indexOf("Author Keywords") == -1
+                && fieldName.indexOf("Author e-mail") == -1){
+
+                h.put("author", content);
+                /*if (content.indexOf(";") > 0){ //LN FN; [LN FN;]*
+                    names = content.replaceAll("[^\\.A-Za-z,;\\- ]", "").replaceAll(";", " and");
+                }else{// LN FN. [LN FN.]*
+                    //author = content.replaceAll("\\.", " and").replaceAll(" and$", "");
+                    names = content;
+                }
+
+                StringBuffer buf = new StringBuffer();
+                for (int ii=0; ii<names.length; ii++) {
+                    names[ii] = names[ii].trim();
+                    int space = names[ii].indexOf(' ');
+                    if (space >= 0) {
+                        buf.append(names[ii].substring(0, space));
+                        buf.append(',');
+                        buf.append(names[ii].substring(space));
+                    } else {
+                        buf.append(names[ii]);
+                    }
+
+                    buf.append()
+                    if (ii < names.length-1)
+                        buf.append(" and ");
+                }
+                h.put("author", AuthorList.fixAuthor_lastNameFirst(names));  */
+
+                //    author = content.replaceAll("  ", " and ").replaceAll(" and $", "");
+
+
+            //h.put("author", ImportFormatReader.fixAuthor_lastNameFirst(author));
+
+        }else if (fieldName.indexOf("Title") == 0) {
+                content = content.replaceAll("\\[.+\\]", "").trim();
+                if (content.endsWith("."))
+                    content = content.substring(0, content.length()-1);
+                h.put("title", content);
+        }
+
+        else if (fieldName.indexOf("Chapter Title") == 0) h.put("chaptertitle", content);
+
+        // The "Source" field is a complete mess - it can have several different formats,
+        // but since it can contain journal name, book title, year, month, volume etc. we
+        // must try to parse it. We use different regular expressions to check different
+        // possible formattings.
+        else if (fieldName.indexOf("Source") == 0){
+                Matcher matcher;
+            if ((matcher = ovid_src_pat.matcher(content)).find()) {
+            h.put("journal", matcher.group(1));
+            h.put("volume", matcher.group(2));
+            h.put("issue", matcher.group(3));
+            h.put("pages", matcher.group(4));
+            h.put("year", matcher.group(5));
+            } else if ((matcher = ovid_src_pat_no_issue.matcher(content)).find()) {// may be missing the issue
+                h.put("journal", matcher.group(1));
+                h.put("volume", matcher.group(2));
+                h.put("pages", matcher.group(3));
+                h.put("year", matcher.group(4));
+            } else if ((matcher = ovid_src_pat_2.matcher(content)).find()) {
+
+                h.put("journal", matcher.group(1));
+                h.put("volume", matcher.group(2));
+                h.put("issue", matcher.group(3));
+                h.put("month", matcher.group(4));
+                h.put("year", matcher.group(5));
+                h.put("pages", matcher.group(6));
+
+            } else if ((matcher = incollection_pat.matcher(content)).find()) {
+                h.put("editor", matcher.group(1).replaceAll(" \\(Ed\\)", ""));
+                h.put("year", matcher.group(2));
+                h.put("booktitle", matcher.group(3));
+                h.put("pages", matcher.group(4));
+                h.put("address", matcher.group(5));
+                h.put("publisher", matcher.group(6));
+            } else if ((matcher = book_pat.matcher(content)).find()) {
+                h.put("year", matcher.group(1));
+                h.put("pages", matcher.group(2));
+                h.put("address", matcher.group(3));
+                h.put("publisher", matcher.group(4));
+
+            }
+            // Add double hyphens to page ranges:
+            if (h.get("pages") != null) {
+                h.put("pages", ((String)h.get("pages")).replaceAll("-", "--"));
+            }
+
+        } else if (fieldName.equals("Abstract")) {
+                //System.out.println("'"+content+"'");
+                h.put("abstract", content);
+
+        } else if (fieldName.equals("Publication Type")) {
+             if (content.indexOf("Book") >= 0)
+                h.put("entrytype", "book");
+             else if (content.indexOf("Journal") >= 0)
+                h.put("entrytype", "article");
+        }
+        }
+
+        // Now we need to check if a book entry has given editors in the author field;
+        // if so, rearrange:
+        String auth = (String)h.get("author");
+        if ((auth != null) && (auth.indexOf(" [Ed]") >= 0)) {
+            h.remove("author");
+            h.put("editor", auth.replaceAll(" \\[Ed\\]", ""));
+        }
+
+        // Rearrange names properly:
+        auth = (String)h.get("author");
+        if (auth != null)
+            h.put("author", fixNames(auth));
+        auth = (String)h.get("editor");
+        if (auth != null)
+            h.put("editor", fixNames(auth));
+
+
+
+        // Set the entrytype properly:
+        String entryType = h.containsKey("entrytype") ? (String)h.get("entrytype") : "other";
+        h.remove("entrytype");
+        if (entryType.equals("book")) {
+            if (h.containsKey("chaptertitle")) {
+                // This means we have an "incollection" entry.
+                entryType = "incollection";
+                // Move the "chaptertitle" to just "title":
+                h.put("title", h.remove("chaptertitle"));
+            }
+        }
+        BibtexEntry b = new BibtexEntry(Util.createNeutralId(), Globals.getEntryType(entryType));
+        b.setField(h);
+
+        bibitems.add(b);
+
+    }
+
+    return bibitems;
+    }
+
+    private String fixNames(String content) {
+        String names;
+        if (content.indexOf(";") > 0){ //LN FN; [LN FN;]*
+            names = content.replaceAll("[^\\.A-Za-z,;\\- ]", "").replaceAll(";", " and");
+        } else
+            names = content;
+        return AuthorList.fixAuthor_lastNameFirst(names);
+    }
+
+}
+
+
diff --git a/src/java/net/sf/jabref/imports/ParserResult.java b/src/java/net/sf/jabref/imports/ParserResult.java
new file mode 100644
index 0000000..0f94157
--- /dev/null
+++ b/src/java/net/sf/jabref/imports/ParserResult.java
@@ -0,0 +1,121 @@
+/*
+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.
+
+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.imports;
+
+import java.util.HashMap;
+import java.io.File;
+import net.sf.jabref.*;
+import java.util.Vector;
+import java.util.ArrayList;
+
+public class ParserResult {
+
+    public static ParserResult INVALID_FORMAT = new ParserResult(null, null, null);
+    private BibtexDatabase base;
+    private HashMap metaData, entryTypes;
+    private File file = null;
+    private ArrayList warnings = new ArrayList();
+    private String encoding = null; // Which encoding was used?
+    private boolean toOpenTab = false;
+
+    public ParserResult(BibtexDatabase base, HashMap metaData, HashMap entryTypes) {
+	this.base = base;
+	this.metaData = metaData;
+	this.entryTypes = entryTypes;
+    }
+
+    /**
+     * Check if this base is marked to be added to the currently open tab. Default is false.
+     * @return
+     */
+    public boolean toOpenTab() {
+        return toOpenTab;
+    }
+
+    public void setToOpenTab(boolean toOpenTab) {
+        this.toOpenTab = toOpenTab;
+    }
+
+    public BibtexDatabase getDatabase() {
+	return base;
+    }
+
+    public HashMap getMetaData() {
+	return metaData;
+    }
+
+    public HashMap getEntryTypes() {
+	return entryTypes;
+    }
+
+    public File getFile() {
+      return file;
+    }
+
+    public void setFile(File f) {
+      file = f;
+    }
+
+    /**
+     * Sets the variable indicating which encoding was used during parsing.
+     *
+     * @param enc String the name of the encoding.
+     */
+    public void setEncoding(String enc) {
+      encoding = enc;
+    }
+
+    /**
+     * Returns the name of the encoding used during parsing, or null if not specified
+     * (indicates that prefs.get("defaultEncoding") was used).
+     */
+    public String getEncoding() {
+      return encoding;
+    }
+
+    /**
+     * Add a parser warning.
+     *
+     * @param s String Warning text. Must be pretranslated. Only added if there isn't already a dupe.
+     */
+    public void addWarning(String s) {
+        if (!warnings.contains(s))
+            warnings.add(s);
+    }
+
+    public boolean hasWarnings() {
+      return (warnings.size() > 0);
+    }
+
+    public String[] warnings() {
+      String[] s = new String[warnings.size()];
+      for (int i=0; i<warnings.size(); i++)
+        s[i] = (String)warnings.get(i);
+      return s;
+    }
+
+}
diff --git a/src/java/net/sf/jabref/imports/RepecNepImporter.java b/src/java/net/sf/jabref/imports/RepecNepImporter.java
new file mode 100644
index 0000000..7993171
--- /dev/null
+++ b/src/java/net/sf/jabref/imports/RepecNepImporter.java
@@ -0,0 +1,491 @@
+/*
+ Copyright (C) 2005 Andreas Rudert
+
+ 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.imports;
+import java.io.InputStream;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.Collection;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.List;
+import java.util.ArrayList;
+import net.sf.jabref.BibtexEntry;
+import net.sf.jabref.BibtexEntryType;
+import net.sf.jabref.Util;
+import net.sf.jabref.imports.ImportFormat;
+import net.sf.jabref.imports.ImportFormatReader;
+
+
+/**
+ * Imports a New Economics Papers-Message from the REPEC-NEP Service.
+ * 
+ * <p>{@link http://www.repec.org RePEc} (Research Papers in Economics) 
+ * is a collaborative effort of over 100 volunteers in 49 countries 
+ * to enhance the dissemination of research in economics. The heart of 
+ * the project is a decentralized database of working papers, journal 
+ * articles and software components. All RePEc material is freely available.</p>
+ * At the time of writing RePEc holds over 300.000 items.</p>
+ * 
+ * <p>{@link http://nep.repec.org NEP} (New Economic Papers) is an announcement 
+ * service which filters information on new additions to RePEc into edited 
+ * reports. The goal is to provide subscribers with up-to-date information 
+ * to the research literature.</p>
+ * 
+ * <p>This importer is capable of importing NEP messages into JabRef.</p>
+ * 
+ * <p>There is no officially defined message format for NEP. NEP messages are assumed to have 
+ * (and almost always have) the form given by the following semi-formal grammar:
+ * <pre>
+ * NEPMessage:
+ *       MessageSection NEPMessage
+ *       MessageSection
+ *       
+ * MessageSection:            
+ *       OverviewMessageSection 
+ *       OtherMessageSection
+ *
+ * # we skip the overview
+ * OverviewMessageSection:
+ *       'In this issue we have: ' SectionSeparator OtherStuff
+ *
+ * OtherMessageSection:
+ *       SectionSeparator  OtherMessageSectionContent
+ *
+ * # we skip other stuff and read only full working paper references
+ * OtherMessageSectionContent:
+ *       WorkingPaper EmptyLine OtherMessageSectionContent 
+ *       OtherStuff EmptyLine OtherMessageSectionContent
+ *       ''
+ *       
+ * OtherStuff:
+ *       NonEmptyLine OtherStuff
+ *       NonEmptyLine
+ *       
+ * NonEmptyLine:
+ *       a non-empty String that does not start with a number followed by a '.'
+ *       
+ * # working papers are recognized by a number followed by a '.' 
+ * # in a non-overview section
+ * WorkingPaper:
+ *       Number'.' WhiteSpace TitleString EmptyLine Authors EmptyLine Abstract AdditionalFields
+ *       Number'.' WhiteSpace TitleString AdditionalFields Abstract AdditionalFields
+ *       
+ * TitleString:
+ *       a String that may span several lines and should be joined
+ *       
+ * # there must be at least one author
+ * Authors:
+ *       Author '\n' Authors
+ *       Author '\n'
+ * 
+ * # optionally, an institution is given for an author
+ * Author:
+ *       AuthorName
+ *       AuthorName '(' Institution ')'
+ *       
+ * # there are no rules about the name, it may be firstname lastname or lastname, firstname or anything else
+ * AuthorName:
+ *       a non-empty String without '(' or ')' characters, not spanning more that one line
+ *       
+ * Institution:
+ *       a non-empty String that may span several lines
+ *       
+ * Abstract:
+ *       a (possibly empty) String that may span several lines
+ *
+ * AdditionalFields:
+ *       AdditionalField '\n' AdditionalFields
+ *       EmptyLine AdditionalFields
+ *       ''
+ *       
+ * AdditionalField:
+ *       'Keywords:' KeywordList
+ *       'URL:' non-empty String
+ *       'Date:' DateString
+ *       'JEL:' JelClassificationList
+ *       'By': Authors
+ *       
+ * KeywordList:
+ *        Keyword ',' KeywordList
+ *        Keyword ';' KeywordList
+ *        Keyword
+ *        
+ * Keyword:
+ *        non-empty String that does not contain ',' (may contain whitespace)
+ *        
+ * # if no date is given, the current year as given by the system clock is assumed
+ * DateString:
+ *        'yyyy-MM-dd'
+ *        'yyyy-MM'
+ *        'yyyy'
+ *        
+ * JelClassificationList:
+ *        JelClassification JelClassificationList
+ *        JelClassification
+ *      
+ * # the JEL Classifications are set into a new BIBTEX-field 'jel'
+ * # they will appear if you add it as a field to one of the BIBTex Entry sections
+ * JelClassification:
+ *        one of the allowed classes, see http://ideas.repec.org/j/
+ *       
+ * SectionSeparator:
+ *       '\n-----------------------------'
+ * </pre>
+ * </p>
+ * 
+ * @see http://nep.repec.org
+ * @author andreas_sf at rudert-home dot de
+ */
+public class RepecNepImporter extends ImportFormat {
+
+  private final static Collection recognizedFields = Arrays.asList(new String[]{"Keywords", "JEL", "Date", "URL", "By"});
+  
+  private int line = 0;
+  private String lastLine = "";
+  private String preLine = "";
+  private BufferedReader in = null;
+  private boolean inOverviewSection = false;
+  
+  /**
+   * Return the name of this import format.
+   */
+  public String getFormatName() {
+    return "REPEC New Economic Papers (NEP)";
+  }
+
+  /*
+   *  (non-Javadoc)
+   * @see net.sf.jabref.imports.ImportFormat#getCLIId()
+   */
+  public String getCLIId() {
+    return "repecnep";
+  }
+  
+  /*
+   *  (non-Javadoc)
+   * @see net.sf.jabref.imports.ImportFormat#getExtensions()
+   */  
+  public String getExtensions() {
+    return ".txt";
+  }
+  
+  /*
+   *  (non-Javadoc)
+   * @see net.sf.jabref.imports.ImportFormat#getDescription()
+   */
+  public String getDescription() {
+    return 
+      "Imports a New Economics Papers-Message (see http://nep.repec.org)\n"
+    + "from the REPEC-NEP Service (see http://www.repec.org).\n"
+    + "To import papers either save a NEP message as a text file and then import or\n"
+    + "copy&paste the papers you want to import and make sure, one of the first lines\n"
+    + "contains the line \"nep.repec.org\".";
+  }
+  
+  /*
+   *  (non-Javadoc)
+   * @see net.sf.jabref.imports.ImportFormat#isRecognizedFormat(java.io.InputStream)
+   */
+  public boolean isRecognizedFormat(InputStream stream) throws IOException {
+    // read the first couple of lines
+    // NEP message usually contain the String 'NEP: New Economics Papers'
+    // or, they are from nep.repec.org
+    BufferedReader in = new BufferedReader(ImportFormatReader.getReaderDefaultEncoding(stream));
+    String startOfMessage = "";
+    String line = in.readLine();
+    for (int i = 0; i < 25 && line != null; i++) {
+      startOfMessage += line;
+      line = in.readLine();
+    }
+    return startOfMessage.indexOf("NEP: New Economics Papers") >= 0 || startOfMessage.indexOf("nep.repec.org") >= 0;
+  }
+
+  private boolean startsWithKeyword(Collection keywords) {
+    boolean result = this.lastLine.indexOf(':') > 0;
+    if (result) {
+      String possibleKeyword = this.lastLine.substring(0, this.lastLine.indexOf(':'));
+      result = keywords.contains(possibleKeyword);
+    }
+    return result;
+  }
+  
+  private void readLine() throws IOException {
+    this.line++;
+    this.preLine = this.lastLine;
+    this.lastLine = this.in.readLine();
+  }
+  
+  /**
+   * Read multiple lines.
+   * 
+   * <p>Reads multiple lines until either
+   * <ul>
+   *   <li>an empty line</li>
+   *   <li>the end of file</li>
+   *   <li>the next working paper or</li>
+   *   <li>a keyword</li>
+   * </ul>
+   * is found. Whitespace at start or end of lines is trimmed except for one blank character.</p>
+   * 
+   * @return  result
+   */
+  private String readMultipleLines() throws IOException {
+    String result = this.lastLine.trim();
+    readLine();
+    while (this.lastLine != null && !this.lastLine.trim().equals("") && !startsWithKeyword(recognizedFields) && !isStartOfWorkingPaper()) {
+      result += this.lastLine.length() == 0 ? this.lastLine.trim() : " " + this.lastLine.trim();
+      readLine();
+    }
+    return result;
+  }
+
+  /**
+   * Implements grammar rule "TitleString".
+   * 
+   * @param be
+   * @throws IOException
+   */
+  private void parseTitleString(BibtexEntry be) throws IOException {
+    // skip article number
+    this.lastLine = this.lastLine.substring(this.lastLine.indexOf('.') + 1, this.lastLine.length());
+    be.setField("title", readMultipleLines());
+  }
+  
+  /**
+   * Implements grammer rule "Authors"
+   * 
+   * @param be
+   * @throws IOException
+   */
+  private void parseAuthors(BibtexEntry be) throws IOException {
+    // read authors and institutions
+    String authors = "";
+    String institutions = "";
+    while (this.lastLine != null && !this.lastLine.equals("") && !startsWithKeyword(recognizedFields)) {
+      
+      // read single author
+      String author = null;
+      String institution = null;
+      boolean institutionDone = false;
+      if (this.lastLine.indexOf('(') >= 0) {
+        author = this.lastLine.substring(0, this.lastLine.indexOf('(')).trim();
+        institutionDone = this.lastLine.indexOf(')') > 0;
+        institution = this.lastLine.substring(this.lastLine.indexOf('(') + 1, institutionDone && this.lastLine.indexOf(')') > this.lastLine.indexOf('(') + 1 ? this.lastLine.indexOf(')') : this.lastLine.length()).trim();
+      } else {
+        author = this.lastLine.substring(0, this.lastLine.length()).trim();
+        institutionDone = true;
+      }
+      
+      readLine();
+      while (!institutionDone && this.lastLine!= null) {
+        institutionDone = this.lastLine.indexOf(')') > 0;
+        institution += this.lastLine.substring(0, institutionDone ? this.lastLine.indexOf(')') : this.lastLine.length()).trim();
+        readLine();
+      }
+      
+      if (author != null) {
+        authors += !authors.equals("") ? " and " + author : "" + author;
+      }
+      if (institution != null) {
+        institutions += !institutions.equals("") ? " and " + institution : "" + institution;
+      }            
+    }
+    
+    if (!authors.equals("")) {
+      be.setField("author", authors);
+    }
+    if (!institutions.equals("")) {
+      be.setField("institution", institutions);
+    }
+  }
+  
+  /**
+   * Implements grammar rule "Abstract".
+   * 
+   * @param be
+   * @throws IOException
+   */
+  private void parseAbstract(BibtexEntry be) throws IOException {
+    String theabstract = readMultipleLines();
+    
+    if (!theabstract.equals("")) {
+      be.setField("abstract", theabstract);
+    }
+  }
+    
+  /**
+   * Implements grammar rule "AdditionalFields".
+   * 
+   * @param be
+   * @throws IOException
+   */
+  private void parseAdditionalFields(BibtexEntry be, boolean multilineUrlFieldAllowed) throws IOException {
+    
+    // one empty line is possible before fields start
+    if (this.lastLine != null && this.lastLine.trim().equals("")) {
+      readLine();  
+    }
+    
+    // read other fields
+    while (this.lastLine != null && !isStartOfWorkingPaper() && (startsWithKeyword(recognizedFields) || this.lastLine.equals(""))) {
+      
+      // if multiple lines for a field are allowed and field consists of multiple lines, join them
+      String keyword = this.lastLine.equals("") ? "" : this.lastLine.substring(0, this.lastLine.indexOf(':')).trim();
+      // skip keyword
+      this.lastLine = this.lastLine.equals("") ? "" : this.lastLine.substring(this.lastLine.indexOf(':')+1, this.lastLine.length()).trim();
+      
+      // parse keywords field
+      if (keyword.equals("Keywords")) {
+        String content = readMultipleLines();
+        String[] keywords = content.split("[,;]");
+        String keywordStr = "";
+        for (int i = 0; i < keywords.length; i++) {
+          keywordStr += " '" + keywords[i].trim() + "'";
+        }
+        be.setField("keywords", keywordStr.trim());
+        
+      // parse JEL field
+      } else if (keyword.equals("JEL")) {
+        be.setField("jel", readMultipleLines());
+        
+      // parse date field
+      } else if (keyword.startsWith("Date")) {
+        Date date = null;
+        String content = readMultipleLines();
+        String[] recognizedDateFormats = new String[] {"yyyy-MM-dd","yyyy-MM","yyyy"};
+        int i = 0;
+        for (; i < recognizedDateFormats.length && date == null; i++) {
+          try {            
+            date = new SimpleDateFormat(recognizedDateFormats[i]).parse(content);
+          } catch (ParseException e) {
+            // wrong format
+          }
+        }
+        
+        Calendar cal = new GregorianCalendar();              
+        cal.setTime(date != null ? date : new Date());
+        be.setField("year", "" + cal.get(Calendar.YEAR));
+        if (date != null && recognizedDateFormats[i-1].indexOf("MM") >= 0) {
+          be.setField("month", "" + cal.get(Calendar.MONTH));
+        }
+        
+      // parse URL field
+      } else if (keyword.startsWith("URL")) {
+        String content = null;
+        if (multilineUrlFieldAllowed) {
+          content = readMultipleLines(); 
+        } else {
+          content = this.lastLine;
+          readLine();
+        }
+        be.setField("url", content);
+        
+      // authors field
+      } else if (keyword.startsWith("By")) {
+        // parse authors      
+        parseAuthors(be); 
+      } else {
+        readLine();
+      }
+    }
+  }
+
+  /**
+   * if line starts with a string of the form 'x. ' and we are not in the overview
+   * section, we have a working paper entry we are interested in
+   */
+  private boolean isStartOfWorkingPaper() {
+    return this.lastLine.matches("\\d+\\.\\s.*") && !this.inOverviewSection && this.preLine.trim().equals("");
+  }
+  
+  /*
+   *  (non-Javadoc)
+   * @see net.sf.jabref.imports.ImportFormat#importEntries(java.io.InputStream)
+   */
+  public List importEntries(InputStream stream) throws IOException {    
+  	ArrayList bibitems = new ArrayList();
+    String paperNoStr = null;
+    this.line = 0;
+    
+    try {
+    	this.in = new BufferedReader(ImportFormatReader.getReaderDefaultEncoding(stream));
+      
+      readLine(); // skip header and editor information
+    	while (this.lastLine != null) {
+  
+        if (this.lastLine.startsWith("-----------------------------")) {
+          this.inOverviewSection = this.preLine.startsWith("In this issue we have");
+        } 
+        if (isStartOfWorkingPaper()) {
+          BibtexEntry be = new BibtexEntry(Util.createNeutralId());
+          be.setType(BibtexEntryType.getType("techreport"));
+          paperNoStr = this.lastLine.substring(0, this.lastLine.indexOf('.'));  
+          parseTitleString(be);
+          if (startsWithKeyword(recognizedFields)) {
+            parseAdditionalFields(be, false);
+          } else {
+            readLine(); // skip empty line
+            parseAuthors(be);
+            readLine(); // skip empty line
+          }
+          if (!startsWithKeyword(recognizedFields)) {
+            parseAbstract(be);
+          }
+          parseAdditionalFields(be, true);
+          
+          bibitems.add(be);
+          paperNoStr = null;
+          
+        } else {        
+          this.preLine = this.lastLine;
+          readLine();
+        }
+      }
+      
+    } catch (Exception e) {
+      String message = "Error in REPEC-NEP import on line " + this.line;
+      if (paperNoStr != null) {
+        message += ", paper no. " + paperNoStr + ": ";
+      }
+      message += e.getMessage();
+      System.err.println(message);
+      if (!(e instanceof IOException)) {
+        e.printStackTrace();
+        e = new IOException(message);
+      }
+      throw (IOException)e;
+    }
+
+  	return bibitems;	  	
+  }
+}
+
+
diff --git a/src/java/net/sf/jabref/imports/RisImporter.java b/src/java/net/sf/jabref/imports/RisImporter.java
new file mode 100644
index 0000000..0654de5
--- /dev/null
+++ b/src/java/net/sf/jabref/imports/RisImporter.java
@@ -0,0 +1,204 @@
+package net.sf.jabref.imports;
+
+import java.util.regex.Pattern;
+import java.io.InputStream;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.HashMap;
+import net.sf.jabref.BibtexEntry;
+import net.sf.jabref.Globals;
+import net.sf.jabref.AuthorList;
+
+/**
+ * Imports a Biblioscape Tag File. The format is described on
+ * http://www.biblioscape.com/manual_bsp/Biblioscape_Tag_File.htm Several
+ * Biblioscape field types are ignored. Others are only included in the BibTeX
+ * field "comment".
+ */
+public class RisImporter extends ImportFormat {
+
+    /**
+     * Return the name of this import format.
+     */
+    public String getFormatName() {
+    return "RIS";
+    }
+
+    /*
+     *  (non-Javadoc)
+     * @see net.sf.jabref.imports.ImportFormat#getCLIId()
+     */
+    public String getCLIId() {
+      return "ris";
+    }
+    
+    /**
+     * 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 "AU  - *" line.
+    BufferedReader in = new BufferedReader(ImportFormatReader.getReaderDefaultEncoding(stream));
+    Pattern pat1 = Pattern
+        .compile("AU  - .*"),
+        pat2 = Pattern
+        .compile("A1  - .*");
+
+    String str;
+    while ((str = in.readLine()) != null){
+        if (pat1.matcher(str).find() || pat2.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));
+    String str;
+    while ((str = in.readLine()) != null){
+        sb.append(str);
+        sb.append("\n");
+    }
+    String[] entries = sb.toString().split("ER  -");
+
+
+    for (int i = 0; i < entries.length - 1; i++){
+            String Type = "", Author = "", Editor = "", StartPage = "", EndPage = "",
+                comment = "";
+            HashMap hm = new HashMap();
+
+        String[] fields = entries[i].split("\n");
+
+        for (int j = 0; j < fields.length; j++){
+                StringBuffer current = new StringBuffer(fields[j]);
+                boolean done = false;
+                while (!done && (j < fields.length-1)) {
+                    if ((fields[j+1].length() >= 6) && !fields[j+1].substring(2, 6).equals("  - ")) {
+                        if ((current.length() > 0)
+                                && !Character.isWhitespace(current.charAt(current.length()-1))
+                                && !Character.isWhitespace(fields[j+1].charAt(0)))
+                            current.append(' ');
+                        current.append(fields[j+1]);
+                        j++;
+                    } else
+                        done = true;
+                }
+                String entry = current.toString();
+        if (entry.length() < 6) continue;
+        else{
+            String lab = entry.substring(0, 2);
+            String val = entry.substring(6).trim();
+            if (lab.equals("TY")){
+            if (val.equals("BOOK")) Type = "book";
+            else if (val.equals("JOUR") || val.equals("MGZN")) Type = "article";
+                        else if (val.equals("THES")) Type = "phdthesis";
+                        else if (val.equals("UNPB")) Type = "unpublished";
+                        else if (val.equals("RPRT")) Type = "techreport";
+                        else if (val.equals("CONF")) Type = "inproceedings";
+                        else if (val.equals("CHAP")) Type = "incollection";//"inbook";
+
+            else Type = "other";
+            }else if (lab.equals("T1") || lab.equals("TI")) hm.put("title", val);//Title
+            // =
+            // val;
+            else if (lab.equals("T2") || lab.equals("T3") || lab.equals("BT")) {
+                hm.put("booktitle", val);
+            }
+            else if (lab.equals("A1") || lab.equals("AU")){
+                if (Author.equals("")) // don't add " and " for the first author
+                    Author = val;
+                else Author += " and " + val;
+            }
+            else if (lab.equals("A2")){
+                if (Editor.equals("")) // don't add " and " for the first editor
+                    Editor = val;
+                else Editor += " and " + val;
+            } else if (lab.equals("JA") || lab.equals("JF") || lab.equals("JO")) {
+                if (Type.equals("inproceedings"))
+                    hm.put("booktitle", val);
+                else
+                    hm.put("journal", val);
+            }
+
+            else if (lab.equals("SP")) StartPage = val;
+            else if (lab.equals("PB"))
+                hm.put("publisher", val);
+            else if (lab.equals("AD") || lab.equals("CY"))
+                hm.put("address", val);
+            else if (lab.equals("EP")) EndPage = val;
+                    else if (lab.equals("SN"))
+                        hm.put("issn", val);
+            else if (lab.equals("VL")) hm.put("volume", val);
+            else if (lab.equals("IS")) hm.put("number", val);
+            else if (lab.equals("N2") || lab.equals("AB")) hm
+                                       .put("abstract", val);
+            else if (lab.equals("UR")) hm.put("url", val);
+            else if ((lab.equals("Y1") || lab.equals("PY")) && val.length() >= 4) {
+                        String[] parts = val.split("/");
+                        hm.put("year", parts[0]);
+                        if ((parts.length > 1) && (parts[1].length() > 0)) {
+                            try {
+                                int month = Integer.parseInt(parts[1]);
+                                if ((month > 0) && (month <= 12)) {
+                                    //System.out.println(Globals.MONTHS[month-1]);
+                                    hm.put("month", "#"+Globals.MONTHS[month-1]+"#");
+                                }
+                            } catch (NumberFormatException ex) {
+                                // The month part is unparseable, so we ignore it.
+                            }
+                        }
+                    }
+
+            else if (lab.equals("KW")){
+            if (!hm.containsKey("keywords")) hm.put("keywords", val);
+            else{
+                String kw = (String) hm.get("keywords");
+                hm.put("keywords", kw + ", " + val);
+            }
+            }
+            else if (lab.equals("U1") || lab.equals("U2") || lab.equals("N1")) {
+                if (comment.length() > 0)
+                    comment = comment+"\n";
+                comment = comment+val;
+            }
+            // Added ID import 2005.12.01, Morten Alver:
+            else if (lab.equals("ID"))
+                hm.put("refid", val);
+        }
+        }
+        // fix authors
+        if (Author.length() > 0) {
+            Author = AuthorList.fixAuthor_lastNameFirst(Author);
+            hm.put("author", Author);
+        }
+        if (Editor.length() > 0) {
+            Editor = AuthorList.fixAuthor_lastNameFirst(Editor);
+            hm.put("editor", Editor);
+        }
+        if (comment.length() > 0) {
+            hm.put("comment", comment);
+        }
+
+        hm.put("pages", StartPage + "--" + EndPage);
+        BibtexEntry b = new BibtexEntry(Globals.DEFAULT_BIBTEXENTRY_ID, Globals
+                        .getEntryType(Type)); // id assumes an existing database so don't
+        // create one here
+        b.setField(hm);
+
+        bibitems.add(b);
+
+    }
+
+    return bibitems;
+    }
+}
+
+
diff --git a/src/java/net/sf/jabref/imports/ScifinderImporter.java b/src/java/net/sf/jabref/imports/ScifinderImporter.java
new file mode 100644
index 0000000..cbee6a8
--- /dev/null
+++ b/src/java/net/sf/jabref/imports/ScifinderImporter.java
@@ -0,0 +1,101 @@
+package net.sf.jabref.imports;
+
+import java.io.InputStream;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.HashMap;
+import net.sf.jabref.BibtexEntry;
+import net.sf.jabref.Globals;
+import net.sf.jabref.AuthorList;
+
+/**
+ * Imports a Biblioscape Tag File. The format is described on
+ * http://www.biblioscape.com/manual_bsp/Biblioscape_Tag_File.htm Several
+ * Biblioscape field types are ignored. Others are only included in the BibTeX
+ * field "comment".
+ */
+public class ScifinderImporter extends ImportFormat {
+
+    /**
+     * Return the name of this import format.
+     */
+    public String getFormatName() {
+    return "Scifinder";
+    }
+
+    /*
+     *  (non-Javadoc)
+     * @see net.sf.jabref.imports.ImportFormat#getCLIId()
+     */
+    public String getCLIId() {
+      return "scifinder";
+    }
+    
+    /**
+     * Check whether the source is in the correct format for this importer.
+     */
+    public boolean isRecognizedFormat(InputStream in) throws IOException {
+    return true;
+    }
+
+    /**
+     * 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));
+    String str;
+    while ((str = in.readLine()) != null){
+        sb.append(str);
+    }
+
+    String[] entries = sb.toString().split("START_RECORD");
+    HashMap hm = new HashMap();
+    for (int i = 1; i < entries.length; i++){
+        String[] fields = entries[i].split("FIELD ");
+        String Type = "";
+        hm.clear(); // reset
+        for (int j = 0; j < fields.length; j++)
+        if (fields[j].indexOf(":") >= 0){
+            String tmp[] = new String[2];
+            tmp[0] = fields[j].substring(0, fields[j].indexOf(":"));
+            tmp[1] = fields[j].substring(fields[j].indexOf(":") + 1).trim();
+            if (tmp.length > 1){//==2
+            if (tmp[0].equals("Author")) hm.put("author", AuthorList.fixAuthor_lastNameFirst(tmp[1].replaceAll(";", " and ")));
+            else if (tmp[0].equals("Title")) hm.put("title", tmp[1]);
+
+            else if (tmp[0].equals("Journal Title")) hm.put("journal", tmp[1]);
+
+            else if (tmp[0].equals("Volume")) hm.put("volume", tmp[1]);
+            else if (tmp[0].equals("Page")) hm.put("pages", tmp[1]);
+            else if (tmp[0].equals("Publication Year")) hm.put("year", tmp[1]);
+            else if (tmp[0].equals("Abstract")) hm.put("abstract", tmp[1]);
+            else if (tmp[0].equals("Supplementary Terms")) hm.put("keywords",
+                                          tmp[1]);
+            else if (tmp[0].equals("Document Type")) {
+                                if (tmp[1].startsWith("Journal") || tmp[1].startsWith("Review"))
+                                    Type = "article";
+                                else if (tmp[1].equals("Dissertation"))
+                                    Type = "phdthesis";
+                                else
+                                    Type = tmp[1];
+                        }
+            }
+        }
+
+        BibtexEntry b = new BibtexEntry(Globals.DEFAULT_BIBTEXENTRY_ID, Globals
+                        .getEntryType(Type)); // id assumes an existing database so don't
+        // create one here
+        b.setField(hm);
+        bibitems.add(b);
+
+    }
+    return bibitems;
+    }
+}
+
+
diff --git a/src/java/net/sf/jabref/imports/SilverPlatterImporter.java b/src/java/net/sf/jabref/imports/SilverPlatterImporter.java
new file mode 100644
index 0000000..2c5d19e
--- /dev/null
+++ b/src/java/net/sf/jabref/imports/SilverPlatterImporter.java
@@ -0,0 +1,177 @@
+package net.sf.jabref.imports;
+
+import java.io.InputStream;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.HashMap;
+import net.sf.jabref.BibtexEntry;
+import net.sf.jabref.Globals;
+import net.sf.jabref.AuthorList;
+
+import java.util.regex.Pattern;
+
+/**
+ * Imports a SilverPlatter exported file. This is a poor format to parse,
+ * so it currently doesn't handle everything correctly.
+ */
+public class SilverPlatterImporter extends ImportFormat {
+
+    /**
+     * Return the name of this import format.
+     */
+    public String getFormatName() {
+	return "SilverPlatter";
+    }
+
+    /*
+     *  (non-Javadoc)
+     * @see net.sf.jabref.imports.ImportFormat#getCLIId()
+     */
+    public String getCLIId() {
+      return "silverplatter";
+    }
+    
+    /**
+     * 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));
+
+	// This format is very similar to Inspec, so we have a two-fold strategy:
+	// If we see the flag signalling that it is an inspec file, return false.
+	// This flag should appear above the first entry and prevent us from 
+	// accepting the Inspec format. Then we look for the title entry.
+	Pattern pat1 = Pattern.compile("Record.*INSPEC.*");
+	String str;
+	while ((str = in.readLine()) != null){
+
+	    if (pat1.matcher(str).find())
+		return false; // This is an inspec file, so return false.
+
+	    if ((str.length()>=5) && (str.substring(0, 5).equals("TI:  ")))
+		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();
+	BufferedReader in = new BufferedReader(ImportFormatReader.getReaderDefaultEncoding(stream));
+	boolean isChapter = false;
+	String str;
+	StringBuffer sb = new StringBuffer();
+	while ((str = in.readLine()) != null){
+	    if (str.length() < 2) sb.append("__::__").append(str);
+	    else
+            sb.append("__NEWFIELD__").append(str);
+	}
+	in.close();
+	String[] entries = sb.toString().split("__::__");
+	String Type = "";
+	HashMap h = new HashMap();
+	entryLoop: for (int i = 0; i < entries.length; i++){
+	    if (entries[i].trim().length() < 6) continue entryLoop;
+	    //System.out.println("'"+entries[i]+"'");
+	    h.clear();
+	    String[] fields = entries[i].split("__NEWFIELD__");
+	    fieldLoop: for (int j = 0; j < fields.length; j++){
+		if (fields[j].length() < 6) continue fieldLoop;
+		//System.out.println(">"+fields[j]+"<");
+		String s = fields[j];
+		String f3 = s.substring(0, 2);
+		String frest = s.substring(5);
+		if (f3.equals("TI")) h.put("title", frest);
+		//else if(f3.equals("PY")) h.put("year", frest);
+		else if (f3.equals("AU")){
+		    if (frest.trim().endsWith("(ed)")){
+			String ed = frest.trim();
+			ed = ed.substring(0, ed.length() - 4);
+			h.put("editor", AuthorList.fixAuthor_lastNameFirst(ed.replaceAll(",-", ", ")
+                                .replaceAll(";", " and ")));
+		    }else h.put("author", AuthorList.fixAuthor_lastNameFirst(frest.replaceAll(
+                                           ",-", ", ").replaceAll(";", " and ")));
+		}else if (f3.equals("AB")) h.put("abstract", frest);
+		else if (f3.equals("DE")){
+		    String kw = frest.replaceAll("-;", ",").toLowerCase();
+		    h.put("keywords", kw.substring(0, kw.length() - 1));
+		}else if (f3.equals("SO")){
+		    int m = frest.indexOf(".");
+		    if (m >= 0){
+			String jr = frest.substring(0, m);
+			h.put("journal", jr.replaceAll("-", " "));
+			frest = frest.substring(m);
+			m = frest.indexOf(";");
+			if (m >= 5){
+			    String yr = frest.substring(m - 5, m).trim();
+			    h.put("year", yr);
+			    frest = frest.substring(m);
+			    m = frest.indexOf(":");
+			    if (m >= 0){
+				String pg = frest.substring(m + 1).trim();
+				h.put("pages", pg);
+				h.put("volume", frest.substring(1, m));
+			    }
+			}
+		    }
+		}else if (f3.equals("PB")){
+		    int m = frest.indexOf(":");
+		    if (m >= 0){
+			String jr = frest.substring(0, m);
+			h.put("publisher", jr.replaceAll("-", " ").trim());
+			frest = frest.substring(m);
+			m = frest.indexOf(", ");
+			if (m + 2 < frest.length()){
+			    String yr = frest.substring(m + 2).trim();
+			    h.put("year", yr);
+			}
+		    }
+		}else if (f3.equals("DT")){
+		    frest = frest.trim();
+		    if (frest.equals("Monograph")) Type = "book";
+		    else if (frest.toLowerCase().indexOf("journal") >= 0) Type = "article";
+		    else if (frest.equals("Contribution") || frest.equals("Chapter")){
+			Type = "incollection";
+			// This entry type contains page numbers and booktitle in the
+			// title field.
+			isChapter = true;
+		    }
+		    
+		    else Type = frest.replaceAll(" ", "");
+		}
+	    }
+
+	    if (isChapter) {
+		Object titleO = h.get("title");
+		if (titleO != null) {
+		    String title = ((String)titleO).trim();
+		    int inPos = title.indexOf("\" in ");
+		    int pgPos = title.lastIndexOf(" ");
+		    if (inPos > 1) h.put("title", title.substring(1, inPos));
+		    if (pgPos > inPos) h.put("pages", title.substring(pgPos)
+					     .replaceAll("-", "--"));
+		    
+		}
+
+	    }
+
+	    BibtexEntry b = new BibtexEntry(Globals.DEFAULT_BIBTEXENTRY_ID, Globals
+					    .getEntryType(Type)); // id assumes an existing database so don't
+	    // create one here
+	    b.setField(h);
+	    
+	    bibitems.add(b);
+	    
+	}
+	
+	
+	return bibitems;
+    }
+}
+
+
diff --git a/src/java/net/sf/jabref/imports/SixpackImporter.java b/src/java/net/sf/jabref/imports/SixpackImporter.java
new file mode 100644
index 0000000..41823b7
--- /dev/null
+++ b/src/java/net/sf/jabref/imports/SixpackImporter.java
@@ -0,0 +1,138 @@
+package net.sf.jabref.imports;
+
+import java.io.InputStream;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.HashMap;
+import net.sf.jabref.BibtexEntry;
+import net.sf.jabref.BibtexEntryType;
+import net.sf.jabref.Globals;
+import net.sf.jabref.Util;
+
+/**
+ * Imports a Biblioscape Tag File. The format is described on
+ * http://www.biblioscape.com/manual_bsp/Biblioscape_Tag_File.htm Several
+ * Biblioscape field types are ignored. Others are only included in the BibTeX
+ * field "comment".
+ */
+public class SixpackImporter extends ImportFormat {
+
+    /**
+     * Return the name of this import format.
+     */
+    public String getFormatName() {
+	return "Sixpack";
+    }
+
+    /*
+     *  (non-Javadoc)
+     * @see net.sf.jabref.imports.ImportFormat#getCLIId()
+     */
+    public String getCLIId() {
+      return "sixpack";
+    }
+    
+    /**
+     * Check whether the source is in the correct format for this importer.
+     */
+    public boolean isRecognizedFormat(InputStream in) throws IOException {
+	return true;
+    }
+
+    /**
+     * Parse the entries in the source, and return a List of BibtexEntry
+     * objects.
+     */
+    public List importEntries(InputStream stream) throws IOException {
+
+	final String SEPARATOR = new String(new char[] { 0, 48 });
+	HashMap fI = new HashMap();
+	fI.put("id", "bibtexkey");
+	fI.put("au", "author");
+	fI.put("ti", "title");
+	fI.put("jo", "journal");
+	fI.put("vo", "volume");
+	fI.put("nu", "number");
+	fI.put("pa", "pages");
+	fI.put("mo", "month");
+	fI.put("yr", "year");
+	fI.put("kw", "keywords");
+	fI.put("ab", "abstract");
+	fI.put("no", "note");
+	fI.put("ed", "editor");
+	fI.put("pu", "publisher");
+	fI.put("se", "series");
+	fI.put("ad", "address");
+	fI.put("en", "edition");
+	fI.put("ch", "chapter");
+	fI.put("hp", "howpublished");
+	fI.put("tb", "booktitle");
+	fI.put("or", "organization");
+	fI.put("sc", "school");
+	fI.put("in", "institution");
+	fI.put("ty", "type");
+	fI.put("url", "url");
+	fI.put("cr", "crossref");
+    fI.put("fi", "file");
+
+	ArrayList bibitems = new ArrayList();
+	BufferedReader in = new BufferedReader(ImportFormatReader.getReaderDefaultEncoding(stream));
+	in.readLine();
+    String ln = in.readLine();
+    if (ln == null)
+        return null;
+    String[] fieldDef = ln.split(",");
+
+    String s = null;
+	BibtexEntry entry = null;
+	lines: while ((s = in.readLine()) != null){
+	    try{
+		s = s.replaceAll("<par>", ""); // What is <par> ????
+		String[] fields = s.split(SEPARATOR);
+		// Check type and create entry:
+		if (fields.length < 2)
+		    continue lines; // Avoid ArrayIndexOutOfBoundsException
+		BibtexEntryType typ = BibtexEntryType
+		    .getType(fields[1].toLowerCase());
+		if (typ == null){
+		    String type = "";
+		    if (fields[1].equals("Masterthesis")) type = "mastersthesis";
+		    if (fields[1].equals("PhD-Thesis")) type = "phdthesis";
+		    if (fields[1].equals("miscellaneous")) type = "misc";
+		    if (fields[1].equals("Conference")) type = "proceedings";
+		    typ = BibtexEntryType.getType(type.toLowerCase());
+		}
+		entry = new BibtexEntry(Util.createNeutralId(), typ);
+		String fld;
+		for (int i = 0; i < Math.min(fieldDef.length, fields.length); i++){
+		    fld = (String) fI.get(fieldDef[i]);
+		    if (fld != null){
+			if (fld.equals("author") || fld.equals("editor")) ImportFormatReader.setIfNecessary(entry,
+												      fld, fields[i].replaceAll(" and ", ", ").replaceAll(", ",
+																			  " and "));
+			else if (fld.equals("pages")) ImportFormatReader.setIfNecessary(entry, fld, fields[i]
+							       .replaceAll("-", "--"));
+            else if (fld.equals("file")) {
+                String fieldName = "pdf"; // We set pdf as default.
+                if (fields[i].endsWith("ps") || fields[i].endsWith("ps.gz"))
+                    fieldName = "ps";
+                else if (fields[i].endsWith("html"))
+                    fieldName = "url";
+                ImportFormatReader.setIfNecessary(entry, fieldName, fields[i]);
+            }
+			else ImportFormatReader.setIfNecessary(entry, fld, fields[i]);
+		    }
+		}
+		bibitems.add(entry);
+	    }catch (NullPointerException ex){
+		Globals.logger("Problem parsing Sixpack entry, ignoring entry.");
+	    }
+	}
+
+	return bibitems;
+    }
+}
+
+
diff --git a/src/java/net/sf/jabref/imports/TextAnalyzer.java b/src/java/net/sf/jabref/imports/TextAnalyzer.java
new file mode 100644
index 0000000..ff0cad0
--- /dev/null
+++ b/src/java/net/sf/jabref/imports/TextAnalyzer.java
@@ -0,0 +1,208 @@
+package net.sf.jabref.imports;
+
+import java.util.TreeSet;
+import net.sf.jabref.*;
+import java.util.Iterator;
+import java.util.Vector;
+
+public class TextAnalyzer {
+
+  BibtexEntry be = null;
+
+  public TextAnalyzer(String text) {
+    guessBibtexFields(text);
+  }
+
+  public BibtexEntry getEntry() {
+    return be;
+  }
+
+  public void guessBibtexFields(String text) {
+
+      TreeSet usedParts = new TreeSet();
+
+      text = "  "+text+"  ";
+
+      String[] split = null;
+
+      // Look for the year:
+      String year = null;
+      String yearRx = "(\\s|\\()\\d\\d\\d\\d(\\.|,|\\))";
+      String[] cand = getMatches(text, yearRx);
+      if (cand.length == 1) {
+        // Only one four-digit number, so we guess that is the year.
+        year = clean(cand[0]);
+        int pos = text.indexOf(year);
+        usedParts.add(new Substring("year", pos, pos+year.length()));
+        Util.pr("Guessing 'year': '"+year+"'");
+      } else if (cand.length > 1) {
+        // More than one four-digit numbers, so we look for one giving a reasonable year:
+
+        int good = -1, yearFound = -1;
+        find: for (int i=0; i<cand.length; i++) {
+          int number = Integer.parseInt(cand[i].trim());
+          if (number == yearFound)
+            continue find;
+          if (number < 2500) {
+            if (good == -1) {
+              good = i;
+              yearFound = number;
+            } else {
+              // More than one found. Be a bit more specific.
+              if ((yearFound < Globals.FUTURE_YEAR) && (number < Globals.FUTURE_YEAR)) {
+                good = -1;
+                break find; // Give up, both seem good enough.
+              }
+              else if ((yearFound >= Globals.FUTURE_YEAR) && (number < Globals.FUTURE_YEAR)) {
+                good = i;
+                yearFound = number;
+              }
+            }
+          }
+        }
+        if (good >= 0) {
+          year = clean(cand[good]);
+          int pos = text.indexOf(year);
+          usedParts.add(new Substring("year", pos, pos+year.length()));
+          Util.pr("Guessing 'year': '"+year+"'");
+        }
+      }
+
+      // Look for Pages:
+      String pages = null;
+      String pagesRx = "\\s(\\d{1,4})( ??)-( ??)(\\d{1,4})(\\.|,|\\s)";
+      cand = getMatches(text, pagesRx);
+      if (cand.length == 1) {
+        pages = clean(cand[0].replaceAll("-|( - )", "--"));
+        int pos = text.indexOf(cand[0]);
+        usedParts.add(new Substring("pages", pos, pos+year.length()));
+        Util.pr("Guessing 'pages': '" + pages + "'");
+      } else if (cand.length > 1) {
+        int found = -1;
+        checkScope: for (int i=0; i<cand.length; i++) {
+          split = clean(cand[i].replaceAll("\\s", "")).split("-");
+               //   Util.pr("Pg: "+pages);
+          int first = Integer.parseInt(split[0]),
+              second = Integer.parseInt(split[1]);
+          if (second-first > 3) {
+            found = i;
+            break checkScope;
+          }
+        }
+        if (found >= 0) {
+          pages = clean(cand[found].replaceAll("-|( - )", "--"));
+          int pos = text.indexOf(cand[found]);
+          Util.pr("Guessing 'pages': '" + pages + "'");
+          usedParts.add(new Substring("pages", pos, pos+pages.length()));
+        }
+      }
+
+      //String journalRx = "(\\.|\\n)\\s??([a-zA-Z\\. ]{8,30}+)((vol\\.|Vol\\.|Volume|volume))??(.??)(\\d{1,3})(\\.|,|\\s)";
+      String journal = null,
+          volume = null;
+      String journalRx = "(,|\\.|\\n)\\s??([a-zA-Z\\. ]{8,30}+)((.){0,2})((vol\\.|Vol\\.|Volume|volume))??\\s??(\\d{1,3})(\\.|,|\\s|:)";
+      cand = getMatches(text, journalRx);
+      if (cand.length > 0) {
+        //Util.pr("guessing 'journal': '" + cand[0] + "'");
+        cand[0] = cand[0].trim();
+        int pos = cand[0].lastIndexOf(' ');
+        if (pos > 0) {
+          volume = clean(cand[0].substring(pos+1));
+          Util.pr("Guessing 'volume': '" + volume + "'");
+          journal = clean(cand[0].substring(0, pos));
+          //Util.pr("guessing 'journal': '" + journal + "'");
+          pos = journal.lastIndexOf(' ');
+          if (pos > 0) {
+            String last = journal.substring(pos+1).toLowerCase();
+            if (last.equals("volume") || last.equals("vol") || last.equals("v"))
+              journal = clean(journal.substring(0, pos));
+          }
+          pos = text.indexOf(journal);
+          usedParts.add(new Substring("journal", pos, pos+journal.length()));
+          Util.pr("Guessing 'journal': '" + journal + "'");
+        }
+        //Util.pr("Journal? '"+cand[0]+"'");
+      } else {
+        // No journal found. Maybe the year precedes the volume? Try another regexp:
+        journalRx = "(,|\\.|\\n)\\s??([a-zA-Z\\. ]{8,30}+)((.){0,2})\\s??(\\d{1,3})(\\.|,|\\s|:)";
+      }
+
+      // Then try to find title and authors.
+      Substring ss;
+      Vector free = new Vector();
+      int piv = 0;
+      for (Iterator i=usedParts.iterator(); i.hasNext();) {
+        ss = (Substring)i.next();
+        if (ss.begin()-piv > 10) {
+          Util.pr("... "+text.substring(piv, ss.begin()));
+          free.add(clean(text.substring(piv, ss.begin())));
+        }
+        piv = ss.end();
+      }
+      if (text.length()-piv > 10) {
+        free.add(clean(text.substring(piv)));
+      }
+      Util.pr("Free parts:");
+      for (Iterator i=free.iterator(); i.hasNext();) {
+        String part = (String)i.next();
+        int dots = part.split("\\.").length - 1;
+
+        Util.pr(": '"+i.next()+"'");
+      }
+    }
+
+
+    public String[] getMatches(String text, String regexp) {
+      int piv = 0;
+      String[] test = text.split(regexp);
+      if (test.length < 2)
+        return new String[0];
+
+      String[] out = new String[test.length-1];
+      for (int i=0; i<out.length; i++) {
+        String[] curr = text.split(regexp, i+2);
+        out[i] = text.substring(piv+curr[i].length(), text.length()-curr[i+1].length());
+        piv += curr[i].length()+out[i].length();
+        //Util.pr("--"+out[i]+"\n-> "+piv);
+      }
+      return out;
+    }
+
+    private String clean(String s) {
+      boolean found = false;
+      int left = 0, right = s.length()-1;
+      while (!found && left<s.length()) {
+        char c = s.charAt(left);
+        if (Character.isWhitespace(c) || (c=='.') || (c==',') || (c=='(')
+            || (c==':') || (c==')'))
+          left++;
+        else
+          found = true;
+      }
+      found = false;
+      while (!found && right>left) {
+        char c = s.charAt(right);
+        if (Character.isWhitespace(c) || (c=='.') || (c==',') || (c==')')
+            || (c==':') || (c=='('))
+          right--;
+        else
+          found = true;
+      }
+      //Util.pr(s+"\n"+left+" "+right);
+      return s.substring(left, Math.min(right+1, s.length()));
+    }
+
+    private class Substring implements Comparable {
+      int begin, end;
+      public Substring(String name, int begin, int end) {
+        this.begin = begin;
+        this.end = end;
+      }
+      public int begin() { return begin; }
+      public int end() { return end; }
+      public int compareTo(Object o) {
+        Substring other = (Substring)o;
+        return (new Integer(begin)).compareTo(new Integer(other.begin()));
+      }
+        }
+}
diff --git a/src/java/net/sf/jabref/imports/ZipFileChooser.java b/src/java/net/sf/jabref/imports/ZipFileChooser.java
new file mode 100644
index 0000000..5a50182
--- /dev/null
+++ b/src/java/net/sf/jabref/imports/ZipFileChooser.java
@@ -0,0 +1,269 @@
+/*
+ Copyright (C) 2005 Andreas Rudert
+
+ 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.imports;
+
+import javax.swing.JDialog;
+import java.awt.*;
+import net.sf.jabref.*;
+
+import javax.swing.*;
+import java.awt.event.ActionListener;
+import java.awt.event.ActionEvent;
+import java.text.SimpleDateFormat;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+
+import javax.swing.table.AbstractTableModel;
+import javax.swing.table.TableColumnModel;
+
+
+/**
+ * Dialog to allow users to choose a file contained in a ZIP file.
+ * 
+ * @author andreas_sf at rudert-home dot de
+ */
+class ZipFileChooser extends JDialog {
+
+  /**
+   * Table model for the ZIP archive contents.
+   * 
+   * <p>Contains one row for each entry.
+   * Does not contain rows for directory entries.</p>
+   * 
+   * <p>The columns contain information about ZIIP file entries:
+   * <ol><li>
+   *   name {@link String}
+   * </li><li>
+   *   time of last modification {@link Date}
+   * </li><li>
+   *   size (uncompressed) {@link Long}
+   * </li></ol></p>
+   */
+  class ZipFileChooserTableModel extends AbstractTableModel {
+    
+    private String[] columnNames = new String[] {
+      Globals.lang("Name"),
+      Globals.lang("Last modified"),
+      Globals.lang("Size")
+    };
+    private ZipEntry[] rows = null;
+    private ZipFile zipFile = null;
+    
+    ZipFileChooserTableModel(ZipFile zipFile, ZipEntry[] rows) {
+      super();
+      this.rows = rows;
+      this.zipFile = zipFile;        
+    }
+    
+    /*
+     *  (non-Javadoc)
+     * @see javax.swing.table.TableModel#getColumnCount()
+     */
+    public int getColumnCount() {
+      return columnNames.length;
+    }
+
+    /*
+     *  (non-Javadoc)
+     * @see javax.swing.table.TableModel#getRowCount()
+     */
+    public int getRowCount() {
+      return this.rows.length;
+    }
+
+    /*
+     *  (non-Javadoc)
+     * @see javax.swing.table.TableModel#getColumnName(int)
+     */
+    public String getColumnName(int col) {
+      return columnNames[col];
+    }
+
+    /**
+     * Zip-File entry at the given row index.
+     * 
+     * @param rowIndex  row index
+     * @return  Zip file entry
+     */
+    public ZipEntry getZipEntry(int rowIndex) {
+      return this.rows[rowIndex];
+    }
+    
+    /**
+     * Zip file which contains all entries of this model.
+     * 
+     * @return zip file
+     */
+    public ZipFile getZipFile() {
+      return this.zipFile;
+    }
+    
+    /*
+     *  (non-Javadoc)
+     * @see javax.swing.table.TableModel#getValueAt(int, int)
+     */
+    public Object getValueAt(int rowIndex, int columnIndex) {
+      Object value = null;
+      ZipEntry entry = getZipEntry(rowIndex);
+      if (columnIndex == 0) {
+        value = entry.getName();
+      } else if (columnIndex == 1) {
+        value = SimpleDateFormat.getDateTimeInstance().format(new Date(entry.getTime()));
+      } else if (columnIndex == 2) {
+        value = new Long(entry.getSize());
+      }
+      return value;
+    }
+  }
+
+  private CustomImportList.Importer selectedImporter = null;
+  private JButton okButton = new JButton(Globals.lang("Ok"));
+  private JButton cancelButton = new JButton(Globals.lang("Cancel"));
+
+  /** table of Zip entries */
+  private JTable table;
+  /** shortcut to preferences */
+  private JabRefPreferences prefs = Globals.prefs;
+  /** this */
+  private ZipFileChooser zipFileChooser;
+  /** import customization dialog, owner of this dialog */
+  private ImportCustomizationDialog importCustomizationDialog;
+  
+  /*
+   *  (non-Javadoc)
+   * @see java.awt.Component#getSize()
+   */
+  public Dimension getSize() {
+    return new Dimension(400, 300);
+  }
+  
+  /**
+   * Entries that can be selected with this dialog.
+   * 
+   * @param zipFile  Zip-File
+   * @return  entries that can be selected
+   */
+  private ZipEntry[] getSelectableZipEntries(ZipFile zipFile) {
+    List entries = new ArrayList();
+    Enumeration e = zipFile.entries();
+    while (e.hasMoreElements()) {
+      ZipEntry entry = (ZipEntry)e.nextElement();
+      if (!entry.isDirectory() && entry.getName().endsWith(".class")) {
+        entries.add(entry); 
+      }
+    }
+    return (ZipEntry[])entries.toArray(new ZipEntry[]{});
+  }
+  
+  /**
+   * New Zip file chooser.
+   * 
+   * @param owner  Owner of the file chooser
+   * @param zipFile  Zip-Fle to choose from, must be readable
+   * @throws HeadlessException
+   */
+  public ZipFileChooser(ImportCustomizationDialog owner, ZipFile zipFile) throws HeadlessException {
+    super(owner, Globals.lang("Select file from ZIP-archive"), false);
+    
+    this.importCustomizationDialog = owner;
+    this.zipFileChooser = this;
+    
+    // cancel: no entry is selected
+    cancelButton.addActionListener(new ActionListener() {
+      public void actionPerformed(ActionEvent e) {
+        dispose();
+      }
+    });
+
+    // ok: get selected class and check if it is instantiable as an importer
+    okButton.addActionListener(new ActionListener() {
+     public void actionPerformed(ActionEvent e) {
+       int row = table.getSelectedRow();
+       if (row != -1) {
+         ZipFileChooserTableModel model = (ZipFileChooserTableModel)table.getModel();
+         ZipEntry tempZipEntry = model.getZipEntry(row);
+         CustomImportList.Importer importer = prefs.customImports.new Importer();
+         importer.setBasePath(model.getZipFile().getName());
+         String className = tempZipEntry.getName().substring(0, tempZipEntry.getName().lastIndexOf('.'));
+         importer.setClassName(className);
+         try {
+           ImportFormat importFormat = importer.getInstance();
+           importer.setName(importFormat.getFormatName());
+           importer.setCliId(importFormat.getCLIId());
+           importCustomizationDialog.addOrReplaceImporter(importer);
+           dispose();
+         } catch (Exception exc) {           
+           exc.printStackTrace();
+           JOptionPane.showMessageDialog(zipFileChooser, Globals.lang("Could not instantiate %0 %1", importer.getName() + ":\n", exc.getMessage()));
+         }
+       } else {
+         JOptionPane.showMessageDialog(zipFileChooser, Globals.lang("Please select an importer."));
+       }
+     }
+    });
+    
+
+    ZipFileChooserTableModel tableModel = new ZipFileChooserTableModel( zipFile, getSelectableZipEntries(zipFile) );
+    table = new JTable(tableModel);
+    TableColumnModel cm = table.getColumnModel();
+    cm.getColumn(0).setPreferredWidth(200);
+    cm.getColumn(1).setPreferredWidth(150);
+    cm.getColumn(2).setPreferredWidth(100);
+    JScrollPane sp = new JScrollPane(table, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
+                                     JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
+    table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+    table.setPreferredScrollableViewportSize(new Dimension(500, 150));
+    if (table.getRowCount() > 0) {
+      table.setRowSelectionInterval(0, 0);
+    }
+
+    // Key bindings:
+    JPanel mainPanel = new JPanel();
+    //ActionMap am = mainPanel.getActionMap();
+    //InputMap im = mainPanel.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
+    //im.put(prefs.getKey("Close dialog"), "close");
+    //am.put("close", closeAction);
+    mainPanel.setLayout(new BorderLayout());
+    mainPanel.add(sp, BorderLayout.CENTER);
+
+    JPanel optionsPanel = new JPanel();
+    optionsPanel.add(okButton);
+    optionsPanel.add(cancelButton);
+    optionsPanel.add(Box.createHorizontalStrut(5));
+
+    getContentPane().add(mainPanel, BorderLayout.CENTER);
+    getContentPane().add(optionsPanel, BorderLayout.SOUTH);
+    this.setSize(getSize());
+    pack();
+    Util.placeDialog(this, owner);
+    new FocusRequester(table);
+  }
+}
diff --git a/src/java/net/sf/jabref/journals/AbbreviateAction.java b/src/java/net/sf/jabref/journals/AbbreviateAction.java
new file mode 100644
index 0000000..b7b5c0b
--- /dev/null
+++ b/src/java/net/sf/jabref/journals/AbbreviateAction.java
@@ -0,0 +1,58 @@
+package net.sf.jabref.journals;
+
+import net.sf.jabref.BibtexEntry;
+import net.sf.jabref.Globals;
+import net.sf.jabref.BasePanel;
+import net.sf.jabref.AbstractWorker;
+import net.sf.jabref.undo.NamedCompound;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: alver
+ * Date: Sep 17, 2005
+ * Time: 12:48:23 AM
+ * To browseOld this template use File | Settings | File Templates.
+ */
+public class AbbreviateAction extends AbstractWorker {
+    BasePanel panel;
+    String message = "";
+    boolean iso;
+
+    public AbbreviateAction(BasePanel panel, boolean iso) {
+        this.panel = panel;
+        this.iso = iso;
+    }
+
+
+    public void init() {
+        //  new FieldWeightDialog(frame).setVisible(true);
+        panel.output("Abbreviating...");
+    }
+
+    public void run() {
+        //net.sf.jabref.journals.JournalList.downloadJournalList(frame);
+
+
+        BibtexEntry[] entries = panel.getSelectedEntries();
+        if (entries == null)
+            return;
+        NamedCompound ce = new NamedCompound("Abbreviate journal names");
+        int count = 0;
+        for (int i = 0; i < entries.length; i++) {
+            if (Globals.journalAbbrev.abbreviate(entries[i], "journal", ce, iso))
+                count++;
+        }
+        if (count > 0) {
+            ce.end();
+            panel.undoManager.addEdit(ce);
+            panel.markBaseChanged();
+            message = Globals.lang("Abbreviated %0 journal names.", String.valueOf(count));
+        } else {
+            message = Globals.lang("No journal names could be abbreviated.");
+        }
+    }
+
+    public void update() {
+        panel.output(message);
+    }
+}
diff --git a/src/java/net/sf/jabref/journals/JournalAbbreviations.java b/src/java/net/sf/jabref/journals/JournalAbbreviations.java
new file mode 100644
index 0000000..0dd0a1f
--- /dev/null
+++ b/src/java/net/sf/jabref/journals/JournalAbbreviations.java
@@ -0,0 +1,314 @@
+package net.sf.jabref.journals;
+
+import net.sf.jabref.util.CaseChanger;
+import net.sf.jabref.FieldEditor;
+import net.sf.jabref.Globals;
+import net.sf.jabref.EntryEditor;
+import net.sf.jabref.BibtexEntry;
+import net.sf.jabref.undo.UndoableFieldChange;
+
+import javax.swing.*;
+import javax.swing.table.DefaultTableModel;
+import javax.swing.table.TableModel;
+import javax.swing.undo.UndoManager;
+import javax.swing.undo.CompoundEdit;
+import java.io.*;
+import java.util.*;
+import java.awt.event.ActionListener;
+import java.awt.event.ActionEvent;
+import java.net.URL;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: alver
+ * Date: Sep 16, 2005
+ * Time: 10:49:08 PM
+ * To browseOld this template use File | Settings | File Templates.
+ */
+public class JournalAbbreviations {
+
+    static String TOOLTIPTEXT = "<HTML>"+Globals.lang("Switches between full and abbreviated journal name "
+        +"if the journal name is known.")
+        +"<BR>"+Globals.lang("To set up, go to <B>Tools -> Manage journal abbreviations</B>")+".</HTML>";
+    TreeMap fullNameKeyed = new TreeMap();
+    HashMap abbrNameKeyed = new HashMap();
+    HashMap abbrNoDotsToAbbr = new HashMap();
+    TreeMap all = new TreeMap();
+    CaseChanger caseChanger = new CaseChanger();
+
+    public JournalAbbreviations() {
+        
+    }
+
+    public JournalAbbreviations(String resource) {
+        readJournalList(resource);
+    }
+
+    public JournalAbbreviations(File file) throws FileNotFoundException {
+        readJournalList(file);
+    }
+
+    /**
+     * Get an iterator for the known journals in alphabetical order.
+     * @return Iterator for journal full names
+     */
+    public Iterator fullNameIterator() {
+        return fullNameKeyed.keySet().iterator();
+    }
+
+    public boolean isKnownName(String journalName) {
+        String s = journalName.toLowerCase();
+        return ((fullNameKeyed.get(s) != null) || (abbrNameKeyed.get(s) != null) || (abbrNoDotsToAbbr.get(s) != null));
+    }
+
+    public boolean isAbbreviatedName(String journalName) {
+        String s = journalName.toLowerCase();
+        return ((abbrNameKeyed.get(s) != null) || (abbrNoDotsToAbbr.get(s) != null));
+    }
+
+    public String dotsToNodots(String name) {
+        return name.replaceAll("\\.", " ").replaceAll("  ", " ").trim();
+    }
+
+    /**
+     * Attempts to get the abbreviated name of the journal given. Returns null if no
+     * abbreviated name is known.
+     * @param journalName The journal name to abbreviate.
+     * @param withDots True if the abbreviation should have dots.
+     * if only the first character should be.
+     * @return The abbreviated name, or null if it couldn't be found.
+     */
+    public String getAbbreviatedName(String journalName, boolean withDots) {
+        String s = journalName.toLowerCase();
+        String abbr;
+        if (fullNameKeyed.containsKey(s)) {
+            abbr = (String)fullNameKeyed.get(s);
+        }
+        else if (abbrNameKeyed.containsKey(s)) {
+            abbr = journalName;
+        }
+        else if (abbrNoDotsToAbbr.containsKey(s)) {
+            abbr = (String)abbrNoDotsToAbbr.get(s);
+        } else
+            return null;
+
+        if (!withDots) {
+            abbr = dotsToNodots(abbr);
+        }
+
+        return abbr;
+    }
+
+    /**
+     * Attempts to get the full name of the abbreviation given. Returns null if no
+     * full name is known.
+     * @param journalName The abbreviation to resolve.
+     * @return The full name, or null if it couldn't be found.
+     */
+    public String getFullName(String journalName) {
+        // Normalize name first:
+        String s = getAbbreviatedName(journalName, true);
+	if (s != null) 
+	    s = s.toLowerCase();
+	else
+	    return null;
+        Object o = abbrNameKeyed.get(s);
+        if (o == null) {
+            if (fullNameKeyed.containsKey(s))
+                o = s;
+            else
+                return null;
+        }
+        s = (String)o;
+        return s;//caseChanger.changeCase(s, CaseChanger.UPPER_EACH_FIRST);
+    }
+
+    public void readJournalList(String resourceFileName) {
+        URL url = JournalAbbreviations.class.getResource(resourceFileName);
+        try {
+            readJournalList(new InputStreamReader(url.openStream()));
+        } catch (FileNotFoundException e) {
+            e.printStackTrace();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+
+    public void readJournalList(File file) throws FileNotFoundException {
+        readJournalList(new FileReader(file));
+    }
+
+    /**
+     * Read the given file, which should contain a list of journal names and their
+     * abbreviations. Each line should be formatted as: "Full Journal Name=Abbr. Journal Name"
+     * @param in
+     */
+    public void readJournalList(Reader in) throws FileNotFoundException {
+        BufferedReader reader = new BufferedReader(in);
+        try {
+            String line;
+            while ((line = reader.readLine()) != null) {
+                //System.out.println(line);
+                if (line.startsWith("#"))
+                    continue;
+                String[] parts = line.split("=");
+                if (parts.length == 2) {
+                    String fullName = parts[0].trim();
+                    String fullNameLC = fullName.toLowerCase();
+                    String abbrName = parts[1].trim();
+                    if (abbrName.indexOf(';') >= 0) {
+                        String[] restParts = abbrName.split(";");
+                        abbrName = restParts[0];
+                    }
+                    String abbrNameLC = abbrName.toLowerCase();
+                    String abbrNoDots = dotsToNodots(abbrName);
+                    String abbrNoDotsLC = abbrNoDots.toLowerCase();
+                    //System.out.println(abbrNoDots);
+                    if ((fullName.length()>0) && (abbrName.length()>0)) {
+                        //System.out.println("'"+fullName+"' : '"+abbrNoDots+"'");
+                        fullNameKeyed.put(fullNameLC, abbrName);
+                        abbrNameKeyed.put(abbrNameLC, fullName);
+                        abbrNoDotsToAbbr.put(abbrNoDotsLC, abbrName);
+                        all.put(fullName, abbrName);
+                    }
+                }
+            }
+
+        } catch (IOException ex) {
+            ex.printStackTrace();
+        } finally {
+            try {
+                reader.close();
+            } catch (IOException ex2) {
+                ex2.printStackTrace();
+            }
+        }
+    }
+
+    /**
+     * Abbreviate the journal name of the given entry.
+     * @param entry The entry to be treated.
+     * @param fieldName The field name (e.g. "journal")
+     * @param ce If the entry is changed, add an edit to this compound.
+     * @param withDots True if the abbreviations should have dots.
+     * @return true if the entry was changed, false otherwise.
+     */
+    public boolean abbreviate(BibtexEntry entry, String fieldName, CompoundEdit ce, boolean withDots) {
+        Object o = entry.getField(fieldName);
+        if (o == null)
+            return false;
+        String text = (String)o;
+        if (isKnownName(text) && !isAbbreviatedName(text)) {
+            String newText = getAbbreviatedName(text, withDots);
+            if (newText == null)
+                return false;
+            entry.setField(fieldName, newText);
+            ce.addEdit(new UndoableFieldChange(entry, fieldName, text, newText));
+            return true;
+        } else {
+            String unabbr = getFullName(text);
+            if (unabbr != null) {
+                String newText = getAbbreviatedName(unabbr, withDots);
+                if (newText == null)
+                    return false;
+                entry.setField(fieldName, newText);
+                ce.addEdit(new UndoableFieldChange(entry, fieldName, text, newText));
+                return true;
+            } else
+                return false;
+        }
+    }
+
+    /**
+     * Unabbreviate the journal name of the given entry.
+     * @param entry The entry to be treated.
+     * @param fieldName The field name (e.g. "journal")
+     * @param ce If the entry is changed, add an edit to this compound.
+     * @return true if the entry was changed, false otherwise.
+     */
+    public boolean unabbreviate(BibtexEntry entry, String fieldName, CompoundEdit ce) {
+        Object o = entry.getField(fieldName);
+        if (o == null)
+            return false;
+        String text = (String)o;
+        if (isKnownName(text) && isAbbreviatedName(text)) {
+            String newText = getFullName(text);
+            if (newText == null)
+                return false;
+            entry.setField(fieldName, newText);
+            ce.addEdit(new UndoableFieldChange(entry, fieldName, text, newText));
+            return true;
+        } else
+            return false;
+    }
+
+
+    public Map getJournals() {
+        return Collections.unmodifiableMap(all);
+    }
+
+    /**
+     * Create a control panel for the entry editor's journal field, to toggle
+     * abbreviated/full journal name
+     * @param editor The FieldEditor for the journal field.
+     * @return The control panel for the entry editor.
+     */
+    public static JComponent getNameSwitcher(final EntryEditor entryEditor, final FieldEditor editor,
+                                      final UndoManager undoManager) {
+        JButton button = new JButton(Globals.lang("Toggle abbreviation"));
+        button.setToolTipText(TOOLTIPTEXT);
+        button.addActionListener(new ActionListener() {
+            boolean withDots = true;
+            public void actionPerformed(ActionEvent actionEvent) {
+                String text = editor.getText();
+                if (Globals.journalAbbrev.isKnownName(text)) {
+                    String s;
+                    if (Globals.journalAbbrev.isAbbreviatedName(text)) {
+                        //System.out.println(withDots);
+                        if (!withDots) {
+                            s = Globals.journalAbbrev.getAbbreviatedName(text, false);
+                            withDots = true;
+                        } else {
+                            s = Globals.journalAbbrev.getFullName(text);
+                        }
+                    }
+                    else {
+                        s = Globals.journalAbbrev.getAbbreviatedName(text, true);
+                        withDots = false;
+                    }
+
+                    if (s != null) {
+                        editor.setText(s);
+                        entryEditor.storeFieldAction.actionPerformed(new ActionEvent(editor, 0, ""));
+                        undoManager.addEdit(new UndoableFieldChange(entryEditor.getEntry(), editor.getFieldName(),
+                                text, s));
+                    }
+                }
+            }
+        });
+
+        return button;
+    }
+
+    public TableModel getTableModel() {
+        Object[][] cells = new Object[fullNameKeyed.size()][2];
+        int row = 0;
+        for (Iterator i=fullNameIterator(); i.hasNext();) {
+            String name = (String)i.next();
+            cells[row][0] = getFullName(name);
+            cells[row][1] = getAbbreviatedName(name, true);
+            row++;
+        }
+        DefaultTableModel tableModel = new DefaultTableModel(cells, new Object[] {Globals.lang("Full name"),
+            Globals.lang("Abbreviation")}) {
+
+            public boolean isCellEditable(int row, int column) {
+                return false;
+            }
+        };
+
+        return tableModel;
+    }
+
+}
+
diff --git a/src/java/net/sf/jabref/journals/ManageJournalsAction.java b/src/java/net/sf/jabref/journals/ManageJournalsAction.java
new file mode 100644
index 0000000..24ac97e
--- /dev/null
+++ b/src/java/net/sf/jabref/journals/ManageJournalsAction.java
@@ -0,0 +1,31 @@
+package net.sf.jabref.journals;
+
+import net.sf.jabref.JabRefFrame;
+import net.sf.jabref.Globals;
+import net.sf.jabref.Util;
+
+import javax.swing.*;
+import java.awt.event.ActionEvent;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: alver
+ * Date: Sep 22, 2005
+ * Time: 10:45:02 PM
+ * To browseOld this template use File | Settings | File Templates.
+ */
+public class ManageJournalsAction extends AbstractAction {
+
+    JabRefFrame frame;
+
+    public ManageJournalsAction(JabRefFrame frame) {
+        super(Globals.lang("Manage journal abbreviations"));
+        this.frame = frame;
+    }
+    public void actionPerformed(ActionEvent actionEvent) {
+        ManageJournalsPanel panel = new ManageJournalsPanel(frame);
+        Util.placeDialog(panel.getDialog(), frame);
+        panel.setValues();
+        panel.getDialog().setVisible(true);
+    }
+}
diff --git a/src/java/net/sf/jabref/journals/ManageJournalsPanel.java b/src/java/net/sf/jabref/journals/ManageJournalsPanel.java
new file mode 100644
index 0000000..9d3478d
--- /dev/null
+++ b/src/java/net/sf/jabref/journals/ManageJournalsPanel.java
@@ -0,0 +1,602 @@
+package net.sf.jabref.journals;
+
+import net.sf.jabref.*;
+import net.sf.jabref.net.URLDownload;
+
+import javax.swing.*;
+import javax.swing.table.AbstractTableModel;
+
+import com.jgoodies.forms.layout.FormLayout;
+import com.jgoodies.forms.layout.CellConstraints;
+import com.jgoodies.forms.builder.DefaultFormBuilder;
+import com.jgoodies.forms.builder.ButtonBarBuilder;
+import com.jgoodies.forms.builder.ButtonStackBuilder;
+
+import java.awt.event.*;
+import java.awt.*;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.Map;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.Collections;
+import java.net.URL;
+import java.net.MalformedURLException;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: alver
+ * Date: Sep 19, 2005
+ * Time: 7:57:29 PM
+ * To browseOld this template use File | Settings | File Templates.
+ */
+public class ManageJournalsPanel extends JPanel{
+
+    JabRefFrame frame;
+    JTextField personalFile = new JTextField();
+    AbbreviationsTableModel tableModel = new AbbreviationsTableModel();
+    JTable userTable; // builtInTable
+    JPanel userPanel = new JPanel(),
+        journalEditPanel,
+        externalFilesPanel = new JPanel(),
+        addExtPan = new JPanel();
+    JTextField nameTf = new JTextField(),
+        newNameTf = new JTextField(),
+        abbrTf = new JTextField();
+    java.util.List externals = new ArrayList(); // To hold references to external journal lists.
+    JDialog dialog;
+    JRadioButton newFile = new JRadioButton(Globals.lang("New file")),
+        oldFile = new JRadioButton(Globals.lang("Existing file"));
+
+    JButton add = new JButton(new ImageIcon(GUIGlobals.addIconFile)),
+        remove = new JButton(new ImageIcon(GUIGlobals.removeIconFile)),
+        ok = new JButton(Globals.lang("Ok")),
+        cancel = new JButton(Globals.lang("Cancel")),
+        help = new JButton(Globals.lang("Help")),
+        browseOld = new JButton(Globals.lang("Browse")),
+        browseNew = new JButton(Globals.lang("Browse")),
+        addExt = new JButton(new ImageIcon(GUIGlobals.addIconFile));
+
+
+    public ManageJournalsPanel(final JabRefFrame frame) {
+        this.frame = frame;
+
+        personalFile.setEditable(false);
+
+        ButtonGroup group = new ButtonGroup();
+        group.add(newFile);
+        group.add(oldFile);
+        addExtPan.setLayout(new BorderLayout());
+        addExtPan.add(addExt, BorderLayout.EAST);
+        addExtPan.setToolTipText(Globals.lang("Add"));
+        //addExtPan.setBorder(BorderFactory.createMatteBorder(1,1,1,1,Color.red));
+        FormLayout layout = new FormLayout
+                ("1dlu, 8dlu, left:pref, 4dlu, fill:200dlu:grow, 4dlu, fill:pref", // 4dlu, left:pref, 4dlu",
+                        "pref, 20dlu, 20dlu, fill:200dlu, 4dlu, pref");//150dlu");
+        DefaultFormBuilder builder = new DefaultFormBuilder(layout);
+
+        CellConstraints cc = new CellConstraints();
+
+        JPanel pan = new JPanel();
+
+        /*JLabel description = new JLabel("<HTML>"+Globals.lang("JabRef can switch journal names between "
+            +"abbreviated and full form. Since it knows only a limited number of journal names, "
+            +"you may need to add your own definitions.")+"</HTML>");*/
+        builder.addSeparator(Globals.lang("Personal journal list"), cc.xyw(2,1,6));
+
+        //builder.add(description, cc.xyw(2,1,6));
+        builder.add(newFile, cc.xy(3,2));
+        builder.add(newNameTf, cc.xy(5,2));
+        builder.add(browseNew, cc.xy(7,2));
+        builder.add(oldFile, cc.xy(3,3));
+        builder.add(personalFile, cc.xy(5,3));
+        //BrowseAction action = new BrowseAction(personalFile, false);
+        //JButton browse = new JButton(Globals.lang("Browse"));
+        //browse.addActionListener(action);
+        builder.add(browseOld, cc.xy(7,3));
+
+        userPanel.setLayout(new BorderLayout());
+        //builtInTable = new JTable(Globals.journalAbbrev.getTableModel());
+        builder.add(userPanel, cc.xyw(2,4,4));
+        ButtonStackBuilder butBul = new ButtonStackBuilder();
+        butBul.addGridded(add);
+        butBul.addGridded(remove);
+
+        butBul.addGlue();
+        builder.add(butBul.getPanel(), cc.xy(7,4));
+
+        builder.addSeparator(Globals.lang("External files"), cc.xyw(2,6,6));
+        externalFilesPanel.setLayout(new BorderLayout());
+        //builder.add(/*new JScrollPane(*/externalFilesPanel/*)*/, cc.xyw(2,8,6));
+
+        setLayout(new BorderLayout());
+        builder.getPanel().setBorder(BorderFactory.createEmptyBorder(5,5,5,5));//createMatteBorder(1,1,1,1,Color.green));
+        add(builder.getPanel(), BorderLayout.NORTH);
+        add(externalFilesPanel, BorderLayout.CENTER);
+        ButtonBarBuilder bb = new ButtonBarBuilder();
+        bb.addGlue();
+        bb.addGridded(ok);
+        bb.addGridded(cancel);
+        bb.addGridded((JComponent)Box.createHorizontalStrut(10));
+        bb.addGridded(help);
+        bb.addGlue();
+        bb.getPanel().setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+        dialog = new JDialog(frame, Globals.lang("Journal abbreviations"), false);
+        dialog.getContentPane().add(this, BorderLayout.CENTER);
+        dialog.getContentPane().add(bb.getPanel(), BorderLayout.SOUTH);
+
+        //add(new JScrollPane(builtInTable), BorderLayout.CENTER);
+
+        // Set up panel for editing a single journal, to be used in a dialog box:
+        FormLayout layout2 = new FormLayout
+                ("right:pref, 4dlu, fill:180dlu", "");
+        DefaultFormBuilder builder2 = new DefaultFormBuilder(layout2);
+        builder2.append(Globals.lang("Journal name"));
+        builder2.append(nameTf);
+        builder2.nextLine();
+        builder2.append(Globals.lang("ISO abbreviation"));
+        builder2.append(abbrTf);
+        journalEditPanel = builder2.getPanel();
+
+        browseNew.addActionListener(new ActionListener() {
+            public void actionPerformed(ActionEvent e) {
+                File old = null;
+                if (!newNameTf.getText().equals(""))
+                    old = new File(newNameTf.getText());
+                String name = Globals.getNewFile(frame, Globals.prefs, old, null, JFileChooser.SAVE_DIALOG, false);
+                if (name != null) {
+                    if ((old != null) && (tableModel.getRowCount() > 0)) {
+                    }
+                    newNameTf.setText(name);
+                    newFile.setSelected(true);
+                }
+            }
+        });
+        browseOld.addActionListener(new ActionListener() {
+            public void actionPerformed(ActionEvent e) {
+                File old = null;
+                if (!personalFile.getText().equals(""))
+                    old = new File(personalFile.getText());
+                String name = Globals.getNewFile(frame, Globals.prefs, old, null, JFileChooser.OPEN_DIALOG, false);
+                if (name != null) {
+                    if ((old != null) && (tableModel.getRowCount() > 0)) {
+                    }
+                    personalFile.setText(name);
+                    oldFile.setSelected(true);
+                    oldFile.setEnabled(true);
+                    setupUserTable();
+                }
+            }
+        });
+
+
+        ok.addActionListener(new ActionListener() {
+            public void actionPerformed(ActionEvent e) {
+                if (readyToClose()) {
+                    storeSettings();
+                    dialog.dispose();
+                }
+            }
+        });
+        help.addActionListener(new HelpAction(Globals.helpDiag, GUIGlobals.journalAbbrHelp));
+        cancel.addActionListener(new ActionListener() {
+                    public void actionPerformed(ActionEvent e) {
+                        dialog.dispose();
+                    }
+                });
+
+        add.addActionListener(tableModel);
+        remove.addActionListener(tableModel);
+        addExt.addActionListener(new ActionListener() {
+            public void actionPerformed(ActionEvent e) {
+                externals.add(new ExternalFileEntry());
+                buildExternalsPanel();
+            }
+        });
+
+        //dialog.pack();
+        dialog.setSize(600,700);
+    }
+
+    public JDialog getDialog() {
+        return dialog;
+    }
+
+    public void setValues() {
+        personalFile.setText(Globals.prefs.get("personalJournalList"));
+        if (personalFile.getText().length() == 0) {
+            newFile.setSelected(true);
+            oldFile.setEnabled(false);
+        } else {
+            oldFile.setSelected(true);
+            oldFile.setEnabled(true);
+        }
+        setupUserTable();
+        setupExternals();
+        buildExternalsPanel();
+
+    }
+
+    private void buildExternalsPanel() {
+
+        DefaultFormBuilder builder = new DefaultFormBuilder(new FormLayout("fill:pref:grow",""));
+        for (Iterator i=externals.iterator(); i.hasNext();) {
+            ExternalFileEntry efe = (ExternalFileEntry)i.next();
+            builder.append(efe.getPanel());
+            builder.nextLine();
+        }
+        builder.append(Box.createVerticalGlue());
+        builder.nextLine();
+        builder.append(addExtPan);
+        builder.nextLine();
+        builder.append(Box.createVerticalGlue());
+
+        //builder.getPanel().setBorder(BorderFactory.createMatteBorder(1,1,1,1,Color.green));
+        //externalFilesPanel.setBorder(BorderFactory.createMatteBorder(1,1,1,1,Color.red));
+        JScrollPane pane = new JScrollPane(builder.getPanel());
+        pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+        externalFilesPanel.setMinimumSize(new Dimension(400,400));
+        externalFilesPanel.removeAll();
+        externalFilesPanel.add(pane, BorderLayout.CENTER);
+        externalFilesPanel.revalidate();
+        externalFilesPanel.repaint();
+
+    }
+
+    private void setupExternals() {
+        String[] externalFiles = Globals.prefs.getStringArray("externalJournalLists");
+        if ((externalFiles == null) || (externalFiles.length == 0)) {
+            ExternalFileEntry efe = new ExternalFileEntry();
+            externals.add(efe);
+        } else {
+            for (int i=0; i<externalFiles.length; i++) {
+                ExternalFileEntry efe = new ExternalFileEntry(externalFiles[i]);
+                externals.add(efe);
+
+            }
+
+        }
+
+        //efe = new ExternalFileEntry();
+        //externals.add(efe);
+
+    }
+
+    public void setupUserTable() {
+        JournalAbbreviations userAbbr = new JournalAbbreviations();
+        String filename = personalFile.getText();
+        if (!filename.equals("") && (new File(filename)).exists()) {
+            try {
+                userAbbr.readJournalList(new File(filename));
+            } catch (FileNotFoundException e) {
+                e.printStackTrace();
+            }
+        }
+
+        tableModel.setJournals(userAbbr.getJournals());
+        userTable = new JTable(tableModel);
+        userTable.addMouseListener(tableModel.getMouseListener());
+        userPanel.add(new JScrollPane(userTable), BorderLayout.CENTER);
+    }
+
+    public boolean readyToClose() {
+        File f;
+        if (newFile.isSelected()) {
+            if (newNameTf.getText().length() > 0) {
+                f = new File(newNameTf.getText());
+                return (!f.exists() ||
+                    (JOptionPane.showConfirmDialog
+                     (this, "'"+f.getName()+"' "+Globals.lang("exists. Overwrite file?"),
+                      Globals.lang("Store journal abbreviations"), JOptionPane.OK_CANCEL_OPTION)
+                     == JOptionPane.OK_OPTION));
+            } else {
+                if (tableModel.getRowCount() > 0) {
+                    JOptionPane.showMessageDialog(this, Globals.lang("You must choose a file name to store journal abbreviations"),
+                            Globals.lang("Store journal abbreviations"), JOptionPane.ERROR_MESSAGE);
+                        return false;
+                }
+                else return true;
+
+            }
+        }
+        return true;
+    }
+
+    public void storeSettings() {
+        File f = null;
+        if (newFile.isSelected()) {
+            if (newNameTf.getText().length() > 0) {
+                f = new File(newNameTf.getText());
+            }// else {
+            //    return; // Nothing to do.
+            //}
+        } else
+            f = new File(personalFile.getText());
+
+        if (f != null) {
+            FileWriter fw = null;
+            try {
+                fw = new FileWriter(f, false);
+                for (Iterator i=tableModel.getJournals().iterator(); i.hasNext();) {
+                    JournalEntry entry = (JournalEntry)i.next();
+                    fw.write(entry.name);
+                    fw.write(" = ");
+                    fw.write(entry.abbreviation);
+                    fw.write(Globals.NEWLINE);
+                }
+
+            } catch (IOException e) {
+                e.printStackTrace();
+
+            } finally {
+                if (fw != null)
+                    try {
+                        fw.close();
+                    } catch (IOException e) {
+                        e.printStackTrace();
+                    }
+            }
+
+            String filename = f.getPath();
+            if (filename.equals(""))
+                filename = null;
+            Globals.prefs.put("personalJournalList", filename);
+        }
+
+        // Store the list of external files set up:
+        ArrayList extFiles = new ArrayList();
+        for (Iterator i=externals.iterator(); i.hasNext();) {
+            ExternalFileEntry efe = (ExternalFileEntry)i.next();
+            if (!efe.getValue().equals("")) {
+                extFiles.add(efe.getValue());
+            }
+        }
+        if (extFiles.size() == 0)
+            Globals.prefs.put("externalJournalLists", "");
+        else {
+            String[] list = (String[])extFiles.toArray(new String[extFiles.size()]);
+            Globals.prefs.putStringArray("externalJournalLists", list);
+        }
+
+
+        Globals.initializeJournalNames();
+
+    }
+
+    class DownloadAction extends AbstractAction {
+        JTextField comp;
+
+        public DownloadAction(JTextField tc) {
+            super(Globals.lang("Download"));
+            comp = tc;
+        }
+
+        public void actionPerformed(ActionEvent e) {
+            String chosen = null;
+            chosen = JOptionPane.showInputDialog(Globals.lang("Choose the URL to download. The default value points to a list provided by the JabRef developers."),
+                    "http://jabref.sf.net/journals/journal_abbreviations_general.txt");
+            if (chosen == null)
+                return;
+            File toFile;
+            try {
+                URL url = new URL(chosen);
+                String toName = Globals.getNewFile(frame, Globals.prefs, new File(System.getProperty("user.home")),
+                        null, JFileChooser.SAVE_DIALOG, false);
+                if (toName == null)
+                    return;
+                else toFile = new File(toName);
+                URLDownload ud = new URLDownload(comp, url, toFile);
+                ud.download();
+                comp.setText(toFile.getPath());
+            } catch (MalformedURLException ex) {
+                ex.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
+            } catch (IOException ex2) {
+                ex2.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
+            }
+        }
+    }
+
+    class BrowseAction extends AbstractAction {
+        JTextField comp;
+        boolean dir;
+
+        public BrowseAction(JTextField tc, boolean dir) {
+            super(Globals.lang("Browse"));
+            this.dir = dir;
+            comp = tc;
+        }
+
+        public void actionPerformed(ActionEvent e) {
+            String chosen = null;
+            if (dir)
+                chosen = Globals.getNewDir(frame, Globals.prefs, new File(comp.getText()), Globals.NONE,
+                        JFileChooser.OPEN_DIALOG, false);
+            else
+                chosen = Globals.getNewFile(frame, Globals.prefs, new File(comp.getText()), Globals.NONE,
+                        JFileChooser.OPEN_DIALOG, false);
+            if (chosen != null) {
+                File newFile = new File(chosen);
+                comp.setText(newFile.getPath());
+            }
+        }
+    }
+
+    class AbbreviationsTableModel extends AbstractTableModel implements ActionListener {
+
+        String[] names = new String[] {Globals.lang("Journal name"), Globals.lang("Abbreviation")};
+        ArrayList journals = null;
+
+        public AbbreviationsTableModel() {
+
+
+        }
+
+        public void setJournals(Map journals) {
+            this.journals = new ArrayList();
+            for (Iterator i=journals.keySet().iterator(); i.hasNext();) {
+                String journal = (String)i.next(),
+                        abbr = (String)journals.get(journal);
+                this.journals.add(new JournalEntry(journal, abbr));
+            }
+            fireTableDataChanged();
+        }
+
+        public ArrayList getJournals() {
+            return journals;
+        }
+
+        public int getColumnCount() {
+            return 2;
+        }
+
+        public int getRowCount() {
+            return journals.size();
+        }
+
+        public Object getValueAt(int row, int col) {
+            if (col == 0)
+                return ((JournalEntry)journals.get(row)).name;
+            else
+                return ((JournalEntry)journals.get(row)).abbreviation;
+        }
+
+        public void setValueAt(Object object, int row, int col) {
+            JournalEntry entry = (JournalEntry)journals.get(row);
+            if (col == 0)
+                entry.name = (String)object;
+            else
+                entry.abbreviation = (String)object;
+
+        }
+
+        public String getColumnName(int i) {
+            return names[i];
+        }
+
+        public boolean isCellEditable(int i, int i1) {
+            return false;
+        }
+
+        public MouseListener getMouseListener() {
+            return new MouseAdapter() {
+                public void mouseClicked(MouseEvent e) {
+                    if (e.getClickCount() == 2) {
+                        JTable table = (JTable)e.getSource();
+                        int row = table.rowAtPoint(e.getPoint());
+                        nameTf.setText((String)getValueAt(row,0));
+                        abbrTf.setText((String)getValueAt(row,1));
+                        if (JOptionPane.showConfirmDialog(dialog, journalEditPanel, Globals.lang("Edit journal"),
+                            JOptionPane.OK_CANCEL_OPTION) == JOptionPane.OK_OPTION) {
+                            setValueAt(nameTf.getText(), row, 0);
+                            setValueAt(abbrTf.getText(), row, 1);
+                            Collections.sort(journals);
+                            fireTableDataChanged();
+                        }
+
+                    }
+                }
+            };
+        }
+
+        public void actionPerformed(ActionEvent e) {
+            if (e.getSource() == add) {
+                //int sel = userTable.getSelectedRow();
+                //if (sel < 0)
+                //    sel = 0;
+
+                nameTf.setText("");
+                abbrTf.setText("");
+                if (JOptionPane.showConfirmDialog(dialog, journalEditPanel, Globals.lang("Edit journal"),
+                        JOptionPane.OK_CANCEL_OPTION) == JOptionPane.OK_OPTION) {
+                    journals.add(new JournalEntry(nameTf.getText(), abbrTf.getText()));
+                    //setValueAt(nameTf.getText(), sel, 0);
+                    //setValueAt(abbrTf.getText(), sel, 1);
+                    Collections.sort(journals);
+                    fireTableDataChanged();
+                }
+            }
+            else if (e.getSource() == remove) {
+                int[] rows = userTable.getSelectedRows();
+                if (rows.length > 0) {
+                    for (int i=rows.length-1; i>=0; i--) {
+                        journals.remove(rows[i]);
+                    }
+                    fireTableDataChanged();
+                }
+            }
+        }
+    }
+
+    class ExternalFileEntry {
+        private JPanel pan;
+        private JTextField tf;
+        private JButton browse = new JButton(Globals.lang("Browse")),
+            view = new JButton(Globals.lang("Preview")),
+            clear = new JButton(new ImageIcon(GUIGlobals.removeIconFile)),
+            download = new JButton(Globals.lang("Download"));
+        public ExternalFileEntry() {
+            tf = new JTextField();
+            setupPanel();
+        }
+        public ExternalFileEntry(String filename) {
+            tf = new JTextField(filename);
+            setupPanel();
+        }
+        private void setupPanel() {
+            tf.setEditable(false);
+            BrowseAction browseA = new BrowseAction(tf, false);
+            browse.addActionListener(browseA);
+            DownloadAction da = new DownloadAction(tf);
+            download.addActionListener(da);
+            DefaultFormBuilder builder = new DefaultFormBuilder
+                    (new FormLayout("fill:pref:grow, 4dlu, fill:pref, 4dlu, fill:pref, 4dlu, fill:pref, 4dlu, fill:pref", ""));
+            builder.append(tf);
+            builder.append(browse);
+            builder.append(download);
+            builder.append(view);
+            builder.append(clear);
+
+            pan = builder.getPanel();
+
+            view.addActionListener(new ActionListener() {
+                public void actionPerformed(ActionEvent e) {
+                    try {
+                        JournalAbbreviations abbr = new JournalAbbreviations(new File(tf.getText()));
+                        JTable table = new JTable(abbr.getTableModel());
+                        JScrollPane pane = new JScrollPane(table);
+                        JOptionPane.showMessageDialog(null, pane, Globals.lang("Journal list preview"), JOptionPane.INFORMATION_MESSAGE);
+                    } catch (FileNotFoundException ex) {
+                        JOptionPane.showMessageDialog(null, Globals.lang("File '%0' not found", tf.getText()),
+                                Globals.lang("Error"), JOptionPane.ERROR_MESSAGE);
+                    }
+                }
+            });
+            clear.addActionListener(new ActionListener() {
+                public void actionPerformed(ActionEvent e) {
+                    externals.remove(ExternalFileEntry.this);
+                    buildExternalsPanel();
+                }
+            });
+            clear.setToolTipText(Globals.lang("Remove"));
+
+        }
+        public JPanel getPanel() { return pan; }
+        public String getValue() { return tf.getText(); }
+    }
+
+    class JournalEntry implements Comparable {
+        String name, abbreviation;
+        public JournalEntry(String name, String abbreviation) {
+            this.name = name;
+            this.abbreviation = abbreviation;
+        }
+        public int compareTo(Object other) {
+            JournalEntry entry = (JournalEntry)other;
+            return this.name.compareTo(entry.name);
+        }
+    }
+}
+
+
diff --git a/src/java/net/sf/jabref/journals/UnabbreviateAction.java b/src/java/net/sf/jabref/journals/UnabbreviateAction.java
new file mode 100644
index 0000000..ece21d5
--- /dev/null
+++ b/src/java/net/sf/jabref/journals/UnabbreviateAction.java
@@ -0,0 +1,56 @@
+package net.sf.jabref.journals;
+
+import net.sf.jabref.BibtexEntry;
+import net.sf.jabref.Globals;
+import net.sf.jabref.BasePanel;
+import net.sf.jabref.AbstractWorker;
+import net.sf.jabref.undo.NamedCompound;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: alver
+ * Date: Sep 17, 2005
+ * Time: 12:48:23 AM
+ * To browseOld this template use File | Settings | File Templates.
+ */
+public class UnabbreviateAction extends AbstractWorker {
+    BasePanel panel;
+    String message = "";
+
+    public UnabbreviateAction(BasePanel panel) {
+        this.panel = panel;
+    }
+
+
+    public void init() {
+        //  new FieldWeightDialog(frame).setVisible(true);
+        panel.output("Unabbreviating...");
+    }
+
+    public void run() {
+        //net.sf.jabref.journals.JournalList.downloadJournalList(frame);
+
+
+        BibtexEntry[] entries = panel.getSelectedEntries();
+        if (entries == null)
+            return;
+        NamedCompound ce = new NamedCompound("Unabbreviate journal names");
+        int count = 0;
+        for (int i = 0; i < entries.length; i++) {
+            if (Globals.journalAbbrev.unabbreviate(entries[i], "journal", ce))
+                count++;
+        }
+        if (count > 0) {
+            ce.end();
+            panel.undoManager.addEdit(ce);
+            panel.markBaseChanged();
+            message = Globals.lang("Unabbreviated %0 journal names.", String.valueOf(count));
+        } else {
+            message = Globals.lang("No journal names could be unabbreviated.");
+        }
+    }
+
+    public void update() {
+        panel.output(message);
+    }
+}
diff --git a/src/java/net/sf/jabref/label/ArticleLabelRule.java b/src/java/net/sf/jabref/label/ArticleLabelRule.java
new file mode 100644
index 0000000..bf4da82
--- /dev/null
+++ b/src/java/net/sf/jabref/label/ArticleLabelRule.java
@@ -0,0 +1,129 @@
+/*
+  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.
+
+  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.label;
+
+import net.sf.jabref.*;
+
+public class ArticleLabelRule extends DefaultLabelRule {
+
+    // this is the rule used handle articles
+    // we try (first author last name)/(year)/(first unique journal word)
+    public String applyRule(BibtexEntry oldEntry){
+        String oldLabel = (String) (oldEntry.getField(Globals.KEY_FIELD)) ;
+        String newLabel = "" ;
+
+        String author="";
+
+        //## to be done: i need to check if the key is unique else need to make another one with suffix
+        try{
+            author=(String)oldEntry.getField("author");
+            String[] tokens= author.split("\\band\\b");
+            if( tokens.length > 0){ // if author is empty
+                if(tokens[0].indexOf(",") > 0)
+                    tokens[0] = AuthorList.fixAuthor_firstNameFirst( tokens[0] ); // convert lastname, firstname to firstname lastname
+                String[] firstAuthor = tokens[0].replaceAll("\\s+"," ").split(" ");
+                // lastname, firstname
+
+                newLabel += firstAuthor[ firstAuthor.length-1];
+            }
+        }catch(Throwable t){
+            System.out.println("error getting author: "+t) ;
+        }
+
+        // use the year token
+        try{
+            if( ! newLabel.equals("")){
+                if( oldEntry.getField("year")!= null){
+                    newLabel += String.valueOf( oldEntry.getField("year")) ;
+                }
+            }else
+                newLabel=oldLabel; // don't make a key since there is no author
+        }catch(Throwable t){
+            System.out.println("error getting year: "+t) ;
+        }
+
+// now check for uniqueness
+// i need access to basepanes: checkForDuplicateKey
+
+//oldEntry.setField(Globals.KEY_FIELD,newLabel) ;
+        return newLabel ;
+
+
+/*
+// use the journal name
+// return the first token 4 wrds or longer, that's not journal
+// , society, or the like (using the Keyword class)
+try{
+
+if(oldEntry.getField("journal") != null) {
+authorTokens = new StringTokenizer( ((String) oldEntry.getField("journal")).replaceAll(","," ").replaceAll("/"," ")) ;
+String tempString = authorTokens.nextToken() ;
+tempString = tempString.replaceAll(",","") ;
+boolean done = false ;
+while(tempString!=null && !done ){
+tempString = tempString.replaceAll(",","").trim() ;
+if(tempString.trim().length() > 3 && !KeyWord.isKeyWord(tempString))  {
+done = true ;
+}
+else{
+
+if(authorTokens.hasMoreTokens()){
+tempString = authorTokens.nextToken() ;
+}else{
+done = true ;
+}
+}
+}
+
+if(tempString!=null && (tempString.indexOf("null")<0) ){
+newLabel += String.valueOf( tempString.toLowerCase()) ;
+}
+}
+}
+catch(Throwable t){  System.err.println(t) ; }
+*/
+
+    }
+
+
+//    public static void main(String args[]){
+//
+//        System.out.println(args[0]) ;
+//        BibtexEntry entry = new BibtexEntry("1",BibtexEntryType.ARTICLE) ;
+//        entry.setField("journal",args[0]) ;
+//        entry.setField("author","jones, b") ;
+//        entry.setField("year","1984") ;
+//        ArticleLabelRule rule = new ArticleLabelRule() ;
+//        entry = rule.applyRule(entry) ;
+//        System.out.println(entry.getField(BibtexBaseFrame.KEY_PROPERTY) );
+//
+//    }
+
+}
+
+
+
diff --git a/src/java/net/sf/jabref/label/BookLabelRule.java b/src/java/net/sf/jabref/label/BookLabelRule.java
new file mode 100644
index 0000000..288cab7
--- /dev/null
+++ b/src/java/net/sf/jabref/label/BookLabelRule.java
@@ -0,0 +1,89 @@
+/*
+Copyright (C) 2003 Nathan Dunn, 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.label;
+
+import net.sf.jabref.BibtexEntry;
+import net.sf.jabref.Globals;
+import java.util.StringTokenizer ; 
+
+public class BookLabelRule extends DefaultLabelRule {
+
+    // this is the rule used handle articles
+    // we try (first author)/(year)
+    public String applyRule(BibtexEntry oldEntry){
+        String oldLabel = (String) (oldEntry.getField(Globals.KEY_FIELD)) ; 
+        String newLabel = "" ; 
+
+
+        StringTokenizer authorTokens = null ; 
+        // use the author token
+        try{ 
+            if((String) oldEntry.getField("author")!= null){
+                authorTokens= new StringTokenizer((String) oldEntry.getField("author"),",") ; 
+            }else
+            if((String) oldEntry.getField("editor")!= null){
+                authorTokens= new StringTokenizer((String) oldEntry.getField("editor"),",") ; 
+            }
+            newLabel += authorTokens.nextToken().toLowerCase() ; 
+        }catch(Throwable t){
+			System.out.println("error getting author/editor: "+t) ; 
+        }
+
+        // use the year token
+        try{
+            if( oldEntry.getField("year")!= null){
+                newLabel += String.valueOf( oldEntry.getField("year")) ;  
+            }
+        }catch(Throwable t){
+			System.out.println("error getting author: "+t) ; 
+        }
+
+        newLabel += "book" ;
+        
+	//	oldEntry.setField(Globals.KEY_FIELD,newLabel) ; 
+	return newLabel; 
+    }
+
+
+//    public static void main(String args[]){
+//        
+//        System.out.println(args[0]) ; 
+//        BibtexEntry entry = new BibtexEntry("1",BibtexEntryType.ARTICLE) ; 
+//        entry.setField("journal",args[0]) ; 
+//        entry.setField("author","jones, b") ; 
+//        entry.setField("year","1984") ; 
+//        BookLabelRule rule = new BookLabelRule() ; 
+//        entry = rule.applyRule(entry) ; 
+////        System.out.println(entry.getField("journal") ); 
+//        System.out.println(entry.getField(BibtexBaseFrame.KEY_PROPERTY) ); 
+//
+//    }
+    
+}
+
+
+
diff --git a/src/java/net/sf/jabref/label/DefaultLabelRule.java b/src/java/net/sf/jabref/label/DefaultLabelRule.java
new file mode 100644
index 0000000..03ed977
--- /dev/null
+++ b/src/java/net/sf/jabref/label/DefaultLabelRule.java
@@ -0,0 +1,44 @@
+/*
+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.
+
+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.label;
+
+import net.sf.jabref.BibtexEntry;
+import net.sf.jabref.Globals;
+
+public class DefaultLabelRule implements LabelRule {
+
+
+    // the default rule is that oit simply returns what it was given
+    public String applyRule(BibtexEntry oldEntry){
+	return (String)oldEntry.getField(Globals.KEY_FIELD); 
+    }
+
+
+}
+
+
+
diff --git a/src/java/net/sf/jabref/label/IncollectionLabelRule.java b/src/java/net/sf/jabref/label/IncollectionLabelRule.java
new file mode 100644
index 0000000..ea99d7f
--- /dev/null
+++ b/src/java/net/sf/jabref/label/IncollectionLabelRule.java
@@ -0,0 +1,46 @@
+/*
+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.
+
+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.label;
+
+import net.sf.jabref.*;
+import java.util.StringTokenizer ; 
+
+public class IncollectionLabelRule extends ArticleLabelRule {
+
+    // this is the rule used handle articles
+    // we try (first author)/(year)
+
+    // Same thing as the ArticleLabelRule
+//    public BibtexEntry applyRule(BibtexEntry oldEntry){
+//    }
+//
+
+    
+}
+
+
+
diff --git a/src/java/net/sf/jabref/label/InproceedingsLabelRule.java b/src/java/net/sf/jabref/label/InproceedingsLabelRule.java
new file mode 100644
index 0000000..bea83d4
--- /dev/null
+++ b/src/java/net/sf/jabref/label/InproceedingsLabelRule.java
@@ -0,0 +1,99 @@
+/*
+Copyright (C) 2003 Nathan Dunn, 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.label;
+
+import net.sf.jabref.*;
+import java.util.StringTokenizer ; 
+
+public class InproceedingsLabelRule extends DefaultLabelRule {
+
+    // this is the rule used handle articles
+    // we try (first author)/(year)/(first unique booktitle word)
+    public String applyRule(BibtexEntry oldEntry){
+        String oldLabel = (String) (oldEntry.getField(Globals.KEY_FIELD)) ; 
+        String newLabel = "" ; 
+
+
+        StringTokenizer authorTokens = null ; 
+        // use the author token
+        try{ 
+            authorTokens= new StringTokenizer((String) oldEntry.getField("author"),",") ; 
+            newLabel += authorTokens.nextToken().toLowerCase().replaceAll(" ","").replaceAll("\\.","")   ; 
+        }catch(Throwable t){
+			System.out.println("error getting author: "+t) ; 
+        }
+
+        // use the year token
+        try{
+            if( oldEntry.getField("year")!= null){
+                newLabel += String.valueOf( oldEntry.getField("year")) ;  
+            }
+        }catch(Throwable t){
+			System.out.println("error getting year: "+t) ; 
+        }
+
+        // use the booktitle name
+        // return the first token 4 wrds or longer, that's not a keyword
+        try{
+           
+          if(oldEntry.getField("booktitle") != null) {
+            authorTokens = new StringTokenizer( ((String) oldEntry.getField("booktitle")).replaceAll(","," ").replaceAll("/"," ")) ; 
+            String tempString = authorTokens.nextToken() ; 
+            tempString = tempString.replaceAll(",","") ; 
+            boolean done = false ; 
+            while(tempString!=null && !done ){
+                tempString = tempString.replaceAll(",","").trim() ; 
+                if(tempString.trim().length() > 3 && !KeyWord.isKeyWord(tempString))  {
+                    done = true ; 
+                }
+                else{
+
+                    if(authorTokens.hasMoreTokens()){
+                        tempString = authorTokens.nextToken() ; 
+                    }else{
+                        done = true ; 
+                    }
+                }
+            }
+
+            if(tempString!=null && (tempString.indexOf("null")<0) ){
+                newLabel += String.valueOf( tempString.toLowerCase()) ;  
+            }
+          }
+        }
+        catch(Throwable t){  System.err.println(t) ; }
+
+	//	oldEntry.setField(Globals.KEY_FIELD,newLabel) ; 
+	return newLabel; 
+    }
+
+
+    
+}
+
+
+
diff --git a/src/java/net/sf/jabref/label/KeyWord.java b/src/java/net/sf/jabref/label/KeyWord.java
new file mode 100644
index 0000000..55d03d9
--- /dev/null
+++ b/src/java/net/sf/jabref/label/KeyWord.java
@@ -0,0 +1,93 @@
+/*
+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.
+
+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.label;
+
+import java.util.Hashtable ; 
+
+public class KeyWord{
+
+   
+    private KeyWord(){
+        // puts all keywords in 
+        setKeyWords() ; 
+    }
+
+    private static void setKeyWords(){
+        keyWordTable.put("society","society") ; 
+        keyWordTable.put("transaction","transaction") ; 
+        keyWordTable.put("transactions","transactions") ; 
+        keyWordTable.put( "journal" , "journal" )  ; 
+        keyWordTable.put( "review" , "review" )  ; 
+        keyWordTable.put( "revue" , "revue" )  ; 
+        keyWordTable.put( "communication" , "communication" )  ; 
+        keyWordTable.put( "communications" , "communications" )  ; 
+        keyWordTable.put( "letters" , "letters" )  ; 
+        keyWordTable.put( "advances" , "advances" )  ; 
+        keyWordTable.put( "proceedings" , "proceedings" )  ; 
+        keyWordTable.put( "proceeding" , "proceeding" )  ; 
+        keyWordTable.put( "international" , "international" )  ; 
+        keyWordTable.put( "joint" , "joint" )  ; 
+        keyWordTable.put( "conference" , "conference" )  ; 
+    }
+
+
+    // accessors, if users, or anyone would want to change these defaults
+    // later
+    public static void addKeyWord(String newKeyWord){
+		keyWordTable.put(newKeyWord,newKeyWord) ; 
+    }
+
+    public static String removeKeyWord(String newKeyWord){
+		return (String) keyWordTable.remove(newKeyWord) ; 
+
+    }
+
+    
+   public static boolean isKeyWord(String matchWord){
+       if(keyWordTable.size()==0){
+		   setKeyWords() ; 
+       }
+       if(keyWordTable.containsKey(matchWord.toLowerCase())) {
+            return true ; 
+       }
+       return false ; 
+   }
+
+   public static boolean isKeyWordMatchCase(String matchWord){
+       if(keyWordTable.size()==0){
+		   setKeyWords() ; 
+       }
+       if(keyWordTable.containsKey(matchWord)) {
+            return true ; 
+       }
+       return false ; 
+   }
+
+   private static Hashtable keyWordTable = new Hashtable() ; 
+
+}
+
diff --git a/src/java/net/sf/jabref/label/LabelMaker.java b/src/java/net/sf/jabref/label/LabelMaker.java
new file mode 100644
index 0000000..514233b
--- /dev/null
+++ b/src/java/net/sf/jabref/label/LabelMaker.java
@@ -0,0 +1,85 @@
+/*
+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.
+
+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.label;
+
+import net.sf.jabref.*;
+import java.util.Hashtable ;
+
+
+/**
+ *  This class is the abstract class which contains all of the rules
+ *  for making the different types of Rules.
+ */
+public class LabelMaker {
+
+    public BibtexEntry applyRule(BibtexEntry newEntry, BibtexDatabase base){
+	String newKey = "";
+        if(ruleTable.containsKey(newEntry.getType().getName())){
+            newKey = ((LabelRule)ruleTable.get(newEntry.getType().getName())).applyRule(newEntry) ;
+        }
+        else{
+		newKey = applyDefaultRule(newEntry) ;
+        }
+
+	// Remove all illegal characters from the key.
+	newKey = Util.checkLegalKey(newKey);
+
+	// Try new keys until we get a unique one:
+	if (base.setCiteKeyForEntry(newEntry.getId(), newKey)) {
+	    
+	    char c = 'b';
+	    String modKey = newKey+"a";
+	    while (base.setCiteKeyForEntry(newEntry.getId(), modKey))
+		modKey = newKey+((char)(c++));	    
+	}
+
+	//newEntry.setField(Globals.KEY_FIELD, newKey);
+	// ...
+
+		return newEntry ;
+    }
+
+    public void setDefaultRule(LabelRule newRule) {
+		defaultRule = newRule ;
+    }
+
+    public String applyDefaultRule(BibtexEntry newEntry) {
+        return defaultRule.applyRule(newEntry) ;
+    }
+
+
+    // there should be a default rule for any type
+    public void addRule(LabelRule rule,BibtexEntryType type){
+       ruleTable.put(type.getName(),rule) ;
+    }
+
+    protected LabelRule defaultRule = new ArticleLabelRule() ;
+    protected Hashtable ruleTable = new Hashtable() ;
+
+}
+
+
diff --git a/src/java/net/sf/jabref/label/LabelRule.java b/src/java/net/sf/jabref/label/LabelRule.java
new file mode 100644
index 0000000..b3258d3
--- /dev/null
+++ b/src/java/net/sf/jabref/label/LabelRule.java
@@ -0,0 +1,39 @@
+/*
+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.
+
+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.label;
+
+import net.sf.jabref.BibtexEntry;
+
+public interface LabelRule{
+
+    // the default rule is that oit simply returns what it was given
+    public String applyRule(BibtexEntry oldEntry) ;
+
+
+}
+
+
diff --git a/src/java/net/sf/jabref/labelPattern/DefaultLabelPatterns.java b/src/java/net/sf/jabref/labelPattern/DefaultLabelPatterns.java
new file mode 100644
index 0000000..fa1db7c
--- /dev/null
+++ b/src/java/net/sf/jabref/labelPattern/DefaultLabelPatterns.java
@@ -0,0 +1,58 @@
+/*
+ * Created on 09-Dec-2003
+ */
+package net.sf.jabref.labelPattern;
+
+
+/*
+ * Created on 09-Dec-2003
+ */
+
+/**
+  * How this works:
+  * The fields used to autogeneratr keys are stored in an ArrayList
+  * with the first item of the list being a string representation of
+  * the key pattern and the second item the spacer character.
+  * The order of the fields in the autogenerated key will match the
+  * order of the fields in the ArrayList.
+  *
+  * Each entry type will have its own corrosponding ArrayList, to handle
+  * this, we will have a Hashtable where an entry type > ArrayList.
+  * There will be a default KP, which will parent a userdefined KP.
+  *
+  * Upon generatring keys we will itentify the type of entry, fetch
+  * the proper Array, store the spacer in a temp. String. By reading the
+  * field in the Array, the proper value will be fetched and stored in a
+  * StringBuffer, with the spacer between each field.
+  *
+  * Btw. we wont allow for keys like [auth][year]_[pages], is this a
+  * problem?
+  *
+  *
+ * @author Ulrik Stervbo (ulriks AT ruc.dk)
+ */
+//public class DefaultLabelPatterns extends ListResourceBundle{
+public class DefaultLabelPatterns extends LabelPattern{
+
+    public DefaultLabelPatterns(){
+
+	/**
+	 * There's no need to set all defaults; only those that should differ
+	 * from the global default in LabelPatternUtil.DEFAULT_LABELPATTERN.
+	 */
+
+	/*addLabelPattern("book",	"[auth]_[year]");
+	addLabelPattern("booklet", "[auth]_[year]");
+	addLabelPattern("conference", "[auth]_[year]");
+	addLabelPattern("inbook", "[auth]_[year]");
+	addLabelPattern("incollection", "[auth]_[year]");
+	addLabelPattern("inproceedings", "[auth]_[year]");
+	addLabelPattern("manual", "[auth]_[year]");
+	addLabelPattern("mastersthesis", "[auth]_[year]");
+	addLabelPattern("misc",	"[auth]_[year]");
+	addLabelPattern("phdthesis", "[auth]_[year]");
+	addLabelPattern("proceedings","[auth]_[year]");
+	addLabelPattern("techreport", "[auth]_[year]");
+	addLabelPattern("unpublished", "[auth]_[year]");*/
+    }
+}
diff --git a/src/java/net/sf/jabref/labelPattern/LabelPattern.java b/src/java/net/sf/jabref/labelPattern/LabelPattern.java
new file mode 100644
index 0000000..5d1e8d2
--- /dev/null
+++ b/src/java/net/sf/jabref/labelPattern/LabelPattern.java
@@ -0,0 +1,100 @@
+/*
+ * Created on 09-Dec-2003
+ */
+package net.sf.jabref.labelPattern;
+
+import java.util.ArrayList;
+import java.util.Hashtable;
+
+/**
+ * A small table, where an entry type is associated with a label pattern (an 
+ * <code>ArrayList</code>).
+ * 
+ * A parent LabelPattern can be set. 
+ * @author Ulrik Stervbo (ulriks AT ruc.dk)
+ */
+public class LabelPattern extends Hashtable{
+	/**
+	 * The parent of this LabelPattern.
+	 */
+	protected LabelPattern parent = null;
+	
+	public LabelPattern(){}
+	
+	public LabelPattern(LabelPattern parent){
+		this.parent = parent;
+	}
+	/**
+	 * Sets the parent LabelPattern.
+	 * @param parent a <code>String</code>
+	 */
+	public void setParent(LabelPattern parent){
+		this.parent = parent;
+	}
+	
+	/**
+	 * Get the parent LabelPattern
+	 * @return the parent LabelPattern
+	 */
+	public LabelPattern getParent(){
+		return parent;
+	}
+	
+	public void addLabelPattern(String type, String pattern){
+	    //put(type, pattern);
+	    put(type, LabelPatternUtil.split(pattern));
+	}
+	
+	
+	/**
+	 * Remove a label pattern from the LabelPattern. No key patterns can be removed from
+	 * the very parent LabelPattern since is thought of as a default. To do this, use
+	 * the  removeKeyPattern(String type, boolean sure)
+	 * @param type a <code>String</code>
+	 */
+	public void removeLabelPattern(String type){
+		if(containsKey(type) && parent != null){
+		    remove(type);
+		}
+	}
+	
+	public void removeLabelPattern(String type, boolean sure){
+		
+		if(containsKey(type) && sure){
+			remove(type);
+		}
+	}	
+	/**
+	 * Gets an object for a desired label from this LabelPattern or one of it's parents.
+	 * This method first tries to obtain the object from this LabelPattern via the 
+	 * <code>get</code> method of <code>Hashtable</code>. If this fails, we try the 
+	 * parent.
+	 *  
+	 * @param key a <code>String</code>
+	 * @return the object for the given key
+	 * @throws NullPointerException
+	 */
+	public final ArrayList getValue(String key){
+		Object _obj = get(key); // throws the NullPointerException
+		// Test to see if we found anything
+		if(_obj == null){
+			if(parent != null){
+				_obj = parent.getValue(key);
+			}
+			if(_obj == null){
+			    // Not found - return the default value
+			    return LabelPatternUtil.DEFAULT_LABELPATTERN;
+			}
+		}
+
+		return (ArrayList)_obj;
+	}
+
+        /**
+         * Checks whether this pattern is customized or the default value.
+         */
+        public final boolean isDefaultValue(String key) {
+            Object _obj = get(key);
+            return _obj == null;
+        }
+}
diff --git a/src/java/net/sf/jabref/labelPattern/LabelPatternUtil.java b/src/java/net/sf/jabref/labelPattern/LabelPatternUtil.java
new file mode 100644
index 0000000..cfcc5d0
--- /dev/null
+++ b/src/java/net/sf/jabref/labelPattern/LabelPatternUtil.java
@@ -0,0 +1,733 @@
+/*
+ * Created on 13-Dec-2003
+ */
+package net.sf.jabref.labelPattern;
+
+import java.util.ArrayList;
+import java.util.StringTokenizer;
+
+import net.sf.jabref.*;
+import net.sf.jabref.export.layout.format.RemoveLatexCommands;
+
+/**
+ *
+ * @author Ulrik Stervbo (ulriks AT ruc.dk)
+ */
+/**
+ * This is the utility class of the LabelPattern package.
+ * @author Ulrik Stervbo (ulriks AT ruc.dk)
+ */
+public class LabelPatternUtil {
+
+  // All single characters that we can use for extending a key to make it unique:
+  private static String CHARS = "abcdefghijklmnopqrstuvwxyz";
+
+  public static ArrayList DEFAULT_LABELPATTERN;
+  static {
+      updateDefaultPattern();
+  }
+  //"[auth][year]");
+
+  private static BibtexDatabase _db;
+
+  public static void updateDefaultPattern() {
+      DEFAULT_LABELPATTERN = split(Globals.prefs.get("defaultLabelPattern"));
+  }
+  
+  /**
+   * This method takes a string of the form [field1]spacer[field2]spacer[field3]...,
+   * where the fields are the (required) fields of a BibTex entry. The string is split
+   * into firlds and spacers by recognizing the [ and ].
+   *
+   * @param keyPattern a <code>String</code>
+   * @return an <code>ArrayList</code> The first item of the list
+   * is a string representation of the key pattern (the parameter),
+   * the second item is the spacer character (a <code>String</code>).
+   */
+  public static ArrayList split(String labelPattern) {
+    // A holder for fields of the entry to be used for the key
+    ArrayList _alist = new ArrayList();
+
+    // Before we do anything, we add the parameter to the ArrayLIst
+    _alist.add(labelPattern);
+
+    //String[] ss = labelPattern.split("\\[|\\]");
+    StringTokenizer tok = new StringTokenizer(labelPattern, "[]", true);
+    while (tok.hasMoreTokens()) {
+      _alist.add(tok.nextToken());
+
+    }
+    return _alist;
+
+    /*
+       // Regular expresion for identifying the fields
+       Pattern pi = Pattern.compile("\\[\\w*\\]");
+       // Regular expresion for identifying the spacer
+       Pattern ps = Pattern.compile("\\].()*\\[");
+
+       // The matcher for the field
+       Matcher mi = pi.matcher(labelPattern);
+       // The matcher for the spacer char
+       Matcher ms = ps.matcher(labelPattern);
+
+       // Before we do anything, we add the parameter to the ArrayLIst
+       _alist.add(labelPattern);
+
+       // If we can find the spacer character
+       if(ms.find()){
+     String t_spacer = ms.group();
+      // Remove the `]' and `[' at the ends
+      // We cant imagine a spacer of omre than one character.
+      t_spacer = t_spacer.substring(1,2);
+      _alist.add(t_spacer);
+       }
+
+       while(mi.find()){
+     // Get the matched string
+     String t_str = mi.group();
+      int _sindex = 1;
+      int _eindex = t_str.length() -1;
+      // Remove the `[' and `]' at the ends
+      t_str = t_str.substring(_sindex, _eindex);
+     _alist.add(t_str);
+       }
+
+       return _alist;*/
+  }
+
+  /**
+   * Generates a BibTeX label according to the pattern for a given entry type, and
+   * returns the <code>Bibtexentry</code> with the unique label.
+   * @param table a <code>LabelPattern</code>
+   * @param database a <code>BibtexDatabase</code>
+   * @param _entry a <code>BibtexEntry</code>
+   * @return modified Bibtexentry
+   */
+  public static BibtexEntry makeLabel(LabelPattern table,
+                                      BibtexDatabase database,
+                                      BibtexEntry _entry) {
+    _db = database;
+    ArrayList _al;
+    String _spacer, _label;
+    StringBuffer _sb = new StringBuffer();
+    boolean forceUpper = false, forceLower = false;
+
+    try {
+      // get the type of entry
+      String _type = _entry.getType().getName().toLowerCase();
+      // Get the arrayList corrosponding to the type
+      _al = table.getValue(_type);
+      int _alSize = _al.size();
+      boolean field = false;
+      for (int i = 1; i < _alSize; i++) {
+        String val = _al.get(i).toString();
+        if (val.equals("[")) {
+          field = true;
+        }
+        else if (val.equals("]")) {
+          field = false;
+        }
+        else if (field) {
+	    /* Edited by Seb Wills <saw27 at mrao.cam.ac.uk> on 13-Apr-2004
+	       Added new pseudo-fields "shortyear" and "veryshorttitle", and
+	       and ":lower" modifier for all fields (in a way easily extended to other modifiers).
+	       Helpfile help/LabelPatterns.html updated accordingly.
+	    */
+	    // check whether there is a modifier on the end such as ":lower"
+	    //String modifier = null;
+        String[] parts = val.split(":");
+        val = parts[0];
+        //int _mi = val.indexOf(":");
+	    //if(_mi != -1 && _mi != val.length()-1 && _mi != 0) { // ":" is in val and isn't first or last character
+		//modifier=val.substring(_mi+1);
+		//val=val.substring(0,_mi);
+	    //}
+	    StringBuffer _sbvalue = new StringBuffer();
+
+	    try {
+
+               if (val.startsWith("auth") || val.startsWith("pureauth")) {
+
+                  // For label code "auth...": if there is no author, but there are editor(s)
+                  // (e.g. for an Edited Book), use the editor(s) instead. (saw27 at mrao.cam.ac.uk).
+                  // This is what most people want, but in case somebody really needs a field which
+                  // expands to nothing if there is no author (e.g. someone who uses both "auth"
+                  // and "ed" in the same label), we provide an alternative form "pureauth..." which
+                  // does not do this fallback substitution of editor.
+
+                  String authString;
+                  if(val.startsWith("pure")) {
+                    // remove the "pure" prefix so the remaining code in this section functions correctly
+                    val = val.substring(4);
+		    System.out.println("val is now "+val);
+                    authString = _entry.getField("author").toString(); // use even if empty
+		    System.out.println("Got authString " + authString);
+                  } else {
+                    if (_entry.getField("author") == null || _entry.getField("author").toString().equals("")) {
+                      System.out.println("author empty, so replacing with editor for label generation");
+                      authString = _entry.getField("editor").toString();
+                    } else {
+                      authString = _entry.getField("author").toString();
+                    }
+                  }
+
+                  // Gather all author-related checks, so we don't have to check all all the time.
+                  if (val.equals("auth")) {
+                    _sbvalue.append(firstAuthor(authString));
+                  }
+                  else if (val.equals("authors")) {
+                    _sbvalue.append(allAuthors(authString));
+                  }
+                  else if (val.equals("authorIni")) {
+                    _sbvalue.append(oneAuthorPlusIni(authString));
+                  }
+                  else if (val.matches("authIni[\\d]+")) {
+                    int num = Integer.parseInt(val.substring(7));
+					_sbvalue.append(authIniN(authString,num));
+                  }
+				  else if (val.equals("auth.auth.ea")) {
+                    _sbvalue.append(authAuthEa(authString));
+                  }
+                  else if (val.equals("authshort")) {
+                    _sbvalue.append(authshort(authString));
+                  }
+                  else if (val.matches("auth[\\d]+_[\\d]+")) {
+                    String[] nums = val.substring(4).split("_");
+                    _sbvalue.append(authN_M(authString,
+                                            Integer.parseInt(nums[0]),
+                                            Integer.parseInt(nums[1]) - 1));
+                  }
+                  // authN.  First N chars of the first author's last name.
+                  else if (val.matches("auth\\d+")) {
+                    int num = Integer.parseInt(val.substring(4));
+                    String fa = firstAuthor(authString);
+                    if ( num > fa.length() )
+                      num = fa.length();
+                    _sbvalue.append(fa.substring(0,num));
+                  }
+                  else if (val.matches("authors\\d+")) {
+                    _sbvalue.append(NAuthors(authString,Integer.parseInt(val.substring(7))));
+                  }
+
+                  else {
+                    // This "auth" business was a dead end, so just use it literally:
+                    _sbvalue.append(_entry.getField(val).toString());
+                  }
+                }
+                else if (val.startsWith("ed")) {
+                  // Gather all markers starting with "ed" here, so we don't have to check all all the time.
+                  if (val.equals("edtr")) {
+                    _sbvalue.append(firstAuthor(_entry.getField("editor").toString()));
+                  }
+                  else if (val.equals("editors")) {
+                    _sbvalue.append(allAuthors(_entry.getField("editor").toString()));
+                  }
+                  else if (val.equals("editorIni")) {
+                      _sbvalue.append(oneAuthorPlusIni(_entry.getField("editor").toString()));
+                  }
+                  else if (val.matches("edtrIni[\\d]+")) {
+                    int num = Integer.parseInt(val.substring(7));
+					_sbvalue.append(authIniN(_entry.getField("editor").toString(),num));
+                  }
+                  else if (val.matches("edtr[\\d]+_[\\d]+")) {
+                    String[] nums = val.substring(4).split("_");
+                    _sbvalue.append(authN_M(_entry.getField("editor").toString(), Integer.parseInt(nums[0]),
+                                            Integer.parseInt(nums[1])-1));
+                  }
+                  else if (val.equals("edtr.edtr.ea")) {
+                    _sbvalue.append(authAuthEa(_entry.getField("editor").toString()));
+                  }
+                  else if (val.equals("edtrshort")) {
+                    _sbvalue.append(authshort(_entry.getField("editor").toString()));
+                  }
+                  // authN.  First N chars of the first author's last name.
+                  else if (val.matches("edtr\\d+")) {
+                    int num = Integer.parseInt(val.substring(4));
+                    String fa = firstAuthor(_entry.getField("editor").toString());
+                    if ( num > fa.length() )
+                      num = fa.length();
+                    _sbvalue.append(fa.substring(0,num));
+                  }
+                  else {
+                    // This "ed" business was a dead end, so just use it literally:
+                    _sbvalue.append(_entry.getField(val).toString());
+                  }
+                }
+                else if (val.equals("firstpage")) {
+                  _sbvalue.append(firstPage(_entry.getField("pages").toString()));
+                }
+                else if (val.equals("lastpage")) {
+                  _sbvalue.append(lastPage(_entry.getField("pages").toString()));
+                }
+                else if (val.equals("shorttitle")) {
+                  _sbvalue.append(getTitleWords(3, _entry));
+                }
+                else if (val.equals("shortyear")) {
+                  String ss = _entry.getField("year").toString();
+                  if (ss.startsWith("in") || ss.startsWith("sub")) {
+                    _sbvalue.append("IP");
+                  }
+                  else if (ss.length() > 2) {
+                    _sbvalue.append(ss.substring(ss.length() - 2));
+                  }
+                  else {
+                    _sbvalue.append(ss);
+                  }
+                }
+                
+                else if(val.equals("veryshorttitle")) {
+                  _sbvalue.append(getTitleWords(1, _entry));
+                }
+
+		// we havent seen any special demands
+		else {
+                  _sbvalue.append(_entry.getField(val).toString());
+		}
+	    }
+	    catch (NullPointerException ex) {
+		    //Globals.logger("Key generator warning: field '" + val + "' empty.");
+	    }
+	    // apply modifier if present
+        if (parts.length > 1) for (int j=1; j<parts.length; j++) {
+            String modifier = parts[j];
+
+            if(modifier.equals("lower")) {
+                String tmp = _sbvalue.toString().toLowerCase();
+                _sbvalue = new StringBuffer(tmp);
+		    }
+            else if (modifier.equals("abbr")) {
+                // Abbreviate - that is,
+                //System.out.println(_sbvalue.toString());
+                StringBuffer abbr = new StringBuffer();
+                String[] words = _sbvalue.toString().split("\\b");
+                for (int word=0; word<words.length; word++)
+                    if (words[word].length() > 0)
+                        abbr.append(words[word].charAt(0));
+                _sbvalue = abbr;
+            }
+            else {
+		        Globals.logger("Key generator warning: unknown modifier '"+modifier+"'.");
+		    }
+	    }
+
+        _sb.append(_sbvalue);
+
+
+        }
+        else {
+          _sb.append(val);
+        }
+      }
+    }
+
+    catch (Exception e) {
+      System.err.println(e);
+    }
+
+    /**
+     * Edited by Morten Alver 2004.02.04.
+     *
+     * We now have a system for easing key duplicate prevention, so
+     * I am changing this method to conform to it.
+     *
+
+        // here we make sure the key is unique
+       _label = makeLabelUnique(_sb.toString());
+       _entry.setField(Globals.KEY_FIELD, _label);
+       return _entry;
+     */
+
+    // Remove all illegal characters from the key.
+    _label = Util.checkLegalKey(_sb.toString());
+
+    // Patch by Toralf Senger:
+    // Remove Regular Expressions while generating Keys
+    String regex = Globals.prefs.get("KeyPatternRegex");
+    if ((regex != null) && (regex.trim().length() > 0)) {
+        String replacement = Globals.prefs.get("KeyPatternReplacement");
+        _label = _label.replaceAll(regex, replacement);
+    }
+
+    if (forceUpper) {
+      _label = _label.toUpperCase();
+    }
+    if (forceLower) {
+      _label = _label.toLowerCase();
+    }
+      
+    
+    String oldKey = _entry.getCiteKey();
+    int occurences = _db.getNumberOfKeyOccurences(_label);
+    if ((oldKey != null) && oldKey.equals(_label))
+        occurences--; // No change, so we can accept one dupe.
+    
+    // Try new keys until we get a unique one:
+    //if (_db.setCiteKeyForEntry(_entry.getId(), _label)) {
+    
+    if (occurences == 0) {
+        // No dupes found, so we can just go ahead.
+        if (!_label.equals(oldKey))
+            _db.setCiteKeyForEntry(_entry.getId(), _label);
+    }
+    else {
+
+        // The key is already in use, so we must modify it.
+        int number = 0;
+
+        String moddedKey = _label+getAddition(number);
+        occurences = _db.getNumberOfKeyOccurences(moddedKey);
+        if ((oldKey != null) && oldKey.equals(moddedKey))
+            occurences--;
+        while (occurences > 0) {
+            number++;
+            moddedKey = _label+getAddition(number);
+
+            occurences = _db.getNumberOfKeyOccurences(moddedKey);
+            if ((oldKey != null) && oldKey.equals(moddedKey))
+                occurences--;
+        }
+
+        /*
+        char c = 'b';
+        String modKey = _label + "a";
+        occurences = _db.getNumberOfKeyOccurences(modKey);
+        if ((oldKey != null) && oldKey.equals(modKey))
+            occurences--;
+        //while (_db.setCiteKeyForEntry(_entry.getId(), modKey)) {
+        while (occurences > 0) {
+            modKey = _label + ( (char) (c++));
+
+            occurences = _db.getNumberOfKeyOccurences(modKey);
+            if ((oldKey != null) && oldKey.equals(modKey))
+                occurences--;
+        }
+        */
+
+        if (!moddedKey.equals(oldKey))  {
+            _db.setCiteKeyForEntry(_entry.getId(), moddedKey);
+        }
+    }
+
+    return _entry;
+    /** End of edit, Morten Alver 2004.02.04.  */
+
+  }
+
+    /**
+     * Computes an appendix to a BibTeX key that could make it unique. We use a-z for numbers
+     * 0-25, and then aa-az, ba-bz, etc.
+     * @param number The appendix number.
+     * @return The String to append.
+     */
+    private static String getAddition(int number) {
+        String s = "";
+        if (number >= CHARS.length()) {
+            int lastChar = number % CHARS.length();
+            return getAddition(number/CHARS.length()-1) + CHARS.substring(lastChar, lastChar+1);
+        } else
+            return CHARS.substring(number, number+1);
+    }
+
+
+    static String getTitleWords(int number, BibtexEntry _entry) {
+    String ss = (new RemoveLatexCommands()).format(_entry.getField("title").toString());
+    StringBuffer _sbvalue = new StringBuffer(),
+        current;
+    int piv=0, words = 0;
+
+    // sorry for being English-centric. I guess these
+    // words should really be an editable preference.
+    mainl: while ((piv < ss.length()) && (words < number)) {
+      current = new StringBuffer();
+      // Get the next word:
+      while ((piv<ss.length()) && !Character.isWhitespace(ss.charAt(piv))) {
+        current.append(ss.charAt(piv));
+        piv++;
+        //System.out.println(".. "+piv+" '"+current.toString()+"'");
+      }
+      piv++;
+      // Check if it is ok:
+      String word = current.toString().trim();
+      if (word.length() == 0)
+        continue mainl;
+      for(int _i=0; _i< Globals.SKIP_WORDS.length; _i++) {
+        if (word.equalsIgnoreCase(Globals.SKIP_WORDS[_i])) {
+          continue mainl;
+        }
+      }
+
+      // If we get here, the word was accepted.
+      if (_sbvalue.length() > 0)
+        _sbvalue.append(" ");
+      _sbvalue.append(word);
+      words++;
+    }
+
+    return _sbvalue.toString();
+  }
+
+
+  /**
+   * Tests whether a given label is unique.
+   * @param label a <code>String</code>
+   * @return <code>true</code> if and only if the <code>label</code> is unique
+   */
+  public static boolean isLabelUnique(String label) {
+    boolean _isUnique = true;
+    BibtexEntry _entry;
+    int _dbSize = _db.getEntryCount();
+    // run through the whole DB and check the key field
+    // if this could be made recursive I would be very happy
+    // it kinda sux that we have to run through the whole db.
+    // The idea here is that if we meet NO match, the _duplicate
+    // field will be true
+
+    for (int i = 0; i < _dbSize; i++) {
+      _entry = _db.getEntryById(String.valueOf(i));
+
+      // oh my! there is a match! we better set the uniqueness to false
+      // and leave this for-loop all together
+      if (_entry.getField(Globals.KEY_FIELD).equals(label)) {
+        _isUnique = false;
+        break;
+      }
+    }
+
+    return _isUnique;
+
+  }
+
+  /**
+   * Gets the last name of the first author/editor
+   * @param authorField a <code>String</code>
+   * @return the sur name of an author/editor
+   */
+  private static String firstAuthor(String authorField) {
+    String author = "";
+    // This code was part of 'ApplyRule' in 'ArticleLabelRule'
+    //String[] tokens = ImportFormatReader.fixAuthor_lastNameFirst(authorField).split("\\band\\b");
+      String[] tokens = AuthorList.fixAuthorForAlphabetization(authorField).split("\\band\\b");
+    if (tokens.length > 0) { // if author is empty
+      String[] firstAuthor = tokens[0].replaceAll("\\s+", " ").split(" ");
+      author += firstAuthor[0];
+
+    }
+    return author;
+  }
+
+  /**
+   * Gets the last name of all authors/editors
+   * @param authorField a <code>String</code>
+   * @return the sur name of all authors/editors
+   */
+  private static String allAuthors(String authorField) {
+    String author = "";
+    // This code was part of 'ApplyRule' in 'ArticleLabelRule'
+    String[] tokens = AuthorList.fixAuthorForAlphabetization(authorField).split("\\band\\b");
+    int i = 0;
+    while (tokens.length > i) {
+      // convert lastname, firstname to firstname lastname
+      String[] firstAuthor = tokens[i].replaceAll("\\s+", " ").trim().split(" ");
+      // lastname, firstname
+      author += firstAuthor[0];
+      i++;
+    }
+    return author;
+  }
+
+  /**
+   * Gets the surnames of the first N authors and appends EtAl if there are more than N authors
+   * @param authorField a <code>String</code>
+   * @param int n the number of desired authors
+   * @return Gets the surnames of the first N authors and appends EtAl if there are more than N authors
+   */
+  private static String NAuthors(String authorField, int n) {
+	    String author = "";
+	    // This code was part of 'ApplyRule' in 'ArticleLabelRule'
+	    String[] tokens = AuthorList.fixAuthorForAlphabetization(authorField).split("\\band\\b");
+	    int i = 0;
+	    while (tokens.length > i && i < n) {
+	      // convert lastname, firstname to firstname lastname
+	      String[] firstAuthor = tokens[i].replaceAll("\\s+", " ").trim().split(" ");
+	      // lastname, firstname
+	      author += firstAuthor[0];
+	      i++;
+	    }
+	    if (tokens.length <= n) return author;
+	    return author += "EtAl";
+  }
+
+  /**
+   * Gets the first part of the last name of the first
+   * author/editor, and appends the last name initial of the
+   * remaining authors/editors.
+   * @param authorField a <code>String</code>
+   * @return the sur name of all authors/editors
+   */
+  private static String oneAuthorPlusIni(String authorField) {
+    final int CHARS_OF_FIRST = 5;
+    authorField = AuthorList.fixAuthorForAlphabetization(authorField);
+    String author = "";
+    // This code was part of 'ApplyRule' in 'ArticleLabelRule'
+    String[] tokens = authorField.split("\\band\\b");
+    int i = 1;
+    if (tokens.length == 0) {
+      return author;
+    }
+    String[] firstAuthor = tokens[0].replaceAll("\\s+", " ").split(" ");
+    author = firstAuthor[0].substring(0,
+                                      (int) Math.min(CHARS_OF_FIRST,
+        firstAuthor[0].length()));
+    while (tokens.length > i) {
+      // convert lastname, firstname to firstname lastname
+      author += tokens[i].trim().charAt(0);
+      i++;
+    }
+    return author;
+
+  }
+
+  /**
+   * auth.auth.ea format:
+   * Isaac Newton and James Maxwell and Albert Einstein (1960)
+   * Isaac Newton and James Maxwell (1960)
+   *  give:
+   * Newton.Maxwell.ea
+   * Newton.Maxwell
+   */
+  private static String authAuthEa(String authorField) {
+    authorField = AuthorList.fixAuthorForAlphabetization(authorField);
+    StringBuffer author = new StringBuffer();
+
+    String[] tokens = authorField.split("\\band\\b");
+    if (tokens.length == 0) {
+      return "";
+    }
+    author.append((tokens[0].split(","))[0]);
+    if (tokens.length >= 2)
+        author.append(".").append((tokens[1].split(","))[0]);
+    if (tokens.length > 2)
+      author.append(".ea");
+
+    return author.toString();
+  }
+
+  /**
+   * The first N characters of the Mth author/editor.
+   */
+  private static String authN_M(String authorField, int n, int m) {
+    authorField = AuthorList.fixAuthorForAlphabetization(authorField);
+    StringBuffer author = new StringBuffer();
+
+    String[] tokens = authorField.split("\\band\\b");
+    if ((tokens.length <= m) || (n<0) || (m<0)) {
+      return "";
+    }
+    String lastName = (tokens[m].split(","))[0].trim();
+    //System.out.println(lastName);
+    if (lastName.length() <= n)
+      return lastName;
+    else
+      return lastName.substring(0, n);
+  }
+
+  /**
+   * authshort format:
+   * added by Kolja Brix, kbx at users.sourceforge.net
+   *
+   * given author names
+   *   Isaac Newton and James Maxwell and Albert Einstein and N. Bohr
+   *   Isaac Newton and James Maxwell and Albert Einstein 
+   *   Isaac Newton and James Maxwell 
+   *   Isaac Newton 
+   * yield
+   *   NME+
+   *   NME
+   *   NM
+   *   Newton
+   */
+  private static String authshort(String authorField) {
+    authorField = AuthorList.fixAuthorForAlphabetization(authorField);
+    StringBuffer author = new StringBuffer();
+    String[] tokens = authorField.split("\\band\\b");
+    int i = 0;
+
+    if (tokens.length == 1) {
+
+      author.append(authN_M(authorField,authorField.length(),0));
+
+    } else if (tokens.length >= 2) {
+    
+      while (tokens.length > i && i<3) {
+        author.append(authN_M(authorField,1,i));
+        i++;
+      }
+      
+      if (tokens.length > 3) 
+        author.append("+");
+      
+    }
+
+    return author.toString();
+  }
+
+  /**
+   * authIniN format:
+   * Each author gets (N div #authors) chars, the remaining
+   * (N mod #authors) chars are equally distributed to the
+   * authors first in the row.
+   * If (N < #authors), only the fist N authors get mentioned.
+   * a) I. Newton and J. Maxwell and A. Einstein and N. Bohr (..)
+   * b) I. Newton and J. Maxwell and A. Einstein 
+   * c) I. Newton and J. Maxwell 
+   * d) I. Newton 
+   * E.g. authIni4 gives: a) NMEB, b) NeME, c) NeMa, d) Newt
+   */
+  private static String authIniN(String authorField, int n) {
+    authorField = AuthorList.fixAuthorForAlphabetization(authorField);
+    StringBuffer author = new StringBuffer();
+    String[] tokens = authorField.split("\\band\\b");
+    int i = 0;
+    int charsAll = n / tokens.length;
+    
+    if (tokens.length == 0) {
+      return author.toString();
+    }
+
+    while (tokens.length > i) {
+      if ( i < (n % tokens.length) ) {
+        author.append(authN_M(authorField,charsAll+1,i));
+      } else {
+        author.append(authN_M(authorField,charsAll,i));
+      }
+      i++;
+    }
+
+    if (author.length() <= n)
+      return author.toString();
+    else
+      return author.toString().substring(0, n);
+  }
+      
+
+  /**
+   * Split the pages field into two and return the first one
+   * @param pages a <code>String</code>
+   * @return the first page number
+   */
+  private static String firstPage(String pages) {
+    String[] _pages = pages.split("-");
+    return _pages[0];
+  }
+
+  /**
+   * Split the pages field into two and return the last one
+   * @param pages a <code>String</code>
+   * @return the last page number
+   */
+  private static String lastPage(String pages) {
+    String[] _pages = pages.split("-");
+    return _pages[1];
+  }
+
+}
diff --git a/src/java/net/sf/jabref/mods/MODSDatabase.java b/src/java/net/sf/jabref/mods/MODSDatabase.java
new file mode 100644
index 0000000..b5ca6e8
--- /dev/null
+++ b/src/java/net/sf/jabref/mods/MODSDatabase.java
@@ -0,0 +1,62 @@
+/*
+ * Created on Oct 23, 2004
+ *
+ * TODO To change the template for this generated file go to
+ * Window - Preferences - Java - Code Style - Code Templates
+ */
+package net.sf.jabref.mods;
+import net.sf.jabref.*;
+import java.util.*;
+import javax.xml.parsers.*;
+import org.w3c.dom.*;
+/**
+ * @author Michael Wrighton
+ *
+ * TODO To change the template for this generated type comment go to
+ * Window - Preferences - Java - Code Style - Code Templates
+ */
+public class MODSDatabase {
+	protected Set entries;
+	
+	public MODSDatabase() {
+		// maybe make this sorted later...
+		entries = new HashSet();
+	}
+	
+	public MODSDatabase(BibtexDatabase bibtex) {
+		this();
+		Collection c = bibtex.getEntries();
+		for(Iterator iter = c.iterator(); iter.hasNext(); ) {
+			BibtexEntry entry = (BibtexEntry) iter.next();
+			MODSEntry newMods = new MODSEntry(entry);
+			entries.add(newMods);
+		}
+	}
+	public Document getDOMrepresentation() {
+		Document result = null;
+	   	try {
+	   		DocumentBuilder dbuild = DocumentBuilderFactory.
+														newInstance().
+														newDocumentBuilder();
+	   		result = dbuild.newDocument();
+	   		Element modsCollection = result.createElement("modsCollection");
+	   		modsCollection.setAttribute("xmlns", "http://www.loc.gov/mods/v3");
+	   		modsCollection.setAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
+	   		modsCollection.setAttribute("xsi:schemaLocation", "http://www.loc.gov/mods/v3 http://www.loc.gov/standards/mods/v3/mods-3-0.xsd");
+	   		
+	   		for(Iterator iter = entries.iterator(); iter.hasNext(); ) {
+	   			MODSEntry entry = (MODSEntry) iter.next();
+	   			Node node = entry.getDOMrepresentation(result);
+	   			modsCollection.appendChild(node);
+	   		}
+	   		
+	   		result.appendChild(modsCollection);	   		
+	   	}
+	   	catch (Exception e)
+		{
+	   		System.out.println("Exception caught..." + e);
+	   		e.printStackTrace();
+		}
+	   	return result;
+	   }
+}
diff --git a/src/java/net/sf/jabref/mods/MODSEntry.java b/src/java/net/sf/jabref/mods/MODSEntry.java
new file mode 100644
index 0000000..b158ed0
--- /dev/null
+++ b/src/java/net/sf/jabref/mods/MODSEntry.java
@@ -0,0 +1,283 @@
+package net.sf.jabref.mods;
+import net.sf.jabref.*;
+import net.sf.jabref.export.layout.format.*;
+import net.sf.jabref.export.layout.*;
+
+import javax.xml.parsers.*;
+import javax.xml.transform.*;
+import javax.xml.transform.dom.*;
+import javax.xml.transform.stream.*;
+import org.w3c.dom.*;
+import java.util.*;
+import java.io.*;
+/**
+ * @author Michael Wrighton
+ *
+ * TODO To change the template for this generated type comment go to
+ * Window - Preferences - Java - Code Style - Code Templates
+ */
+public class MODSEntry {
+	protected String entryType = "mods"; // could also be relatedItem
+	protected String id;
+	protected List authors = null;
+	protected List editors = null;
+	// should really be handled with an enum
+	protected String issuance = "monographic";
+	protected PageNumbers pages = null;
+	
+	protected String publisher = null;
+	protected String date = null;
+	protected String place = null;
+	
+	protected String title = null;
+	// should really be handled with an enum
+	protected String type = "text";
+	
+	protected String number;
+	protected String volume;
+	protected String genre = null;
+	protected Set handledExtensions;
+	
+	protected MODSEntry host;
+	Map extensionFields;
+	
+	public static String BIBTEX = "bibtex_";
+	
+	public MODSEntry() {
+		extensionFields = new HashMap();
+		handledExtensions = new HashSet();
+	
+	}
+	
+	public MODSEntry(BibtexEntry bibtex) {
+		this();
+		handledExtensions.add(BIBTEX + "publisher");
+		handledExtensions.add(BIBTEX + "title");
+		handledExtensions.add(BIBTEX + "bibtexkey");
+		handledExtensions.add(BIBTEX + "author");
+		populateFromBibtex(bibtex);
+	}
+	
+	protected void populateFromBibtex(BibtexEntry bibtex) {
+		LayoutFormatter chars = new XMLChars();
+		if (bibtex.getField("title") != null)
+			title = chars.format(bibtex.getField("title").toString());
+		
+		if (bibtex.getField("publisher") != null)
+			publisher = chars.format(bibtex.getField("publisher").toString());
+		if (bibtex.getField("bibtexkey") != null)
+			id = bibtex.getField("bibtexkey").toString();
+		if (bibtex.getField("place") != null)
+			place = chars.format(bibtex.getField("place").toString());
+		date = getDate(bibtex);	
+		genre = getMODSgenre(bibtex);
+		if (bibtex.getField("author") != null)
+			authors = getAuthors(bibtex.getField("author").toString());
+		if (bibtex.getType() == BibtexEntryType.ARTICLE || 
+			bibtex.getType() == BibtexEntryType.INPROCEEDINGS)
+		{
+			host = new MODSEntry();
+			host.entryType = "relatedItem";
+			host.title = (String) bibtex.getField("booktitle");
+			host.publisher = (String) bibtex.getField("publisher");
+			host.number = (String) bibtex.getField("number");
+			if (bibtex.getField("pages") != null)
+				host.volume = (String) bibtex.getField("volume");
+			host.issuance = "continuing";
+			if (bibtex.getField("pages") != null)
+				host.pages = new PageNumbers((String) bibtex.getField("pages"));
+		}
+		
+		populateExtensionFields(bibtex);
+		
+	}
+	
+	protected void populateExtensionFields(BibtexEntry e) {
+		Object fields [] = e.getAllFields();
+		for(int i = 0; i < fields.length; i++) {
+			String field = (String) fields[i];
+			String value = (String) e.getField(field);
+			field = BIBTEX + field;
+			extensionFields.put(field, value);
+		}
+	}
+	
+	protected List getAuthors(String authors) {
+		List result = new LinkedList();
+		LayoutFormatter chars = new XMLChars();
+		
+		if (authors.indexOf(" and ") == -1)
+          result.add(new PersonName(chars.format(authors)));
+        else
+        {
+            String[] names = authors.split(" and ");
+            for (int i=0; i<names.length; i++)
+              result.add(new PersonName(chars.format(names[i])));
+        }
+		return result;
+	}
+	
+	/* construct a MODS date object */
+	protected String getDate(BibtexEntry bibtex) {
+		String result = "";
+		if (bibtex.getField("year") != null)
+			result += (bibtex.getField("year").toString());
+		if (bibtex.getField("month") != null)
+			result += "-" + bibtex.getField("month").toString();
+		
+		return result;
+	}
+	// must be from http://www.loc.gov/marc/sourcecode/genre/genrelist.html
+	protected String getMODSgenre(BibtexEntry bibtex) {
+		String bibtexType = bibtex.getType().getName();
+		String result;
+		if (bibtexType.equals("Mastersthesis"))
+			result = "theses";
+		else
+			result = "conference publication";
+		// etc...
+		return bibtexType;		
+	}
+	
+	public Document getDOMrepresentation() {
+		Document result = null;
+		try {
+			DocumentBuilder d = DocumentBuilderFactory.newInstance().newDocumentBuilder();
+			
+		//	result = getDOMrepresentation(d);
+		}
+		catch (Exception e) 
+		{
+			throw new Error(e);
+		}
+		return result;
+	}
+		
+	
+	public Element getDOMrepresentation(Document d) {
+		Node result = null;
+	   	try {
+	   		Element mods = d.createElement(entryType);
+	   		mods.setAttribute("version", "3.0");
+	   		// mods.setAttribute("xmlns:xlink:", "http://www.w3.org/1999/xlink");
+	   		// title
+	   		if(title != null) {
+	   			Element titleInfo = d.createElement("titleInfo");
+	   			Element mainTitle = d.createElement("title");
+	   			mainTitle.appendChild(d.createTextNode(title));
+	   			titleInfo.appendChild(mainTitle);
+		   		mods.appendChild(titleInfo);
+	   		}
+	   		if (authors != null) {
+	   			for(Iterator iter = authors.iterator(); iter.hasNext();) {
+	   				PersonName name = (PersonName) iter.next();
+	   				Element modsName = d.createElement("name");
+	   				modsName.setAttribute("type", "personal");
+	   				if (name.getSurname() != null) {
+	   					Element namePart = d.createElement("namePart");
+	   					namePart.setAttribute("type", "family");
+	   					namePart.appendChild(d.createTextNode(name.getSurname()));
+	   					modsName.appendChild(namePart);
+	   				}
+	   				if (name.getGivenNames() != null) {
+	   					Element namePart = d.createElement("namePart");
+	   					namePart.setAttribute("type", "given");
+	   					namePart.appendChild(d.createTextNode(name.getGivenNames()));
+	   					modsName.appendChild(namePart);
+	   				}
+	   				Element role = d.createElement("role");
+	   				Element roleTerm = d.createElement("roleTerm");
+	   				roleTerm.setAttribute("type", "text");
+	   				roleTerm.appendChild(d.createTextNode("author"));
+	   				role.appendChild(roleTerm);
+	   				modsName.appendChild(role);
+	   				mods.appendChild(modsName);
+	   			}
+	   		}
+	   		//publisher
+	   		Element originInfo = d.createElement("originInfo");
+	   		mods.appendChild(originInfo);
+	   		if (this.publisher != null) {
+	   			Element publisher = d.createElement("publisher");
+				publisher.appendChild(d.createTextNode(this.publisher));
+	   			originInfo.appendChild(publisher);
+	   		}
+	   		if (date != null) {
+	   			Element dateIssued = d.createElement("dateIssued");
+	   			dateIssued.appendChild(d.createTextNode(date));
+	   			originInfo.appendChild(dateIssued);
+	   		}
+	   		Element issuance = d.createElement("issuance");
+	   		issuance.appendChild(d.createTextNode(this.issuance));
+	   		originInfo.appendChild(issuance);
+	   		
+	   		if (id != null) {
+	   			Element idref = d.createElement("identifier");
+	   			idref.appendChild(d.createTextNode(id));
+	   			mods.appendChild(idref);
+	   			mods.setAttribute("ID", id);
+		   		
+	   		}
+	   		Element typeOfResource = d.createElement("typeOfResource");
+	   		typeOfResource.appendChild(d.createTextNode(type));
+	   		mods.appendChild(typeOfResource);
+	   		
+	   		if (genre != null) {
+	   			Element genreElement = d.createElement("genre");
+	   			genreElement.setAttribute("authority", "marc");
+	   			genreElement.appendChild(d.createTextNode(genre));
+	   			mods.appendChild(genreElement);
+	   		}
+	   		
+	   		if (host != null) {
+	   			Element relatedItem = host.getDOMrepresentation(d);	   			
+	   			relatedItem.setAttribute("type","host");	   			
+	   			mods.appendChild(relatedItem);
+	   		}
+	   		if (pages != null) {
+	   			mods.appendChild(pages.getDOMrepresentation(d));
+	   		}
+	   		
+	   		/* now generate extension fields for unhandled data */
+	   		for(Iterator iter = extensionFields.entrySet().iterator(); iter.hasNext(); ) {
+	   			Element extension = d.createElement("extension");
+	   			Map.Entry theEntry = (Map.Entry) iter.next();
+	   			String field = (String) theEntry.getKey();
+	   			String value = (String) theEntry.getValue();
+	   			if (handledExtensions.contains(field))
+	   				continue;
+	   			Element theData = d.createElement(field);
+	   			theData.appendChild(d.createTextNode(value));
+	   			extension.appendChild(theData);
+	   			mods.appendChild(extension);
+	   		}
+	   		return mods;
+	   	}
+	   	catch (Exception e)
+		{
+	   		System.out.println("Exception caught..." + e);
+	   		e.printStackTrace();
+	   		throw new Error(e);
+		}
+	   	// return result;
+	   }
+	
+	/*
+	 * render as XML
+	 */
+	public String toString() {
+		StringWriter sresult = new StringWriter();
+	   	try {
+	      	 DOMSource source = new DOMSource(getDOMrepresentation());
+	      	 StreamResult result = new StreamResult(sresult);
+	      	 Transformer trans = TransformerFactory.newInstance().newTransformer();
+	      	 trans.setOutputProperty(OutputKeys.INDENT, "yes");
+	      	 trans.transform(source, result);
+	      	}
+	      	catch (Exception e) {
+	      		throw new Error(e);
+	      	}
+	      return sresult.toString();
+	}
+
+}
diff --git a/src/java/net/sf/jabref/mods/PageNumbers.java b/src/java/net/sf/jabref/mods/PageNumbers.java
new file mode 100644
index 0000000..1100932
--- /dev/null
+++ b/src/java/net/sf/jabref/mods/PageNumbers.java
@@ -0,0 +1,61 @@
+/*
+ * Created on Oct 29, 2004
+ *
+ * TODO To change the template for this generated file go to
+ * Window - Preferences - Java - Code Style - Code Templates
+ */
+package net.sf.jabref.mods;
+import net.sf.jabref.export.layout.format.*;
+import net.sf.jabref.export.layout.*;
+
+import javax.xml.parsers.*;
+import javax.xml.transform.*;
+import javax.xml.transform.dom.*;
+import javax.xml.transform.stream.*;
+import org.w3c.dom.*;
+import java.util.*;
+import java.io.*;
+import java.util.regex.*;
+/**
+ * @author Michael Wrighton
+ *
+ * TODO To change the template for this generated type comment go to
+ * Window - Preferences - Java - Code Style - Code Templates
+ */
+public class PageNumbers {
+	String freeform;
+	int start, end;
+	
+	public PageNumbers(String s) {
+		parsePageNums(s);
+	}
+	
+	protected void parsePageNums(String s) {
+		Pattern p = Pattern.compile("(\\d+)--(\\d+)");
+		Matcher m = p.matcher(s);
+		if (m.matches()) {
+			start = Integer.parseInt(m.group(1));
+			end = Integer.parseInt(m.group(2));
+		}
+		else
+			freeform = s;
+	}
+	
+	public Element getDOMrepresentation(Document d) {
+		Element result = d.createElement("extent");
+		result.setAttribute("unit","page");
+		if (freeform != null) { 
+			Node t = d.createTextNode(freeform);
+			result.appendChild(t);
+		}
+		else {
+			Element start = d.createElement("start");
+			Element end = d.createElement("end");
+			start.appendChild(d.createTextNode("" + this.start));
+			end.appendChild(d.createTextNode("" + this.end));
+			result.appendChild(start);
+			result.appendChild(end);			
+		}
+		return result;
+	}
+}
diff --git a/src/java/net/sf/jabref/mods/PersonName.java b/src/java/net/sf/jabref/mods/PersonName.java
new file mode 100644
index 0000000..5758b4c
--- /dev/null
+++ b/src/java/net/sf/jabref/mods/PersonName.java
@@ -0,0 +1,67 @@
+/*
+ * Created on Oct 25, 2004
+ *
+ * TODO To change the template for this generated file go to
+ * Window - Preferences - Java - Code Style - Code Templates
+ */
+package net.sf.jabref.mods;
+
+import java.util.Vector;
+import wsi.ra.tool.WSITools;
+
+
+import net.sf.jabref.AuthorList;
+
+/**
+ * @author Michael Wrighton
+ *
+ * TODO To change the template for this generated type comment go to
+ * Window - Preferences - Java - Code Style - Code Templates
+ */
+public class PersonName {
+    protected String givenName = null;
+    protected String surname = null;
+    protected String middleName = null;
+
+    public PersonName(String name) {
+        parseName(name);
+    }
+
+    protected void parseName(String author) {
+            // TODO: replace special characters
+            Vector v = new Vector();
+            String authorMod = AuthorList.fixAuthor_firstNameFirst(author);
+
+            WSITools.tokenize(v, authorMod, " \n\r");
+
+            if (v.size() == 1)
+                surname = (String) v.get(0);
+            else if (v.size() == 2) {
+                givenName = (String) v.get(0);
+                surname = (String) v.get(1);
+            }
+            else {
+                givenName = (String) v.get(0);
+                middleName = (String) v.get(1);
+                surname = (String) v.get(2);
+            }
+    }
+
+    public String getGivenNames() {
+        String result = "";
+        if (givenName != null)
+            result += givenName;
+        if (middleName != null)
+            result += " " + middleName;
+        return result;
+    }
+
+    public String getSurname()
+    {
+        return surname;
+    }
+
+    public String toString() {
+        return surname;
+    }
+}
diff --git a/src/java/net/sf/jabref/net/URLDownload.java b/src/java/net/sf/jabref/net/URLDownload.java
new file mode 100644
index 0000000..7140f3a
--- /dev/null
+++ b/src/java/net/sf/jabref/net/URLDownload.java
@@ -0,0 +1,75 @@
+/*
+ * Created on 1-Dec-2004
+ *
+ */
+package net.sf.jabref.net;
+
+import java.awt.Component;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.URL;
+
+import javax.swing.ProgressMonitorInputStream;
+
+/**
+ * @author Erik Putrycz erik.putrycz-at-nrc-cnrc.gc.ca
+ */
+
+public class URLDownload {  
+    
+    private URL source;
+    private File dest;
+    private Component parent;
+
+    public URLDownload(Component _parent, URL _source, File _dest) {
+        source = _source;
+        dest = _dest;
+        parent = _parent;
+    }
+    
+    public void download() throws IOException {
+        InputStream input = source.openStream();
+        FileOutputStream output =  new FileOutputStream(dest);
+     
+        try
+          {
+            copy(input, output);
+          }
+        catch (IOException e)
+          {
+            e.printStackTrace();
+          }
+        finally
+          {
+            try
+              {
+                input.close();
+                output.close();
+              }
+            catch (Exception e)
+              {
+              }
+          }        
+    }
+
+    public void copy(InputStream in, OutputStream out) throws IOException
+      {
+        ProgressMonitorInputStream _in = new ProgressMonitorInputStream(parent, "Downloading " + source.toString(), in);
+        byte[] buffer = new byte[256];
+        synchronized(in)
+          {
+            synchronized(out)
+              {
+                while(true)
+                  {
+                    int bytesRead = _in.read(buffer);
+                    if(bytesRead == -1) break;
+                    out.write(buffer, 0, bytesRead);
+                  }
+              }
+          }
+      }    
+}
diff --git a/src/java/net/sf/jabref/remote/RemoteListener.java b/src/java/net/sf/jabref/remote/RemoteListener.java
new file mode 100644
index 0000000..59b354e
--- /dev/null
+++ b/src/java/net/sf/jabref/remote/RemoteListener.java
@@ -0,0 +1,196 @@
+package net.sf.jabref.remote;
+
+import net.sf.jabref.JabRef;
+import net.sf.jabref.BasePanel;
+import net.sf.jabref.Globals;
+import net.sf.jabref.gui.ImportInspectionDialog;
+import net.sf.jabref.imports.ParserResult;
+
+import java.net.*;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.InputStream;
+import java.util.Vector;
+import java.util.List;
+import java.util.ArrayList;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: alver
+ * Date: Aug 14, 2005
+ * Time: 8:11:58 PM
+ * To change this template use File | Settings | File Templates.
+ */
+public class RemoteListener extends Thread implements ImportInspectionDialog.CallBack {
+
+    private JabRef jabref;
+    private ServerSocket socket;
+    private boolean active = true, toStop = false;
+    private static final String IDENTIFIER = "jabref";
+
+    public RemoteListener(JabRef jabref, ServerSocket socket) {
+        this.jabref = jabref;
+        this.socket = socket;
+    }
+
+    public void disable() {
+        toStop = true;
+        try {
+            socket.close();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+
+    public void run() {
+        while (active) {
+            try {
+                Socket newSocket = socket.accept();
+
+                newSocket.setSoTimeout(1000);
+
+                if (toStop) {
+                    active = false;
+                    return;
+                }
+                //byte[] address = socket.getInetAddress().getAddress();
+                //System.out.println("Connection: "+address[0]+" "+address[1]+" "+address[2]+" "+address[3]);
+
+                OutputStream out = newSocket.getOutputStream();
+                InputStream in = newSocket.getInputStream();
+                out.write(IDENTIFIER.getBytes());
+                out.write('\0');
+                out.flush();
+
+                int c;
+                StringBuffer sb = new StringBuffer();
+                try {
+                    while (((c = in.read()) != '\0') && (c >= 0)) {
+                        sb.append((char)c);
+                    }
+                    if (sb.length() == 0) {
+                        continue;
+                    }
+                    String[] args = sb.toString().split("\n");
+                    Vector loaded = jabref.processArguments(args, false);
+
+                    for (int i=0; i<loaded.size(); i++) {
+                        ParserResult pr = (ParserResult) loaded.elementAt(i);
+                        if (!pr.toOpenTab()) {
+                            jabref.jrf.addTab(pr.getDatabase(), pr.getFile(), pr.getMetaData(), pr.getEncoding(), (i == 0));
+                        } else {
+                            // Add the entries to the open tab.
+                            BasePanel panel = jabref.jrf.basePanel();
+                            if (panel == null) {
+                                // There is no open tab to add to, so we create a new tab:
+                                jabref.jrf.addTab(pr.getDatabase(), pr.getFile(), pr.getMetaData(), pr.getEncoding(), (i == 0));
+                            } else {
+                                List entries = new ArrayList(pr.getDatabase().getEntries());
+                                jabref.jrf.addImportedEntries(panel, entries, "", false, this);
+                            }
+                        }
+                    }
+                    in.close();
+                    out.close();
+                    newSocket.close();
+
+                } catch (SocketTimeoutException ex) {
+                    //System.out.println("timeout");
+                    in.close();
+                    out.close();
+                    newSocket.close();
+                }
+
+
+
+            } catch (SocketException ex) {
+                active = false;
+                //ex.printStackTrace();
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+    }
+
+    public static RemoteListener openRemoteListener(JabRef jabref) {
+        try {
+            ServerSocket socket = new ServerSocket(Globals.prefs.getInt("remoteServerPort"), 1,
+                    InetAddress.getByAddress(new byte[] {127, 0, 0, 1}));
+            RemoteListener listener = new RemoteListener(jabref, socket);
+            return listener;
+        } catch (IOException e) {
+            if (!e.getMessage().startsWith("Address already in use"))
+                e.printStackTrace();
+            return null;
+
+        }
+
+    }
+
+    /**
+     * Attempt to send command line arguments to already running JabRef instance.
+     * @param args Command line arguments.
+     * @return true if successful, false otherwise.
+     */
+    public static boolean sendToActiveJabRefInstance(String[] args) {
+        try {
+            InetAddress local = InetAddress.getByName("localhost");
+            Socket socket = new Socket(local, Globals.prefs.getInt("remoteServerPort"));
+            socket.setSoTimeout(2000);
+
+            InputStream in = socket.getInputStream();
+            OutputStream out = socket.getOutputStream();
+            int c;
+            StringBuffer sb = new StringBuffer();
+            try {
+                while (((c = in.read()) != '\0') && (c >= 0)) {
+                    sb.append((char)c);
+                }
+            } catch (SocketTimeoutException ex) {
+                 System.out.println("Connection timed out.");
+            }
+
+            if (!IDENTIFIER.equals(sb.toString())) {
+                String error = Globals.lang("Cannot use port %0 for remote operation; another "
+                    +"application may be using it. Try specifying another port.",
+                        new String[] {String.valueOf(Globals.prefs.getInt("remoteServerPort"))});
+                System.out.println(error);
+                return false;
+            }
+
+            for (int i=0; i<args.length; i++) {
+                byte[] bytes = args[i].getBytes();
+                out.write(bytes);
+                out.write('\n');
+            }
+            out.write('\0');
+            out.flush();
+            in.close();
+            out.close();
+            socket.close();
+            return true;
+        } catch (Exception e) {
+            e.printStackTrace();
+            return false;
+        }
+    }
+
+    // This method is called by the dialog when the user has selected the
+// wanted entries, and clicked Ok. The callback object can update status
+// line etc.
+    public void done(int entriesImported) {
+        jabref.jrf.output(Globals.lang("Imported entries"));
+    }
+
+    // This method is called by the dialog when the user has cancelled the import.
+    public void cancelled() {
+
+    }
+
+    // This method is called by the dialog when the user has cancelled or
+// signalled a stop. It is expected that any long-running fetch operations
+// will stop after this method is called.
+    public void stopFetching() {
+
+    }
+}
diff --git a/src/java/net/sf/jabref/search/HitOrMissComparator.java b/src/java/net/sf/jabref/search/HitOrMissComparator.java
new file mode 100644
index 0000000..2ba25dd
--- /dev/null
+++ b/src/java/net/sf/jabref/search/HitOrMissComparator.java
@@ -0,0 +1,29 @@
+package net.sf.jabref.search;
+
+import java.util.Comparator;
+import ca.odell.glazedlists.matchers.Matcher;
+
+/**
+ * This Comparator compares two objects based on whether none, one of them, or both
+ * match a given Matcher. It is used to "float" group and search hits in the main table.
+ */
+public class HitOrMissComparator implements Comparator {
+    private Matcher hitOrMiss;
+
+    public HitOrMissComparator(Matcher hitOrMiss) {
+        this.hitOrMiss = hitOrMiss;
+    }
+
+    public int compare(Object o1, Object o2) {
+        if (hitOrMiss == null)
+            return 0;
+        
+        boolean
+                hit1 = hitOrMiss.matches(o1),
+                hit2 = hitOrMiss.matches(o2);
+        if (hit1 == hit2)
+            return 0;
+        else
+            return hit1 ? -1 : 1;
+    }
+}
diff --git a/src/java/net/sf/jabref/search/Lexer.g b/src/java/net/sf/jabref/search/Lexer.g
new file mode 100644
index 0000000..f2786c0
--- /dev/null
+++ b/src/java/net/sf/jabref/search/Lexer.g
@@ -0,0 +1,65 @@
+header {
+package net.sf.jabref.search;
+}
+
+class SearchExpressionLexer extends Lexer;
+
+options {
+	k = 2;
+	exportVocab = SearchExpressionLexer;
+	caseSensitive = false;
+	caseSensitiveLiterals = false;
+	charVocabulary = '\3'..'\377'; // 8 bit
+	testLiterals = false;
+}
+
+tokens {
+	"and";
+	"or";
+	"not";
+	"contains";
+	"matches";
+
+}
+
+
+
+WS options { paraphrase = "white space"; }
+	:	(' '
+	|
+	'\t'
+	)
+		{ $setType(Token.SKIP); }
+	;
+
+LPAREN options { paraphrase = "'('"; }
+	:	'('
+	;
+
+RPAREN options { paraphrase = "')'"; }
+	:	')'
+	;
+
+EQUAL options { paraphrase = "'='"; }
+	:	"=";
+
+EEQUAL options { paraphrase = "'=='"; }
+	:	"==";
+
+NEQUAL options { paraphrase = "'!='"; }
+	:	"!=";
+
+QUOTE options { paraphrase = "'\"'"; }
+	:	'"';
+
+STRING options { paraphrase = "a text literal"; }
+	:	QUOTE! (~'"')* QUOTE!;
+
+protected
+LETTER options { paraphrase = "a letter"; testLiterals = true; }
+	: ~(' ' | '\t' | '"' | '(' | ')' | '=' | '!'); //'a'..'z';
+
+FIELDTYPE options { paraphrase = "a field type"; testLiterals = true; }
+	:	( LETTER )+
+	;
+
diff --git a/src/java/net/sf/jabref/search/NoSearchMatcher.java b/src/java/net/sf/jabref/search/NoSearchMatcher.java
new file mode 100644
index 0000000..24d2e50
--- /dev/null
+++ b/src/java/net/sf/jabref/search/NoSearchMatcher.java
@@ -0,0 +1,18 @@
+package net.sf.jabref.search;
+
+import ca.odell.glazedlists.matchers.Matcher;
+
+/**
+ * Matcher that accepts all entries. Used for filtering when so search is active.
+ */
+public class NoSearchMatcher implements Matcher {
+    public static final Matcher INSTANCE = new NoSearchMatcher();
+
+    private NoSearchMatcher() {
+        
+    }
+
+    public boolean matches(Object object) {
+        return true;
+    }
+}
diff --git a/src/java/net/sf/jabref/search/Parser.g b/src/java/net/sf/jabref/search/Parser.g
new file mode 100644
index 0000000..e5d9635
--- /dev/null
+++ b/src/java/net/sf/jabref/search/Parser.g
@@ -0,0 +1,103 @@
+header {
+package net.sf.jabref.search;
+import java.io.StringReader;
+}
+
+class SearchExpressionParser extends Parser;
+
+options {
+	importVocab = SearchExpressionLexer; // use vocab generated by lexer
+	exportVocab = SearchExpressionParser;
+	defaultErrorHandler = false;
+	buildAST = true;
+	k = 3;
+}
+
+tokens {
+	RegularExpression;
+	And;
+	Or;
+	Not;
+	ExpressionSearch;
+}
+
+// ---------- Java Source Code ----------
+
+{
+	public boolean caseSensitive = false;
+    public boolean regex = true;
+	/** Creates a parser and lexer instance and tests the specified String.
+	  * Returns the AST if s is in valid syntax for advanced field search, null otherwise. */
+	public static AST checkSyntax(String s, boolean caseSensitive, boolean regex) {
+		// Is there some way to prevent instance creation here?
+		// How can a parser and/or lexer be reused?
+		SearchExpressionParser parser = new SearchExpressionParser(new SearchExpressionLexer(
+				new StringReader(s)));
+		parser.caseSensitive = caseSensitive;
+		parser.regex = regex;
+		try {
+			parser.searchExpression();
+			return parser.getAST();
+		} catch (Exception e) {
+			return null;
+		}
+	}
+}
+
+// ---------- Text and Regular Expressions ----------
+
+quotedRegularExpression[boolean caseSensitive, boolean regex]:
+		var_s:STRING
+			{
+				## = astFactory.make((new ASTArray(2)).add(new RegExNode(RegularExpression,var_s.getText(),caseSensitive,regex)).add(##));
+			}
+		;
+
+simpleRegularExpression[boolean caseSensitive, boolean regex]:
+		var_s:FIELDTYPE
+			{
+				## = astFactory.make((new ASTArray(2)).add(new RegExNode(RegularExpression,var_s.getText(),caseSensitive,regex)).add(##));
+			}
+		;
+
+// ---------- Condition and Expressions ----------
+
+searchExpression:
+	condition EOF;
+
+condition:
+		(expression LITERAL_and condition) => expression LITERAL_and! condition { ## = #( [And], ##); }
+		|
+		(expression LITERAL_or condition) => expression LITERAL_or! condition { ## = #( [Or], ##); }
+		|
+		expression // negation is done in expression
+		;
+
+expression:
+		expressionSearch
+		|
+		LPAREN! condition RPAREN!
+		|
+		LITERAL_not! expressionSearch { ## = #( [Not], ## ); }         // NOT single expression
+		|
+		LITERAL_not! LPAREN! condition RPAREN! { ## = #( [Not], ## ); } // NOT ( ... )
+		;
+
+expressionSearch:
+		quotedRegularExpression[false,true] compareType quotedRegularExpression[caseSensitive,regex]
+			{ ## = #( [ExpressionSearch], ## ); }
+		|
+		simpleRegularExpression[false,true] compareType quotedRegularExpression[caseSensitive,regex]
+			{ ## = #( [ExpressionSearch], ## ); }
+		|
+		simpleRegularExpression[false,true] compareType simpleRegularExpression[caseSensitive,regex]
+			{ ## = #( [ExpressionSearch], ## ); }
+		|
+		quotedRegularExpression[false,true] compareType simpleRegularExpression[caseSensitive,regex]
+			{ ## = #( [ExpressionSearch], ## ); }
+		;
+
+compareType:
+		LITERAL_contains | LITERAL_matches | EQUAL | EEQUAL | NEQUAL
+		;
+
diff --git a/src/java/net/sf/jabref/search/RegExNode.java b/src/java/net/sf/jabref/search/RegExNode.java
new file mode 100644
index 0000000..8216100
--- /dev/null
+++ b/src/java/net/sf/jabref/search/RegExNode.java
@@ -0,0 +1,24 @@
+/**
+ * RegExNode.java
+ *
+ * @author Created by Omnicore CodeGuide
+ */
+
+package net.sf.jabref.search;
+
+import antlr.CommonAST;
+import java.util.regex.Pattern;
+
+public class RegExNode extends CommonAST {
+	private Pattern pattern = null;
+	public RegExNode(int tokenType, String text, boolean caseSensitive, boolean regex) {
+		initialize(tokenType,text);
+		pattern = Pattern.compile(
+			regex ? text : "\\Q" + text + "\\E", // quote if !regex
+			caseSensitive ? 0 : Pattern.CASE_INSENSITIVE);
+	}
+	public Pattern getPattern() {
+		return pattern;
+	}
+}
+
diff --git a/src/java/net/sf/jabref/search/SearchExpression.java b/src/java/net/sf/jabref/search/SearchExpression.java
new file mode 100644
index 0000000..2978290
--- /dev/null
+++ b/src/java/net/sf/jabref/search/SearchExpression.java
@@ -0,0 +1,44 @@
+/**
+ * SearchExpression.java
+ *
+ * @author Created by Omnicore CodeGuide
+ */
+
+package net.sf.jabref.search;
+
+import antlr.RecognitionException;
+import antlr.TokenStreamException;
+import antlr.collections.AST;
+import java.io.StringReader;
+import java.util.*;
+import java.util.Hashtable;
+import java.util.regex.PatternSyntaxException;
+import net.sf.jabref.BibtexEntry;
+import net.sf.jabref.JabRefPreferences;
+import net.sf.jabref.SearchRule;
+
+public class SearchExpression implements SearchRule {
+	private SearchExpressionTreeParser treeParser = new SearchExpressionTreeParser();
+	private AST ast = null;
+	private JabRefPreferences prefs = null;
+	public SearchExpression(JabRefPreferences prefs, Hashtable searchOptions)
+		throws TokenStreamException, RecognitionException, PatternSyntaxException
+	{
+		this.prefs = prefs;
+		// parse search expression
+		SearchExpressionParser parser = new SearchExpressionParser(new SearchExpressionLexer(new StringReader(
+			searchOptions.elements().nextElement().toString()))); // supports only single entry
+		parser.caseSensitive = this.prefs.getBoolean("caseSensitiveSearch");
+		parser.regex = this.prefs.getBoolean("regExpSearch");
+		parser.searchExpression(); // this is the "global" rule
+		ast = parser.getAST(); // remember abstract syntax tree
+	}
+	public int applyRule(Map searchStrings, BibtexEntry bibtexEntry) {
+		try {
+			return treeParser.apply(ast,bibtexEntry);
+		} catch (RecognitionException e) {
+			return 0; // this should never occur
+		} //catch (NullPointerException ex) { return 0; } // Just testing (Morten)
+	}
+}
+
diff --git a/src/java/net/sf/jabref/search/SearchExpressionLexer.java b/src/java/net/sf/jabref/search/SearchExpressionLexer.java
new file mode 100644
index 0000000..e297535
--- /dev/null
+++ b/src/java/net/sf/jabref/search/SearchExpressionLexer.java
@@ -0,0 +1,330 @@
+// $ANTLR : "Lexer.g" -> "SearchExpressionLexer.java"$
+
+package net.sf.jabref.search;
+
+import java.io.InputStream;
+import antlr.TokenStreamException;
+import antlr.TokenStreamIOException;
+import antlr.TokenStreamRecognitionException;
+import antlr.CharStreamException;
+import antlr.CharStreamIOException;
+import antlr.ANTLRException;
+import java.io.Reader;
+import java.util.Hashtable;
+import antlr.CharScanner;
+import antlr.InputBuffer;
+import antlr.ByteBuffer;
+import antlr.CharBuffer;
+import antlr.Token;
+import antlr.CommonToken;
+import antlr.RecognitionException;
+import antlr.NoViableAltForCharException;
+import antlr.MismatchedCharException;
+import antlr.TokenStream;
+import antlr.ANTLRHashString;
+import antlr.LexerSharedInputState;
+import antlr.collections.impl.BitSet;
+import antlr.SemanticException;
+
+public class SearchExpressionLexer extends antlr.CharScanner implements SearchExpressionLexerTokenTypes, TokenStream
+ {
+public SearchExpressionLexer(InputStream in) {
+	this(new ByteBuffer(in));
+}
+public SearchExpressionLexer(Reader in) {
+	this(new CharBuffer(in));
+}
+public SearchExpressionLexer(InputBuffer ib) {
+	this(new LexerSharedInputState(ib));
+}
+public SearchExpressionLexer(LexerSharedInputState state) {
+	super(state);
+	caseSensitiveLiterals = false;
+	setCaseSensitive(false);
+	literals = new Hashtable();
+	literals.put(new ANTLRHashString("matches", this), new Integer(8));
+	literals.put(new ANTLRHashString("or", this), new Integer(5));
+	literals.put(new ANTLRHashString("and", this), new Integer(4));
+	literals.put(new ANTLRHashString("not", this), new Integer(6));
+	literals.put(new ANTLRHashString("contains", this), new Integer(7));
+}
+
+public Token nextToken() throws TokenStreamException {
+	Token theRetToken=null;
+tryAgain:
+	for (;;) {
+		Token _token = null;
+		int _ttype = Token.INVALID_TYPE;
+		resetText();
+		try {   // for char stream error handling
+			try {   // for lexical error handling
+				switch ( LA(1)) {
+				case '\t':  case ' ':
+				{
+					mWS(true);
+					theRetToken=_returnToken;
+					break;
+				}
+				case '(':
+				{
+					mLPAREN(true);
+					theRetToken=_returnToken;
+					break;
+				}
+				case ')':
+				{
+					mRPAREN(true);
+					theRetToken=_returnToken;
+					break;
+				}
+				case '!':
+				{
+					mNEQUAL(true);
+					theRetToken=_returnToken;
+					break;
+				}
+				default:
+					if ((LA(1)=='=') && (LA(2)=='=')) {
+						mEEQUAL(true);
+						theRetToken=_returnToken;
+					}
+					else if ((LA(1)=='"') && ((LA(2) >= '\u0003' && LA(2) <= '\u00ff'))) {
+						mSTRING(true);
+						theRetToken=_returnToken;
+					}
+					else if ((LA(1)=='=') && (true)) {
+						mEQUAL(true);
+						theRetToken=_returnToken;
+					}
+					else if ((LA(1)=='"') && (true)) {
+						mQUOTE(true);
+						theRetToken=_returnToken;
+					}
+					else if ((_tokenSet_0.member(LA(1)))) {
+						mFIELDTYPE(true);
+						theRetToken=_returnToken;
+					}
+				else {
+					if (LA(1)==EOF_CHAR) {uponEOF(); _returnToken = makeToken(Token.EOF_TYPE);}
+				else {throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());}
+				}
+				}
+				if ( _returnToken==null ) continue tryAgain; // found SKIP token
+				_ttype = _returnToken.getType();
+				_returnToken.setType(_ttype);
+				return _returnToken;
+			}
+			catch (RecognitionException e) {
+				throw new TokenStreamRecognitionException(e);
+			}
+		}
+		catch (CharStreamException cse) {
+			if ( cse instanceof CharStreamIOException ) {
+				throw new TokenStreamIOException(((CharStreamIOException)cse).io);
+			}
+			else {
+				throw new TokenStreamException(cse.getMessage());
+			}
+		}
+	}
+}
+
+	public final void mWS(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException {
+		int _ttype; Token _token=null; int _begin=text.length();
+		_ttype = WS;
+		int _saveIndex;
+		
+		{
+		switch ( LA(1)) {
+		case ' ':
+		{
+			match(' ');
+			break;
+		}
+		case '\t':
+		{
+			match('\t');
+			break;
+		}
+		default:
+		{
+			throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());
+		}
+		}
+		}
+		_ttype = Token.SKIP;
+		if ( _createToken && _token==null && _ttype!=Token.SKIP ) {
+			_token = makeToken(_ttype);
+			_token.setText(new String(text.getBuffer(), _begin, text.length()-_begin));
+		}
+		_returnToken = _token;
+	}
+	
+	public final void mLPAREN(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException {
+		int _ttype; Token _token=null; int _begin=text.length();
+		_ttype = LPAREN;
+		int _saveIndex;
+		
+		match('(');
+		if ( _createToken && _token==null && _ttype!=Token.SKIP ) {
+			_token = makeToken(_ttype);
+			_token.setText(new String(text.getBuffer(), _begin, text.length()-_begin));
+		}
+		_returnToken = _token;
+	}
+	
+	public final void mRPAREN(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException {
+		int _ttype; Token _token=null; int _begin=text.length();
+		_ttype = RPAREN;
+		int _saveIndex;
+		
+		match(')');
+		if ( _createToken && _token==null && _ttype!=Token.SKIP ) {
+			_token = makeToken(_ttype);
+			_token.setText(new String(text.getBuffer(), _begin, text.length()-_begin));
+		}
+		_returnToken = _token;
+	}
+	
+	public final void mEQUAL(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException {
+		int _ttype; Token _token=null; int _begin=text.length();
+		_ttype = EQUAL;
+		int _saveIndex;
+		
+		match("=");
+		if ( _createToken && _token==null && _ttype!=Token.SKIP ) {
+			_token = makeToken(_ttype);
+			_token.setText(new String(text.getBuffer(), _begin, text.length()-_begin));
+		}
+		_returnToken = _token;
+	}
+	
+	public final void mEEQUAL(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException {
+		int _ttype; Token _token=null; int _begin=text.length();
+		_ttype = EEQUAL;
+		int _saveIndex;
+		
+		match("==");
+		if ( _createToken && _token==null && _ttype!=Token.SKIP ) {
+			_token = makeToken(_ttype);
+			_token.setText(new String(text.getBuffer(), _begin, text.length()-_begin));
+		}
+		_returnToken = _token;
+	}
+	
+	public final void mNEQUAL(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException {
+		int _ttype; Token _token=null; int _begin=text.length();
+		_ttype = NEQUAL;
+		int _saveIndex;
+		
+		match("!=");
+		if ( _createToken && _token==null && _ttype!=Token.SKIP ) {
+			_token = makeToken(_ttype);
+			_token.setText(new String(text.getBuffer(), _begin, text.length()-_begin));
+		}
+		_returnToken = _token;
+	}
+	
+	public final void mQUOTE(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException {
+		int _ttype; Token _token=null; int _begin=text.length();
+		_ttype = QUOTE;
+		int _saveIndex;
+		
+		match('"');
+		if ( _createToken && _token==null && _ttype!=Token.SKIP ) {
+			_token = makeToken(_ttype);
+			_token.setText(new String(text.getBuffer(), _begin, text.length()-_begin));
+		}
+		_returnToken = _token;
+	}
+	
+	public final void mSTRING(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException {
+		int _ttype; Token _token=null; int _begin=text.length();
+		_ttype = STRING;
+		int _saveIndex;
+		
+		_saveIndex=text.length();
+		mQUOTE(false);
+		text.setLength(_saveIndex);
+		{
+		_loop28:
+		do {
+			if ((_tokenSet_1.member(LA(1)))) {
+				matchNot('"');
+			}
+			else {
+				break _loop28;
+			}
+			
+		} while (true);
+		}
+		_saveIndex=text.length();
+		mQUOTE(false);
+		text.setLength(_saveIndex);
+		if ( _createToken && _token==null && _ttype!=Token.SKIP ) {
+			_token = makeToken(_ttype);
+			_token.setText(new String(text.getBuffer(), _begin, text.length()-_begin));
+		}
+		_returnToken = _token;
+	}
+	
+	protected final void mLETTER(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException {
+		int _ttype; Token _token=null; int _begin=text.length();
+		_ttype = LETTER;
+		int _saveIndex;
+		
+		{
+		match(_tokenSet_0);
+		}
+		_ttype = testLiteralsTable(new String(text.getBuffer(),_begin,text.length()-_begin),_ttype);
+		if ( _createToken && _token==null && _ttype!=Token.SKIP ) {
+			_token = makeToken(_ttype);
+			_token.setText(new String(text.getBuffer(), _begin, text.length()-_begin));
+		}
+		_returnToken = _token;
+	}
+	
+	public final void mFIELDTYPE(boolean _createToken) throws RecognitionException, CharStreamException, TokenStreamException {
+		int _ttype; Token _token=null; int _begin=text.length();
+		_ttype = FIELDTYPE;
+		int _saveIndex;
+		
+		{
+		int _cnt33=0;
+		_loop33:
+		do {
+			if ((_tokenSet_0.member(LA(1)))) {
+				mLETTER(false);
+			}
+			else {
+				if ( _cnt33>=1 ) { break _loop33; } else {throw new NoViableAltForCharException((char)LA(1), getFilename(), getLine(), getColumn());}
+			}
+			
+			_cnt33++;
+		} while (true);
+		}
+		_ttype = testLiteralsTable(_ttype);
+		if ( _createToken && _token==null && _ttype!=Token.SKIP ) {
+			_token = makeToken(_ttype);
+			_token.setText(new String(text.getBuffer(), _begin, text.length()-_begin));
+		}
+		_returnToken = _token;
+	}
+	
+	
+	private static final long[] mk_tokenSet_0() {
+		long[] data = new long[8];
+		data[0]=-2305846337813348872L;
+		for (int i = 1; i<=3; i++) { data[i]=-1L; }
+		return data;
+	}
+	public static final BitSet _tokenSet_0 = new BitSet(mk_tokenSet_0());
+	private static final long[] mk_tokenSet_1() {
+		long[] data = new long[8];
+		data[0]=-17179869192L;
+		for (int i = 1; i<=3; i++) { data[i]=-1L; }
+		return data;
+	}
+	public static final BitSet _tokenSet_1 = new BitSet(mk_tokenSet_1());
+	
+	}
diff --git a/src/java/net/sf/jabref/search/SearchExpressionLexerTokenTypes.java b/src/java/net/sf/jabref/search/SearchExpressionLexerTokenTypes.java
new file mode 100644
index 0000000..f573c16
--- /dev/null
+++ b/src/java/net/sf/jabref/search/SearchExpressionLexerTokenTypes.java
@@ -0,0 +1,23 @@
+// $ANTLR : "Lexer.g" -> "SearchExpressionLexer.java"$
+
+package net.sf.jabref.search;
+
+public interface SearchExpressionLexerTokenTypes {
+	int EOF = 1;
+	int NULL_TREE_LOOKAHEAD = 3;
+	int LITERAL_and = 4;
+	int LITERAL_or = 5;
+	int LITERAL_not = 6;
+	int LITERAL_contains = 7;
+	int LITERAL_matches = 8;
+	int WS = 9;
+	int LPAREN = 10;
+	int RPAREN = 11;
+	int EQUAL = 12;
+	int EEQUAL = 13;
+	int NEQUAL = 14;
+	int QUOTE = 15;
+	int STRING = 16;
+	int LETTER = 17;
+	int FIELDTYPE = 18;
+}
diff --git a/src/java/net/sf/jabref/search/SearchExpressionParser.java b/src/java/net/sf/jabref/search/SearchExpressionParser.java
new file mode 100644
index 0000000..a48b9a2
--- /dev/null
+++ b/src/java/net/sf/jabref/search/SearchExpressionParser.java
@@ -0,0 +1,486 @@
+// $ANTLR : "Parser.g" -> "SearchExpressionParser.java"$
+
+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.NoViableAltException;
+import antlr.MismatchedTokenException;
+import antlr.SemanticException;
+import antlr.ParserSharedInputState;
+import antlr.collections.impl.BitSet;
+import antlr.collections.AST;
+import java.util.Hashtable;
+import antlr.ASTFactory;
+import antlr.ASTPair;
+import antlr.collections.impl.ASTArray;
+
+public class SearchExpressionParser extends antlr.LLkParser       implements SearchExpressionParserTokenTypes
+ {
+
+	public boolean caseSensitive = false;
+    public boolean regex = true;
+	/** Creates a parser and lexer instance and tests the specified String.
+	  * Returns the AST if s is in valid syntax for advanced field search, null otherwise. */
+	public static AST checkSyntax(String s, boolean caseSensitive, boolean regex) {
+		// Is there some way to prevent instance creation here?
+		// How can a parser and/or lexer be reused?
+		SearchExpressionParser parser = new SearchExpressionParser(new SearchExpressionLexer(
+				new StringReader(s)));
+		parser.caseSensitive = caseSensitive;
+		parser.regex = regex;
+		try {
+			parser.searchExpression();
+			return parser.getAST();
+		} catch (Exception e) {
+			return null;
+		}
+	}
+
+protected SearchExpressionParser(TokenBuffer tokenBuf, int k) {
+  super(tokenBuf,k);
+  tokenNames = _tokenNames;
+  buildTokenTypeASTClassMap();
+  astFactory = new ASTFactory(getTokenTypeToASTClassMap());
+}
+
+public SearchExpressionParser(TokenBuffer tokenBuf) {
+  this(tokenBuf,3);
+}
+
+protected SearchExpressionParser(TokenStream lexer, int k) {
+  super(lexer,k);
+  tokenNames = _tokenNames;
+  buildTokenTypeASTClassMap();
+  astFactory = new ASTFactory(getTokenTypeToASTClassMap());
+}
+
+public SearchExpressionParser(TokenStream lexer) {
+  this(lexer,3);
+}
+
+public SearchExpressionParser(ParserSharedInputState state) {
+  super(state,3);
+  tokenNames = _tokenNames;
+  buildTokenTypeASTClassMap();
+  astFactory = new ASTFactory(getTokenTypeToASTClassMap());
+}
+
+	public final void quotedRegularExpression(
+		boolean caseSensitive, boolean regex
+	) throws RecognitionException, TokenStreamException {
+		
+		returnAST = null;
+		ASTPair currentAST = new ASTPair();
+		AST quotedRegularExpression_AST = null;
+		Token  var_s = null;
+		AST var_s_AST = null;
+		
+		var_s = LT(1);
+		var_s_AST = astFactory.create(var_s);
+		astFactory.addASTChild(currentAST, var_s_AST);
+		match(STRING);
+		if ( inputState.guessing==0 ) {
+			quotedRegularExpression_AST = (AST)currentAST.root;
+			
+							quotedRegularExpression_AST = astFactory.make((new ASTArray(2)).add(new RegExNode(RegularExpression,var_s.getText(),caseSensitive,regex)).add(quotedRegularExpression_AST));
+						
+			currentAST.root = quotedRegularExpression_AST;
+			currentAST.child = quotedRegularExpression_AST!=null &&quotedRegularExpression_AST.getFirstChild()!=null ?
+				quotedRegularExpression_AST.getFirstChild() : quotedRegularExpression_AST;
+			currentAST.advanceChildToEnd();
+		}
+		quotedRegularExpression_AST = (AST)currentAST.root;
+		returnAST = quotedRegularExpression_AST;
+	}
+	
+	public final void simpleRegularExpression(
+		boolean caseSensitive, boolean regex
+	) throws RecognitionException, TokenStreamException {
+		
+		returnAST = null;
+		ASTPair currentAST = new ASTPair();
+		AST simpleRegularExpression_AST = null;
+		Token  var_s = null;
+		AST var_s_AST = null;
+		
+		var_s = LT(1);
+		var_s_AST = astFactory.create(var_s);
+		astFactory.addASTChild(currentAST, var_s_AST);
+		match(FIELDTYPE);
+		if ( inputState.guessing==0 ) {
+			simpleRegularExpression_AST = (AST)currentAST.root;
+			
+							simpleRegularExpression_AST = astFactory.make((new ASTArray(2)).add(new RegExNode(RegularExpression,var_s.getText(),caseSensitive,regex)).add(simpleRegularExpression_AST));
+						
+			currentAST.root = simpleRegularExpression_AST;
+			currentAST.child = simpleRegularExpression_AST!=null &&simpleRegularExpression_AST.getFirstChild()!=null ?
+				simpleRegularExpression_AST.getFirstChild() : simpleRegularExpression_AST;
+			currentAST.advanceChildToEnd();
+		}
+		simpleRegularExpression_AST = (AST)currentAST.root;
+		returnAST = simpleRegularExpression_AST;
+	}
+	
+	public final void searchExpression() throws RecognitionException, TokenStreamException {
+		
+		returnAST = null;
+		ASTPair currentAST = new ASTPair();
+		AST searchExpression_AST = null;
+		
+		condition();
+		astFactory.addASTChild(currentAST, returnAST);
+		AST tmp1_AST = null;
+		tmp1_AST = astFactory.create(LT(1));
+		astFactory.addASTChild(currentAST, tmp1_AST);
+		match(Token.EOF_TYPE);
+		searchExpression_AST = (AST)currentAST.root;
+		returnAST = searchExpression_AST;
+	}
+	
+	public final void condition() throws RecognitionException, TokenStreamException {
+		
+		returnAST = null;
+		ASTPair currentAST = new ASTPair();
+		AST condition_AST = null;
+		
+		boolean synPredMatched80 = false;
+		if (((_tokenSet_0.member(LA(1))) && (_tokenSet_1.member(LA(2))) && (_tokenSet_1.member(LA(3))))) {
+			int _m80 = mark();
+			synPredMatched80 = true;
+			inputState.guessing++;
+			try {
+				{
+				expression();
+				match(LITERAL_and);
+				condition();
+				}
+			}
+			catch (RecognitionException pe) {
+				synPredMatched80 = false;
+			}
+			rewind(_m80);
+inputState.guessing--;
+		}
+		if ( synPredMatched80 ) {
+			expression();
+			astFactory.addASTChild(currentAST, returnAST);
+			match(LITERAL_and);
+			condition();
+			astFactory.addASTChild(currentAST, returnAST);
+			if ( inputState.guessing==0 ) {
+				condition_AST = (AST)currentAST.root;
+				condition_AST = (AST)astFactory.make( (new ASTArray(2)).add(astFactory.create(And)).add(condition_AST));
+				currentAST.root = condition_AST;
+				currentAST.child = condition_AST!=null &&condition_AST.getFirstChild()!=null ?
+					condition_AST.getFirstChild() : condition_AST;
+				currentAST.advanceChildToEnd();
+			}
+			condition_AST = (AST)currentAST.root;
+		}
+		else {
+			boolean synPredMatched82 = false;
+			if (((_tokenSet_0.member(LA(1))) && (_tokenSet_1.member(LA(2))) && (_tokenSet_1.member(LA(3))))) {
+				int _m82 = mark();
+				synPredMatched82 = true;
+				inputState.guessing++;
+				try {
+					{
+					expression();
+					match(LITERAL_or);
+					condition();
+					}
+				}
+				catch (RecognitionException pe) {
+					synPredMatched82 = false;
+				}
+				rewind(_m82);
+inputState.guessing--;
+			}
+			if ( synPredMatched82 ) {
+				expression();
+				astFactory.addASTChild(currentAST, returnAST);
+				match(LITERAL_or);
+				condition();
+				astFactory.addASTChild(currentAST, returnAST);
+				if ( inputState.guessing==0 ) {
+					condition_AST = (AST)currentAST.root;
+					condition_AST = (AST)astFactory.make( (new ASTArray(2)).add(astFactory.create(Or)).add(condition_AST));
+					currentAST.root = condition_AST;
+					currentAST.child = condition_AST!=null &&condition_AST.getFirstChild()!=null ?
+						condition_AST.getFirstChild() : condition_AST;
+					currentAST.advanceChildToEnd();
+				}
+				condition_AST = (AST)currentAST.root;
+			}
+			else if ((_tokenSet_0.member(LA(1))) && (_tokenSet_1.member(LA(2))) && (_tokenSet_1.member(LA(3)))) {
+				expression();
+				astFactory.addASTChild(currentAST, returnAST);
+				condition_AST = (AST)currentAST.root;
+			}
+			else {
+				throw new NoViableAltException(LT(1), getFilename());
+			}
+			}
+			returnAST = condition_AST;
+		}
+		
+	public final void expression() throws RecognitionException, TokenStreamException {
+		
+		returnAST = null;
+		ASTPair currentAST = new ASTPair();
+		AST expression_AST = null;
+		
+		switch ( LA(1)) {
+		case STRING:
+		case FIELDTYPE:
+		{
+			expressionSearch();
+			astFactory.addASTChild(currentAST, returnAST);
+			expression_AST = (AST)currentAST.root;
+			break;
+		}
+		case LPAREN:
+		{
+			match(LPAREN);
+			condition();
+			astFactory.addASTChild(currentAST, returnAST);
+			match(RPAREN);
+			expression_AST = (AST)currentAST.root;
+			break;
+		}
+		default:
+			if ((LA(1)==LITERAL_not) && (LA(2)==STRING||LA(2)==FIELDTYPE)) {
+				match(LITERAL_not);
+				expressionSearch();
+				astFactory.addASTChild(currentAST, returnAST);
+				if ( inputState.guessing==0 ) {
+					expression_AST = (AST)currentAST.root;
+					expression_AST = (AST)astFactory.make( (new ASTArray(2)).add(astFactory.create(Not)).add(expression_AST));
+					currentAST.root = expression_AST;
+					currentAST.child = expression_AST!=null &&expression_AST.getFirstChild()!=null ?
+						expression_AST.getFirstChild() : expression_AST;
+					currentAST.advanceChildToEnd();
+				}
+				expression_AST = (AST)currentAST.root;
+			}
+			else if ((LA(1)==LITERAL_not) && (LA(2)==LPAREN)) {
+				match(LITERAL_not);
+				match(LPAREN);
+				condition();
+				astFactory.addASTChild(currentAST, returnAST);
+				match(RPAREN);
+				if ( inputState.guessing==0 ) {
+					expression_AST = (AST)currentAST.root;
+					expression_AST = (AST)astFactory.make( (new ASTArray(2)).add(astFactory.create(Not)).add(expression_AST));
+					currentAST.root = expression_AST;
+					currentAST.child = expression_AST!=null &&expression_AST.getFirstChild()!=null ?
+						expression_AST.getFirstChild() : expression_AST;
+					currentAST.advanceChildToEnd();
+				}
+				expression_AST = (AST)currentAST.root;
+			}
+		else {
+			throw new NoViableAltException(LT(1), getFilename());
+		}
+		}
+		returnAST = expression_AST;
+	}
+	
+	public final void expressionSearch() throws RecognitionException, TokenStreamException {
+		
+		returnAST = null;
+		ASTPair currentAST = new ASTPair();
+		AST expressionSearch_AST = null;
+		
+		if ((LA(1)==STRING) && (_tokenSet_2.member(LA(2))) && (LA(3)==STRING)) {
+			quotedRegularExpression(false,true);
+			astFactory.addASTChild(currentAST, returnAST);
+			compareType();
+			astFactory.addASTChild(currentAST, returnAST);
+			quotedRegularExpression(caseSensitive,regex);
+			astFactory.addASTChild(currentAST, returnAST);
+			if ( inputState.guessing==0 ) {
+				expressionSearch_AST = (AST)currentAST.root;
+				expressionSearch_AST = (AST)astFactory.make( (new ASTArray(2)).add(astFactory.create(ExpressionSearch)).add(expressionSearch_AST));
+				currentAST.root = expressionSearch_AST;
+				currentAST.child = expressionSearch_AST!=null &&expressionSearch_AST.getFirstChild()!=null ?
+					expressionSearch_AST.getFirstChild() : expressionSearch_AST;
+				currentAST.advanceChildToEnd();
+			}
+			expressionSearch_AST = (AST)currentAST.root;
+		}
+		else if ((LA(1)==FIELDTYPE) && (_tokenSet_2.member(LA(2))) && (LA(3)==STRING)) {
+			simpleRegularExpression(false,true);
+			astFactory.addASTChild(currentAST, returnAST);
+			compareType();
+			astFactory.addASTChild(currentAST, returnAST);
+			quotedRegularExpression(caseSensitive,regex);
+			astFactory.addASTChild(currentAST, returnAST);
+			if ( inputState.guessing==0 ) {
+				expressionSearch_AST = (AST)currentAST.root;
+				expressionSearch_AST = (AST)astFactory.make( (new ASTArray(2)).add(astFactory.create(ExpressionSearch)).add(expressionSearch_AST));
+				currentAST.root = expressionSearch_AST;
+				currentAST.child = expressionSearch_AST!=null &&expressionSearch_AST.getFirstChild()!=null ?
+					expressionSearch_AST.getFirstChild() : expressionSearch_AST;
+				currentAST.advanceChildToEnd();
+			}
+			expressionSearch_AST = (AST)currentAST.root;
+		}
+		else if ((LA(1)==FIELDTYPE) && (_tokenSet_2.member(LA(2))) && (LA(3)==FIELDTYPE)) {
+			simpleRegularExpression(false,true);
+			astFactory.addASTChild(currentAST, returnAST);
+			compareType();
+			astFactory.addASTChild(currentAST, returnAST);
+			simpleRegularExpression(caseSensitive,regex);
+			astFactory.addASTChild(currentAST, returnAST);
+			if ( inputState.guessing==0 ) {
+				expressionSearch_AST = (AST)currentAST.root;
+				expressionSearch_AST = (AST)astFactory.make( (new ASTArray(2)).add(astFactory.create(ExpressionSearch)).add(expressionSearch_AST));
+				currentAST.root = expressionSearch_AST;
+				currentAST.child = expressionSearch_AST!=null &&expressionSearch_AST.getFirstChild()!=null ?
+					expressionSearch_AST.getFirstChild() : expressionSearch_AST;
+				currentAST.advanceChildToEnd();
+			}
+			expressionSearch_AST = (AST)currentAST.root;
+		}
+		else if ((LA(1)==STRING) && (_tokenSet_2.member(LA(2))) && (LA(3)==FIELDTYPE)) {
+			quotedRegularExpression(false,true);
+			astFactory.addASTChild(currentAST, returnAST);
+			compareType();
+			astFactory.addASTChild(currentAST, returnAST);
+			simpleRegularExpression(caseSensitive,regex);
+			astFactory.addASTChild(currentAST, returnAST);
+			if ( inputState.guessing==0 ) {
+				expressionSearch_AST = (AST)currentAST.root;
+				expressionSearch_AST = (AST)astFactory.make( (new ASTArray(2)).add(astFactory.create(ExpressionSearch)).add(expressionSearch_AST));
+				currentAST.root = expressionSearch_AST;
+				currentAST.child = expressionSearch_AST!=null &&expressionSearch_AST.getFirstChild()!=null ?
+					expressionSearch_AST.getFirstChild() : expressionSearch_AST;
+				currentAST.advanceChildToEnd();
+			}
+			expressionSearch_AST = (AST)currentAST.root;
+		}
+		else {
+			throw new NoViableAltException(LT(1), getFilename());
+		}
+		
+		returnAST = expressionSearch_AST;
+	}
+	
+	public final void compareType() throws RecognitionException, TokenStreamException {
+		
+		returnAST = null;
+		ASTPair currentAST = new ASTPair();
+		AST compareType_AST = null;
+		
+		switch ( LA(1)) {
+		case LITERAL_contains:
+		{
+			AST tmp10_AST = null;
+			tmp10_AST = astFactory.create(LT(1));
+			astFactory.addASTChild(currentAST, tmp10_AST);
+			match(LITERAL_contains);
+			compareType_AST = (AST)currentAST.root;
+			break;
+		}
+		case LITERAL_matches:
+		{
+			AST tmp11_AST = null;
+			tmp11_AST = astFactory.create(LT(1));
+			astFactory.addASTChild(currentAST, tmp11_AST);
+			match(LITERAL_matches);
+			compareType_AST = (AST)currentAST.root;
+			break;
+		}
+		case EQUAL:
+		{
+			AST tmp12_AST = null;
+			tmp12_AST = astFactory.create(LT(1));
+			astFactory.addASTChild(currentAST, tmp12_AST);
+			match(EQUAL);
+			compareType_AST = (AST)currentAST.root;
+			break;
+		}
+		case EEQUAL:
+		{
+			AST tmp13_AST = null;
+			tmp13_AST = astFactory.create(LT(1));
+			astFactory.addASTChild(currentAST, tmp13_AST);
+			match(EEQUAL);
+			compareType_AST = (AST)currentAST.root;
+			break;
+		}
+		case NEQUAL:
+		{
+			AST tmp14_AST = null;
+			tmp14_AST = astFactory.create(LT(1));
+			astFactory.addASTChild(currentAST, tmp14_AST);
+			match(NEQUAL);
+			compareType_AST = (AST)currentAST.root;
+			break;
+		}
+		default:
+		{
+			throw new NoViableAltException(LT(1), getFilename());
+		}
+		}
+		returnAST = compareType_AST;
+	}
+	
+	
+	public static final String[] _tokenNames = {
+		"<0>",
+		"EOF",
+		"<2>",
+		"NULL_TREE_LOOKAHEAD",
+		"\"and\"",
+		"\"or\"",
+		"\"not\"",
+		"\"contains\"",
+		"\"matches\"",
+		"white space",
+		"'('",
+		"')'",
+		"'='",
+		"'=='",
+		"'!='",
+		"'\\\"'",
+		"a text literal",
+		"a letter",
+		"a field type",
+		"RegularExpression",
+		"And",
+		"Or",
+		"Not",
+		"ExpressionSearch"
+	};
+	
+	protected void buildTokenTypeASTClassMap() {
+		tokenTypeToASTClassMap=null;
+	}
+
+     private static final long[] mk_tokenSet_0() {
+         long[] data = { 328768L, 0L};
+         return data;
+     }
+	public static final BitSet _tokenSet_0 = new BitSet(mk_tokenSet_0());
+	private static final long[] mk_tokenSet_1() {
+		long[] data = { 357824L, 0L};
+		return data;
+	}
+	public static final BitSet _tokenSet_1 = new BitSet(mk_tokenSet_1());
+	private static final long[] mk_tokenSet_2() {
+		long[] data = { 29056L, 0L};
+		return data;
+	}
+	public static final BitSet _tokenSet_2 = new BitSet(mk_tokenSet_2());
+	
+	}
diff --git a/src/java/net/sf/jabref/search/SearchExpressionParserTokenTypes.java b/src/java/net/sf/jabref/search/SearchExpressionParserTokenTypes.java
new file mode 100644
index 0000000..daaaca3
--- /dev/null
+++ b/src/java/net/sf/jabref/search/SearchExpressionParserTokenTypes.java
@@ -0,0 +1,29 @@
+// $ANTLR : "Parser.g" -> "SearchExpressionParser.java"$
+
+package net.sf.jabref.search;
+import java.io.StringReader;
+
+public interface SearchExpressionParserTokenTypes {
+	int EOF = 1;
+	int NULL_TREE_LOOKAHEAD = 3;
+	int LITERAL_and = 4;
+	int LITERAL_or = 5;
+	int LITERAL_not = 6;
+	int LITERAL_contains = 7;
+	int LITERAL_matches = 8;
+	int WS = 9;
+	int LPAREN = 10;
+	int RPAREN = 11;
+	int EQUAL = 12;
+	int EEQUAL = 13;
+	int NEQUAL = 14;
+	int QUOTE = 15;
+	int STRING = 16;
+	int LETTER = 17;
+	int FIELDTYPE = 18;
+	int RegularExpression = 19;
+	int And = 20;
+	int Or = 21;
+	int Not = 22;
+	int ExpressionSearch = 23;
+}
diff --git a/src/java/net/sf/jabref/search/SearchExpressionTreeParser.java b/src/java/net/sf/jabref/search/SearchExpressionTreeParser.java
new file mode 100644
index 0000000..63bf9a9
--- /dev/null
+++ b/src/java/net/sf/jabref/search/SearchExpressionTreeParser.java
@@ -0,0 +1,308 @@
+// $ANTLR : "TreeParser.g" -> "SearchExpressionTreeParser.java"$
+
+package net.sf.jabref.search;
+import java.util.*;
+import java.util.regex.*;
+import net.sf.jabref.*;
+
+import antlr.TreeParser;
+import antlr.Token;
+import antlr.collections.AST;
+import antlr.RecognitionException;
+import antlr.ANTLRException;
+import antlr.NoViableAltException;
+import antlr.MismatchedTokenException;
+import antlr.SemanticException;
+import antlr.collections.impl.BitSet;
+import antlr.ASTPair;
+import antlr.collections.impl.ASTArray;
+
+
+public class SearchExpressionTreeParser extends antlr.TreeParser       implements SearchExpressionTreeParserTokenTypes
+ {
+
+	private static final int MATCH_EXACT = 0;
+	private static final int MATCH_CONTAINS = 1;
+	private static final int MATCH_DOES_NOT_CONTAIN = 2;
+
+	private BibtexEntry bibtexEntry;
+	private Object[] searchKeys;
+
+    private static final int PSEUDOFIELD_TYPE = 1;
+
+    public int apply(AST ast, BibtexEntry bibtexEntry) throws antlr.RecognitionException {
+		this.bibtexEntry = bibtexEntry;
+		// specification of fields to search is done in the search expression itself
+		this.searchKeys = bibtexEntry.getAllFields();
+		return tSearchExpression(ast) ? 1 : 0;
+	}
+public SearchExpressionTreeParser() {
+	tokenNames = _tokenNames;
+}
+
+	public final boolean  tSearchExpression(AST _t) throws RecognitionException, PatternSyntaxException {
+		boolean ret = false;
+
+        AST tSearchExpression_AST_in = (_t == ASTNULL) ? null : (AST)_t;
+		
+			boolean a = false, b = false;
+		
+		
+		try {      // for error handling
+			if (_t==null) _t=ASTNULL;
+			switch ( _t.getType()) {
+			case And:
+			{
+				AST __t87 = _t;
+				AST tmp1_AST_in = (AST)_t;
+				match(_t,And);
+				_t = _t.getFirstChild();
+				a=tSearchExpression(_t);
+				_t = _retTree;
+				{
+				if (_t==null) _t=ASTNULL;
+				if ((((_t.getType() >= And && _t.getType() <= ExpressionSearch)))&&(a)) {
+					b=tSearchExpression(_t);
+					_t = _retTree;
+				}
+				else if (((_t.getType() >= LITERAL_and && _t.getType() <= ExpressionSearch))) {
+					AST tmp2_AST_in = (AST)_t;
+					if ( _t==null ) throw new MismatchedTokenException();
+					_t = _t.getNextSibling();
+				}
+				else {
+					throw new NoViableAltException(_t);
+				}
+				
+				}
+				_t = __t87;
+				_t = _t.getNextSibling();
+				ret = a && b;
+				break;
+			}
+			case Or:
+			{
+				AST __t89 = _t;
+				AST tmp3_AST_in = (AST)_t;
+				match(_t,Or);
+				_t = _t.getFirstChild();
+				a=tSearchExpression(_t);
+				_t = _retTree;
+				{
+				if (_t==null) _t=ASTNULL;
+				if ((((_t.getType() >= And && _t.getType() <= ExpressionSearch)))&&(!a)) {
+					b=tSearchExpression(_t);
+					_t = _retTree;
+				}
+				else if (((_t.getType() >= LITERAL_and && _t.getType() <= ExpressionSearch))) {
+					AST tmp4_AST_in = (AST)_t;
+					if ( _t==null ) throw new MismatchedTokenException();
+					_t = _t.getNextSibling();
+				}
+				else {
+					throw new NoViableAltException(_t);
+				}
+				
+				}
+				_t = __t89;
+				_t = _t.getNextSibling();
+				ret = a || b;
+				break;
+			}
+			case Not:
+			{
+				AST __t91 = _t;
+				AST tmp5_AST_in = (AST)_t;
+				match(_t,Not);
+				_t = _t.getFirstChild();
+				a=tSearchExpression(_t);
+				_t = _retTree;
+				_t = __t91;
+				_t = _t.getNextSibling();
+				ret = !a;
+				break;
+			}
+			case ExpressionSearch:
+			{
+				ret=tExpressionSearch(_t);
+				_t = _retTree;
+				break;
+			}
+			default:
+			{
+				throw new NoViableAltException(_t);
+			}
+			}
+		}
+		catch (RecognitionException ex) {
+			reportError(ex);
+			if (_t!=null) {_t = _t.getNextSibling();}
+		}
+		_retTree = _t;
+		return ret;
+	}
+	
+	public final boolean  tExpressionSearch(AST _t) throws RecognitionException, PatternSyntaxException {
+		 boolean ret = false;
+
+        AST tExpressionSearch_AST_in = (_t == ASTNULL) ? null : (AST)_t;
+		AST var_f = null;
+		AST var_v = null;
+		
+			int matchType = 0;
+		
+		
+		try {      // for error handling
+			AST __t94 = _t;
+			AST tmp6_AST_in = (AST)_t;
+			match(_t,ExpressionSearch);
+			_t = _t.getFirstChild();
+			var_f = (AST)_t;
+			match(_t,RegularExpression);
+			_t = _t.getNextSibling();
+			matchType=tSearchType(_t);
+			_t = _retTree;
+			var_v = (AST)_t;
+			match(_t,RegularExpression);
+			_t = _t.getNextSibling();
+			
+						Pattern fieldSpec = ((RegExNode)var_f).getPattern();
+						Pattern valueSpec = ((RegExNode)var_v).getPattern();
+						int pseudoField = 0;
+			boolean noSuchField = true;
+						// this loop iterates over all regular keys, then over pseudo keys like "type"
+						for (int i = 0; i < searchKeys.length + PSEUDOFIELD_TYPE && !ret; ++i) {
+							String content;
+							switch (i - searchKeys.length + 1) {
+								case PSEUDOFIELD_TYPE:
+									if (!fieldSpec.matcher("entrytype").matches())
+										continue;
+									content = bibtexEntry.getType().getName();
+									break;
+								default: // regular field
+									if (!fieldSpec.matcher(searchKeys[i].toString()).matches())
+										continue;
+									content = (String)bibtexEntry.getField(searchKeys[i].toString());
+							}
+			noSuchField = false;
+							if (content == null)
+								continue; // paranoia
+							Matcher matcher = valueSpec.matcher(content);
+							switch (matchType) {
+							case MATCH_CONTAINS:
+								ret = matcher.find();
+								break;
+							case MATCH_EXACT:
+								ret = matcher.matches();
+								break;
+							case MATCH_DOES_NOT_CONTAIN:
+								ret = !matcher.find();
+								break;
+							}
+						}
+			if (noSuchField && matchType == MATCH_DOES_NOT_CONTAIN)
+			ret = true; // special case
+					
+			_t = __t94;
+			_t = _t.getNextSibling();
+		}
+		catch (RecognitionException ex) {
+			reportError(ex);
+			if (_t!=null) {_t = _t.getNextSibling();}
+		}
+		_retTree = _t;
+		return ret;
+	}
+	
+	public final int  tSearchType(AST _t) throws RecognitionException {
+		 int matchType = 0;
+
+        AST tSearchType_AST_in = (_t == ASTNULL) ? null : (AST)_t;
+		
+		try {      // for error handling
+			if (_t==null) _t=ASTNULL;
+			switch ( _t.getType()) {
+			case LITERAL_contains:
+			{
+				AST tmp7_AST_in = (AST)_t;
+				match(_t,LITERAL_contains);
+				_t = _t.getNextSibling();
+				matchType = MATCH_CONTAINS;
+				break;
+			}
+			case LITERAL_matches:
+			{
+				AST tmp8_AST_in = (AST)_t;
+				match(_t,LITERAL_matches);
+				_t = _t.getNextSibling();
+				matchType = MATCH_EXACT;
+				break;
+			}
+			case EQUAL:
+			{
+				AST tmp9_AST_in = (AST)_t;
+				match(_t,EQUAL);
+				_t = _t.getNextSibling();
+				matchType = MATCH_CONTAINS;
+				break;
+			}
+			case EEQUAL:
+			{
+				AST tmp10_AST_in = (AST)_t;
+				match(_t,EEQUAL);
+				_t = _t.getNextSibling();
+				matchType = MATCH_EXACT;
+				break;
+			}
+			case NEQUAL:
+			{
+				AST tmp11_AST_in = (AST)_t;
+				match(_t,NEQUAL);
+				_t = _t.getNextSibling();
+				matchType = MATCH_DOES_NOT_CONTAIN;
+				break;
+			}
+			default:
+			{
+				throw new NoViableAltException(_t);
+			}
+			}
+		}
+		catch (RecognitionException ex) {
+			reportError(ex);
+			if (_t!=null) {_t = _t.getNextSibling();}
+		}
+		_retTree = _t;
+		return matchType;
+	}
+	
+	
+	public static final String[] _tokenNames = {
+		"<0>",
+		"EOF",
+		"<2>",
+		"NULL_TREE_LOOKAHEAD",
+		"\"and\"",
+		"\"or\"",
+		"\"not\"",
+		"\"contains\"",
+		"\"matches\"",
+		"white space",
+		"'('",
+		"')'",
+		"'='",
+		"'=='",
+		"'!='",
+		"'\\\"'",
+		"a text literal",
+		"a letter",
+		"a field type",
+		"RegularExpression",
+		"And",
+		"Or",
+		"Not",
+		"ExpressionSearch"
+	};
+	
+	}
+	
diff --git a/src/java/net/sf/jabref/search/SearchExpressionTreeParserTokenTypes.java b/src/java/net/sf/jabref/search/SearchExpressionTreeParserTokenTypes.java
new file mode 100644
index 0000000..1cfd528
--- /dev/null
+++ b/src/java/net/sf/jabref/search/SearchExpressionTreeParserTokenTypes.java
@@ -0,0 +1,31 @@
+// $ANTLR : "TreeParser.g" -> "SearchExpressionTreeParser.java"$
+
+package net.sf.jabref.search;
+import java.util.*;
+import java.util.regex.*;
+import net.sf.jabref.*;
+
+public interface SearchExpressionTreeParserTokenTypes {
+	int EOF = 1;
+	int NULL_TREE_LOOKAHEAD = 3;
+	int LITERAL_and = 4;
+	int LITERAL_or = 5;
+	int LITERAL_not = 6;
+	int LITERAL_contains = 7;
+	int LITERAL_matches = 8;
+	int WS = 9;
+	int LPAREN = 10;
+	int RPAREN = 11;
+	int EQUAL = 12;
+	int EEQUAL = 13;
+	int NEQUAL = 14;
+	int QUOTE = 15;
+	int STRING = 16;
+	int LETTER = 17;
+	int FIELDTYPE = 18;
+	int RegularExpression = 19;
+	int And = 20;
+	int Or = 21;
+	int Not = 22;
+	int ExpressionSearch = 23;
+}
diff --git a/src/java/net/sf/jabref/search/SearchMatcher.java b/src/java/net/sf/jabref/search/SearchMatcher.java
new file mode 100644
index 0000000..31167cb
--- /dev/null
+++ b/src/java/net/sf/jabref/search/SearchMatcher.java
@@ -0,0 +1,21 @@
+package net.sf.jabref.search;
+
+import net.sf.jabref.BibtexEntry;
+
+import java.util.Hashtable;
+
+import ca.odell.glazedlists.matchers.Matcher;
+
+/**
+ * Matcher for filtering or sorting the table according to whether entries
+ * are tagged as search matches.
+ */
+public class SearchMatcher implements Matcher {
+
+        public static SearchMatcher INSTANCE = new SearchMatcher();
+
+        public boolean matches(Object object) {
+            BibtexEntry entry = (BibtexEntry)object;
+            return entry.isSearchHit();
+        }
+}
diff --git a/src/java/net/sf/jabref/search/TreeParser.g b/src/java/net/sf/jabref/search/TreeParser.g
new file mode 100644
index 0000000..6d9bf0a
--- /dev/null
+++ b/src/java/net/sf/jabref/search/TreeParser.g
@@ -0,0 +1,110 @@
+header {
+package net.sf.jabref.search;
+import java.util.*;
+import java.util.regex.*;
+import net.sf.jabref.*;
+}
+
+class SearchExpressionTreeParser extends TreeParser;
+
+options {
+	importVocab = SearchExpressionParser;
+	exportVocab = SearchExpressionTreeParser;
+}
+
+{
+	private static final int MATCH_EXACT = 0;
+	private static final int MATCH_CONTAINS = 1;
+	private static final int MATCH_DOES_NOT_CONTAIN = 2;
+
+	private BibtexEntry bibtexEntry;
+	private Object[] searchKeys;
+
+    private static final int PSEUDOFIELD_TYPE = 1;
+
+    public int apply(AST ast, BibtexEntry bibtexEntry) throws antlr.RecognitionException {
+		this.bibtexEntry = bibtexEntry;
+		// specification of fields to search is done in the search expression itself
+		this.searchKeys = bibtexEntry.getAllFields();
+		return tSearchExpression(ast) ? 1 : 0;
+	}
+}
+
+
+
+// ---------- Condition and Expressions ----------
+
+tSearchExpression returns [boolean ret = false;] throws PatternSyntaxException
+{
+	boolean a = false, b = false;
+}
+	: // predicates for and/or used to evaluate 2nd expression only if necessary
+	#( And a=tSearchExpression ( {a}? b=tSearchExpression | . ) ) { ret = a && b; }
+	|
+	#( Or a=tSearchExpression ( {!a}? b=tSearchExpression | . ) ) { ret = a || b; }
+	|
+	#( Not a=tSearchExpression ) { ret = !a; }
+	|
+	ret=tExpressionSearch
+	;
+
+tSearchType returns [ int matchType = 0; ]
+	:
+	LITERAL_contains { matchType = MATCH_CONTAINS; }
+	|
+	LITERAL_matches { matchType = MATCH_EXACT; }
+	|
+	EQUAL { matchType = MATCH_CONTAINS; }
+	|
+	EEQUAL { matchType = MATCH_EXACT; }
+	|
+	NEQUAL { matchType = MATCH_DOES_NOT_CONTAIN; }
+	;
+
+tExpressionSearch returns [ boolean ret = false; ] throws PatternSyntaxException
+{
+	int matchType = 0;
+}
+	:
+	#( ExpressionSearch var_f:RegularExpression matchType=tSearchType var_v:RegularExpression
+		{
+			Pattern fieldSpec = ((RegExNode)var_f).getPattern();
+			Pattern valueSpec = ((RegExNode)var_v).getPattern();
+			int pseudoField = 0;
+            boolean noSuchField = true;
+			// this loop iterates over all regular keys, then over pseudo keys like "type"
+			for (int i = 0; i < searchKeys.length + PSEUDOFIELD_TYPE && !ret; ++i) {
+				String content;
+				switch (i - searchKeys.length + 1) {
+					case PSEUDOFIELD_TYPE:
+						if (!fieldSpec.matcher("entrytype").matches())
+							continue;
+						content = bibtexEntry.getType().getName();
+						break;
+					default: // regular field
+						if (!fieldSpec.matcher(searchKeys[i].toString()).matches())
+							continue;
+						content = (String)bibtexEntry.getField(searchKeys[i].toString());
+				}
+                noSuchField = false;
+				if (content == null)
+					continue; // paranoia
+				Matcher matcher = valueSpec.matcher(content);
+				switch (matchType) {
+				case MATCH_CONTAINS:
+					ret = matcher.find();
+					break;
+				case MATCH_EXACT:
+					ret = matcher.matches();
+					break;
+				case MATCH_DOES_NOT_CONTAIN:
+					ret = !matcher.find();
+					break;
+				}
+			}
+            if (noSuchField && matchType == MATCH_DOES_NOT_CONTAIN)
+                ret = true; // special case
+		}
+	)
+	;
+
diff --git a/src/java/net/sf/jabref/undo/CountingUndoManager.java b/src/java/net/sf/jabref/undo/CountingUndoManager.java
new file mode 100644
index 0000000..613fb53
--- /dev/null
+++ b/src/java/net/sf/jabref/undo/CountingUndoManager.java
@@ -0,0 +1,82 @@
+/*
+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.
+
+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.undo;
+
+import javax.swing.undo.*;
+import javax.swing.*;
+
+import net.sf.jabref.BasePanel;
+
+public class CountingUndoManager extends UndoManager {
+
+    private int unchangedPoint = 0,
+	current = 0;
+    private BasePanel panel = null;
+
+    public CountingUndoManager(BasePanel basePanel) {
+	super();
+	panel = basePanel;
+    }
+
+    public synchronized boolean addEdit(UndoableEdit edit) {
+	current++;
+	return super.addEdit(edit);
+    }
+    
+    public synchronized void undo() throws CannotUndoException {
+	    super.undo();
+	    current--;
+        panel.updateEntryEditorIfShowing();
+        //panel.updateViewToSelected();
+        /*SwingUtilities.invokeLater(new Runnable() {
+            public void run() {
+                panel.updateViewToSelected();
+            }
+        });*/
+
+    }
+
+    public synchronized void redo() throws CannotUndoException {
+	    super.redo();
+	    current++;
+        panel.updateEntryEditorIfShowing();
+        //panel.updateViewToSelected();
+        /*SwingUtilities.invokeLater(new Runnable() {
+            public void run() {
+                panel.updateViewToSelected();
+            }
+        });*/
+    }
+
+    public synchronized void markUnchanged() {
+	unchangedPoint = current;
+    }
+
+    public boolean hasChanged() {
+	return !(current == unchangedPoint);
+    }
+}
diff --git a/src/java/net/sf/jabref/undo/NamedCompound.java b/src/java/net/sf/jabref/undo/NamedCompound.java
new file mode 100644
index 0000000..7e6354f
--- /dev/null
+++ b/src/java/net/sf/jabref/undo/NamedCompound.java
@@ -0,0 +1,56 @@
+/*
+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.
+
+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.undo;
+
+import javax.swing.undo.*;
+import net.sf.jabref.Globals;
+
+public class NamedCompound extends CompoundEdit {
+
+    String name;
+
+    public NamedCompound(String name) {
+	super();
+	this.name = name;
+    }
+
+    public String getUndoPresentationName() {
+	return Globals.lang("Undo")+": "+name;
+    }
+
+    public String getRedoPresentationName() {
+	return Globals.lang("Redo")+": "+name;
+    }
+
+    /**
+     * Returns the name of this compound, without the Undo or Redo prefix.
+     */
+    public String getNameOnly() {
+      return name;
+    }
+}
diff --git a/src/java/net/sf/jabref/undo/UndoableChangeType.java b/src/java/net/sf/jabref/undo/UndoableChangeType.java
new file mode 100644
index 0000000..d3cb12c
--- /dev/null
+++ b/src/java/net/sf/jabref/undo/UndoableChangeType.java
@@ -0,0 +1,66 @@
+/*
+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.
+
+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.undo;
+
+import javax.swing.undo.*;
+import java.util.HashMap;
+import net.sf.jabref.*;
+
+/**
+ * This class represents the change of type for an entry.
+ */
+public class UndoableChangeType extends AbstractUndoableEdit {
+
+    BibtexEntryType oldType, newType;
+    BibtexEntry be;
+
+    public UndoableChangeType(BibtexEntry be, BibtexEntryType oldType,
+			      BibtexEntryType newType) {
+	this.oldType = oldType;
+	this.newType = newType;
+	this.be = be;
+    }
+
+    public String getUndoPresentationName() {
+	return "Undo: change type";
+    }
+
+    public String getRedoPresentationName() {
+	return "Redo: change type";
+    }
+
+    public void undo() {
+	super.undo();
+	be.setType(oldType);
+    }
+
+    public void redo() {
+	super.redo();
+	be.setType(newType);
+    }
+
+}
diff --git a/src/java/net/sf/jabref/undo/UndoableFieldChange.java b/src/java/net/sf/jabref/undo/UndoableFieldChange.java
new file mode 100644
index 0000000..db7bd9c
--- /dev/null
+++ b/src/java/net/sf/jabref/undo/UndoableFieldChange.java
@@ -0,0 +1,92 @@
+/*
+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.
+
+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.undo;
+
+import javax.swing.undo.*;
+import net.sf.jabref.BibtexEntry;
+import net.sf.jabref.Util;
+
+/**
+ * This class represents a change in any field value. The relevant
+ * information is the BibtexEntry, the field name, the old and the
+ * new value. Old/new values can be null.
+ */
+public class UndoableFieldChange extends AbstractUndoableEdit {
+
+    private BibtexEntry entry;
+    private String field;
+    private Object oldValue, newValue;
+
+    public UndoableFieldChange(BibtexEntry entry, String field,
+			       Object oldValue, Object newValue) {
+	this.entry = entry;
+	this.field = field;
+	this.oldValue = oldValue;
+	this.newValue = newValue;
+    }
+
+    public String getUndoPresentationName() {
+	return "Undo: change field";
+    }
+
+    public String getRedoPresentationName() {
+	return "Redo: change field";
+    }
+
+    public void undo() {
+	super.undo();
+
+	// Revert the change.
+	try {
+          if (oldValue != null)
+            entry.setField(field, oldValue);
+          else
+            entry.clearField(field);
+
+	} catch (Throwable ex) {
+	    Util.pr(ex.getMessage());
+	}
+    }
+
+    public void redo() {
+	super.redo();
+
+	// Redo the change.
+	try {
+          if (newValue != null)
+            entry.setField(field, newValue);
+          else
+            entry.clearField(field);
+
+	} catch (Throwable ex) {
+	    Util.pr(ex.getMessage());
+	}
+    }
+
+
+
+}
diff --git a/src/java/net/sf/jabref/undo/UndoableInsertEntry.java b/src/java/net/sf/jabref/undo/UndoableInsertEntry.java
new file mode 100644
index 0000000..1febf03
--- /dev/null
+++ b/src/java/net/sf/jabref/undo/UndoableInsertEntry.java
@@ -0,0 +1,88 @@
+/*
+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.
+
+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.undo;
+
+import javax.swing.undo.*;
+import net.sf.jabref.*;
+import java.util.HashMap;
+
+/**
+ * This class represents the removal of an entry. The constructor needs
+ * references to the database, the entry, and the map of open entry editors.
+ * The latter to be able to close the entry's editor if it is opened before
+ * the insert is undone.
+ */
+public class UndoableInsertEntry extends AbstractUndoableEdit {
+
+    private BibtexDatabase base;
+    private BibtexEntry entry;
+    private BasePanel panel;
+
+    public UndoableInsertEntry(BibtexDatabase base, BibtexEntry entry,
+			       BasePanel panel) {
+	this.base = base;
+	this.entry = entry;
+	this.panel = panel;
+    }
+
+    public String getUndoPresentationName() {
+	return "Undo: insert entry";
+    }
+
+    public String getRedoPresentationName() {
+	return "Redo: insert entry";
+    }
+
+    public void undo() {
+	super.undo();
+
+	// Revert the change.
+	try {
+	    base.removeEntry(entry.getId());
+	    // If the entry has an editor currently open, we must close it.
+	    panel.ensureNotShowing(entry);
+	} catch (Throwable ex) {
+          ex.printStackTrace();
+	}
+    }
+
+    public void redo() {
+	super.redo();
+
+	// Redo the change.
+	try {
+          String id = Util.createNeutralId();
+	    entry.setId(id);
+	    base.insertEntry(entry);
+	} catch (Throwable ex) {
+          ex.printStackTrace();
+	}
+    }
+
+
+
+}
diff --git a/src/java/net/sf/jabref/undo/UndoableInsertString.java b/src/java/net/sf/jabref/undo/UndoableInsertString.java
new file mode 100644
index 0000000..6e91514
--- /dev/null
+++ b/src/java/net/sf/jabref/undo/UndoableInsertString.java
@@ -0,0 +1,76 @@
+/*
+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.
+
+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.undo;
+
+import javax.swing.undo.*;
+import net.sf.jabref.*;
+
+public class UndoableInsertString extends AbstractUndoableEdit {
+    
+    private BibtexDatabase base;
+    private BasePanel panel;
+    private BibtexString string;
+
+    public UndoableInsertString(BasePanel panel, BibtexDatabase base,
+				BibtexString string) {
+	this.base = base;
+	this.panel = panel;
+	this.string = string;
+    }
+
+    public String getUndoPresentationName() {
+	return Globals.lang("Undo")+": "+Globals.lang("insert string ");
+    }
+
+    public String getRedoPresentationName() {
+	return Globals.lang("Redo")+": "+Globals.lang("insert string ");
+    }
+
+    public void undo() {
+	super.undo();
+	
+	// Revert the change.
+	base.removeString(string.getId());
+	panel.updateStringDialog();
+    }
+
+    public void redo() {
+	super.redo();
+
+	// Redo the change.
+	try {
+	    base.addString(string);
+	} catch (KeyCollisionException ex) {
+	    ex.printStackTrace();
+	}
+
+	panel.updateStringDialog();
+    }
+
+
+
+}
diff --git a/src/java/net/sf/jabref/undo/UndoableKeyChange.java b/src/java/net/sf/jabref/undo/UndoableKeyChange.java
new file mode 100644
index 0000000..8a2f95d
--- /dev/null
+++ b/src/java/net/sf/jabref/undo/UndoableKeyChange.java
@@ -0,0 +1,79 @@
+/*
+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.
+
+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.html
+
+*/
+package net.sf.jabref.undo;
+
+import javax.swing.undo.*;
+import net.sf.jabref.BibtexDatabase;
+import net.sf.jabref.Util;
+import net.sf.jabref.Globals;
+
+/**
+ * This class represents a change in any field value. The relevant
+ * information is the BibtexEntry, the field name, the old and the
+ * new value. Old/new values can be null.
+ */
+public class UndoableKeyChange extends AbstractUndoableEdit {
+
+    private String entryId;
+    private BibtexDatabase base;
+    private String oldValue, newValue;
+
+    public UndoableKeyChange(BibtexDatabase base, String entryId,
+			     String oldValue, String newValue) {
+	this.base = base;
+	this.entryId = entryId;
+	this.oldValue = oldValue;
+	this.newValue = newValue;
+    }
+
+    public String getUndoPresentationName() {
+	return Globals.lang("Undo")+": "+Globals.lang("change key");
+    }
+
+    public String getRedoPresentationName() {
+	return Globals.lang("Redo")+": "+Globals.lang("change key");
+    }
+
+    public void undo() {
+	super.undo();
+	
+	// Revert the change.
+	set(oldValue);
+    }
+
+    public void redo() {
+	super.redo();
+
+	// Redo the change.
+	set(newValue);
+    }
+
+    private void set(String to) {
+	base.setCiteKeyForEntry(entryId, to);
+    }
+
+}
diff --git a/src/java/net/sf/jabref/undo/UndoablePreambleChange.java b/src/java/net/sf/jabref/undo/UndoablePreambleChange.java
new file mode 100644
index 0000000..2200f92
--- /dev/null
+++ b/src/java/net/sf/jabref/undo/UndoablePreambleChange.java
@@ -0,0 +1,82 @@
+/*
+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.
+
+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.undo;
+
+import javax.swing.undo.*;
+import net.sf.jabref.*;
+
+/**
+ * This class represents a change in any field value. The relevant
+ * information is the BibtexEntry, the field name, the old and the
+ * new value. Old/new values can be null.
+ */
+public class UndoablePreambleChange extends AbstractUndoableEdit {
+
+    private BibtexDatabase base;
+    private String oldValue, newValue;
+    private BasePanel panel;
+
+    public UndoablePreambleChange(BibtexDatabase base, BasePanel panel,
+				  String oldValue, String newValue) {
+	this.base = base;
+	this.oldValue = oldValue;
+	this.newValue = newValue;
+	this.panel = panel;
+    }
+
+    public String getUndoPresentationName() {
+	return Globals.lang("Undo")+": "+Globals.lang("change preamble");
+    }
+
+    public String getRedoPresentationName() {
+	return Globals.lang("Redo")+": "+Globals.lang("change preamble");
+    }
+
+    public void undo() {
+	super.undo();
+	
+	// Revert the change.
+	base.setPreamble(oldValue);
+
+	// If the preamble editor is open, update it.
+	panel.updatePreamble();
+    }
+
+    public void redo() {
+	super.redo();
+
+	// Redo the change.
+	base.setPreamble(newValue);
+
+	// If the preamble editor is open, update it.
+	panel.updatePreamble();
+
+    }
+
+
+
+}
diff --git a/src/java/net/sf/jabref/undo/UndoableRemoveEntry.java b/src/java/net/sf/jabref/undo/UndoableRemoveEntry.java
new file mode 100644
index 0000000..f78eb86
--- /dev/null
+++ b/src/java/net/sf/jabref/undo/UndoableRemoveEntry.java
@@ -0,0 +1,88 @@
+/*
+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.
+
+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.undo;
+
+import javax.swing.undo.*;
+import net.sf.jabref.*;
+import java.util.HashMap;
+
+/**
+ * This class represents the removal of an entry. The constructor needs
+ * references to the database, the entry, and the map of open entry editors.
+ * The latter to be able to close the entry's editor if it is opened after
+ * an undo, and the removal is then undone.
+ */
+public class UndoableRemoveEntry extends AbstractUndoableEdit {
+
+    private BibtexDatabase base;
+    private BibtexEntry entry;
+    private BasePanel panel;
+
+    public UndoableRemoveEntry(BibtexDatabase base, BibtexEntry entry,
+			       BasePanel panel) {
+	this.base = base;
+	this.entry = entry;
+	this.panel = panel;
+    }
+
+    public String getUndoPresentationName() {
+	return "Undo: remove entry";
+    }
+
+    public String getRedoPresentationName() {
+	return "Redo: remove entry";
+    }
+
+    public void undo() {
+	super.undo();
+
+	// Revert the change.
+	try {
+	    String id = Util.createNeutralId();
+	    entry.setId(id);
+	    base.insertEntry(entry);
+	} catch (Throwable ex) {
+          ex.printStackTrace();
+	}
+    }
+
+    public void redo() {
+	super.redo();
+
+	// Redo the change.
+	try {
+	    base.removeEntry(entry.getId());
+	    // If the entry has an editor currently open, we must close it.
+	    panel.ensureNotShowing(entry);
+	} catch (Throwable ex) {
+          ex.printStackTrace();
+	}
+    }
+
+
+
+}
diff --git a/src/java/net/sf/jabref/undo/UndoableRemoveString.java b/src/java/net/sf/jabref/undo/UndoableRemoveString.java
new file mode 100644
index 0000000..21ba103
--- /dev/null
+++ b/src/java/net/sf/jabref/undo/UndoableRemoveString.java
@@ -0,0 +1,77 @@
+/*
+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.
+
+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.undo;
+
+import javax.swing.undo.*;
+import net.sf.jabref.*;
+
+public class UndoableRemoveString extends AbstractUndoableEdit {
+
+    private BibtexDatabase base;
+    private BibtexString string;
+    private BasePanel panel;
+
+    public UndoableRemoveString(BasePanel panel,
+				BibtexDatabase base, BibtexString string) {
+	this.base = base;
+	this.string = string;
+	this.panel = panel;
+    }
+
+    public String getUndoPresentationName() {
+	return Globals.lang("Undo")+": "+Globals.lang("remove string ");
+    }
+
+    public String getRedoPresentationName() {
+	return Globals.lang("Redo")+": "+Globals.lang("remove string ");
+    }
+
+    public void undo() {
+	super.undo();
+	
+	// Revert the change.
+	try {
+	    base.addString(string);
+	} catch (KeyCollisionException ex) {
+	    ex.printStackTrace();
+	}
+
+	panel.updateStringDialog();
+    }
+
+    public void redo() {
+	super.redo();
+
+	// Redo the change.
+	base.removeString(string.getId());
+
+	panel.updateStringDialog();
+    }
+
+
+
+}
diff --git a/src/java/net/sf/jabref/undo/UndoableStringChange.java b/src/java/net/sf/jabref/undo/UndoableStringChange.java
new file mode 100644
index 0000000..146a47a
--- /dev/null
+++ b/src/java/net/sf/jabref/undo/UndoableStringChange.java
@@ -0,0 +1,92 @@
+/*
+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.
+
+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.undo;
+
+import javax.swing.undo.*;
+import net.sf.jabref.*;
+
+public class UndoableStringChange extends AbstractUndoableEdit {
+
+    private BibtexString string;
+    private String oldValue, newValue;
+    private boolean nameChange;
+    private BasePanel panel;
+    
+
+    public UndoableStringChange(BasePanel panel,
+				BibtexString string, boolean nameChange,
+				String oldValue, String newValue) {
+	this.string = string;
+	this.oldValue = oldValue;
+	this.newValue = newValue;
+	this.nameChange = nameChange;
+	this.panel = panel;
+    }
+
+    public String getUndoPresentationName() {
+	return Globals.lang("Undo")+": "
+	    +Globals.lang(nameChange ? "change string name" : "change string content");
+    }
+
+    public String getRedoPresentationName() {
+	return Globals.lang("Redo")+": "
+	    +Globals.lang(nameChange ? "change string name" : "change string content");
+    }
+
+    public void undo() {
+	super.undo();
+	
+	// Revert the change.
+
+	panel.assureStringDialogNotEditing();
+
+	if (nameChange)
+	    string.setName(oldValue);
+	else
+	    string.setContent(oldValue);
+
+	panel.updateStringDialog();
+    }
+
+    public void redo() {
+	super.redo();
+
+	// Redo the change.
+
+	panel.assureStringDialogNotEditing();
+	if (nameChange)
+	    string.setName(newValue);
+	else
+	    string.setContent(newValue);
+
+	panel.updateStringDialog();
+    }
+
+
+
+}
diff --git a/src/java/net/sf/jabref/util/CaseChangeMenu.java b/src/java/net/sf/jabref/util/CaseChangeMenu.java
new file mode 100644
index 0000000..c9a011b
--- /dev/null
+++ b/src/java/net/sf/jabref/util/CaseChangeMenu.java
@@ -0,0 +1,62 @@
+package net.sf.jabref.util;
+
+/* Mp3dings - manage mp3 meta-information
+ * Copyright (C) 2003 Moritz Ringler
+ * $Id: CaseChangeMenu.java,v 1.2 2005/03/20 20:47:51 mortenalver Exp $
+ *
+ * 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.
+ */
+
+import net.sf.jabref.Globals;
+
+import javax.swing.JMenu;
+import javax.swing.JMenuItem;
+import javax.swing.text.JTextComponent;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+
+public class CaseChangeMenu extends JMenu implements ActionListener{
+    static CaseChanger cc = new CaseChanger();
+    JMenuItem changeCaseItems[];
+    private JTextComponent parent;
+
+    public CaseChangeMenu(JTextComponent opener){
+        /* case */
+        super(Globals.lang("Change case"));
+        parent = opener;
+        int m = cc.getNumModes();
+        changeCaseItems = new JMenuItem[m];
+        for (int i=0;i<m;i++){
+            changeCaseItems[i]=new JMenuItem(Globals.lang(cc.getModeName(i)));
+            changeCaseItems[i].addActionListener(this);
+            this.add(changeCaseItems[i]);
+        }
+    }
+
+    public void actionPerformed(ActionEvent e) {
+        Object source = (e.getSource());
+        for(int i=0, m=cc.getNumModes(); i<m; i++){
+            if(source == changeCaseItems[i]){
+                caseChange(i);
+                break;
+            }
+        }
+    }
+
+    private void caseChange(int mode){
+        parent.setText(cc.changeCase(parent.getText(), mode));
+    }
+}
\ No newline at end of file
diff --git a/src/java/net/sf/jabref/util/CaseChanger.java b/src/java/net/sf/jabref/util/CaseChanger.java
new file mode 100644
index 0000000..bfceb05
--- /dev/null
+++ b/src/java/net/sf/jabref/util/CaseChanger.java
@@ -0,0 +1,120 @@
+package net.sf.jabref.util;
+
+/* Mp3dings - manage mp3 meta-information
+ * Copyright (C) 2003 Moritz Ringler
+ * $Id: CaseChanger.java,v 1.2.6.1 2006/01/17 21:33:26 mortenalver Exp $
+ *
+ * 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.
+ */
+
+
+import java.util.regex.Pattern;
+import java.util.regex.Matcher;
+
+/** Class used to manage case changing
+ * @author Moritz Ringler
+ * @version $Revision: 1.2.6.1 $ ($Date: 2006/01/17 21:33:26 $)
+ */
+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;
+        }
+    }
+}
+
diff --git a/src/java/net/sf/jabref/util/QuotedStringTokenizer.java b/src/java/net/sf/jabref/util/QuotedStringTokenizer.java
new file mode 100644
index 0000000..e1ab8f1
--- /dev/null
+++ b/src/java/net/sf/jabref/util/QuotedStringTokenizer.java
@@ -0,0 +1,64 @@
+package net.sf.jabref.util;
+
+/**
+ * A String tokenizer that works just like StringTokenizer, but considers quoted
+ * characters (which do not act as delimiters).
+ */
+public class QuotedStringTokenizer {
+    private final String m_content;
+    private final int m_contentLength;
+    private final String m_delimiters;
+    private final char m_quoteChar;
+    private int m_index = 0;
+    
+    /**
+     * @param content
+     *            The String to be tokenized.
+     * @param delimiters
+     *            The delimiter characters.
+     * @param quoteCharacter
+     *            The quoting character. Every character (including, but not
+     *            limited to, delimiters) that is preceded by this character is
+     *            not treated as a delimiter, but as a token component.
+     */
+    public QuotedStringTokenizer(String content, String delimiters, char quoteCharacter) {
+        m_content = content;
+        m_delimiters = delimiters;
+        m_quoteChar = quoteCharacter;
+        m_contentLength = m_content.length();
+        // skip leading delimiters
+        while (isDelimiter(m_content.charAt(m_index)) && m_index < m_contentLength)
+            ++m_index;
+    }
+    
+    public String nextToken() {
+        char c;
+        StringBuffer sb = new StringBuffer();
+        while (m_index < m_contentLength) {
+    		c = m_content.charAt(m_index);
+    		if (c == m_quoteChar) { // next is quoted
+    		    ++m_index;
+    		    if (m_index < m_contentLength) // sanity check
+    		        sb.append(m_content.charAt(m_index));
+    			// ignore for delimiter search!
+    		} else if (isDelimiter(c)) { // unit finished
+    		    // advance index until next token or end
+    		    do {
+    		        ++m_index;
+    		    } while (m_index < m_contentLength && isDelimiter(m_content.charAt(m_index)));
+    		    return sb.toString();
+    		}
+   			sb.append(c);
+   			++m_index;
+    	}
+        return sb.toString();
+    }
+    
+    private boolean isDelimiter(char c) {
+        return m_delimiters.indexOf(c) >= 0;
+    }
+    
+    public boolean hasMoreTokens() {
+        return m_index < m_contentLength;
+    }
+}
diff --git a/src/java/net/sf/jabref/util/ResourceExtractor.java b/src/java/net/sf/jabref/util/ResourceExtractor.java
new file mode 100644
index 0000000..d355c5d
--- /dev/null
+++ b/src/java/net/sf/jabref/util/ResourceExtractor.java
@@ -0,0 +1,45 @@
+/*
+ * ResourceExtractor.java
+ *
+ * Created on January 20, 2005, 10:37 PM
+ */
+
+package net.sf.jabref.util;
+
+import java.awt.Component;
+import java.net.URL;
+import java.io.*;
+import net.sf.jabref.*;
+import net.sf.jabref.net.URLDownload;
+/**
+ * This class performs the somewhat weird action of extracting a file from within the running JabRef jar,
+ * and storing it to the given File. It may prove useful e.g. for extracting Endnote export/import filters which
+ * are needed for full integration with the export filter in JabRef, so we can bundle these for the user even though
+ * they are not used by JabRef directly.
+ *
+ *
+ *
+ * @author alver
+ */
+public class ResourceExtractor implements Worker {
+    
+    final URL resource;
+    final Component parent;
+    final File destination;
+    
+    /** Creates a new instance of ResourceExtractor */
+    public ResourceExtractor(final Component parent, final String filename, File destination) {
+         resource = JabRef.class.getResource(filename);
+         this.parent = parent;
+         this.destination = destination;
+    }
+    
+    public void run() {
+        URLDownload ud = new URLDownload(parent, resource, destination);
+        try {
+            ud.download();
+        } catch (IOException ex) {
+            Globals.logger("Error extracting resource: "+ex.getMessage());            
+        }
+    }
+}
diff --git a/src/java/net/sf/jabref/util/TBuildInfo.java b/src/java/net/sf/jabref/util/TBuildInfo.java
new file mode 100644
index 0000000..d8d0ba3
--- /dev/null
+++ b/src/java/net/sf/jabref/util/TBuildInfo.java
@@ -0,0 +1,144 @@
+/*
+ Copyright (C) 2005 R. Nagel
+
+ 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
+
+ */
+
+// created by : r.nagel 01.06.2005
+//
+// function : read build informations from build.properies file
+//
+// todo:
+//
+// modified:
+//
+
+package net.sf.jabref.util;
+
+import java.io.* ;
+
+public class TBuildInfo
+{
+  private String BUILD_DATE = "" ;
+  private String BUILD_VERSION = "devel - 1st edition family" ;
+  private String BUILD_NUMBER = "1" ;
+
+//  private TBuilderInfo runtime = new TBuildInfo() ;
+  public TBuildInfo(String path)
+  {
+    readBuildVersionData(path) ;
+  }
+
+// --------------------------------------------------------------------------
+  // some informations from extern build file
+  private void readBuildVersionData(String path)
+  {
+    String buf = null ;
+    int sep = 0 ;
+    String Key, Value ;
+    BufferedReader input = null ;
+
+    try
+    {
+
+      input = new BufferedReader(
+          new InputStreamReader( getClass().getResourceAsStream( path) ), 100 ) ;
+    }
+    catch ( Exception e1 )
+    {
+//      System.out.println( e1 ) ;
+//      e1.printStackTrace();
+//      Logger.global.info( e1.getMessage() ) ;
+        return ;
+    }
+
+    try
+    {
+      while ( ( buf = input.readLine() ) != null )
+      {
+        if ( buf.length() > 0 )
+        { // no empty lines
+          if ( buf.charAt( 0 ) != '#' )
+          { // data line, comments - first char = #
+            sep = buf.indexOf( '=' ) ;
+            if ( sep > 0 )
+            { // = found
+              Key = buf.substring( 0, sep ) ;
+              Value = buf.substring( sep + 1 ) ;
+              if ( Key.equals( "builddate" ) )
+              {
+                BUILD_DATE = Value ;
+              }
+              else if ( Key.equals( "build" ) )
+              {
+                BUILD_NUMBER = Value ;
+              }
+              else if ( Key.equals( "version" ) )
+              {
+                BUILD_VERSION = Value ;
+              }
+
+            }
+          } // data line
+        }
+      } // while
+    }
+    catch ( IOException iex )
+    {
+//      System.err.println(iex.getMessage());
+//      Logger.global.info( iex.getMessage() ) ;
+    }
+
+    try
+    {
+      input.close() ;
+    }
+    catch ( Exception e )
+    {
+//      System.out.println(e.getMessage());
+//      Logger.global.info( e.getMessage() ) ;
+    }
+  }
+
+  // --------------------------------------------------------------------------
+
+  public String getBUILD_DATE()
+  {
+    return BUILD_DATE;
+  }
+
+  public String getBUILD_VERSION()
+  {
+    return BUILD_VERSION;
+  }
+
+  public String getBUILD_NUMBER()
+  {
+    return BUILD_NUMBER;
+  }
+
+
+// --------------------------------------------------------------------------
+
+}
diff --git a/src/java/net/sf/jabref/wizard/auximport/AuxCommandLine.java b/src/java/net/sf/jabref/wizard/auximport/AuxCommandLine.java
new file mode 100644
index 0000000..cd02bd6
--- /dev/null
+++ b/src/java/net/sf/jabref/wizard/auximport/AuxCommandLine.java
@@ -0,0 +1,77 @@
+/*
+Copyright (C) 2004 R. Nagel
+
+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
+
+*/
+
+// created by : r.nagel 13.10.2004
+//
+// function : handles the subdatabase from aux command line option
+//
+// modified :
+
+package net.sf.jabref.wizard.auximport ;
+
+import net.sf.jabref.* ;
+import java.util.*;
+
+public class AuxCommandLine
+{
+  private String auxName ;
+  private BibtexDatabase bib ;
+
+  public AuxCommandLine(String auxFileName, BibtexDatabase refDBase)
+  {
+    auxName = Util.getCorrectFileName(auxFileName, "aux") ;
+    bib = refDBase ;
+  }
+
+  public BibtexDatabase perform()
+  {
+    BibtexDatabase back = null ;
+    if ( (auxName.length() > 0) && (bib != null) )
+    {
+      AuxSubGenerator auxParser = new AuxSubGenerator(bib) ;
+      Vector returnValue = auxParser.generate(auxName, bib) ;
+      back = auxParser.getGeneratedDatabase() ;
+
+      // print statistics
+//      System.out.println(Globals.lang( "Results" ));
+      System.out.println( Globals.lang("keys_in_database") +" " +bib.getEntryCount() ) ;
+      System.out.println( Globals.lang("found_in_aux_file") +" "+auxParser.getFoundKeysInAux());
+      System.out.println( Globals.lang("resolved") +" " +auxParser.getResolvedKeysCount());
+      if (auxParser.getNotResolvedKeysCount() > 0)
+      {
+        System.out.println( Globals.lang( "not_found" ) + " " +
+                            auxParser.getNotResolvedKeysCount() ) ;
+        System.out.println( returnValue ) ;
+      }
+      int nested = auxParser.getNestedAuxCounter() ;
+      if (nested > 0)
+        System.out.println( Globals.lang("nested_aux_files") +" " +nested);
+
+    }
+    return back ;
+  }
+}
diff --git a/src/java/net/sf/jabref/wizard/auximport/AuxSubGenerator.java b/src/java/net/sf/jabref/wizard/auximport/AuxSubGenerator.java
new file mode 100644
index 0000000..f50fd80
--- /dev/null
+++ b/src/java/net/sf/jabref/wizard/auximport/AuxSubGenerator.java
@@ -0,0 +1,371 @@
+/*
+Copyright (C) 2004 R. Nagel
+
+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
+
+*/
+
+/**
+ * <p>Title: Latex Aux to Bibtex</p>
+ *
+ * <p>Description: generates a sub-database which contains only bibtex entries
+ * from input aux file</p>
+ *
+ * <p>Copyright: Copyright (c) 2004</p>
+ *
+ * <p>Company: </p>
+ *
+ * @version 1.0
+ * @author r.nagel
+ *
+ * @todo Redesign of dialog structure for an assitent like feeling....
+ *   Now - the unknown bibtex entries cannot inserted into the reference
+ *   database without closing the dialog.
+ */
+
+// created by : r.nagel 23.08.2004
+//
+// modified : - 11.04.2005
+//              handling \\@input{file.aux} tag in aux files (nested aux files)
+
+
+package net.sf.jabref.wizard.auximport ;
+
+import java.io.* ;
+import java.util.regex.* ;
+import java.util.* ;
+
+import net.sf.jabref.* ;
+import net.sf.jabref.imports.* ;
+
+public class AuxSubGenerator
+{
+
+  private HashSet mySet ; // all unique bibtex keys in aux file
+
+  private Vector notFoundList ; // all not solved bibtex keys
+
+  private BibtexDatabase db ; // reference database
+  private BibtexDatabase auxDB ; // contains only the bibtex keys who found in aux file
+
+  private int nestedAuxCounter ;  // counts the nested aux files
+
+
+  public AuxSubGenerator(BibtexDatabase refDBase)
+  {
+    mySet = new HashSet(20) ;
+    notFoundList = new Vector() ;
+    db = refDBase ;
+  }
+
+  public final void setReferenceDatabase(BibtexDatabase newRefDB)
+  {
+    db = newRefDB ;
+  }
+
+  /**
+   * parseAuxFile
+   * read the Aux file and fill up some intern data structures.
+   * Nested aux files (latex \\include) supported!
+   *
+   * @param filename String : Path to LatexAuxFile
+   * @return boolean, true = no error occurs
+   */
+
+  // found at comp.text.tex
+  //  > Can anyone tell be the information held within a .aux file?  Is there a
+  //  > specific format to this file?
+  //
+  // I don't think there is a particular format. Every package, class
+  // or document can write to the aux file. The aux file consists of LaTeX macros
+  // and is read at the \begin{document} and again at the \end{document}.
+  //
+  // It usually contains information about existing labels
+  //  \\newlabel{sec:Intro}{{1}{1}}
+  // and citations
+  //  \citation{hiri:conv:1993}
+  // and macros to write information to other files (like toc, lof or lot files)
+  //  \@writefile{toc}{\contentsline {section}{\numberline
+  // {1}Intro}{1}}
+  // but as I said, there can be a lot more
+
+  // aux file :
+  //
+  // \\citation{x}  x = used reference of bibtex library entry
+  //
+  // \\@input{x}  x = nested aux file
+  //
+  // the \\bibdata{x} directive contains information about the
+  // bibtex library file -> x = name of bib file
+  //
+  // \\bibcite{x}{y}
+  //   x is a label for an item and y is the index in bibliography
+
+  public final boolean parseAuxFile(String filename)
+  {
+    // regular expressions
+    Pattern pattern ;
+    Matcher matcher ;
+
+    // while condition
+    boolean weiter = false ;
+
+    // return value -> default: no error
+    boolean back = true ;
+
+    // fileopen status
+    boolean loopFileOpen = false ;
+
+    // the important tag
+    pattern = Pattern.compile( "\\\\citation\\{.+\\}" ) ;
+
+    // input-file-buffer
+    BufferedReader br = null ;
+
+    // filelist, used for nested aux files
+    Vector fileList = new Vector(5) ;
+    fileList.add( filename );
+
+    // get the file path
+    File dummy = new File( filename ) ;
+    String path = dummy.getParent() ;
+    if (path != null)
+      path = path + dummy.separator ;
+    else
+      path = "" ;
+
+    nestedAuxCounter = -1 ;  // count only the nested reads
+
+    // index of current file in list
+    int fileIndex = 0 ;
+
+    while (fileIndex < fileList.size())
+    {
+      String fName = (String) fileList.elementAt( fileIndex ) ;
+      try
+      {
+//        System.out.println("read #"+fName +"#") ;
+        br = new BufferedReader( new FileReader( fName ) ) ;
+        weiter = true ;
+        loopFileOpen = true ;
+      }
+      catch ( FileNotFoundException fnfe )
+      {
+        System.out.println( "Cannot locate input file! " + fnfe.getMessage() ) ;
+        // System.exit( 0 ) ;
+        back = false ;
+        weiter = false ;
+        loopFileOpen = false ;
+      }
+
+      while ( weiter )
+      {
+        String line ;
+        try
+        {
+          line = br.readLine() ;
+        }
+        catch ( IOException ioe )
+        {
+          line = null ;
+          weiter = false ;
+        }
+
+        if ( line != null )
+        {
+          matcher = pattern.matcher( line ) ;
+
+          while ( matcher.find() )
+          {
+            // extract the bibtex-key(s) XXX from \citation{XXX} string
+            int len = matcher.end() - matcher.start() ;
+            if ( len > 11 )
+            {
+              String str = matcher.group().substring( matcher.start() + 10,
+                  matcher.end() - 1 ) ;
+              // could be an comma separated list of keys
+              String keys[] = str.split( "," ) ;
+              if ( keys != null )
+              {
+                int keyCount = keys.length ;
+                for ( int t = 0 ; t < keyCount ; t++ )
+                {
+                  String dummyStr = keys[t] ;
+                  if ( dummyStr != null )
+                  {
+                    // delete all unnecessary blanks and save key into an set
+                    mySet.add( dummyStr.trim() ) ;
+//                System.out.println("found " +str +" in AUX") ;
+                  }
+                }
+              }
+            }
+          }
+          // try to find a nested aux file
+          int index = line.indexOf( "\\@input{" ) ;
+          if ( index >= 0 )
+          {
+            int start = index + 8 ;
+            int end = line.indexOf( "}", start ) ;
+            if ( end > start )
+            {
+              String str = path + line.substring( index + 8, end ) ;
+
+              // if filename already in filelist
+              if (!fileList.contains( str ) )
+              {
+                 fileList.add(str);   // insert file into filelist
+              }
+            }
+          }
+        } // line != null
+        else weiter = false ;
+      } // end of while
+
+      if ( loopFileOpen ) // only close, if open sucessful
+      {
+        try
+        {
+          br.close() ;
+          nestedAuxCounter++ ;
+        }
+        catch ( IOException ioe )
+        {}
+      }
+
+      fileIndex++ ; // load next file
+    }
+
+    return back ;
+  }
+
+  /**
+   * resolveTags
+   * Try to find an equivalent bibtex entry into reference database for all keys
+   * (found in aux file). This methode will fill up some intern data structures.....
+   */
+  public final void resolveTags()
+  {
+    auxDB = new BibtexDatabase() ;
+    notFoundList.clear();
+
+    Iterator it = mySet.iterator() ;
+
+    // forall bibtex keys (found in aux-file) try to find an equivalent
+    // entry into reference database
+    while (it.hasNext())
+    {
+      String str = (String) it.next() ;
+      BibtexEntry entry = db.getEntryByKey(str);
+
+      if (entry == null)
+      {
+        notFoundList.add(str) ;
+      } else
+      {
+        try
+        {
+          auxDB.insertEntry( entry ) ;
+        }
+        catch (Exception e) {}
+      }
+    }
+  }
+
+  /**
+   * generate
+   * Shortcut methode for easy generation.
+   *
+   * @param auxFileName String
+   * @param bibDB BibtexDatabase - reference database
+   * @return Vector - contains all not resolved bibtex entries
+   */
+  public final Vector generate(String auxFileName, BibtexDatabase bibDB)
+  {
+    setReferenceDatabase(bibDB);
+    parseAuxFile(auxFileName) ;
+    resolveTags();
+
+    return notFoundList ;
+  }
+
+  public BibtexDatabase getGeneratedDatabase()
+  {
+    if (auxDB == null)
+      auxDB = new BibtexDatabase() ;
+
+    return auxDB ;
+  }
+
+  public final int getFoundKeysInAux()
+  {
+    return mySet.size() ;
+  }
+
+  public final int getResolvedKeysCount()
+  {
+    return auxDB.getEntryCount() ;
+  }
+
+  public final int getNotResolvedKeysCount()
+  {
+    return notFoundList.size() ;
+  }
+
+  /** reset all used datastructures */
+  public final void clear()
+  {
+    mySet.clear() ;
+    notFoundList.clear();
+    // db = null ;  ???
+  }
+
+  /** returns a vector off all not resolved bibtex entries found in auxfile */
+  public Vector getNotFoundList()
+  {
+    return notFoundList ;
+  }
+
+  /** returns the number of nested aux files, read by the last call of
+   *  generate method */
+  public int getNestedAuxCounter()
+  {
+    return this.nestedAuxCounter ;
+  }
+
+/*
+  public class FileNameString extends String
+  {
+    public boolean equals(Object anObject)
+    {
+      if (anObject == null)
+        return false ;
+
+      if (anObject.hashCode() == this.hashCode())
+        return true ;
+
+      return false ;
+    }
+  }
+*/
+}
diff --git a/src/java/net/sf/jabref/wizard/auximport/gui/FromAuxDialog.java b/src/java/net/sf/jabref/wizard/auximport/gui/FromAuxDialog.java
new file mode 100644
index 0000000..ada464a
--- /dev/null
+++ b/src/java/net/sf/jabref/wizard/auximport/gui/FromAuxDialog.java
@@ -0,0 +1,382 @@
+/*
+Copyright (C) 2004 R. Nagel
+
+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
+
+*/
+
+// created by : r.nagel 23.08.2004
+//
+// modified :
+
+
+package net.sf.jabref.wizard.auximport.gui ;
+
+import java.awt.* ;
+import javax.swing.* ;
+import javax.swing.border.* ;
+import java.awt.event.* ;
+import java.io.File;
+
+
+import net.sf.jabref.* ;
+import net.sf.jabref.wizard.auximport.* ;
+
+public class FromAuxDialog
+    extends JDialog
+{
+
+  private JPanel panel1 = new JPanel() ;
+  private BorderLayout borderLayout1 = new BorderLayout() ;
+  private JPanel statusPanel = new JPanel() ;
+  private JPanel jPanel2 = new JPanel() ;
+  private JPanel optionsPanel = new JPanel() ;
+  private JButton okButton = new JButton() ;
+  private JButton cancelButton = new JButton() ;
+  private JButton generateButton = new JButton() ;
+  private TitledBorder titledBorder1 ;
+
+  private JComboBox dbChooser = new JComboBox() ;
+  private JTextField auxFileField ;
+  private JButton browseAuxFileButton ;
+
+  private JList notFoundList ;
+  private JTextArea statusInfos ;
+
+  // all open databases from JabRefFrame
+  private JTabbedPane parentTabbedPane ;
+
+  private boolean okPressed = false ;
+
+  private AuxSubGenerator auxParser ;
+
+
+  public FromAuxDialog( JabRefFrame frame, String title, boolean modal,
+                        JTabbedPane viewedDBs )
+  {
+    super( frame, title, modal ) ;
+
+    parentTabbedPane = viewedDBs ;
+
+    auxParser = new AuxSubGenerator(null) ;
+
+    try
+    {
+      jbInit( frame ) ;
+      pack() ;
+    }
+    catch ( Exception ex )
+    {
+      ex.printStackTrace() ;
+    }
+  }
+
+  private void jbInit( JabRefFrame parent ) {
+    panel1.setLayout( borderLayout1 ) ;
+    okButton.setText( Globals.lang( "Ok" ) ) ;
+    okButton.setEnabled(false);
+    okButton.addActionListener( new FromAuxDialog_ok_actionAdapter( this ) ) ;
+    cancelButton.setText( Globals.lang( "Cancel" ) ) ;
+    cancelButton.addActionListener( new FromAuxDialog_Cancel_actionAdapter( this ) ) ;
+    generateButton.setText(Globals.lang("Generate"));
+    generateButton.addActionListener( new FromAuxDialog_generate_actionAdapter( this ) );
+
+    initOptionsPanel(parent) ;
+
+    initStatusPanel() ;
+
+    this.setModal( true ) ;
+    this.setResizable( false ) ;
+    this.setTitle( Globals.lang("AUX file import" )) ;
+    getContentPane().add( panel1 ) ;
+
+    panel1.add( optionsPanel, BorderLayout.NORTH ) ;
+    panel1.add( jPanel2, BorderLayout.SOUTH ) ;
+    jPanel2.add( generateButton, null) ;
+    jPanel2.add( okButton, null ) ;
+    jPanel2.add( cancelButton, null ) ;
+    panel1.add( statusPanel, BorderLayout.CENTER ) ;
+
+    // Key bindings:
+    ActionMap am = statusPanel.getActionMap() ;
+    InputMap im = statusPanel.getInputMap( JComponent.WHEN_IN_FOCUSED_WINDOW ) ;
+    im.put( parent.prefs().getKey( "Close dialog" ), "close" ) ;
+    am.put( "close", new AbstractAction()
+    {
+      public void actionPerformed( ActionEvent e )
+      {
+        dispose() ;
+      }
+    } ) ;
+
+  }
+
+  private void initOptionsPanel(JabRefFrame parent)
+  {
+    // collect the names of all open databases
+    int len = parentTabbedPane.getTabCount() ;
+    for ( int t = 0 ; t < len ; t++ )
+    {
+      dbChooser.addItem( ( String ) parentTabbedPane.getTitleAt( t ) ) ;
+    }
+
+    // panel view
+    GridBagLayout gbl = new GridBagLayout() ;
+    GridBagConstraints con = new GridBagConstraints() ;
+    con.weightx = 0 ;
+    con.insets = new Insets( 5, 10, 0, 10 ) ;
+    con.fill = GridBagConstraints.HORIZONTAL ;
+
+    TitledBorder border = new TitledBorder( BorderFactory.createLineBorder(
+        new Color( 153, 153, 153 ), 2 ),
+                                            Globals.lang( "Options" ) ) ;
+    optionsPanel.setBorder( border ) ;
+    optionsPanel.setLayout( gbl ) ;
+
+    // Database
+    JLabel lab1 = new JLabel( Globals.lang( "Reference database" ) + ":" ) ;
+    lab1.setHorizontalAlignment( SwingConstants.LEFT ) ;
+    gbl.setConstraints( lab1, con ) ;
+    optionsPanel.add( lab1 ) ;
+    con.gridwidth = GridBagConstraints.REMAINDER ;
+    gbl.setConstraints( dbChooser, con ) ;
+    optionsPanel.add( dbChooser ) ;
+
+    // AUX
+    con.gridwidth = 1 ;
+    con.weightx = 0 ;
+    con.insets = new Insets( 5, 10, 15, 10 ) ;
+    con.fill = GridBagConstraints.BOTH ;
+    lab1 = new JLabel( Globals.lang( "LaTeX AUX file" ) + ":" ) ;
+    lab1.setHorizontalAlignment( SwingConstants.LEFT ) ;
+    gbl.setConstraints( lab1, con ) ;
+    optionsPanel.add( lab1 ) ;
+    con.weightx = 1 ;
+    auxFileField = new JTextField( "", 25 ) ;
+    gbl.setConstraints( auxFileField, con ) ;
+    optionsPanel.add( auxFileField ) ;
+    con.weightx = 0 ;
+    con.insets = new Insets( 5, 10, 15, 2 ) ;
+    browseAuxFileButton = new JButton( Globals.lang( "Browse" ) ) ;
+    browseAuxFileButton.addActionListener( new BrowseAction(
+                                             auxFileField,
+                                             parent));
+    gbl.setConstraints( browseAuxFileButton, con ) ;
+    optionsPanel.add( browseAuxFileButton ) ;
+
+  }
+
+  private void initStatusPanel()
+  {
+    GridBagLayout gbl = new GridBagLayout() ;
+    GridBagConstraints con = new GridBagConstraints() ;
+    con.weightx = 0 ;
+    con.insets = new Insets( 5, 10, 0, 10 ) ;
+    con.fill = GridBagConstraints.HORIZONTAL ;
+
+    titledBorder1 = new TitledBorder( BorderFactory.createLineBorder( new Color(
+        153, 153, 153 ), 2 ), Globals.lang( "Results" ) ) ;
+
+    statusPanel.setLayout(gbl);
+    statusPanel.setBorder( titledBorder1 ) ;
+
+    JLabel lab1 = new JLabel( Globals.lang( "Unknown bibtex entries" ) + ":" ) ;
+    lab1.setHorizontalAlignment( SwingConstants.LEFT ) ;
+    con.gridwidth = 1 ;
+    gbl.setConstraints( lab1, con ) ;
+    statusPanel.add( lab1 ) ;
+
+    lab1 = new JLabel( Globals.lang( "Messages" ) + ":" ) ;
+    lab1.setHorizontalAlignment( SwingConstants.LEFT ) ;
+    con.gridwidth = GridBagConstraints.REMAINDER ;
+    gbl.setConstraints( lab1, con ) ;
+    statusPanel.add( lab1 ) ;
+
+
+    notFoundList = new JList() ;
+    JScrollPane listScrollPane = new JScrollPane(notFoundList);
+    listScrollPane.setPreferredSize(new Dimension(250, 120));
+    con.gridwidth = 1 ;
+    con.weightx = 0 ;
+    con.gridheight = 2 ;
+    con.insets = new Insets( 5, 10, 15, 10 ) ;
+    con.fill = GridBagConstraints.BOTH ;
+    gbl.setConstraints(listScrollPane, con);
+    statusPanel.add( listScrollPane) ;
+
+    statusInfos = new JTextArea("", 5, 20) ;
+    statusInfos.setBorder(BorderFactory.createEtchedBorder());
+    statusInfos.setEditable(false);
+    con.gridheight = 1 ;
+    gbl.setConstraints(statusInfos, con);
+    statusPanel.add(statusInfos) ;
+
+  }
+
+// ---------------------------------------------------------------------------
+
+  void ok_actionPerformed( ActionEvent e )
+  {
+    okPressed = true ;
+    dispose() ;
+  }
+
+  void Cancel_actionPerformed( ActionEvent e )
+  {
+    dispose() ;
+  }
+
+  void generate_actionPerformed( ActionEvent e )
+  {
+     generateButton.setEnabled(false);
+     BasePanel bp = (BasePanel) parentTabbedPane.getComponentAt(
+                                          dbChooser.getSelectedIndex())  ;
+     notFoundList.removeAll() ;
+     statusInfos.setText(null);
+     BibtexDatabase refBase = bp.getDatabase() ;
+     String auxName = auxFileField.getText() ;
+
+     if (auxName != null)
+       if ((refBase != null) && (auxName.length() > 0))
+       {
+         auxParser.clear();
+         notFoundList.setListData(auxParser.generate( auxName, refBase ) ) ;
+
+         statusInfos.append( Globals.lang("keys in database") +" " +refBase.getEntryCount() ) ;
+         statusInfos.append( "\n" +Globals.lang("found in aux file") +" "+auxParser.getFoundKeysInAux());
+         statusInfos.append( "\n" +Globals.lang("resolved") +" " +auxParser.getResolvedKeysCount());
+         statusInfos.append( "\n" +Globals.lang("not found") +" " +auxParser.getNotResolvedKeysCount());
+
+         int nested = auxParser.getNestedAuxCounter() ;
+         if (nested > 0)
+           statusInfos.append( "\n" +Globals.lang("nested_aux_files") +" " +nested);
+
+
+         okButton.setEnabled(true);
+      }
+
+     // the generated database contains no entries -> no active ok-button
+     if (auxParser.getGeneratedDatabase().getEntryCount() < 1)
+     {
+       statusInfos.append( "\n" +Globals.lang("empty database")) ;
+       okButton.setEnabled( false ) ;
+     }
+
+     generateButton.setEnabled(true);
+  }
+
+
+  public boolean okPressed()
+  {
+    return okPressed ;
+  }
+
+  public BibtexDatabase getGenerateDB()
+  {
+    return auxParser.getGeneratedDatabase() ;
+  }
+
+// ---------------------------------------------------------------------------
+
+  /**
+   * Action used to produce a "Browse" button for one of the text fields.
+   */
+  class BrowseAction extends AbstractAction
+  {
+    private JTextField comp ;
+    private JabRefFrame _frame;
+
+    public BrowseAction( JTextField tc, JabRefFrame frame)
+    {
+      super( Globals.lang( "Browse" ) ) ;
+      _frame = frame ;
+      comp = tc ;
+    }
+
+    public void actionPerformed( ActionEvent e )
+    {
+      String chosen = null ;
+      chosen = Globals.getNewFile( _frame, Globals.prefs, new File( comp.getText() ),
+                                   ".aux",
+                                   JFileChooser.OPEN_DIALOG, false ) ;
+      if ( chosen != null )
+      {
+        File newFile = new File( chosen ) ;
+        comp.setText( newFile.getPath() ) ;
+      }
+    }
+  }
+
+
+}
+
+// ----------- helper class -------------------
+class FromAuxDialog_ok_actionAdapter
+    implements java.awt.event.ActionListener
+{
+  FromAuxDialog adaptee ;
+
+  FromAuxDialog_ok_actionAdapter( FromAuxDialog adaptee )
+  {
+    this.adaptee = adaptee ;
+  }
+
+  public void actionPerformed( ActionEvent e )
+  {
+    adaptee.ok_actionPerformed( e ) ;
+  }
+}
+
+class FromAuxDialog_Cancel_actionAdapter
+    implements java.awt.event.ActionListener
+{
+  FromAuxDialog adaptee ;
+
+  FromAuxDialog_Cancel_actionAdapter( FromAuxDialog adaptee )
+  {
+    this.adaptee = adaptee ;
+  }
+
+  public void actionPerformed( ActionEvent e )
+  {
+    adaptee.Cancel_actionPerformed( e ) ;
+  }
+}
+
+class FromAuxDialog_generate_actionAdapter
+    implements java.awt.event.ActionListener
+{
+  FromAuxDialog adaptee ;
+
+  FromAuxDialog_generate_actionAdapter( FromAuxDialog adaptee )
+  {
+    this.adaptee = adaptee ;
+  }
+
+  public void actionPerformed( ActionEvent e )
+  {
+    adaptee.generate_actionPerformed( e ) ;
+  }
+}
+
+
diff --git a/src/java/net/sf/jabref/wizard/integrity/IntegrityCheck.java b/src/java/net/sf/jabref/wizard/integrity/IntegrityCheck.java
new file mode 100644
index 0000000..5edb651
--- /dev/null
+++ b/src/java/net/sf/jabref/wizard/integrity/IntegrityCheck.java
@@ -0,0 +1,283 @@
+/*
+Copyright (C) 2004 R. Nagel
+
+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
+
+*/
+
+// created by : r.nagel 27.10.2004
+//
+// function : check all bibtex items and report errors, inconsistencies,
+//            warnings, hints and ....
+//
+//     todo : find equal authors: e.g.: D. Knuth = Donald Knuth = Donald E. Knuth
+//            and try to give all items an identically look
+//
+// modified :
+
+
+
+package net.sf.jabref.wizard.integrity ;
+
+import net.sf.jabref.*;
+import java.util.*;
+
+public class IntegrityCheck
+{
+  private Vector messages ;
+
+  public IntegrityCheck()
+  {
+    messages = new Vector() ;
+  }
+
+  public Vector checkBibtexDatabase(BibtexDatabase base)
+  {
+    messages.clear();
+    if (base != null)
+    {
+      Collection col = base.getEntries() ;
+      for( Iterator myIt = col.iterator() ; myIt.hasNext() ;)
+      {
+        Object dat = myIt.next() ;
+        if (dat != null)
+        {
+          checkSingleEntry(( BibtexEntry ) dat) ;
+        }
+      }
+   }
+   return (Vector) messages.clone() ;
+  }
+
+  public Vector checkBibtexEntry(BibtexEntry entry)
+  {
+    messages.clear();
+    checkSingleEntry(entry) ;
+    return (Vector) messages.clone() ;
+//    return messages ;
+  }
+
+  public void checkSingleEntry(BibtexEntry entry)
+  {
+    if (entry == null)
+      return ;
+
+    Object data = entry.getField("author") ;
+    if (data != null)
+      authorNameCheck( data.toString(), "author", entry) ;
+
+    data = entry.getField("editor") ;
+    if (data != null)
+      authorNameCheck( data.toString(), "editor", entry) ;
+
+    data = entry.getField("title") ;
+    if (data != null)
+      titleCheck( data.toString(), "title", entry) ;
+
+    data = entry.getField("year") ;
+    if (data != null)
+      yearCheck( data.toString(), "year", entry) ;
+  }
+
+ /** fills the class Vector (of IntegrityMessage Objects) which did inform about
+  *  failures, hints....
+  *  The Authors or Editors field could be invalid -> try to detect it!
+  *  Knuth, Donald E. and Kurt Cobain and A. Einstein = N,NNaNNaNN
+  */
+  private void authorNameCheck(String names, String fieldName, BibtexEntry entry)
+  {
+    // try to extract the structure of author tag
+    // N = name, ","= seperator, "a" = and
+    StringBuffer structure = new StringBuffer() ;
+    int len = names.length() ;
+    int mode = -1 ;
+    for (int t = 0 ; t < len ; t++)
+    {
+      char ch = names.charAt(t) ;
+      switch (ch)
+      {
+        case ',' :
+          if (mode == 5) // "and"
+            structure.append('a') ;
+          else
+            structure.append('N') ;
+
+          structure.append(',') ;
+          mode = 0 ;
+          break ;
+
+        case ' ' :
+          if (mode == 5) // "and"
+            structure.append('a') ;
+          else
+            if (mode != 0)
+              structure.append('N') ;
+          mode = -1 ; // blank processed
+          break ;
+       case 'a' :
+         if (mode == -1)
+           mode = 2 ;
+         break ;
+       case 'n' :
+         if (mode == 2)
+           mode = 3 ;
+         break ;
+       case 'd' :
+         if (mode == 3)
+           mode = 5 ;
+         break ;
+       default :
+         mode = 1 ;
+      }
+    }
+    if (mode == 5) // "and"
+      structure.append('a') ;
+    else
+      if (mode != 0)
+        structure.append('N') ;
+
+    // Check
+    len = structure.length() ;
+    if (len > 0)
+    {
+      boolean failed = false ;
+      char z1 = structure.charAt(0) ;
+
+      if (structure.charAt(0) != 'N')  // must start by name
+      {
+        messages.add( new IntegrityMessage( IntegrityMessage.NAME_START_WARNING,
+                                            entry, fieldName, null))  ;
+//        back.add("beginning of " +fieldName +" field");
+        failed = true ;
+      }
+
+      if (structure.charAt( structure.length() -1) != 'N')  // end without seperator
+      {
+        messages.add( new IntegrityMessage( IntegrityMessage.NAME_END_WARNING,
+                                            entry, fieldName, null))  ;
+//        back.add("bad end (" +fieldName +" field)");
+        failed = true ;
+      }
+      if (structure.indexOf("NN,NN") > -1)
+      {
+        messages.add( new IntegrityMessage( IntegrityMessage.NAME_SEMANTIC_WARNING,
+                                            entry, fieldName, null))  ;
+//        back.add("something could be wrong in " +fieldName +" field") ;
+        failed = true ;
+      }
+
+//      if (failed)
+//        System.out.println(authors +" #" +structure.toString() +"#") ;
+    }
+//    messages.add( new IntegrityMessage( IntegrityMessage.NAME_END_WARNING,
+//                                        entry, fieldName, null))  ;
+
+  }
+
+
+
+  private void titleCheck(String title, String fieldName, BibtexEntry entry)
+  {
+    int len = title.length() ;
+    int mode = 0 ;
+    int upLowCounter = 0 ;
+//    boolean lastWasSpace = false ;
+    for (int t = 0 ; t < len ; t++)
+    {
+      char ch = title.charAt( t ) ;
+      switch (ch)
+      {
+        case '}' : // end of Sequence
+          if (mode == 0)
+          {
+            // closing brace '}' without an opening
+            messages.add( new IntegrityMessage( IntegrityMessage.UNEXPECTED_CLOSING_BRACE_FAILURE,
+                                            entry, fieldName, null))  ;
+          }
+          else  // mode == 1
+          {
+            mode-- ;
+//            lastWasSpace = true ;
+          }
+          break ;
+
+        case '{' :  // open {
+          mode++ ;
+          break ;
+
+        case ' ' :
+//          lastWasSpace = true ;
+          break ;
+
+        default :
+          if (mode == 0) // out of {}
+          {
+            if ( Character.isUpperCase(ch) && (t > 1))
+            {
+              upLowCounter++ ;
+            }
+          }
+      }
+    }
+    if (upLowCounter > 0)
+    {
+        messages.add( new IntegrityMessage( IntegrityMessage.UPPER_AND_LOWER_HINT,
+                                        entry, fieldName, null))  ;
+
+    }
+  }
+
+  /** Checks, if the number String contains a four digit year */
+  private void yearCheck(String number, String fieldName, BibtexEntry entry)
+  {
+    int len = number.length() ;
+    int digitCounter = 0 ;
+    boolean fourDigitsBlock = false ;
+    boolean containsFourDigits = false ;
+
+    for (int t = 0 ; t < len ; t++)
+    {
+      char ch = number.charAt( t ) ;
+      if ( Character.isDigit(ch))
+      {
+        digitCounter++ ;
+        if (digitCounter == 4)
+          fourDigitsBlock = true ;
+        else
+          fourDigitsBlock = false ;
+      } else
+      {
+        if (fourDigitsBlock)
+          containsFourDigits = true ;
+
+        digitCounter = 0 ;
+      }
+    }
+
+    if ((!containsFourDigits) && (!fourDigitsBlock))
+    {
+      messages.add( new IntegrityMessage( IntegrityMessage.FOUR_DIGITS_HINT,
+                                      entry, fieldName, null))  ;
+    }
+  }
+}
diff --git a/src/java/net/sf/jabref/wizard/integrity/IntegrityMessage.java b/src/java/net/sf/jabref/wizard/integrity/IntegrityMessage.java
new file mode 100644
index 0000000..f9e5086
--- /dev/null
+++ b/src/java/net/sf/jabref/wizard/integrity/IntegrityMessage.java
@@ -0,0 +1,145 @@
+/*
+Copyright (C) 2004 R. Nagel
+
+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
+
+*/
+
+
+// created by : r.nagel 09.12.2004
+//
+// function : a class for wrapping a IntegrityCheck message
+//
+//     todo :
+//
+// modified :
+
+package net.sf.jabref.wizard.integrity ;
+
+import net.sf.jabref.*;
+
+public class IntegrityMessage implements Cloneable
+{
+  // Hints and Infos < 1000 :-)
+  public static final int
+      GENERIC_HINT             = 1,
+      UPPER_AND_LOWER_HINT     = 10,
+      FOUR_DIGITS_HINT         = 11
+
+      ;
+
+  // > 1000 Warnings
+  public static final int
+      GENERIC_WARNING                = 1001,
+      NAME_START_WARNING             = 1010,
+      NAME_END_WARNING               = 1011,
+      NAME_SEMANTIC_WARNING          = 1012
+      ;
+
+  // > 2000 Failure Messages
+  public static final int
+      UNKNONW_FAILURE                    = 2001,
+      UNEXPECTED_CLOSING_BRACE_FAILURE   = 2010
+      ;
+
+  public static int
+      FULL_MODE    = 1,  // print with Bibtex Entry
+      SINLGE_MODE  = 2   // print only Message
+      ;
+
+  private static int printMode = SINLGE_MODE ;
+
+  private int type ;
+  private BibtexEntry entry ;
+  private String fieldName ;
+  private Object additionalInfo ;
+  private String msg ;
+  private boolean fixed ; // the user has changed sometings on BibtexEntry
+
+  public final synchronized static void setPrintMode(int newMode)
+  {
+    printMode = newMode ;
+  }
+
+
+  public IntegrityMessage(int pType, BibtexEntry pEntry, String pFieldName, Object pAdditionalInfo)
+  {
+    this.type = pType;
+    this.entry = pEntry;
+    this.fieldName = pFieldName;
+    this.additionalInfo = pAdditionalInfo;
+    fixed = false ;
+
+    msg = getMessage() ;
+  }
+
+  public String getMessage()
+  {
+    String back = Globals.getIntegrityMessage("ITEXT_"+type) ;
+    if ((back != null) && (fieldName != null))
+    {
+      back = back.replaceAll( "\\$FIELD", fieldName ) ;
+    }
+    return back ;
+  }
+
+  public String toString()
+  {
+    String back = msg ;
+    if (printMode == FULL_MODE)
+    {
+      back = "[" + entry.getCiteKey() + "] " + msg ;
+    }
+    return back ;
+  }
+
+  public int getType()
+  {
+    return type;
+  }
+
+  public BibtexEntry getEntry()
+  {
+    return entry;
+  }
+
+  public String getFieldName()
+  {
+    return fieldName;
+  }
+
+  public Object getAdditionalInfo()
+  {
+    return additionalInfo;
+  }
+
+  public boolean getFixed()
+  {
+    return fixed;
+  }
+
+  public void setFixed(boolean pFixed)
+  {
+    this.fixed = pFixed;
+  }
+}
diff --git a/src/java/net/sf/jabref/wizard/integrity/gui/IntegrityMessagePanel.java b/src/java/net/sf/jabref/wizard/integrity/gui/IntegrityMessagePanel.java
new file mode 100644
index 0000000..678d90d
--- /dev/null
+++ b/src/java/net/sf/jabref/wizard/integrity/gui/IntegrityMessagePanel.java
@@ -0,0 +1,234 @@
+/*
+Copyright (C) 2004 R. Nagel
+
+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
+
+*/
+
+// created by : r.nagel 09.12.2004
+//
+// function : shows the IntegrityMessages produced by IntegrityCheck
+//
+//     todo : several entries not supported
+//
+// modified :
+
+package net.sf.jabref.wizard.integrity.gui ;
+
+import javax.swing.* ;
+import javax.swing.undo.UndoManager;
+import net.sf.jabref.undo.UndoableFieldChange;
+import net.sf.jabref.wizard.text.gui.HintListModel ;
+import java.awt.Dimension ;
+import net.sf.jabref.* ;
+import java.awt.* ;
+import net.sf.jabref.wizard.integrity.*;
+import javax.swing.event.*;
+import java.awt.event.*;
+
+public class IntegrityMessagePanel
+    extends JPanel
+    implements ListSelectionListener, KeyListener, ActionListener
+
+{
+  private JList warnings ;
+  private HintListModel warningData ;
+
+  private IntegrityCheck validChecker ;
+
+  private JTextField content  ;
+  private JButton applyButton ;
+  private JButton fixButton ;
+  private BasePanel basePanel;
+
+  public IntegrityMessagePanel(BasePanel basePanel)
+  {
+    this.basePanel = basePanel;
+    validChecker = new IntegrityCheck() ; // errors, warnings, hints
+
+  // JList --------------------------------------------------------------
+    warningData = new HintListModel() ;
+    warnings = new JList( warningData ) ;
+    warnings.setCellRenderer( new IntegrityListRenderer() );
+    warnings.addListSelectionListener(this);
+
+    JScrollPane paneScrollPane = new JScrollPane( warnings ) ;
+    paneScrollPane.setVerticalScrollBarPolicy(
+        JScrollPane.VERTICAL_SCROLLBAR_ALWAYS ) ;
+    paneScrollPane.setPreferredSize( new Dimension( 540, 255 ) ) ;
+    paneScrollPane.setMinimumSize( new Dimension( 10, 10 ) ) ;
+
+  // Fix Panel ---------------------------------------------------------
+    JPanel fixPanel = new JPanel() ;
+    BoxLayout box = new BoxLayout(fixPanel, BoxLayout.LINE_AXIS) ;
+
+    JLabel label1 = new JLabel(Globals.lang("Field_content")) ;
+
+    content = new JTextField(40) ;
+    content.addKeyListener(this);
+    applyButton = new JButton(Globals.lang("Apply")) ;
+    applyButton.addActionListener(this) ;
+    applyButton.setEnabled(false);
+    fixButton = new JButton(Globals.lang("Suggest")) ;
+    fixButton.setEnabled(false);
+
+    fixPanel.add(label1) ;
+    fixPanel.add(content) ;
+    fixPanel.add(applyButton) ;
+    fixPanel.add(fixButton) ;
+
+  // Main Panel --------------------------------------------------------
+    this.setLayout( new BorderLayout() );
+    this.add( paneScrollPane, BorderLayout.CENTER ) ;
+    this.add( fixPanel, BorderLayout.SOUTH) ;
+  }
+
+  // ------------------------------------------------------------------------
+
+  public void updateView( BibtexEntry entry )
+  {
+    warningData.clear();
+    IntegrityMessage.setPrintMode( IntegrityMessage.SINLGE_MODE) ;
+    warningData.setData( validChecker.checkBibtexEntry( entry ) ) ;
+  }
+
+  public void updateView( BibtexDatabase base )
+  {
+    warningData.clear();
+    IntegrityMessage.setPrintMode( IntegrityMessage.FULL_MODE) ;
+    warningData.setData( validChecker.checkBibtexDatabase( base ) ) ;
+  }
+
+
+  // ------------------------------------------------------------------------
+  //This method is required by ListSelectionListener.
+  public void valueChanged( ListSelectionEvent e )
+  {
+    if ( e.getValueIsAdjusting() )
+    {
+      Object obj = warnings.getSelectedValue() ;
+      String str = "" ;
+      if (obj != null)
+      {
+        IntegrityMessage msg = (IntegrityMessage) obj ;
+        BibtexEntry entry = msg.getEntry() ;
+
+        if (entry != null)
+        {
+            str = (String) entry.getField(msg.getFieldName()) ;
+        }
+      }
+      content.setText(str);
+      applyButton.setEnabled(false);
+    }
+  }
+
+// --------------------------------------------------------------------------
+// This methods are required by KeyListener
+  public void keyPressed( KeyEvent e )
+  {
+  }
+
+  public void keyReleased( KeyEvent e )
+  {
+    applyButton.setEnabled(true);
+    if (e.getKeyCode() == e.VK_ENTER)
+    {
+      applyButton.doClick();
+    }
+  }
+
+  public void keyTyped( KeyEvent e )
+  {
+  }
+
+  public void actionPerformed( ActionEvent e )
+  {
+    Object obj = e.getSource() ;
+    if (obj == applyButton)
+    {
+      Object data = warnings.getSelectedValue() ;
+      if (data != null)
+      {
+        IntegrityMessage msg = (IntegrityMessage) data ;
+        BibtexEntry entry = msg.getEntry() ;
+
+        if (entry != null)
+        {
+//          System.out.println("update") ;
+            Object oldContent = entry.getField(msg.getFieldName());
+            UndoableFieldChange edit = new UndoableFieldChange(entry, msg.getFieldName(), oldContent, 
+                        content.getText());
+            entry.setField(msg.getFieldName(), content.getText());
+            basePanel.undoManager.addEdit(edit);
+            basePanel.markBaseChanged();
+            msg.setFixed(true);
+//          updateView(entry) ;
+          warningData.valueUpdated(warnings.getSelectedIndex()) ;
+        }
+      }
+
+      applyButton.setEnabled(false);
+    }
+  }
+
+  // ---------------------------------------------------------------------------
+  // ---------------------------------------------------------------------------
+  class IntegrityListRenderer extends DefaultListCellRenderer
+  {
+    final ImageIcon warnIcon = new ImageIcon( GUIGlobals.integrityWarn ) ;
+    final ImageIcon infoIcon = new ImageIcon( GUIGlobals.integrityInfo ) ;
+    final ImageIcon failIcon = new ImageIcon( GUIGlobals.integrityFail ) ;
+    final ImageIcon fixedIcon = new ImageIcon( GUIGlobals.completeTagIcon) ;
+
+    public Component getListCellRendererComponent(
+        JList list,
+        Object value, // value to display
+        int index, // cell index
+        boolean iss, // is the cell selected
+        boolean chf ) // the list and the cell have the focus
+    {
+      super.getListCellRendererComponent( list, value, index, iss, chf ) ;
+
+      if (value != null)
+      {
+        IntegrityMessage msg = (IntegrityMessage) value ;
+        if (msg.getFixed())
+        {
+          setIcon(fixedIcon) ;
+        }
+        else
+        {
+          int id = msg.getType() ;
+          if ( id < 1000 )
+            setIcon( infoIcon ) ;
+          else if ( id < 2000 )
+            setIcon( warnIcon ) ;
+          else setIcon( failIcon ) ;
+        }
+      }
+      return this ;
+    }
+  }
+
+}
diff --git a/src/java/net/sf/jabref/wizard/integrity/gui/IntegrityWizard.java b/src/java/net/sf/jabref/wizard/integrity/gui/IntegrityWizard.java
new file mode 100644
index 0000000..6a6b4dd
--- /dev/null
+++ b/src/java/net/sf/jabref/wizard/integrity/gui/IntegrityWizard.java
@@ -0,0 +1,182 @@
+/*
+ Copyright (C) 2004 R. Nagel
+
+ 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
+
+ */
+
+// created by : r.nagel 14.09.2004
+//
+// function :
+//
+// todo:
+//
+// modified:
+//
+
+package net.sf.jabref.wizard.integrity.gui ;
+
+import javax.swing.JDialog ;
+import net.sf.jabref.BibtexEntry ;
+import net.sf.jabref.JabRefFrame ;
+import javax.swing.JPanel;
+import java.awt.*;
+import javax.swing.*;
+import net.sf.jabref.*;
+import java.awt.event.*;
+import java.net.URL;
+import javax.swing.border.EtchedBorder;
+import java.io.IOException;
+
+public class IntegrityWizard
+    extends JDialog
+    implements ActionListener
+{
+
+  private JabRefFrame _frame ;
+  private BibtexDatabase dbase ;
+  private BasePanel basePanel;
+  private JButton closeButton ;
+  private JButton startButton ;
+  private IntegrityMessagePanel warnPanel ;
+
+  public IntegrityWizard( JabRefFrame frame, BasePanel basePanel)
+  {
+    super( frame, "dialog", true ) ;
+
+    _frame = frame ;
+    this.basePanel = basePanel;
+    dbase = basePanel.database();
+
+    try
+    {
+      jbInit() ;
+      pack() ;
+    }
+    catch ( Exception ex )
+    {
+      ex.printStackTrace() ;
+    }
+  }
+
+  private void jbInit() {
+//    this.setModal( true ) ;
+    this.setResizable( false ) ;
+
+    // messages
+    this.setTitle( Globals.lang("Integrity_check") ) ;//Globals.lang( "Plain_text_import" ) + " " + typeStr ) ;
+    //warnPanel = new IntegrityMessagePanel() ;
+    //this.setTitle( "Experimental feature - Integrity Check") ;//Globals.lang( "Plain_text_import" ) + " " + typeStr ) ;
+    warnPanel = new IntegrityMessagePanel(basePanel) ;
+
+
+    // ButtonPanel
+    JPanel buttonPanel = new JPanel() ;
+    GridBagLayout gbl = new GridBagLayout() ;
+    GridBagConstraints con = new GridBagConstraints() ;
+    con.weightx = 0 ;
+    con.insets = new Insets( 5, 10, 0, 10 ) ;
+    con.fill = GridBagConstraints.HORIZONTAL ;
+
+    // Buttons
+    startButton = new JButton(Globals.lang("Scan")) ;
+    startButton.addActionListener( this) ;
+    closeButton = new JButton(Globals.lang("Close"));
+    closeButton.addActionListener( this) ;
+
+    // insert Buttons
+    con.gridwidth = GridBagConstraints.REMAINDER ;
+    gbl.setConstraints( startButton, con ) ;
+    buttonPanel.add( startButton ) ;
+
+    gbl.setConstraints( closeButton, con ) ;
+    buttonPanel.add( closeButton ) ;
+
+    // ----------------------------------------------------------------------
+    // add a short info, if available
+
+    JEditorPane infoText = null ;
+
+    URL infoURL = JabRef.class.getResource(GUIGlobals.getLocaleHelpPath()
+                                           +GUIGlobals.shortIntegrityCheck);
+    if (infoURL != null)
+      try
+      {
+        infoText = new JEditorPane() ;
+        infoText.setEditable(false);
+        infoText.setPreferredSize( new Dimension(220, 60));
+        infoText.setMinimumSize( new Dimension(180, 50));
+        infoText.setPage(infoURL);
+        infoText.setBackground(GUIGlobals.infoField);
+        infoText.setBorder(new EtchedBorder(EtchedBorder.LOWERED));
+//        bottomPanel.add( infoText, BorderLayout.CENTER ) ;
+      }
+      catch (IOException e)
+      {
+        infoText = null ;
+      }
+
+    // -----------------------------------------------------------------------
+
+    // content
+    Container content = this.getContentPane() ;
+    content.setLayout( new BorderLayout());
+
+    if (infoText != null) // only if some help available
+    {
+      content.add( infoText, BorderLayout.PAGE_START ) ;
+    }
+    content.add(warnPanel, BorderLayout.CENTER) ;
+    content.add(buttonPanel, BorderLayout.PAGE_END) ;
+  }
+
+
+// ---------------------------------------------------------------------------
+// ---------------------------------------------------------------------------
+
+  public void actionPerformed( ActionEvent e )
+  {
+    Object sender = e.getSource() ;
+
+    if (sender == closeButton)
+    {
+      dispose() ;
+    }
+    else if (sender == startButton)
+    {
+      startButton.setEnabled(false);
+      Runnable scanWork = new Runnable()
+      {
+        public void run()
+        {
+          warnPanel.updateView(dbase);
+        }
+      } ;
+      SwingUtilities.invokeLater(scanWork);
+      startButton.setEnabled(true);
+    }
+  }
+
+
+
+}
diff --git a/src/java/net/sf/jabref/wizard/text/TagToMarkedTextStore.java b/src/java/net/sf/jabref/wizard/text/TagToMarkedTextStore.java
new file mode 100644
index 0000000..aeaec7f
--- /dev/null
+++ b/src/java/net/sf/jabref/wizard/text/TagToMarkedTextStore.java
@@ -0,0 +1,124 @@
+/*
+ Copyright (C) 2004 R. Nagel
+
+ 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
+
+ */
+
+// created by : r.nagel 06.10.2004
+//
+// function : save the textposition for tags in a recent TextInputDialog context
+//
+// todo     :
+//
+// modified :
+
+package net.sf.jabref.wizard.text ;
+
+import java.util.*;
+import javax.swing.* ;
+import javax.swing.text.*;
+
+
+public class TagToMarkedTextStore
+{
+  private class TMarkedStoreItem
+  {
+    int start ;
+    int end ;
+  }
+
+  private HashMap tagMap ;
+
+  public TagToMarkedTextStore()
+  {
+    tagMap = new HashMap(10) ;
+  }
+
+  /** appends a selection propertie for tag */
+  public void appendPosition(String tag, int start, int end)
+  {
+    LinkedList ll ;
+    Object dummy = tagMap.get(tag) ;
+    if (dummy == null)
+    {
+      ll = new LinkedList() ;
+      tagMap.put(tag, ll) ;
+    }
+    else
+    {
+      ll = (LinkedList) dummy ;
+    }
+
+    TMarkedStoreItem item = new TMarkedStoreItem() ;
+    ll.add(item);
+    item.end = end ;
+    item.start = start ;
+  }
+
+  /** insert selection propertie for tag, old entries were deleted */
+  public void insertPosition(String tag, int start, int end)
+  {
+    LinkedList ll ;
+    Object dummy = tagMap.get(tag) ;
+    if (dummy == null)
+    {
+      ll = new LinkedList() ;
+      tagMap.put(tag, ll) ;
+    }
+    else
+    {
+      ll = (LinkedList) dummy ;
+      ll.clear();
+    }
+
+    TMarkedStoreItem item = new TMarkedStoreItem() ;
+    ll.add(item);
+    item.end = end ;
+    item.start = start ;
+  }
+
+  /** set the Style for the tag if an entry is available */
+  public void setStyleForTag(String tag, String style, StyledDocument doc)
+  {
+    Object dummy = tagMap.get(tag) ;
+    if (dummy != null)
+    {
+      LinkedList ll = (LinkedList) dummy ;
+
+      // iterate over all saved selections
+      for (ListIterator lIt = ll.listIterator() ; lIt.hasNext() ; )
+      {
+        Object du2 = lIt.next() ;
+        if (du2 != null)
+        {
+          TMarkedStoreItem item = ( TMarkedStoreItem ) du2 ;
+          doc.setCharacterAttributes( item.start, item.end - item.start,
+                                      doc.getStyle( style ), true ) ;
+        }
+      }
+    }
+  }
+
+
+}
diff --git a/src/java/net/sf/jabref/wizard/text/gui/HintListModel.java b/src/java/net/sf/jabref/wizard/text/gui/HintListModel.java
new file mode 100644
index 0000000..9f5d6f7
--- /dev/null
+++ b/src/java/net/sf/jabref/wizard/text/gui/HintListModel.java
@@ -0,0 +1,27 @@
+package net.sf.jabref.wizard.text.gui ;
+
+import javax.swing.DefaultListModel;
+import javax.swing.table.AbstractTableModel;
+import javax.swing.table.TableModel;
+import javax.swing.event.TableModelListener;
+import java.util.*;
+
+public class HintListModel extends DefaultListModel
+{
+  public void setData(Vector newData)
+  {
+    clear() ;
+    if (newData != null)
+    {
+      for(Enumeration myEnum = newData.elements() ; myEnum.hasMoreElements() ; )
+      {
+        addElement(myEnum.nextElement());
+      }
+    }
+  }
+
+  public void valueUpdated(int index)
+  {
+    super.fireContentsChanged(this, index, index);
+  }
+}
diff --git a/src/java/net/sf/jabref/wizard/text/gui/OverlayPanel.java b/src/java/net/sf/jabref/wizard/text/gui/OverlayPanel.java
new file mode 100644
index 0000000..572fa75
--- /dev/null
+++ b/src/java/net/sf/jabref/wizard/text/gui/OverlayPanel.java
@@ -0,0 +1,97 @@
+/*
+ Copyright (C) 2004 R. Nagel
+
+ 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
+
+ */
+
+// created by : r.nagel 04.11.2004
+//
+// function : supports an underlying text for jcomponents
+//
+// todo     :
+//
+// modified :
+//
+
+
+package net.sf.jabref.wizard.text.gui ;
+
+import java.awt.* ;
+import java.awt.event.* ;
+import javax.swing.* ;
+
+public class OverlayPanel extends JPanel
+{
+
+  private JLabel label ;
+  private JComponent overlay ;
+
+  private JScrollPane scroller ;
+
+  public OverlayPanel(JComponent container, String text)
+  {
+    OverlayLayout layout = new OverlayLayout(this) ;
+    this.setLayout( layout );
+    overlay = container ;
+
+    label = new JLabel(text) ;
+    label.setFont(new Font("dialog", Font.ITALIC, 18));
+//    label.setForeground(Color.lightGray);
+    label.setForeground( new Color(224, 220, 220) );
+    label.setLocation(0, 0);
+
+     scroller = new JScrollPane( overlay ) ;
+     scroller.setLocation(0, 0);
+
+     scroller.setVerticalScrollBarPolicy( JScrollPane.VERTICAL_SCROLLBAR_ALWAYS ) ;
+
+    add(label) ;
+    add(scroller) ;
+  }
+
+  public void paint(Graphics g)
+  {
+    int len = label.getWidth() ;
+
+    Dimension dim = this.getSize() ;
+    if ((dim.height > 25) && (dim.width > len+10))
+    {
+      int x = (dim.width-len) / 2 ;
+      int y = dim.height / 2 ;
+
+      label.setLocation(x, y) ;
+    }
+
+    super.paint(g);
+  }
+
+/*
+  // it doesn't work well
+  public void addMouseListener(MouseListener listener)
+  {
+    overlay.addMouseListener(listener);
+    super.addMouseListener(listener);
+  }
+*/
+}
diff --git a/src/java/net/sf/jabref/wizard/text/gui/TextInputDialog.java b/src/java/net/sf/jabref/wizard/text/gui/TextInputDialog.java
new file mode 100644
index 0000000..51ebd42
--- /dev/null
+++ b/src/java/net/sf/jabref/wizard/text/gui/TextInputDialog.java
@@ -0,0 +1,865 @@
+/*
+ Copyright (C) 2004 R. Nagel
+
+ 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
+
+ */
+
+// created by : r.nagel 14.09.2004
+//
+// function : import from plain text => simple mark/copy/paste into bibtex entry
+//
+// todo     : - change colors and fonts
+//            - delete selected text
+//            - make textarea editable
+//            - create several bibtex entries in dialog
+//            - if the dialog works with an existing entry (right click menu item)
+//              the cancel option doesn't work well
+//
+// modified :
+//            28.07.2005
+//            - fix: insert button doesnt work
+//            - append a author with "and"
+//            04.11.2004
+//            - experimental: text-input-area with underlying infotext
+//            02.11.2004
+//            - integrity check, which reports errors and warnings for the fields
+//            22.10.2004
+//            - little help box
+//
+
+package net.sf.jabref.wizard.text.gui ;
+
+import java.io.* ;
+import java.net.* ;
+
+import java.awt.* ;
+import java.awt.event.* ;
+import javax.swing.* ;
+import javax.swing.border.* ;
+import javax.swing.event.* ;
+import javax.swing.text.* ;
+
+import net.sf.jabref.* ;
+import net.sf.jabref.wizard.integrity.gui.* ;
+import net.sf.jabref.wizard.text.* ;
+
+public class TextInputDialog
+    extends JDialog implements ActionListener
+{
+  private JButton okButton = new JButton() ;
+  private JButton cancelButton = new JButton() ;
+  private JButton insertButton = new JButton() ;
+  private JPanel panel1 = new JPanel() ;
+  private JPanel buttonPanel = new JPanel() ;
+  private JPanel rawPanel = new JPanel() ;
+  private JPanel sourcePanel = new JPanel() ;
+  private IntegrityMessagePanel warnPanel;
+  private JList fieldList ;
+  private JRadioButton overRadio, appRadio ;
+
+  private OverlayPanel testPanel ;
+
+  private BibtexEntry entry ;
+
+  public JPopupMenu inputMenu = new JPopupMenu() ;
+  private StyledDocument doc ; // content from inputPane
+  private JTextPane textPane ;
+  private JTextArea preview ;
+
+  private boolean inputChanged ; // input changed, fired by insert button
+
+  private TagToMarkedTextStore marked ;
+
+  private JabRefFrame _frame ;
+
+  private boolean okPressed = false ;
+
+  public TextInputDialog( JabRefFrame frame, BasePanel panel, String title, boolean modal,
+                          BibtexEntry bibEntry )
+  {
+    super( frame, title, modal ) ;
+
+    warnPanel = new IntegrityMessagePanel(panel);
+    inputChanged = true ;  // for a first validCheck
+
+
+    _frame = frame ;
+
+    entry = bibEntry ;
+    marked = new TagToMarkedTextStore() ;
+
+    try
+    {
+      jbInit( frame ) ;
+      pack() ;
+    }
+    catch ( Exception ex )
+    {
+      ex.printStackTrace() ;
+    }
+
+    updateSourceView() ;
+  }
+
+  private void jbInit( JabRefFrame parent ) {
+    this.setModal( true ) ;
+    //this.setResizable( false ) ;
+    getContentPane().setLayout(new BorderLayout());
+    String typeStr = Globals.lang( "for" ) ;
+    if ( entry != null )
+    {
+      if ( entry.getType() != null )
+      {
+        typeStr = typeStr + " " + entry.getType().getName() ;
+      }
+    }
+
+    this.setTitle( Globals.lang( "Plain_text_import" ) + " " + typeStr ) ;
+    getContentPane().add( panel1, BorderLayout.CENTER ) ;
+
+    initRawPanel() ;
+    initButtonPanel() ;
+    initSourcePanel() ;
+
+    JTabbedPane tabbed = new JTabbedPane() ;
+    tabbed.addChangeListener(
+        new ChangeListener()
+    {
+      public void stateChanged( ChangeEvent e )
+      {
+        if ( inputChanged )
+        {
+          warnPanel.updateView( entry ) ;
+        }
+      }
+    } ) ;
+
+    tabbed.add( rawPanel, Globals.lang( "Raw_source" ) ) ;
+    tabbed.add( sourcePanel, Globals.lang( "BibTeX_source" ) ) ;
+    tabbed.add( warnPanel, Globals.lang( "Messages_and_Hints" ) ) ;
+
+    // Panel Layout
+    GridBagLayout gbl = new GridBagLayout() ;
+    GridBagConstraints con = new GridBagConstraints() ;
+    con.weightx = 1 ;
+    con.weighty = 1 ;
+    con.insets = new Insets( 5, 10, 0, 10 ) ;
+    con.fill = GridBagConstraints.HORIZONTAL ;
+
+    panel1.setLayout( new BorderLayout() ) ;
+
+    con.gridwidth = GridBagConstraints.REMAINDER ;
+    con.fill = GridBagConstraints.BOTH;
+    //gbl.setConstraints( tabbed, con ) ;
+    panel1.add( tabbed, BorderLayout.CENTER ) ;
+    //gbl.setConstraints( buttonPanel, con ) ;
+    panel1.add( buttonPanel, BorderLayout.SOUTH ) ;
+
+    // Key bindings:
+    ActionMap am = buttonPanel.getActionMap() ;
+    InputMap im = buttonPanel.getInputMap( JComponent.WHEN_IN_FOCUSED_WINDOW ) ;
+    im.put( parent.prefs().getKey( "Close dialog" ), "close" ) ;
+    am.put( "close", new AbstractAction()
+    {
+      public void actionPerformed( ActionEvent e )
+      {
+        dispose() ;
+      }
+    } ) ;
+  }
+
+// ---------------------------------------------------------------------------
+  // Panel with text import functionality
+  private void initRawPanel()
+  {
+
+    rawPanel.setLayout( new BorderLayout() ) ;
+
+        // Textarea
+        textPane = new JTextPane() ;
+
+        textPane.setEditable( false ) ;
+
+        doc = textPane.getStyledDocument() ;
+        addStylesToDocument( doc ) ;
+
+        try
+        {
+          doc.insertString( 0, "", doc.getStyle( "regular" ) ) ;
+        }
+        catch ( Exception e )
+        {}
+
+        testPanel = new OverlayPanel(textPane,
+                                     Globals.lang("Text_Input_Area") ) ;
+
+        testPanel.setPreferredSize( new Dimension( 450, 255) );
+        testPanel.setMaximumSize( new Dimension(450, Integer.MAX_VALUE) );
+
+    // copy/paste Menu
+    PasteAction pasteAction = new PasteAction() ;
+    JMenuItem pasteMI = new JMenuItem( pasteAction ) ;
+    inputMenu.add( new MenuHeaderAction() ) ;
+    inputMenu.addSeparator() ;
+    inputMenu.add( pasteMI ) ;
+
+    //Add listener to components that can bring up popup menus.
+    MouseListener popupListener = new PopupListener( inputMenu ) ;
+    textPane.addMouseListener( popupListener );
+    testPanel.addMouseListener( popupListener );
+
+    // Toolbar
+    JToolBar toolBar = new JToolBar() ;
+    toolBar.add( new ClearAction() ) ;
+    toolBar.setBorderPainted( false ) ;
+    toolBar.addSeparator() ;
+    toolBar.add( pasteAction ) ;
+    toolBar.add( new LoadAction() ) ;
+
+    JPanel leftPanel = new JPanel( new BorderLayout() ) ;
+
+    leftPanel.add( toolBar, BorderLayout.NORTH ) ;
+    leftPanel.add( testPanel, BorderLayout.CENTER ) ;
+
+
+    // ----------------------------------------------------------------
+    JPanel inputPanel = new JPanel() ;
+
+    // Panel Layout
+    GridBagLayout gbl = new GridBagLayout() ;
+    GridBagConstraints con = new GridBagConstraints() ;
+    con.weightx = 0 ;
+    con.insets = new Insets( 5, 5, 0, 5 ) ;
+    con.fill = GridBagConstraints.HORIZONTAL ;
+
+    inputPanel.setLayout( gbl ) ;
+
+    // Border
+    TitledBorder titledBorder1 = new TitledBorder(
+        BorderFactory.createLineBorder(
+            new Color( 153, 153, 153 ), 2 ),
+        Globals.lang( "Input" ) ) ;
+    inputPanel.setBorder( titledBorder1 ) ;
+    //inputPanel.setPreferredSize( new Dimension( 200, 255 ) ) ;
+    inputPanel.setMinimumSize( new Dimension( 10, 10 ) ) ;
+
+    fieldList = new JList( getAllFields() ) ;
+    fieldList.setCellRenderer( new SimpleCellRenderer( fieldList.getFont() ) ) ;
+    ListSelectionModel listSelectionModel = fieldList.getSelectionModel() ;
+    listSelectionModel.setSelectionMode( ListSelectionModel.SINGLE_SELECTION ) ;
+    listSelectionModel.addListSelectionListener( new FieldListSelectionHandler() ) ;
+    fieldList.addMouseListener( new FieldListMouseListener() ) ;
+
+    JScrollPane fieldScroller = new JScrollPane( fieldList ) ;
+    fieldScroller.setVerticalScrollBarPolicy(
+        JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED ) ;
+    //fieldScroller.setPreferredSize( new Dimension( 180, 190 ) ) ;
+    //fieldScroller.setMinimumSize( new Dimension( 180, 190 ) ) ;
+
+    // insert button
+    insertButton.setText( Globals.lang( "Insert" ) ) ;
+    insertButton.addActionListener( this ) ;
+
+    // Radio buttons
+    appRadio = new JRadioButton( Globals.lang( "Append" ) ) ;
+    appRadio.setToolTipText( Globals.lang( "append_the_selected_text_to_bibtex_key") ) ;
+    appRadio.setMnemonic( KeyEvent.VK_A ) ;
+    appRadio.setSelected( true ) ;
+
+    overRadio = new JRadioButton( Globals.lang( "Override" ) ) ;
+    overRadio.setToolTipText( Globals.lang( "override_the_bibtex_key_by_the_selected_text") ) ;
+    overRadio.setMnemonic( KeyEvent.VK_O ) ;
+    overRadio.setSelected( false ) ;
+
+    //Group the radio buttons.
+    ButtonGroup group = new ButtonGroup() ;
+    group.add( appRadio ) ;
+    group.add( overRadio ) ;
+
+    JPanel radioPanel = new JPanel( new GridLayout( 0, 1 ) ) ;
+    radioPanel.add( appRadio ) ;
+    radioPanel.add( overRadio ) ;
+
+    // insert sub components
+    JLabel label1 = new JLabel( Globals.lang( "Available fields" ) ) ;
+    con.gridwidth = GridBagConstraints.REMAINDER ;
+    gbl.setConstraints( label1, con ) ;
+    inputPanel.add( label1 ) ;
+
+    con.gridwidth = GridBagConstraints.REMAINDER ;
+    con.gridheight = 8 ;
+    con.weighty = 1;
+    con.fill = GridBagConstraints.BOTH;
+    gbl.setConstraints( fieldScroller, con ) ;
+    inputPanel.add( fieldScroller ) ;
+
+    con.fill = GridBagConstraints.HORIZONTAL ;
+    con.weighty = 0;
+    con.gridwidth = 2 ;
+    gbl.setConstraints( radioPanel, con ) ;
+    inputPanel.add( radioPanel ) ;
+
+    con.gridwidth = GridBagConstraints.REMAINDER ;
+    gbl.setConstraints( insertButton, con ) ;
+    inputPanel.add( insertButton ) ;
+
+    // ----------------------------------------------------------------------
+    rawPanel.add( leftPanel, BorderLayout.CENTER ) ;
+    rawPanel.add( inputPanel, BorderLayout.EAST ) ;
+
+    // ----------------------------------------------------------------------
+    // add a short info, if available
+    // load the info text from a help-file, the "normal" translation is
+    // to long and unpractical for the properties file (single line)
+    // => try to load the help file text, if it fails, show a short text
+
+    //infoText.setText(Globals.lang("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."));
+
+    JEditorPane infoText =  new JEditorPane() ;
+
+    boolean loaded = false ;
+
+    URL infoURL = JabRef.class.getResource(GUIGlobals.getLocaleHelpPath()
+                                           +GUIGlobals.shortPlainImport);
+
+    if (infoURL != null)
+    {
+      try
+      {
+         // get the info text from help file
+        infoText.setPage( infoURL ) ;
+        //infoText.setContentType("text/html");
+
+        loaded = true ; // text successfully loaded
+      }
+      catch (Exception e) {}
+    }
+
+    if (!loaded) // only if no help available
+    {
+      infoText.setText(
+         Globals.lang("This_is_a_simple_copy_and_paste_dialog_for_import_some_fields_from_normal_text.") ) ;
+    }
+
+    infoText.setEditable(false);
+    infoText.setBackground(GUIGlobals.infoField);
+    infoText.setBorder(new EtchedBorder(EtchedBorder.LOWERED));
+    infoText.setPreferredSize( new Dimension(220, 50));
+    infoText.setMinimumSize( new Dimension(180, 50));
+
+    rawPanel.add( infoText, BorderLayout.SOUTH ) ;
+  }
+
+// ---------------------------------------------------------------------------
+
+// ---------------------------------------------------------------------------
+
+  private void initButtonPanel()
+  {
+    // Panel Layout
+    GridBagLayout gbl = new GridBagLayout() ;
+    GridBagConstraints con = new GridBagConstraints() ;
+    con.weightx = 0 ;
+    con.insets = new Insets( 5, 10, 0, 10 ) ;
+    con.fill = GridBagConstraints.HORIZONTAL ;
+
+//    buttonPanel.setLayout(gbl) ;
+
+    // Buttons
+    okButton.setText( Globals.lang( "Accept" ) ) ;
+//    okButton.setEnabled(false);
+    okButton.addActionListener( this ) ;
+    cancelButton.setText( Globals.lang( "Cancel" ) ) ;
+    cancelButton.addActionListener( this ) ;
+
+    // insert Buttons
+    con.gridwidth = GridBagConstraints.REMAINDER ;
+    gbl.setConstraints( okButton, con ) ;
+    buttonPanel.add( okButton ) ;
+
+    gbl.setConstraints( cancelButton, con ) ;
+    buttonPanel.add( cancelButton ) ;
+  }
+
+// ---------------------------------------------------------------------------
+
+  // Panel with bibtex source code
+  private void initSourcePanel()
+  {
+//    preview =  new PreviewPanel(entry) ;
+    preview = new JTextArea() ;
+    preview.setEditable( false ) ;
+
+    JScrollPane paneScrollPane = new JScrollPane( preview ) ;
+    paneScrollPane.setVerticalScrollBarPolicy(
+        JScrollPane.VERTICAL_SCROLLBAR_ALWAYS ) ;
+    paneScrollPane.setPreferredSize( new Dimension( 500, 255 ) ) ;
+    paneScrollPane.setMinimumSize( new Dimension( 10, 10 ) ) ;
+
+    sourcePanel.setLayout( new BorderLayout() ) ;
+    sourcePanel.add( paneScrollPane, BorderLayout.CENTER ) ;
+  }
+
+// ---------------------------------------------------------------------------
+// ---------------------------------------------------------------------------
+  protected void addStylesToDocument( StyledDocument doc )
+  {
+    //Initialize some styles.
+    Style def = StyleContext.getDefaultStyleContext().
+        getStyle( StyleContext.DEFAULT_STYLE ) ;
+
+    Style regular = doc.addStyle( "regular", def ) ;
+    StyleConstants.setFontFamily( def, "SansSerif" ) ;
+    StyleConstants.setFontSize( def, 12 ) ;
+
+    Style s = doc.addStyle( "oldused", regular ) ;
+    StyleConstants.setItalic( s, true ) ;
+    StyleConstants.setForeground( s, Color.blue ) ;
+
+    s = doc.addStyle( "used", regular ) ;
+    StyleConstants.setBold( s, true ) ;
+    StyleConstants.setForeground( s, Color.blue ) ;
+
+    s = doc.addStyle( "marked", regular ) ;
+    StyleConstants.setBold( s, true ) ;
+    StyleConstants.setForeground( s, Color.red ) ;
+
+    s = doc.addStyle( "small", regular ) ;
+    StyleConstants.setFontSize( s, 10 ) ;
+
+    s = doc.addStyle( "large", regular ) ;
+    StyleConstants.setFontSize( s, 16 ) ;
+  }
+
+// ---------------------------------------------------------------------------
+  private void insertTextForTag()
+  {
+    String type = ( String ) fieldList.getSelectedValue() ;
+    if ( type != null )
+    {
+      String txt = textPane.getSelectedText() ;
+
+      if ( txt != null )
+      {
+        int selStart = textPane.getSelectionStart() ;
+        int selEnd = textPane.getSelectionEnd() ;
+
+        // unselect text
+        textPane.setSelectionEnd( selStart ) ;
+
+        // mark the selected text as "used"
+        doc.setCharacterAttributes( selStart, selEnd - selStart,
+                                    doc.getStyle( "marked" ), true ) ;
+
+        // override an existing entry
+        if ( overRadio.isSelected() )
+        {
+          entry.setField( type, txt ) ;
+          // erase old text selection
+          marked.setStyleForTag( type, "regular", doc ) ; // delete all previous styles
+          marked.insertPosition( type, selStart, selEnd ) ; // insert new selection style
+        }
+        else // append text
+        {
+          // memorize the selection for text highlighting
+          marked.appendPosition( type, selStart, selEnd ) ;
+
+          // get old text from bibtex tag
+          String old = ( String ) entry.getField( type ) ;
+
+          // merge old and selected text
+          if ( old != null )
+          {
+            // insert a new author with an additional "and"
+            if (type.hashCode() == "author".hashCode())
+            {
+              entry.setField(type, old +" and " +txt);
+            }
+            else entry.setField( type, old + txt ) ;
+          }
+          else // "null"+"txt" Strings forbidden
+          {
+            entry.setField( type, txt ) ;
+          }
+        }
+        // make the new data in bibtex source code visible
+        updateSourceView() ;
+      }
+    }
+  }
+
+// ---------------------------------------------------------------------------
+// ---------------------------------------------------------------------------
+  public boolean okPressed()
+  {
+    return okPressed ;
+  }
+
+// ---------------------------------------------------------------------------
+
+//  ActionListener
+//  handling of button-click actions
+  public void actionPerformed( ActionEvent e )
+  {
+    Object source = e.getSource() ;
+
+    if (source == this.okButton)
+    {
+      okPressed = true ;
+      dispose() ;
+    }
+    else if (source == this.cancelButton)
+    {
+      dispose() ;
+    }
+    else if (source == this.insertButton)
+    {
+      insertTextForTag() ;
+    }
+  }
+
+// ---------------------------------------------------------------------------
+  // update the bibtex source view and available List
+  private final void updateSourceView()
+  {
+    StringWriter sw = new StringWriter( 200 ) ;
+    try
+    {
+      entry.write( sw, new net.sf.jabref.export.LatexFieldFormatter(), false ) ;
+      String srcString = sw.getBuffer().toString() ;
+      preview.setText( srcString ) ;
+    }
+    catch ( IOException ex )
+    {}
+
+    fieldList.clearSelection() ;
+  }
+
+// ---------------------------------------------------------------------------
+  private final String[] getAllFields()
+  {
+    int len = 0 ;
+    String dummy[][] = new String[3][] ;
+
+    // fill
+    if ( entry != null )
+    {
+      dummy[0] = entry.getRequiredFields() ;
+      dummy[1] = entry.getGeneralFields() ;
+      dummy[2] = entry.getOptionalFields() ;
+    }
+
+    // get size of new result array
+    for ( int t = 0 ; t < 3 ; t++ )
+    {
+      if ( dummy[t] != null )
+      {
+        len = len + dummy[t].length ;
+      }
+    }
+
+    String back[] = new String[len] ;
+    int count = 0 ;
+
+    // put
+    for ( int t = 0 ; t < 3 ; t++ )
+    {
+      if ( dummy[t] != null )
+      {
+        System.arraycopy( dummy[t], 0, back, count, dummy[t].length ) ;
+        count += dummy[t].length ;
+      }
+    }
+    return back ;
+  }
+
+// ---------------------------------------------------------------------------
+  class PasteAction
+      extends BasicAction
+  {
+    public PasteAction()
+    {
+      super( "Paste", "Paste from clipboard", GUIGlobals.pasteIconFile ) ;
+    }
+
+    public void actionPerformed( ActionEvent e )
+    {
+      String data = ClipBoardManager.clipBoard.getClipboardContents() ;
+      if ( data != null )
+      {
+        int selStart = textPane.getSelectionStart() ;
+        int selEnd = textPane.getSelectionEnd() ;
+        if ( selEnd - selStart > 0 )
+        {
+          textPane.replaceSelection( "" ) ;
+        }
+        int cPos = textPane.getCaretPosition() ;
+        try
+        {
+          doc.insertString( cPos, data, doc.getStyle( "regular" ) ) ;
+        }
+        catch ( Exception ex )
+        {}
+      }
+    }
+  }
+
+// ---------------------------------------------------------------------------
+  class LoadAction
+      extends BasicAction
+  {
+    public LoadAction()
+    {
+      super( "Open", "Open_file", GUIGlobals.openIconFile ) ;
+    }
+
+    public void actionPerformed( ActionEvent e )
+    {
+      try
+      {
+        String chosen = null ;
+        chosen = Globals.getNewFile( _frame, null, null,
+                                     ".txt",
+                                     JFileChooser.OPEN_DIALOG, false ) ;
+        if ( chosen != null )
+        {
+          File newFile = new File( chosen ) ;
+          doc.remove( 0, doc.getLength() ) ;
+          EditorKit eKit = textPane.getEditorKit() ;
+          if ( eKit != null )
+          {
+            eKit.read( new FileInputStream( newFile ), doc, 0 ) ;
+            doc.setLogicalStyle( 0, doc.getStyle( "regular" ) ) ;
+          }
+        }
+      }
+      catch ( Exception ex )
+      {}
+    }
+  }
+
+// ---------------------------------------------------------------------------
+  class ClearAction
+      extends BasicAction
+  {
+    public ClearAction()
+    {
+      super( "Clear", "Clear_inputarea", GUIGlobals.clearInputArea ) ;
+    }
+
+    public void actionPerformed( ActionEvent e )
+    {
+      textPane.setText( "" ) ;
+    }
+  }
+
+// ---------------------------------------------------------------------------
+  class MenuHeaderAction
+      extends BasicAction
+  {
+    public MenuHeaderAction()
+    {
+      super( "Edit" ) ;
+      this.setEnabled( false ) ;
+    }
+
+    public void actionPerformed( ActionEvent e )
+    {}
+  }
+
+// ---------------------------------------------------------------------------
+
+  class FieldListSelectionHandler
+      implements ListSelectionListener
+  {
+    private int lastIndex = -1 ;
+
+    public void valueChanged( ListSelectionEvent e )
+    {
+      ListSelectionModel lsm = ( ListSelectionModel ) e.getSource() ;
+
+      int index = lsm.getAnchorSelectionIndex() ;
+      if ( index != lastIndex )
+      {
+
+        boolean isAdjusting = e.getValueIsAdjusting() ;
+
+        if ( !isAdjusting ) // if selection is finished
+        {
+//            System.out.println( "Event for index" + index ) ;
+          if ( lastIndex > -1 )
+          {
+            String tag1 = fieldList.getModel().getElementAt( lastIndex ).
+                toString() ;
+            marked.setStyleForTag( tag1, "used", doc ) ;
+          }
+
+          String tag2 = fieldList.getModel().getElementAt( index ).toString() ;
+          marked.setStyleForTag( tag2, "marked", doc ) ;
+
+          lastIndex = index ;
+        }
+      }
+    }
+  }
+
+// ---------------------------------------------------------------------------
+
+  // simple JList Renderer
+  // based on : Advanced JList Programming at developers.sun.com
+  class SimpleCellRenderer
+      extends DefaultListCellRenderer
+  {
+    private Font baseFont ;
+    private Font usedFont ;
+    private ImageIcon okIcon = new ImageIcon( GUIGlobals.completeTagIcon ) ;
+    private ImageIcon needIcon = new ImageIcon( GUIGlobals.wrongTagIcon ) ;
+
+    public SimpleCellRenderer( Font normFont )
+    {
+      baseFont = normFont ;
+      usedFont = baseFont.deriveFont( Font.ITALIC ) ;
+    }
+
+    /* This is the only method defined by ListCellRenderer.  We just
+     * reconfigure the Jlabel each time we're called.
+     */
+    public Component getListCellRendererComponent(
+        JList list,
+        Object value, // value to display
+        int index, // cell index
+        boolean iss, // is the cell selected
+        boolean chf ) // the list and the cell have the focus
+    {
+      /* The DefaultListCellRenderer class will take care of
+       * the JLabels text property, it's foreground and background
+       * colors, and so on.
+       */
+      super.getListCellRendererComponent( list, value, index, iss, chf ) ;
+
+      /* We additionally set the JLabels icon property here.
+       */
+      String s = value.toString() ;
+//        setIcon((s.length > 10) ? longIcon : shortIcon);
+      if ( entry.getField( s ) != null )
+      {
+        this.setForeground( Color.gray ) ;
+        this.setFont( usedFont ) ;
+        this.setIcon( okIcon ) ;
+        this.setToolTipText( "filled" ) ;
+      }
+      else
+      {
+        this.setIcon( needIcon ) ;
+        this.setToolTipText( "field is missing" ) ;
+      }
+      return this ;
+    }
+  }
+
+//---------------------------------------------------------------
+
+  class FieldListMouseListener
+      extends MouseAdapter
+  {
+    public void mouseClicked( MouseEvent e )
+    {
+      if ( e.getClickCount() == 2 )
+      {
+        insertTextForTag() ;
+      }
+    }
+  }
+}
+
+//---------------------------------------------------------------
+class PopupListener
+    extends MouseAdapter
+{
+  private JPopupMenu popMenu ;
+
+  public PopupListener( JPopupMenu menu )
+  {
+    popMenu = menu ;
+  }
+
+  public void mousePressed( MouseEvent e )
+  {
+    maybeShowPopup( e ) ;
+  }
+
+  public void mouseReleased( MouseEvent e )
+  {
+    maybeShowPopup( e ) ;
+  }
+
+  private void maybeShowPopup( MouseEvent e )
+  {
+    if ( e.isPopupTrigger() )
+    {
+//      System.out.println("show "
+//                         + e.getComponent() +"  x =" + e.getX() +"y =" + e.getY() ) ;
+//      popMenu.setVisible(true);
+      popMenu.show( e.getComponent(), e.getX(), e.getY() ) ;
+    }
+  }
+}
+
+//---------------------------------------------------------------
+
+abstract class BasicAction
+    extends AbstractAction
+{
+  public BasicAction( String text, String description, URL icon )
+  {
+    super( Globals.lang( text ), new ImageIcon( icon ) ) ;
+    putValue( SHORT_DESCRIPTION, Globals.lang( description ) ) ;
+  }
+
+  public BasicAction( String text, String description, URL icon, KeyStroke key )
+  {
+    super( Globals.lang( text ), new ImageIcon( icon ) ) ;
+    putValue( ACCELERATOR_KEY, key ) ;
+    putValue( SHORT_DESCRIPTION, Globals.lang( description ) ) ;
+  }
+
+  public BasicAction( String text )
+  {
+    super( Globals.lang( text ) ) ;
+  }
+
+  public BasicAction( String text, KeyStroke key )
+  {
+    super( Globals.lang( text ) ) ;
+    putValue( ACCELERATOR_KEY, key ) ;
+  }
+
+  public abstract void actionPerformed( ActionEvent e ) ;
+}
+//---------------------------------------------------------------
+
+
+//---------------------------------------------------------------
+
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
new file mode 100644
index 0000000..406a2fc
--- /dev/null
+++ b/src/java/tests/net/sf/jabref/export/layout/format/AuthorLastFirstAbbreviatorTester.java
@@ -0,0 +1,87 @@
+package tests.net.sf.jabref.export.layout.format;
+
+import net.sf.jabref.export.layout.format.AuthorLastFirstAbbreviator;
+import junit.framework.Assert;
+import junit.framework.TestCase;
+
+/**
+ * Test case  that verifies the functionalities of the
+ * formater AuthorLastFirstAbbreviator.
+ * 
+ * @author Carlos Silla
+ */
+public class AuthorLastFirstAbbreviatorTester extends TestCase {
+
+	/**
+	 * Verifies the Abbreviation of one single author with a simple name.
+	 * 
+	 * Ex: Lastname, Name
+	 */
+	public void testOneAuthorSimpleName() {
+		String name = "Lastname, Name";
+		
+		AuthorLastFirstAbbreviator ab = new AuthorLastFirstAbbreviator();
+		
+		String result = ab.format(name);
+		
+		//Expected Results:
+		String expectedResult = "Lastname, N.";
+
+		//Verifies the functionality:				
+		Assert.assertEquals("Abbreviator Test", result, expectedResult);
+	}
+
+	/**
+	 * Verifies the Abbreviation of one single author with a common name.
+	 * 
+	 * Ex: Lastname, Name Middlename
+	 */
+	public void testOneAuthorCommonName() {
+		String name = "Lastname, Name Middlename";
+		
+		AuthorLastFirstAbbreviator ab = new AuthorLastFirstAbbreviator();
+		
+		String result = ab.format(name);
+		
+		//Expected Results:
+		String expectedResult = "Lastname, N.M.";
+		
+		//Verifies the functionality:				
+		Assert.assertEquals("Abbreviator Test", result, expectedResult);
+	}
+
+	/**
+	 * Verifies the Abbreviation of two single with a common name.
+	 * 
+	 * Ex: Lastname, Name Middlename
+	 */
+	public void testTwoAuthorsCommonName() {
+		String name = "Lastname, Name Middlename and Sobrenome, Nome Nomedomeio";
+		
+		AuthorLastFirstAbbreviator ab = new AuthorLastFirstAbbreviator();
+		
+		String result = ab.format(name);
+		
+		//Expected Results:
+		String expectedResult = "Lastname, N.M. and Sobrenome, N.N.";
+		
+		//Verifies the functionality:				
+		Assert.assertEquals("Abbreviator Test", result, expectedResult);
+	}
+
+
+	/**
+	 * Verifies the Abbreviation of two authors in the incorrect format.
+	 * 
+	 * Ex: Lastname, Name Middlename
+	 */
+	//TODO: Verify how to tell this test that it should pass if fail.
+/*	public void testTwoAuthorsBadFormating() {
+		String name = new String("Lastname, Name Middlename and Nome Nomedomeio Sobrenome");
+		
+		AuthorLastFirstAbbreviator ab = new AuthorLastFirstAbbreviator();
+		
+		String result = ab.format(name);		
+	}*/
+	
+}
diff --git a/src/java/wsi/ra/tool/ExternalHelper.java b/src/java/wsi/ra/tool/ExternalHelper.java
new file mode 100755
index 0000000..868d6b2
--- /dev/null
+++ b/src/java/wsi/ra/tool/ExternalHelper.java
@@ -0,0 +1,84 @@
+///////////////////////////////////////////////////////////////////////////////
+//  Filename: $RCSfile: ExternalHelper.java,v $
+//  Purpose:  Atom representation.
+//  Language: Java
+//  Compiler: JDK 1.4
+//  Authors:  Joerg K. Wegner, Gerd Mueller
+//  Version:  $Revision: 1.1 $
+//            $Date: 2004/01/28 22:41:11 $
+//            $Author: wegner $
+//
+//  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.
+///////////////////////////////////////////////////////////////////////////////
+package wsi.ra.tool;
+
+
+/**
+ * Some helper methods for calling external programs.
+ *
+ * @author     wegnerj
+ * @license GPL
+ * @cvsversion    $Revision: 1.1 $, $Date: 2004/01/28 22:41:11 $
+ */
+public class ExternalHelper
+{
+    //~ Static fields/initializers /////////////////////////////////////////////
+
+    public static final String OS_WINDOWS = "windows";
+    public static final String OS_LINUX = "linux";
+    public static final String OS_SOLARIS = "solaris";
+
+    //~ Constructors ///////////////////////////////////////////////////////////
+
+    /*-------------------------------------------------------------------------*
+     * constructor
+     *-------------------------------------------------------------------------*/
+
+    /** Don't let anyone instantiate this class */
+    private ExternalHelper()
+    {
+    }
+
+    //~ Methods ////////////////////////////////////////////////////////////////
+
+    /*-------------------------------------------------------------------------*
+     * private static methods
+     *-------------------------------------------------------------------------*/
+
+    /**
+     * Returns the name of the operation system.
+     *
+     *   @todo maybe move this method to a more common class */
+    public static String getOperationSystemName()
+    {
+        String osName = System.getProperty("os.name");
+
+        // determine name of operation system and convert it into lower caps without blanks
+        if (osName.indexOf("Windows") != -1)
+        {
+            osName = OS_WINDOWS;
+        }
+        else if (osName.indexOf("Linux") != -1)
+        {
+            osName = OS_LINUX;
+        }
+        else if (osName.indexOf("Solaris") != -1)
+        {
+            osName = OS_SOLARIS;
+        }
+
+        return osName;
+    }
+}
+///////////////////////////////////////////////////////////////////////////////
+//  END OF FILE.
+///////////////////////////////////////////////////////////////////////////////
diff --git a/src/java/wsi/ra/tool/ResourceLoader.java b/src/java/wsi/ra/tool/ResourceLoader.java
new file mode 100755
index 0000000..2a16695
--- /dev/null
+++ b/src/java/wsi/ra/tool/ResourceLoader.java
@@ -0,0 +1,486 @@
+///////////////////////////////////////////////////////////////////////////////
+//  Filename: $RCSfile: ResourceLoader.java,v $
+//  Purpose:  Atom representation.
+//  Language: Java
+//  Compiler: JDK 1.4
+//  Authors:  Joerg K. Wegner, Gerd Mueller
+//  Version:  $Revision: 1.1 $
+//            $Date: 2004/01/28 22:41:11 $
+//            $Author: wegner $
+//
+//  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.
+///////////////////////////////////////////////////////////////////////////////
+package wsi.ra.tool;
+
+import java.io.*;
+
+import java.net.*;
+
+import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.zip.*;
+
+/*==========================================================================*
+ * IMPORTS
+ *==========================================================================*/
+//import org.apache.log4j.*;
+
+/*==========================================================================*
+ * CLASS DECLARATION
+ *==========================================================================*/
+
+/**
+ *  Loads resource file from directory OR jar file. Now it is easier possible to
+ *  access resource files in a directory structure or a .jar/.zip file.
+ *
+ * @author     wegnerj
+ * @author     Robin Friedman, rfriedman at TriadTherapeutics.com
+ * @author     Gerd Mueller
+ * @license GPL
+ * @cvsversion    $Revision: 1.1 $, $Date: 2004/01/28 22:41:11 $
+ */
+public class ResourceLoader
+{
+    //~ Static fields/initializers /////////////////////////////////////////////
+
+    /**
+     *  Obtain a suitable logger.
+     */
+//    private static Category logger = Category.getInstance(
+//            "wsi.ra.tool.ResourceLoader");
+    private static ResourceLoader resourceLoader;
+
+    //~ Constructors ///////////////////////////////////////////////////////////
+
+    /*------------------------------------------------------------------------*
+     * constructor
+     *------------------------------------------------------------------------  */
+
+    /**
+     *  Constructor for the ResourceLoader object
+     */
+    private ResourceLoader()
+    {
+    }
+
+    //~ Methods ////////////////////////////////////////////////////////////////
+
+    /*-------------------------------------------------------------------------*
+     * public methods
+     *-------------------------------------------------------------------------  */
+
+    /**
+     *  Description of the Method
+     *
+     * @return    Description of the Return Value
+     */
+    public static synchronized ResourceLoader instance()
+    {
+        if (resourceLoader == null)
+        {
+            resourceLoader = new ResourceLoader();
+        }
+
+        return resourceLoader;
+    }
+
+    /**
+     *  Gets the byte data from a file at the given resource location.
+     *
+     * @param  resourceLocation  Description of the Parameter
+     * @return                   the byte array of file.
+     */
+    public byte[] getBytesFromResourceLocation(String resourceLocation)
+    {
+        if (resourceLocation == null)
+        {
+            return null;
+        }
+		// to avoid hours of debugging non-found-files under linux with
+	    // some f... special characters at the end which will not be shown
+	    // at the console output !!!
+	    resourceLocation = resourceLocation.trim();
+
+        // is a relative path defined ?
+        // this can only be possible, if this is a file resource loacation
+        if (resourceLocation.startsWith("..") ||
+                resourceLocation.startsWith("/") ||
+                resourceLocation.startsWith("\\") ||
+                ((resourceLocation.length() > 1) &&
+                (resourceLocation.charAt(1) == ':')))
+        {
+            return getBytesFromFile(resourceLocation);
+        }
+
+        InputStream in = this.getClass().getClassLoader()
+                             .getSystemResourceAsStream(resourceLocation);
+
+        if (in == null)
+        {
+            // try again for web start applications
+            in = this.getClass().getClassLoader().getResourceAsStream(resourceLocation);
+        }
+
+        if (in == null)
+        {
+            return null;
+        }
+
+        byte bytes[]=getBytesFromStream(in);
+
+//		if(bytes==null)
+//		{
+//			URL location = this.getClass().getClassLoader().getSystemResource(resourceLocation);
+//			String fileLocation = location.getFile();
+//			bytes=getBytesFromFile(fileLocation);
+//		}
+
+        return bytes;
+
+        //        //System.out.println(this.getClass().getClassLoader().getSystemResource(resourceLocation));
+        //        URL location = this.getClass().getClassLoader().getSystemResource(resourceLocation);
+        //
+        //        if (location == null)
+        //        {
+        //            // try again for web start applications
+        //            location = this.getClass().getClassLoader().getResource(resourceLocation);
+        //        }
+        //
+        //        if (logger.isDebugEnabled())
+        //        {
+        //            logger.debug("Trying to get " + resourceLocation + " from URL: " +
+        //                location);
+        //        }
+        //
+        //        if (location == null)
+        //        {
+        //            return null;
+        //        }
+        //
+        //        String locationString = URLDecoder.decode( location.toString() );
+        //
+        //        int posJAR = locationString.indexOf(".jar!");
+        //        int posZIP = locationString.indexOf(".zip!");
+        //        int pos = -1;
+        //
+        //        if ((posJAR > -1) && (posZIP > -1))
+        //        {
+        //            pos = Math.min(posJAR, posZIP);
+        //        }
+        //        else if (posJAR > -1)
+        //        {
+        //            pos = posJAR;
+        //        }
+        //        else if (posZIP > -1)
+        //        {
+        //            pos = posZIP;
+        //        }
+        //
+        //        // is the resource file in a zip or a jar file
+        //        if (pos > -1)
+        //        {
+        //            // load it from zip or jar file
+        //            String urlToZip = locationString.substring(4, pos + 4);
+        //            String internalArchivePath = locationString.substring(pos + 6);
+        //
+        //            if (logger.isDebugEnabled())
+        //            {
+        //                logger.debug("Loading " + internalArchivePath +
+        //                    " from archive " + urlToZip + ".");
+        //            }
+        //
+        //            return getBytesFromArchive(urlToZip, internalArchivePath);
+        //        }
+        //        else
+        //        {
+        //            String fileLocation = location.getFile();
+        //
+        //            // load it from an unpacked file
+        //            if (logger.isDebugEnabled())
+        //            {
+        //                logger.debug("Loading from file " + fileLocation + ".");
+        //            }
+        //
+        //            return getBytesFromFile(fileLocation);
+        //        }
+    }
+
+    /**
+     *  Description of the Method
+     *
+     * @param  resourceFile  Description of the Parameter
+     * @return               Description of the Return Value
+     */
+    public static Vector readLines(String resourceFile)
+    {
+        return readLines(resourceFile, false);
+    }
+
+    /**
+     *  Description of the Method
+     *
+     * @param  resourceFile    Description of the Parameter
+     * @param  ignoreComments  Description of the Parameter
+     * @return                 Description of the Return Value
+     */
+    public static Vector readLines(String resourceFile,
+        boolean ignoreCommentedLines)
+    {
+        if (resourceFile == null)
+        {
+            return null;
+        }
+
+        byte[] bytes = ResourceLoader.instance().getBytesFromResourceLocation(resourceFile);
+
+        if (bytes == null)
+        {
+            return null;
+        }
+
+        ByteArrayInputStream sReader = new ByteArrayInputStream(bytes);
+        LineNumberReader lnr = new LineNumberReader(new InputStreamReader(
+                    sReader));
+
+        String line;
+        Vector vector = new Vector(100);
+
+        try
+        {
+            while ((line = lnr.readLine()) != null)
+            {
+                if (!ignoreCommentedLines)
+                {
+                    if (!(line.charAt(0) == '#'))
+                    {
+                        vector.add(line);
+
+                        //		  System.out.println("ADD:"+line);
+                    }
+                }
+                else
+                {
+                    vector.add(line);
+                }
+            }
+        }
+         catch (IOException ex)
+        {
+            ex.printStackTrace();
+        }
+
+        return vector;
+    }
+
+    /*-------------------------------------------------------------------------*
+     * private methods
+     *-------------------------------------------------------------------------  */
+
+    /**
+     *  Gets the byte data from a file contained in a JAR or ZIP file.
+     *
+     * @param  urlToZipArchive      Description of the Parameter
+     * @param  internalArchivePath  Description of the Parameter
+     * @return                      the byte array of the file.
+     */
+    private byte[] getBytesFromArchive(String urlToZipArchive,
+        String internalArchivePath)
+    {
+        URL url = null;
+        int size = -1;
+        byte[] b = null;
+
+        try
+        {
+            url = new URL(urlToZipArchive);
+
+            // extracts just sizes only.
+            ZipFile zf = new ZipFile(url.getFile());
+            Enumeration e = zf.entries();
+
+            while (e.hasMoreElements())
+            {
+                ZipEntry ze = (ZipEntry) e.nextElement();
+
+                if (ze.getName().equals(internalArchivePath))
+                {
+                    if (ze.isDirectory())
+                    {
+                        return null;
+                    }
+
+                    // only files with <65536 bytes are allowed
+                    if (ze.getSize() > 65536)
+                    {
+                        System.out.println(
+                            "Resource files should be smaller than 65536 bytes...");
+                    }
+
+                    size = (int) ze.getSize();
+                }
+            }
+
+            zf.close();
+
+            FileInputStream fis = new FileInputStream(url.getFile());
+            BufferedInputStream bis = new BufferedInputStream(fis);
+            ZipInputStream zis = new ZipInputStream(bis);
+            ZipEntry ze = null;
+
+            while ((ze = zis.getNextEntry()) != null)
+            {
+                if (ze.getName().equals(internalArchivePath))
+                {
+                    b = new byte[(int) size];
+
+                    int rb = 0;
+                    int chunk = 0;
+
+                    while (((int) size - rb) > 0)
+                    {
+                        chunk = zis.read(b, rb, (int) size - rb);
+
+                        if (chunk == -1)
+                        {
+                            break;
+                        }
+
+                        rb += chunk;
+                    }
+                }
+            }
+        }
+         catch (Exception e)
+        {
+            //logger.error("error while loading", e);
+            System.err.println("error while loading");
+
+            return null;
+        }
+
+        return b;
+    }
+
+    /**
+     *  Gets the byte data from a file.
+     *
+     * @param  fileName  Description of the Parameter
+     * @return           the byte array of the file.
+     */
+    private byte[] getBytesFromFile(String fileName)
+    {
+        if (fileName.startsWith("/cygdrive/"))
+        {
+            int length = "/cygdrive/".length();
+            fileName = fileName.substring(length, length + 1) + ":" +
+                fileName.substring(length + 1);
+        }
+
+        //if (logger.isDebugEnabled())
+        //{
+        //    logger.debug("Trying to get file from " + fileName);
+        //}
+
+        File file = new File(fileName);
+        FileInputStream fis = null;
+
+        try
+        {
+            fis = new FileInputStream(file);
+        }
+         catch (Exception e)
+        {
+            return null;
+        }
+
+        BufferedInputStream bis = new BufferedInputStream(fis);
+
+        // only files with <65536 bytes are allowed
+        //if( file.length() > 65536 ) System.out.println("Resource files should be smaller than 65536 bytes...");
+        int size = (int) file.length();
+        byte[] b = new byte[size];
+        int rb = 0;
+        int chunk = 0;
+
+        try
+        {
+            while (((int) size - rb) > 0)
+            {
+                chunk = bis.read(b, rb, (int) size - rb);
+
+                if (chunk == -1)
+                {
+                    break;
+                }
+
+                rb += chunk;
+            }
+        }
+         catch (Exception e)
+        {
+            return null;
+        }
+
+        return b;
+    }
+
+    /**
+     *  Gets the byte data from a file.
+     *
+     * @param  fileName  Description of the Parameter
+     * @return           the byte array of the file.
+     */
+    private byte[] getBytesFromStream(InputStream stream)
+    {
+        //if (logger.isDebugEnabled())
+        //{
+        //    logger.debug("Trying to get file from stream");
+        //}
+
+        BufferedInputStream bis = new BufferedInputStream(stream);
+
+        try
+        {
+            int size = (int) bis.available();
+            byte[] b = new byte[size];
+            int rb = 0;
+            int chunk = 0;
+
+            while (((int) size - rb) > 0)
+            {
+                chunk = bis.read(b, rb, (int) size - rb);
+
+                if (chunk == -1)
+                {
+                    break;
+                }
+
+                rb += chunk;
+            }
+
+            return b;
+        }
+         catch (Exception e)
+        {
+            return null;
+        }
+    }
+}
+
+/*-------------------------------------------------------------------------*
+ * END
+ *-------------------------------------------------------------------------*/
+
+///////////////////////////////////////////////////////////////////////////////
+//  END OF FILE.
+///////////////////////////////////////////////////////////////////////////////
diff --git a/src/java/wsi/ra/tool/WSITools.java b/src/java/wsi/ra/tool/WSITools.java
new file mode 100755
index 0000000..4e0102b
--- /dev/null
+++ b/src/java/wsi/ra/tool/WSITools.java
@@ -0,0 +1,124 @@
+///////////////////////////////////////////////////////////////////////////////
+//  Filename: $RCSfile: WSITools.java,v $
+//  Purpose:  Atom representation.
+//  Language: Java
+//  Compiler: JDK 1.4
+//  Authors:  Joerg K. Wegner
+//  Version:  $Revision: 1.2 $
+//            $Date: 2005/11/08 04:53:29 $
+//            $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.
+///////////////////////////////////////////////////////////////////////////////
+package wsi.ra.tool;
+
+
+/*==========================================================================*
+ * IMPORTS
+ *========================================================================== */
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+
+/*==========================================================================*
+ * CLASS DECLARATION
+ *========================================================================== */
+
+/**
+ * JabRef helper methods.
+ *
+ * @author     wegnerj
+ * @license GPL
+ * @cvsversion    $Revision: 1.2 $, $Date: 2005/11/08 04:53:29 $
+ */
+public class WSITools
+{
+    //~ Constructors ///////////////////////////////////////////////////////////
+
+    private WSITools()
+    {
+    }
+
+    //~ Methods ////////////////////////////////////////////////////////////////
+
+    /**
+     * @param  vcr  {@link java.util.Vector} of <tt>String</tt>
+     * @param  buf  Description of the Parameter
+     * @return      Description of the Return Value
+     */
+    public static boolean tokenize(Vector vcr, String buf)
+    {
+        return tokenize(vcr, buf, " \t\n");
+    }
+
+    /**
+     * @param  vcr       {@link java.util.Vector} of <tt>String</tt>
+     * @param  buf       Description of the Parameter
+     * @param  delimstr  Description of the Parameter
+     * @return           Description of the Return Value
+     */
+    public static boolean tokenize(Vector vcr, String buf, String delimstr)
+    {
+        vcr.clear();
+        buf = buf + "\n";
+
+        StringTokenizer st = new StringTokenizer(buf, delimstr);
+
+        while (st.hasMoreTokens())
+        {
+            vcr.add(st.nextToken());
+        }
+
+        return true;
+    }
+
+    /**
+     * @param  vcr       {@link java.util.Vector} of <tt>String</tt>
+     * @param  s         Description of the Parameter
+     * @param  delimstr  Description of the Parameter
+     * @param  limit     Description of the Parameter
+     * @return           Description of the Return Value
+     */
+    public static boolean tokenize(Vector vcr, String s, String delimstr,
+        int limit)
+    {
+        System.out.println("Warning: tokenize \"" + s + "\"");
+        vcr.clear();
+        s = s + "\n";
+
+        int endpos = 0;
+        int matched = 0;
+
+        StringTokenizer st = new StringTokenizer(s, delimstr);
+
+        while (st.hasMoreTokens())
+        {
+            String tmp = st.nextToken();
+            vcr.add(tmp);
+
+            matched++;
+
+            if (matched == limit)
+            {
+                endpos = s.lastIndexOf(tmp);
+                vcr.add(s.substring(endpos + tmp.length()));
+
+                break;
+            }
+        }
+
+        return true;
+    }
+}
+///////////////////////////////////////////////////////////////////////////////
+//  END OF FILE.
+///////////////////////////////////////////////////////////////////////////////
diff --git a/src/java/wsi/ra/types/StringInt.java b/src/java/wsi/ra/types/StringInt.java
new file mode 100755
index 0000000..03c1b11
--- /dev/null
+++ b/src/java/wsi/ra/types/StringInt.java
@@ -0,0 +1,77 @@
+///////////////////////////////////////////////////////////////////////////////
+//  Filename: $RCSfile: StringInt.java,v $
+//  Purpose:  Atom representation.
+//  Language: Java
+//  Compiler: JDK 1.4
+//  Authors:  Joerg K. Wegner
+//  Version:  $Revision: 1.1 $
+//            $Date: 2004/01/28 22:41:11 $
+//            $Author: wegner $
+//
+//  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.
+///////////////////////////////////////////////////////////////////////////////
+package wsi.ra.types;
+
+
+/*==========================================================================*
+ * IMPORTS
+ *========================================================================== */
+/*==========================================================================*
+ * CLASS DECLARATION
+ *========================================================================== */
+
+/**
+ * String and integer value.
+ *
+ * @author     wegnerj
+ * @license GPL
+ * @cvsversion    $Revision: 1.1 $, $Date: 2004/01/28 22:41:11 $
+ */
+public class StringInt implements java.io.Serializable
+{
+    //~ Instance fields ////////////////////////////////////////////////////////
+
+    /*-------------------------------------------------------------------------*
+     * public member variables
+     *------------------------------------------------------------------------- */
+
+    /**
+     *  Description of the Field
+     */
+    public String s;
+
+    /**
+     *  Description of the Field
+     */
+    public int i;
+
+    //~ Constructors ///////////////////////////////////////////////////////////
+
+    /*-------------------------------------------------------------------------*
+     * constructor
+     *------------------------------------------------------------------------- */
+
+    /**
+     *  Constructor for the StringString object
+     *
+     * @param  _s1  Description of the Parameter
+     * @param  _s2  Description of the Parameter
+     */
+    public StringInt(String _s, int _i)
+    {
+        s = _s;
+        i = _i;
+    }
+}
+///////////////////////////////////////////////////////////////////////////////
+//  END OF FILE.
+///////////////////////////////////////////////////////////////////////////////
diff --git a/src/osx/osxadapter/OSXAdapter.java b/src/osx/osxadapter/OSXAdapter.java
new file mode 100644
index 0000000..0b7631e
--- /dev/null
+++ b/src/osx/osxadapter/OSXAdapter.java
@@ -0,0 +1,133 @@
+/*
+  File:    OSXAdapter.java
+
+  Description:A single class with clear, static entry points for hooking existing preferences,
+        about, quit functionality from an existing Java app into handlers for the Mac OS X
+        application menu.  Useful for developers looking to support
+        multiple platforms with a single codebase, and support Mac OS X features with
+        minimal impact.
+
+        This sample is designed for Java 1.4.1 and later on Mac OS X.
+
+  Author:    mdrance
+
+  Copyright:   � Copyright 2003 Apple Computer, Inc. All rights reserved.
+
+  Disclaimer:  IMPORTANT:  This Apple software is supplied to you by Apple Computer, Inc.
+        ("Apple") in consideration of your agreement to the following terms, and your
+        use, installation, modification or redistribution of this Apple software
+        constitutes acceptance of these terms.  If you do not agree with these terms,
+        please do not use, install, modify or redistribute this Apple software.
+
+        In consideration of your agreement to abide by the following terms, and subject
+        to these terms, Apple grants you a personal, non-exclusive license, under Apple's
+        copyrights in this original Apple software (the "Apple Software"), to use,
+        reproduce, modify and redistribute the Apple Software, with or without
+        modifications, in source and/or binary forms; provided that if you redistribute
+        the Apple Software in its entirety and without modifications, you must retain
+        this notice and the following text and disclaimers in all such redistributions of
+        the Apple Software.  Neither the name, trademarks, service marks or logos of
+        Apple Computer, Inc. may be used to endorse or promote products derived from the
+        Apple Software without specific prior written permission from Apple.  Except as
+        expressly stated in this notice, no other rights or licenses, express or implied,
+        are granted by Apple herein, including but not limited to any patent rights that
+        may be infringed by your derivative works or by other works in which the Apple
+        Software may be incorporated.
+
+        The Apple Software is provided by Apple on an "AS IS" basis.  APPLE MAKES NO
+        WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+        WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+        PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
+        COMBINATION WITH YOUR PRODUCTS.
+
+        IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
+        CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+        GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+        ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
+        OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
+        (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
+        ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+  Change History (most recent first):
+    04092003  mdrance    added comments
+
+*/
+package osxadapter;
+
+import net.sf.jabref.JabRefFrame;
+import com.apple.eawt.*;
+
+public class OSXAdapter extends ApplicationAdapter {
+
+  // pseudo-singleton model; no point in making multiple instances
+  // of the EAWT application or our adapter
+  private static OSXAdapter            theAdapter;
+  private static com.apple.eawt.Application    theApplication;
+
+  // reference to the app where the existing quit, about, prefs code is
+  private JabRefFrame mainApp;
+
+  private OSXAdapter (JabRefFrame inApp) {
+    mainApp = inApp;
+  }
+
+  // implemented handler methods.  These are basically hooks into existing
+  // functionality from the main app, as if it came over from another platform.
+  public void handleAbout(ApplicationEvent ae) {
+    if (mainApp != null) {
+      ae.setHandled(true);
+      mainApp.about();
+    } else {
+      throw new IllegalStateException("handleAbout: MyApp instance detached from listener");
+    }
+  }
+
+  public void handlePreferences(ApplicationEvent ae) {
+    if (mainApp != null) {
+      mainApp.preferences();
+      ae.setHandled(true);
+    } else {
+      throw new IllegalStateException("handlePreferences: MyApp instance detached from listener");
+    }
+  }
+
+  public void handleQuit(ApplicationEvent ae) {
+    if (mainApp != null) {
+      /*
+      /  You MUST setHandled(false) if you want to delay or cancel the quit.
+      /  This is important for cross-platform development -- have a universal quit
+      /  routine that chooses whether or not to quit, so the functionality is identical
+      /  on all platforms.  This example simply cancels the AppleEvent-based quit and
+      /  defers to that universal method.
+      */
+      ae.setHandled(false);
+      mainApp.quit();
+    } else {
+      throw new IllegalStateException("handleQuit: MyApp instance detached from listener");
+    }
+  }
+
+
+  // The main entry-point for this functionality.  This is the only method
+  // that needs to be called at runtime, and it can easily be done using
+  // reflection (see MyApp.java)
+  public static void registerMacOSXApplication(JabRefFrame inApp) {
+    if (theApplication == null) {
+      theApplication = new com.apple.eawt.Application();
+    }
+
+    if (theAdapter == null) {
+      theAdapter = new OSXAdapter(inApp);
+    }
+    theApplication.addApplicationListener(theAdapter);
+  }
+
+  // Another static entry point for EAWT functionality.  Enables the
+  // "Preferences..." menu item in the application menu.
+  public static void enablePrefs(boolean enabled) {
+    if (theApplication == null) {
+      theApplication = new com.apple.eawt.Application();
+    }
+    theApplication.setEnabledPreferencesMenu(enabled);
+  }
+}
diff --git a/src/resource/IntegrityMessage.properties b/src/resource/IntegrityMessage.properties
new file mode 100644
index 0000000..a89f6b8
--- /dev/null
+++ b/src/resource/IntegrityMessage.properties
@@ -0,0 +1,11 @@
+#! created/edited by Popeye version 0.51 sunshine (popeye.sourceforge.net)
+
+ITEXT_1=there are hints
+ITEXT_1001=warning
+ITEXT_2001=failure
+ITEXT_1010=beginning of $FIELD field
+ITEXT_1011=bad end ($FIELD field)
+ITEXT_1012=something could be wrong in $FIELD field
+ITEXT_10=There are large capitals without any mask {} into the $FIELD field
+ITEXT_11=$FIELD field should be contain a four digit number
+ITEXT_2010=unexpected closing } into $FIELD field
diff --git a/src/resource/IntegrityMessage_de.properties b/src/resource/IntegrityMessage_de.properties
new file mode 100644
index 0000000..9327ba6
--- /dev/null
+++ b/src/resource/IntegrityMessage_de.properties
@@ -0,0 +1,11 @@
+#! created/edited by Popeye version 0.51 sunshine (popeye.sourceforge.net)
+
+ITEXT_1=Hinweise vorhanden
+ITEXT_1001=Warnung
+ITEXT_2001=Fehler
+ITEXT_1010=Anfang des $FIELD Feldes fehlerhaft?
+ITEXT_1011=Ende des $FIELD Feldes mit Fehlern?
+ITEXT_1012=Im $FIELD Feld sind wahrscheinlich Fehler!
+ITEXT_10=Im $FIELD Feld existieren unmaskierte {} Gro\u00dfbuchstaben!
+ITEXT_11=Das $FIELD Feld sollte 4-stellige Zahlen enthalten!
+ITEXT_2010=Unerwartetes schlie\u00dfendes } im $FIELD Feld!
diff --git a/src/resource/IntegrityMessage_en.properties b/src/resource/IntegrityMessage_en.properties
new file mode 100644
index 0000000..a89f6b8
--- /dev/null
+++ b/src/resource/IntegrityMessage_en.properties
@@ -0,0 +1,11 @@
+#! created/edited by Popeye version 0.51 sunshine (popeye.sourceforge.net)
+
+ITEXT_1=there are hints
+ITEXT_1001=warning
+ITEXT_2001=failure
+ITEXT_1010=beginning of $FIELD field
+ITEXT_1011=bad end ($FIELD field)
+ITEXT_1012=something could be wrong in $FIELD field
+ITEXT_10=There are large capitals without any mask {} into the $FIELD field
+ITEXT_11=$FIELD field should be contain a four digit number
+ITEXT_2010=unexpected closing } into $FIELD field
diff --git a/src/resource/IntegrityMessage_fr.properties b/src/resource/IntegrityMessage_fr.properties
new file mode 100644
index 0000000..0eeaa39
--- /dev/null
+++ b/src/resource/IntegrityMessage_fr.properties
@@ -0,0 +1,11 @@
+#! created/edited by Popeye version 0.51 sunshine (popeye.sourceforge.net)
+
+ITEXT_1=il y a des suggestions
+ITEXT_1001=avertissement
+ITEXT_2001=\u00e9chec
+ITEXT_1010=d\u00e9but du champ $FIELD
+ITEXT_1011=mauvaise terminaison (champ $FIELD)
+ITEXT_1012=Il pourrait y avoir une erreur dans le champ $FIELD
+ITEXT_10=Il y a des majuscules non encadr\u00e9es par des accolades dans le champ $FIELD
+ITEXT_11=Le champ $FIELD devrait contenir un nombre \u00e0 4 chiffres
+ITEXT_2010=accolade fermante inattendue dans le champ $FIELD
diff --git a/src/resource/IntegrityMessage_no.properties b/src/resource/IntegrityMessage_no.properties
new file mode 100644
index 0000000..3862e0e
--- /dev/null
+++ b/src/resource/IntegrityMessage_no.properties
@@ -0,0 +1,11 @@
+#! created/edited by Popeye version 0.51 sunshine (popeye.sourceforge.net)
+
+ITEXT_1=det er tips
+ITEXT_1001=advarsel
+ITEXT_2001=feil
+ITEXT_1010=begynnelsen p\u00e5 $FIELD-feltet
+ITEXT_1011=feil avsluting ($FIELD-feltet)
+ITEXT_1012=noe kan v\u00e6re galt i $FIELD-feltet
+ITEXT_10=Det er store bokstaver uten maskering {} inne i $FIELD-feltet
+ITEXT_11=$FIELD-feltet burde inneholde et firesifret tall
+ITEXT_2010=uventet avsluttende } inne i $FIELD-feltet
diff --git a/src/resource/JabRef_de.properties b/src/resource/JabRef_de.properties
new file mode 100644
index 0000000..d1057ba
--- /dev/null
+++ b/src/resource/JabRef_de.properties
@@ -0,0 +1,1034 @@
+#! created/edited by Popeye version 0.51 sunshine (popeye.sourceforge.net)
+
+!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.=Dies_ist_ein_einfacher_Copy_&_Paste-Dialog._Nachdem_Text_in_das_Texteingabefeld_geladen_oder_kopiert_wurde,_k\u00f6nnen_Sie_Textteile_markieren_und_ihnen_ein_BibTeX-Feld_zuordnen.
+%0_contains_the_Regular_Expression_<b>%1</b>=%0_den_Regul\u00E4ren_Ausdruck_<b>%1</b>_enth\u00E4lt
+%0_contains_the_term_<b>%1</b>=%0_den_Ausdruck_<b>%1</b>_enth\u00E4lt
+%0_doesn't_contain_the_Regular_Expression_<b>%1</b>=%0_nicht_den_Regul\u00E4ren_Ausdruck_<b>%1</b>_enth\u00E4lt
+%0_doesn't_contain_the_term_<b>%1</b>=%0_nicht_den_Ausdruck_<b>%1</b>_enth\u00E4lt
+%0_doesn't_match_the_Regular_Expression_<b>%1</b>=%0_nicht_exakt_dem_Regul\u00E4ren_Ausdruck_<b>%1</b>_entspricht
+%0_doesn't_match_the_term_<b>%1</b>=%0_nicht_exakt_dem_Ausdruck_<b>%1</b>_entspricht
+%0_field_set=%0-Feld_erstellt
+%0_import_cancelled.=%0_Importierung_abgebrochen
+%0_matches_the_Regular_Expression_<b>%1</b>=%0_exakt_dem_Regul\u00E4ren_Ausdruck_<b>%1</b>_entspricht
+%0_matches_the_term_<b>%1</b>=%0_exakt_dem_Ausdruck_<b>%1</b>_entspricht
+<field_name>=<Feldname>
+<HTML>Unpack_the_zip_file_containing_import/export_filters_for_Endnote,<BR>for_optimal_interoperability_with_JabRef</HTML>=<HTML>Entpacke_die_zip-Datei_mit_den_Import/Export-Filtern_f\u00FCr_EndNote,<BR>um_die_bestm\u00F6gliche_Kompatibilit\u00E4t_mit_JabRef_zu_gew\u00E4hrleisten</HTML>
+<no_field>=<kein_Feld>
+<select>=<ausw\u00E4hlen>
+<select_word>=<Wort_ausw\u00E4hlen>
+_on_entry_number_=_bei_Eintrag_Nummer_
+A_CiteSeer_fetch_operation_is_currently_in_progress.=CiteSeer-Abruf_ist_in_Bearbeitung.
+A_CiteSeer_import_operation_is_currently_in_progress.=Ein_CiteSeer-Import_ist_gerade_in_Bearbeitung.
+A_string_with_that_label_already_exists=Ein_String_mit_diesem_Namen_exisitiert_bereits
+Abbreviate_journal_names_of_the_selected_entries_(ISO_abbreviation)=Zeitschriftennamen_der_ausgew\u00e4hlten_Eintr\u00e4ge_abk\u00fcrzen_(ISO-Abk\u00fcrzung)
+Abbreviate_journal_names_of_the_selected_entries_(MEDLINE_abbreviation)=Zeitschriftennamen_der_ausgew\u00e4hlten_Eintr\u00e4ge_abk\u00fcrzen_(MEDLINE-Abk\u00fcrzung)
+Abbreviate_names=Namen_abk\u00fcrzen
+Abbreviation=Abk\u00fcrzung
+About_JabRef=\u00DCber_JabRef
+Abstract=Zusammenfassung
+Accept=\u00DCbernehmen
+Accept_change=\u00C4nderung_akzeptieren
+Action=Aktion
+Add=Hinzuf\u00FCgen
+Add_a_(compiled)_custom_ImportFormat_class_from_a_class_path._\nThe_path_need_not_be_on_the_classpath_of_JabRef.=F\u00FCge_(kompilierten)_externe_ImportFormat_Klasse_aus_Verzeichnis_hinzu._\nDas_Verzeichnis_mu\u00DF_nicht_im_Klassenpfad_von_JabRef_enthalten_sein.
+Add_a_(compiled)_custom_ImportFormat_class_from_a_Zip-archive.\nThe_Zip-archive_need_not_be_on_the_classpath_of_JabRef.=F\u00FCge_(kompilierten)_externe_ImportFormat_Klasse_aus_Verzeichnis_hinzu._\nDas_Verzeichnis_mu\u00DF_nicht_im_Klassenpfad_von_JabRef_enthalten_sein.
+add_entries_to_group=Eintr\u00E4ge_zu_Gruppe_hinzuf\u00FCgen
+Add_from_folder=Aus_Klassenpfad_hinzuf\u00FCgen
+Add_from_jar=Aus_Archiv-Datei_hinzuf\u00FCgen
+add_group=Gruppe_hinzuf\u00FCgen
+Add_Group=Gruppe_hinzuf\u00FCgen
+Add_new=Neu
+Add_Subgroup=Untergruppe_hinzuf\u00FCgen
+Add_to_group=Zu_Gruppe_hinzuf\u00FCgen
+Added_entry=Eintrag_hinzugef\u00FCgt
+Added_group=Gruppe_hinzugef\u00FCgt
+Added_group_"%0".=Gruppe_"%0"_hinzugef\u00FCgt.
+Added_new=Neu_hinzugef\u00FCgt
+Added_string=String_hinzugef\u00FCgt
+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.=Zus\u00E4tzlich_k\u00F6nnen_Eintr\u00E4ge,_deren_Feld_<b>%0</b>_nicht_< [...]
+Advanced=Erweitert
+Advanced_options_for_setting...=Erweiterte_Optionen_f\u00fcr_Einstellung...
+All_Entries=Alle_Eintr\u00E4ge
+All_entries=Alle_Eintr\u00E4ge
+All_entries_of_this_type_will_be_declared_typeless._Continue?=Alle_Eintr\u00E4ge_dieses_Typs_werden_als_typlos_eingestuft._Fortfahren?
+All_fields=Alle_Felder
+All_subgroups_(recursively)=Alle_Untergruppen_(rekursiv)
+Allow_editing_in_table_cells=Bearbeiten_in_der_Tabelle_zulassen
+Always_save_database_ordered_by_author_name=Datei_immer_nach_Autorennamen_sortiert_abspeichern
+and=und
+and_the_class_must_be_available_in_your_classpath_next_time_you_start_JabRef.=Au\u00DFerdem_muss_die_Klasse_beim_n\u00E4chsten_Start_von_JabRef_durch_den_"Classpath"_erreichbar_sein.
+any_field_that_matches_the_regular_expression_<b>%0</b>=ein_beliebiges_Feld,_auf_das_der_Regul\u00E4re_Ausdruck_<b>%0</b>_passt,
+Appearance=Erscheinungsbild
+Append=anf\u00FCgen
+Append_contents_from_a_BibTeX_database_into_the_currently_viewed_database=Inhalt_einer_BibTeX-Datei_an_die_aktuelle_Datei_anh\u00E4ngen
+Append_database=Datei_anh\u00E4ngen
+append_the_selected_text_to_bibtex_key=ausgew\u00e4hlten_Text_an_BibTeX-Key_anh\u00e4ngen
+Apply=\u00DCbernehmen
+Assign_entries_based_on:=Eintr\u00e4ge_zuweisen_basierend_auf:
+Assign_new_file=Neue_Datei_zuordnen
+Assign_the_original_group's_entries_to_this_group?=Eintr\u00E4ge_der_urspr\u00FCnglichen_Gruppe_zu_dieser_Gruppe_hinzuf\u00FCgen?
+Assigned_%0_entries_to_group_"%1".=%0_Eintr\u00E4ge_zu_Gruppe_"%1"_hinzugef\u00FCgt.
+Assigned_1_entry_to_group_"%0".=1_Eintrag_zu_Gruppe_"%0"_hinzugef\u00FCgt.
+Attach_%0_file=Datei_%0_anf\u00fcgen
+Attach_URL=URL_anf\u00fcgen
+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.=Versucht,_%0-Links_f\u00fcr_die_Eintr\u00e4ge_automatisch_zuzuordnen._Dies_funktioniert,_wenn_der_Name_einer_%0-Datei_im_%0-Verzeichnis_oder_einem_Unterverzeichnis<BR>identisch_ist_mit_dem_BibTeX-Key_eines_Eintrags_(erweitert_um_die_jeweilige_Dateiendung).
+Auto=Auto
+Autodetect_format=Format_automatisch_erkennen
+Autogenerate_BibTeX_key=BibTeX-Key_automatisch_generieren
+Autogenerate_BibTeX_keys=BibTeX-Keys_automatisch_generieren
+Autogenerate_groups=Gruppen_automatisch_erstellen
+autogenerate_keys=BibTeX-Keys_automatisch_generieren
+Automatically_create_groups=Gruppen_automatisch_erstellen
+Automatically_create_groups_for_database.=Automatisch_Gruppen_f\u00FCr_die_Datei_anlegen.
+Automatically_created_groups=Automatisch_erzeugte_Gruppen
+Automatically_hide_groups_interface_when_switching_to_a_database_that_contains_no_groups=Gruppenansicht_automatisch_ausblenden,_wenn_zu_einer_Datei_ohne_Gruppen_gewechselt_wird
+Automatically_show_groups_interface_when_switching_to_a_database_that_contains_groups=Gruppenansicht_automatisch_einblenden,_wenn_zu_einer_Datei_mit_Gruppen_gewechselt_wird
+Autoset=Automatisch_zuordnen
+Autoset_%0_field=Feld_%0_automatisch_setzen
+Autoset_%0_links._Allow_overwriting_existing_links.=%0_Links_automatisch_zuordnen._Vorhandene_Links_\u00fcberschreiben.
+Autoset_%0_links._Do_not_overwrite_existing_links.=%0_Links_automatisch_zuordnen._Vorhandene_Links_nicht_\u00fcberschreiben.
+Autosetting_%0_field...=Automatisches_Setzen_von_Feld_%0...
+AUX_File_import=Teildatenbank_aus_AUX_Datei_erstellen
+AUX_file_import=AUX_Datei_Import
+Available_export_formats=Verf\u00FCgbare_Exportformate
+Available_fields=verf\u00FCgbare_BibTeX_Felder
+Available_import_formats=Verf\u00FCgbare_Importformate
+Background_color_for_marked_entries=Hintergrundfarbe_f\u00fcr_markierte_Eintr\u00e4ge
+Background_color_for_optional_fields=Hintergrundfarbe_f\u00fcr_optionale_Felder
+Background_color_for_required_fields=Hintergrundfarbe_f\u00fcr_ben\u00f6tigte_Felder
+Backup_old_file_when_saving=Beim_Speichern_ein_Backup_der_alten_Datei_anlegen
+Bibkey_to_filename_conversion=Konvertierung_von_BibTeX-Key_zu_Dateiname
+Biblioscape_Tag_file=Biblioscape_Tag-Datei
+BibTeX=BibTeX
+BibTeX_key=BibTeX-Key
+BibTeX_key_is_unique.=Der_BibTeX-Key_ist_eindeutig.
+BibTeX_key_not_set._Enter_a_name_for_the_downloaded_file=Kein_BibTeX-Key_vorhanden._Bitte_Dateinamen_zum_Download_angeben
+BibTeX_source=BibTeX_Quelltext
+BibTeXML=BibTeXML
+BibTeXML_File=BibTeXML_Datei
+Binding=Tastenk\u00FCrzel
+Broken_link=Fehlerhafter_Link
+Browse=Durchsuchen
+by=von
+Calling_external_viewer...=Externes_Anzeigeprogramm_wird_aufgerufen
+Cancel=Abbrechen
+Cannot_add_entries_to_group_without_generating_keys._Generate_keys_now?=Eintr\u00e4ge_k\u00f6nnen_einer_Gruppe_nicht_hinzugef\u00fcgt_werden,_ohne_Keys_zu_generieren._Sollen_die_Keys_jetzt_generiert_werden?
+Cannot_merge_this_change=Kann_diese_\u00C4nderung_nicht_einf\u00FCgen
+Cannot_move_group=Gruppe_kann_nicht_verschoben_werden
+Cannot_move_group_"%0"_down.=Gruppe_"%0"_kann_nicht_nach_unten_bewegt_werden.
+Cannot_move_group_"%0"_left.=Gruppe_"%0"_kann_nicht_nach_links_bewegt_werden.
+Cannot_move_group_"%0"_right.=Gruppe_"%0"_kann_nicht_nach_rechts_bewegt_werden.
+Cannot_move_group_"%0"_up.=Gruppe_"%0"_kann_nicht_nach_oben_bewegt_werden.
+case_insensitive=Gro\u00DF-/Kleinschreibung_wird_nicht_unterschieden
+case_sensitive=Gro\u00DF-/Kleinschreibung_wird_unterschieden
+Case_sensitive=Gro\u00DF-/Kleinschreibung_unterscheiden
+change_assignment_of_entries=\u00C4nderung_der_zugewiesenen_Eintr\u00E4ge
+# The following are for case change in right-click menu in entry editor. The last four
+# illustrate the four variations of capitalization
+Change_case=Gro\u00DF-_und_Kleinschreibung
+Change_entry_type=Eintragstyp_\u00E4ndern
+change_key=BibTeX-Key_\u00E4ndern
+Change_of_Grouping_Method=\u00C4ndern_der_Gruppierungsmethode
+change_preamble=Pr\u00E4ambel_\u00E4ndern
+change_string_content=Inhalt_des_Strings_\u00E4ndern
+change_string_name=Namen_des_Strings_\u00E4ndern
+change_type=Typ_\u00E4ndern
+changed_=ge\u00E4ndert_
+Changed_font_settings=Schrifteinstellungen_ge\u00E4ndert
+Changed_language_settings=Spracheinstellungen_ge\u00E4ndert.
+Changed_look_and_feel_settings="Look_and_Feel"-Einstellungen_ge\u00E4ndert
+Changed_preamble=Pr\u00E4ambel_ge\u00E4ndert
+Changed_type_to=Typ_ge\u00E4ndert_zu
+Characters_to_ignore=Folgende_Buchstaben_ignorieren
+Check_existing_%0_links=Existierende_%0-Links_\u00fcberpr\u00fcfen
+Check_links=Links_\u00fcberpr\u00fcfen
+Choose_the_URL_to_download._The_default_value_points_to_a_list_provided_by_the_JabRef_developers.=URL_zum_Herunterladen_ausw\u00e4hlen._Der_Standardwert_f\u00fchrt_zu_einer_Liste,_die_von_den_JabRef-Entwicklern_zur_Verf\u00fcgung_gestellt_wird.
+Citation_import_from_CiteSeer_failed.=Fehler_beim_Import_von_CiteSeer.
+CiteSeer_Error=CiteSeer-Fehler
+CiteSeer_Fetch_Error=Fehler_beim_Abrufen_von_CiteSeer
+CiteSeer_import_entries=CiteSeer_Eintr\u00E4ge_importieren
+CiteSeer_Import_Error=Fehler_beim_Import_von_CiteSeer
+CiteSeer_Import_Fields=CiteSeer_Import-Felder
+CiteSeer_Transfer=CiteSeer-Transfer
+CiteSeer_Warning=CiteSeer_Warnung
+Class_name=Klassenname
+Clear=Zur\u00FCcksetzen
+clear_all_groups=Alle_Gruppen_l\u00F6schen
+Clear_field=Feld_l\u00f6schen
+Clear_highlight=Markierten_l\u00f6schen
+Clear_highlighted=Markierte_l\u00f6schen
+Clear_highlighted_groups=Markierte_Gruppen_l\u00f6schen
+Clear_inputarea=gesamten_Text_entfernen
+Clear_search=Suche_l\u00f6schen
+Close=Schlie\u00DFen
+Close_database=Datei_schlie\u00DFen
+Close_dialog=Dialog_schlie\u00DFen
+# The following lines correspond to names of key bindings:
+Close_entry_editor=Eintragseditor_schlie\u00DFen
+Close_preamble_editor=Pr\u00E4ambel-Editor_schlie\u00DFen
+Close_the_current_database=Aktuelle_Datei_schlie\u00DFen
+Close_the_help_window=Hilfefenster_schlie\u00DFen
+Close_window=Fenster_schlie\u00DFen
+Closed_database=Datei_geschlossen
+Collapse_subtree=Unterbaum_zuklappen
+Color_codes_for_required_and_optional_fields=Farbanzeige_f\u00FCr_ben\u00F6tigte_und_optionale_Felder
+Color_for_marking_incomplete_entries=Farbe_zum_Markieren_unvollst\u00e4ndiger_Eintr\u00e4ge
+Column_width=Spaltenbreite
+Command_line_id=Kommandozeilen_ID
+Complete_record=Kompletter_Eintrag
+Completed_citation_import_from_CiteSeer.=Import_von_CiteSeer_abgeschlossen.
+Completed_Import_Fields_from_CiteSeer.=Die_Felder_wurden_aus_CiteSeer_importiert.
+Completed_import_from_CiteSeer.=Import_von_CiteSeer_abgeschlossen
+Contained_in=Enthalten_in
+Content=Inhalt
+Copied=Kopiert
+Copied_cell_contents=Zelleninhalt_kopiert
+Copied_key=BibTeX-Key_kopiert
+Copied_keys=BibTeX-Keys_kopiert
+Copy=Kopieren
+Copy_BibTeX_key=BibTeX-Key_kopieren
+Copy_\\cite{BibTeX_key}=Kopiere_\\cite{BibTeX-Key}
+Copy_to_clipboard=Text_in_Zwischenablage_kopieren
+Could_not_call_executable=Konnte_das_Programm_nicht_aufrufen
+Could_not_connect_to_host=Verbindung_zum_Host_fehlgeschlagen
+# I have reformulated the following lines, because the 1st person form is not suitable:
+Could_not_connect_to_host_=Verbindung_zum_Host_fehlgeschlagen
+Could_not_export_entry_types=Eintragstypen_konnten_nicht_exportiert_werden
+Could_not_export_file=Konnte_Datei_nicht_exportieren
+Could_not_export_preferences=Einstellungen_konnten_nicht_exportiert_werden
+Could_not_find_a_suitable_import_format.=Kein_passendes_Importformat_gefunden.
+Could_not_find_layout_file=Keine_Layoutdatei_gefunden
+Could_not_import_entry_types=Eintragstypen_konnten_nicht_importiert_werden
+Could_not_import_preferences=Einstellungen_konnten_nicht_importiert_werden
+Could_not_instantiate_%0_%1=Konnte_Importer_nicht_erzeugen_%0_%1
+Could_not_resolve_import_format=Das_Importformat_konnte_nicht_bestimmt_werden.
+Could_not_save_file=Datei_konnte_nicht_gespeichert_werden
+Couldn't_find_an_entry_associated_with_this_URL=Es_konnte_kein_Eintrag_gefunden_werden,_der_mit_dieser_URL_verkn\u00FCpft_ist
+Couldn't_parse_the_'citeseerurl'_field_of_the_following_entries=Die_'citeseerurl'_der_folgenden_Eintr\u00E4ge_konnte_nicht_analysiert_werden
+Create_group=Gruppe_anlegen
+Created_group=Gruppe_erstellen
+Created_group_"%0".=Gruppe_"%0"_erstellt.
+Created_groups.=Gruppen_erstellt.
+Curly_braces_{_and_}_must_be_balanced.=Geschweifte_Klammern_{_und_}_m\u00FCssen_sich_ausgleichen.
+Current_content=Aktueller_Inhalt
+Current_value=Aktueller_Wert
+Custom_entry_types=Benutzerdefinierte_Eintragstypen
+Custom_entry_types_found_in_file=Benutzerdefinierte_Eintragstypen_gefunden
+Custom_export=Externe_Exportfilter
+Custom_importers=Externe_Importfilter
+Customize_entry_types=Eintragstypen_anpassen
+Customize_key_bindings=Tastenk\u00FCrzel_anpassen
+Cut=Ausschneiden
+cut_entries=Eintr\u00E4ge_ausschneiden
+cut_entry=Eintrag_ausschneiden
+Cut_pr=Ausschneiden
+Database_encoding=Zeichenkodierung_der_Datei
+Database_has_changed._Do_you_want_to_save_before_closing?=Die_Datei_wurde_ge\u00E4ndert._Wollen_Sie_vor_dem_Beenden_speichern?
+Database_properties=Eigenschaften_der_Datei
+Date_format=Datumsformat
+Default=Standard
+Default_encoding=Standard_Zeichenkodierung
+Default_grouping_field=Standard_Gruppierungs-Feld
+Default_look_and_feel=Standard_"look_and_feel"
+Default_owner=Standard-Besitzer
+Default_pattern=Standardmuster
+Default_sort_criteria=Standard-Sortierkriterium
+defined.=definiert.
+Delete=L\u00F6schen
+Delete_custom=Eintragstyp_l\u00F6schen
+Delete_custom_format=Format_des_Eintragstyps_l\u00F6schen
+# I have reformulated the following lines, because the 1st person form is not suitable:
+# (Folgende_URL_konnte_nicht_analysiert_werden)
+delete_entries=Eintr\u00E4ge_l\u00F6schen
+Delete_entry=Eintrag_l\u00F6schen
+delete_entry=Eintrag_l\u00F6schen
+Delete_multiple_entries=Mehrere_Eintr\u00E4ge_l\u00F6schen
+Delete_rows=Zeilen_l\u00F6schen
+Delete_strings=Strings_l\u00F6schen
+Deleted=Gel\u00F6scht
+Deleted_entry=Eintrag_gel\u00F6scht
+Delimit_fields_with_semicolon,_ex.=Felder_mit_Semikolon_abgrenzen,_z.B.
+Descending=Absteigend
+Description=Beschreibung
+Deselect_all=Auswahl_aufheben
+Details=Details
+Disable_entry_editor_when_multiple_entries_are_selected=Eintragseditor_sperren,_wenn_mehrere_Eintr\u00E4ge_ausgew\u00E4hlt_sind
+Disable_this_confirmation_dialog=Diesen_Best\u00E4tigungsdialog_deaktivieren
+Disable_this_warning_dialog=Diese_Warnmeldung_deaktivieren
+Display_all_entries_belonging_to_one_or_more_of_the_selected_groups.=Alle_Eintr\u00E4ge_anzeigen,_die_zu_einer_oder_mehreren_der_ausgew\u00E4hlten_Gruppen_geh\u00F6ren.
+Display_help_on_command_line_options=Zeige_Kommandozeilenhilfe
+Display_imported_entries_in_an_inspection_window_before_they_are_added.=Importierte_Eintr\u00e4ge_im_Kontrollfenster_anzeigen_bevor_sie_hinzugef\u00fcgt_werden.
+Display_only_entries_belonging_to_all_selected_groups.=Nur_Eintr\u00E4ge_anzeigen,_die_zu_allen_ausgew\u00E4hlten_Gruppen_geh\u00F6ren.
+Displaying_no_groups=Keine_Gruppen_anzeigen
+Do_not_abbreviate_names=Namen_nicht_abk\u00fcrzen
+Do_not_autoset=Nicht_automatisch_zuordnen
+Do_not_import_entry=Eintrag_nicht_importieren
+Do_not_open_any_files_at_startup=Keine_Dateien_beim_Start_\u00f6ffnen
+Do_not_overwrite_existing_keys=Existierende_Keys_nicht_\u00fcberschreiben
+Do_not_wrap_the_following_fields_when_saving=Beim_Speichern_keinen_Zeilenumbruch_in_den_folgenden_Feldern_einf\u00fcgen
+Docbook=Docbook
+Done=Fertig
+Down=Abw\u00e4rts
+Download=Herunterladen
+Download_completed=Download_beendet
+Download_file=Datei_herunterladen
+Downloading...=Download_l\u00E4uft
+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.=Aufgrund_des_doppelten_BibTeX-Keys_kann_die_Gruppenzuordnung_dieses_Eintrags_beim_n\u00E4chstenn\u00D6ffnen_nicht_wiederhergestellt_werden._Es_wird_empfohlen,_von_JabRef_jetzt_einen_eindeutigennKey_automatisch_generieren_zu_lassen,_um_dieses_Problem_zu_verhindern.
+dummy=dummy
+Duplicate_BibTeX_key=Doppelter_BibTeX-Key
+duplicate_BibTeX_key=doppelter_BibTeX-Key
+Duplicate_BibTeX_key.=Doppelter_BibTeX-Key.
+duplicate_BibTeX_key.=doppelter_BibTeX-Key
+Duplicate_BibTeX_key._Grouping_may_not_work_for_this_entry.=Doppelter_BibTeX-Key._Es_kann_sein,_dass_die_Gruppierung_f\u00fcr_diesen_Eintrag_nicht_funktioniert.
+Duplicate_Key_Warning=Warnung:_Key_bereits_vorhanden
+Duplicate_pairs_found=Doppelte_Eintr\u00E4ge_gefunden
+duplicate_removal=Duplikate_entfernen
+Duplicate_string_name=Doppelter_String-Name
+Duplicates_found=Doppelte_Eintr\u00E4ge_gefunden
+Duplicates_removed=Doppelte_Eintr\u00E4ge_gel\u00F6scht
+Dynamic_groups=Dynamische_Gruppen
+Dynamically_group_entries_by_a_free-form_search_expression=Dynamisches_Gruppieren_der_Eintr\u00E4ge_anhand_eines_beliebigen_Suchausdrucks
+Dynamically_group_entries_by_searching_a_field_for_a_keyword=Dynamisches_Gruppieren_der_Eintr\u00e4ge_anhand_eines_Stichworts_in_einem_Feld
+Each_line_must_be_on_the_following_form=Jede_Zeile_muss_das_folgende_Format_aufweisen
+Edit=Bearbeiten
+Edit_custom_export=Bearbeite_externen_Exportfilter
+Edit_entry=Eintrag_bearbeiten
+Edit_group=Gruppe_bearbeiten
+Edit_journal=Zeitschrift_bearbeiten
+Edit_preamble=Pr\u00E4ambel_bearbeiten
+Edit_strings=Strings_bearbeiten
+empty_BibTeX_key=leerer_BibTeX-Key
+Empty_BibTeX_key.=Leerer_BibTeX-Key.
+Empty_BibTeX_key._Grouping_may_not_work_for_this_entry.=Leerer_BibTeX-Key._Es_kann_sein,_dass_die_Gruppierung_f\u00fcr_diesen_Eintrag_nicht_funktioniert.
+Empty_database=Leere_Datei
+empty_database=leere_Datenbank
+Enable source_editing=Bearbeiten_von_Sourcecode_zulassen
+Enable_source_editing=Quelltextbearbeitung_aktivieren
+Endnote=Endnote
+Enter_URL=URL_eingeben
+Enter_URL_to_download=URL_f\u00FCr_den_Download_eingeben
+entries=Eintr\u00E4ge
+Entries_cannot_be_manually_assigned_to_or_removed_from_this_group.=Ein_manuelles_Hinzuf\u00FCgen_oder_Entfernen_von_Eintr\u00E4gen_ist_f\u00FCr_diese_Gruppe_nicht_m\u00F6glich.
+Entries_exported_to_clipboard=Eintr\u00E4ge_in_die_Zwischenablage_kopiert
+entries_have_undefined_BibTeX_key=Eintr\u00E4ge_haben_einen_unbestimmten_BibTeX-Key
+entries_into_new_database=Eintr\u00E4ge_in_neue_Datei
+entry=Eintrag
+Entry_editor=Editor
+# The following lines correspond to names of key bindings:
+Entry_editor,_next_entry=Eintragseditor,_n\u00E4chster_Eintrag
+Entry_editor,_next_panel=Eintragseditor,_n\u00E4chstes_Panel
+Entry_editor,_previous_entry=Eintragseditor,_voriger_Eintrag
+Entry_editor,_previous_panel=Eintragseditor,_voriges_Panel
+Entry_editor,_store_field=Eintragseditor,_Feld_speichern
+Entry_in_current_database=Eintrag_in_aktueller_Datenbank
+Entry_in_import=Eintrag_in_Importierung
+Entry_is_incomplete=Eintrag_ist_nicht_vollst\u00E4ndig
+Entry_preview=Eintragsvorschau
+Entry_table=Tabellenansicht
+Entry_table_columns=Spaltenanordnung
+Entry_type=Eintragstyp
+Entry_type_names_are_not_allowed_to_contain_white_space_or_the_following_characters=Namen_von_Eintragstypen_d\u00FCrfen_weder_Leerzeichen_noch_die_folgenden_Zeichen_enthalten
+Entry_types=Eintragstypen
+EOF_in_mid-string=EOF_in_mid-string
+Error=Fehler
+##Error:_check_your_External_viewer_settings_in_Preferences=Fehler:_\u00FCberpr\u00FCfen_Sie_Ihre_Einstellungen_zu_Externen_Programmen
+Error_in_field=Fehler_in_Feld
+Error_in_line=Fehler_in_Zeile
+Error_opening_file=Fehler_beim_\u00D6ffnen_der_Datei
+Error_setting_field=Fehler_beim_Erstellen_des_Feldes
+Existing_file=Bestehende_Datei
+exists._Overwrite?=Existiert._\u00DCberschreiben?
+exists._Overwrite_file?=existiert._Ersetzen?
+Exit=Beenden
+Expand_subtree=Unterbaum_aufklappen
+Explicit=Explizit
+Export=Exportieren
+Export_entry_types=Eintragstypen_exportieren
+Export_name=Filtername
+Export_preferences=Einstellungen_exportieren
+Export_preferences_to_file=Exportiere_Einstellungen_in_Datei
+Export_properties=Eigenschaften_f\u00FCr_Exportfilter
+Export_selected_to_clipboard=Ausgew\u00E4hlte_in_die_Zwischenablage_kopieren
+Export_to_clipboard=In_die_Zwischenablage_kopieren
+Exported_database_to_file=Datei_exportiert_nach
+Exporting=Exportiere
+External_changes=Externe_\u00C4nderungen
+External_files=Externe_Dateien
+External_programs=Externe_Programme
+External_viewer_called=Externer_Betrachter_aufgerufen
+Failed_to_read_groups_data_(unsupported_version:_%0)=Gruppen_konnten_nicht_eingelesen_werden_(nicht_unterst\u00FCtzte_Version:_%0)
+Fetch=Abrufen
+Fetch_Articles_Citing_your_Database=Literaturangaben_abrufen,_die_mit_Datens\u00E4tzen_ihrer_Datei_\u00FCbereinstimmen
+Fetch_Citations_from_CiteSeer=Literaturangaben_von_CiteSeer_abrufen
+Fetch_citations_from_CiteSeer=Eintr\u00E4ge_von_CiteSeer_holen
+Fetch_CiteSeer=CiteSeer_abrufen
+Fetch_Medline=Medline_abrufen
+fetch_Medline=Medline_abrufen
+Fetch_Medline_by_author=Medline_mittels_Autor_abrufen
+Fetch_Medline_by_ID=Medline_mittels_ID_abrufen
+Fetched_all_citations_from_target_database.=Alle_Literaturangaben_von_der_Zieldatenbank_abgerufen.
+Fetching_Citations=Literaturangaben_werden_abgerufen
+Fetching_Identifiers=Bezeichner_werden_abgerufen
+Fetching_Medline...=Rufe_Medline_ab...
+Fetching_Medline_by_ID...=Rufe_Medline_mittels_ID_ab...
+Fetching_Medline_by_id_...=Rufe_Medline_mittels_ID_ab...
+Fetching_Medline_by_term_...=Rufe_Medline_mittels_Suchbegriff_ab...
+Field=Feld
+field=Feld
+# 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=Feldinhalt
+Field_name=Feldname
+Field_names_are_not_allowed_to_contain_white_space_or_the_following_characters=Der_Feldname_darf_weder_Leerzeichen_noch_eines_der_folgenden_Zeichen_enthalten
+Field_sizes=Feldgr\u00f6\u00dfen
+Field_to_group_by=Sortierfeld
+Field_to_search=Zu_durchsuchendes_Feld
+Fields=Felder
+File=Datei
+file=Datei
+File_'%0'_not_found=Datei_'%0'_nicht_gefunden
+File_changed=Datei_ge\u00E4ndert
+File_extension=Dateiendung
+File_has_been_updated_externally._Are_you_sure_you_want_to_save?=Die_Datei_wurde_extern_ver\u00E4ndert._Sind_Sie_sicher,_dass_Sie_abspeichern_m\u00F6chten?
+File_not_found=Datei_nicht_gefunden
+File_updated_externally=Datei_extern_ge\u00E4ndert
+filename=Dateiname
+Files_opened=Dateien_ge\u00F6ffnet
+Find_duplicates=Nach_doppelten_Eintr\u00E4gen_suchen
+Finished_autosetting_%0_field._Entries_changed:_%1.=Automatisches_Setzen_von_Feld_%0_abgeschlossen._Ge\u00e4nderte_Eintr\u00e4ge:_%1.
+Finished_synchronizing_%0_links._Entries_changed%c_%1.=Synchronisierung_von_%0_Links_abgeschlossen._Ge\u00e4nderte_Eintr\u00e4ge%c_%1.
+First_select_the_entries_you_want_keys_to_be_generated_for.=W\u00E4hlen_Sie_zuerst_die_Eintr\u00E4ge_aus,_f\u00FCr_die_Keys_erstellt_werden_sollen.
+Fit_table_horizontally_on_screen=Tabelle_horizontal_dem_Bildschirm_anpassen
+Float=Oben_einsortieren
+Font_Family=Schriftart
+Font_Preview=Vorschau
+Font_Size=Schriftgr\u00F6\u00DFe
+Font_Style=Schriftstil
+FontSelector=Schriften_w\u00E4hlen
+for=f\u00FCr
+Format_of_author_and_editor_names=Format_der_Autoren-_und_Hrsg.-Namen
+Format_used=benutztes_Format
+Formatter_not_found=Formatierer_nicht_gefunden
+found=gefunden
+found_in_aux_file=gefundene_Schl\u00FCssel_in_AUX_Datei
+Full_name=Kompletter_Name
+General=Allgemein
+General_fields=Allgemeine_Felder
+Generate=Erzeugen
+Generate_BibTeX_key=BibTeX-Key_generieren
+Generate_keys=Erstelle_Key
+Generate_now=Jetzt_generieren
+Generated_BibTeX_key_for=BibTeX-Key_erzeugt_f\u00FCr
+Generating_BibTeX_key_for=Erzeuge_BibTeX-Key_f\u00FCr
+Grab=Tastenk\u00FCrzel_holen
+Gray_out_entries_not_in_group_selection=Eintr\u00E4ge_ausblenden,_die_nicht_in_der_Gruppenauswahl_sind
+Gray_out_non-hits=Nicht-Treffer_grau_einf\u00E4rben
+Gray_out_non-matching_entries=Nicht_\u00FCbereinstimmende_Eintr\u00E4ge_ausblenden
+Group_definitions_have_been_converted_to_JabRef_1.7_format.=Die_Gruppendefinitionen_wurden_zum_JabRef_1.7-Format_konvertiert.
+Group_name=Name_der_Gruppe
+Group_properties=Gruppeneigenschaften
+Groups=Gruppen
+Harvard_RTF=Harvard_RTF
+Help=Hilfe
+Help_contents=Hilfe_-_Inhalt
+Help_on_groups=Hilfe_zu_Gruppen
+Help_on_key_patterns=Hilfe_zu_BibTeX-Key-Mustern
+Hide_non-hits=Nicht-Treffer_ausblenden
+Highlight=Markieren
+Highlight_groups_matching_all_selected_entries=Gruppen_markieren,_die_alle_selektierten_Eintr\u00e4ge_enthalten
+Highlight_groups_matching_any_selected_entry=Gruppen_markieren,_die_mindestens_einen_der_selektierten_Eintr\u00e4ge_enthalten
+Highlight_groups_that_contain_entries_contained_in_any_currently_selected_group=Gruppen_markieren,_die_Eintr\u00e4ge_enthalten,_die_in_einer_der_gerade_markierten_Gruppen_enthalten_sind
+Highlight_overlapping_groups=Sich_\u00fcberschneidende_Gruppen_markieren
+Hint%c_To_search_specific_fields_only,_enter_for_example%c<p><tt>author%esmith_and_title%eelectrical</tt>=Hinweis%c_Um_ausschlie\u00DFlich_bestimmte_Felder_zu_durchsuchen,_geben_Sie_z.B._ein%c<p><tt>author%esmith_and_title%eelectrical</tt>
+HTML=HTML
+Ignore=Ignorieren
+Illegal_type_name=Ung\u00FCltiger_Typ
+Immediate_subgroups=Direkte_Untergruppen
+Import=Importieren
+Import_and_append=Importieren_und_anh\u00E4ngen
+Import_and_keep_old_entry=Importieren_und_alten_Eintrag_behalten
+Import_and_remove_old_entry=Importieren_und_alten_Eintrag_l\u00F6schen
+Import_cancelled.=Importierung_abgebrochen.
+Import_Data_from_CiteSeer=Daten_von_CiteSeer_importieren
+Import_Data_from_CiteSeer_Database=Daten_aus_CiteSeer-Datenbank_importieren
+Import_database=Datei_importieren
+Import_entries=Eintr\u00E4ge_importieren
+Import_entry_types=Eintragstypen_importieren
+Import_failed=Import_fehlgeschlagen
+Import_Fields_from_CiteSeer=Felder_von_CiteSeer_importieren
+Import_fields_from_CiteSeer=Felder_von_CiteSeer_importieren
+Import_fields_from_CiteSeer_Database=Import_fields_from_CiteSeer_Database
+Import_Fields_from_CiteSeer_Database=Felder_aus_CiteSeer-Datenbank_importieren
+Import_file=Importiere_Datei
+Import_group_definitions=Gruppendefinitionen_importieren
+Import_name=Importer_Name
+Import_plain_text=Klartext_importieren
+Import_preferences=Einstellungen_importieren
+Import_preferences_from_file=Importiere_Einstellungen_aus_Datei
+Import_strings=Strings_importieren
+Import_to_open_tab=In_ge\u00f6ffnetes_Tab_importieren
+Import_word_selector_definitions=Wortauswahldefinitionen_importieren
+Imported_database=Datei_importiert
+Imported_entries=Eintr\u00E4ge_importiert
+Imported_entry_types=Eintragstypen_importiert
+Imported_file=Importierte_Datei
+Imported_from_database=Importiert_aus_Datei
+ImportFormat_class=ImportFormat_Klasse
+Importing=Importiere
+Importing_file=importiere_Datei
+Importing_in_unknown_format=Importiere_ein_unbekanntes_Format
+In_JabRef,_use_pairs_of_#_characters_to_indicate_a_string.=Benutzen_Sie_in_JabRef_das_Zeichen_#_paarweise,_um_einen_String_(Abk\u00FCrzung)_anzugeben.
+Include_subgroups=Untergruppen_ber\u00fccksichtigen
+Include_subgroups\:_When_selected,_view_entries_contained_in_this_group_or_its_subgroups=Untergruppen_ber\u00fccksichtigen:_Wenn_ausgew\u00e4hlt,_werden_Eintr\u00e4ge_dieser_Gruppe_und_ihrer_Untergruppen_angezeigt
+Incremental=Direkt
+Incremental_search=Weitersuchen
+Incremental_search_failed._Repeat_to_search_from_top.=Direkte_Suche_fehlgeschlagen._Wiederhole_die_Suche_vom_Anfang_der_Datenbank.
+Independent=Unabh\u00E4ngig
+Independent_group\:_When_selected,_view_only_this_group's_entries=Unabh\u00e4ngige_Gruppen:_Wenn_ausgew\u00e4hlt,_werden_nur_die_Eintr\u00e4ge_dieser_Gruppe_angezeigt
+Initially_show_groups_tree_expanded=Baumansicht_der_Gruppen_standardm\u00e4\u00dfig_aufklappen
+Input=Bearbeitungsoptionen
+Input_error=Eingabefehler
+Insert=einf\u00FCgen
+Insert_rows=Zeilen_einf\u00FCgen
+Insert_selected_citations_into_LyX/Kile=Ausgew\u00E4hlte_Literaturangaben_in_LyX/Kile_einf\u00FCgen
+Insert_selected_citations_into_WinEdt=Ausgew\u00E4hlte_Literaturangaben_in_WinEdt_einf\u00FCgen
+insert_string_=String_einf\u00FCgen_
+Insert_URL=URL_einf\u00fcgen
+INSPEC=INSPEC
+integrity=Integrit\u00E4t
+# 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=Integrit\u00E4ts\u00FCberpr\u00FCfung
+Intersection=Schnittmenge
+Intersection_with_supergroups=Schnittmenge_mit_Obergruppen
+Invalid_BibTeX_key=Ung\u00fcltiger_BibTeX-Key
+Invalid_date_format=Ung\u00fcltiges_Datumsformat
+Invalid_URL=Ung\u00FCltige_URL
+Inverted=Invertiert
+is_a_standard_type.=ist_ein_Standardtyp
+ISI=ISI
+ISO_abbreviation=ISO-Abk\u00fcrzung
+Item_list_for_field=Wortliste_f\u00FCr_Feld
+JabRef_help=JabRef_Hilfe
+JabRef_preferences=JabRef_Einstellungen
+Journal_abbreviations=Abk\u00fcrzung_der_Zeitschriftennamen
+Journal_list_preview=Vorschau_der_Zeitschriftenliste
+Journal_name=Zeitschriftenname
+Journal_names=Zeitschriftennamen
+JStor_file=JStor_Datei
+Keep=Behalten
+Keep_both=Beide_behalten
+Keep_lower=Unteren_behalten
+Keep_upper=Oberen_behalten
+Key_bindings=Tastenk\u00FCrzel
+Key_bindings_changed=Tastenk\u00FCrzel_ge\u00E4ndert
+Key_generator_settings=Einstellungen_des_Key-Generators
+Key_pattern=BibTeX-Key-Muster
+keys_in_database=Keys_in_der_Datenbank
+Keyword=Stichwort
+Label=Name
+Language=Sprache
+Last_modified=zuletzt_ge\u00E4ndert
+Latex_AUX_file=LaTeX_AUX_Datei
+LaTeX_AUX_file=LaTeX_AUX-Datei
+Left=Links
+License=Lizenz
+Limit_to_fields=Auf_folgende_Felder_begrenzen
+Limit_to_selected_entries=Auf_ausgew\u00E4hlte_Eintr\u00E4ge_begrenzen
+Listen_for_remote_operation_on_port=Port_nach_externem_Zugriff_abh\u00f6ren
+Load_session=Sitzung_laden
+Loading_session...=Lade_Sitzung...
+Look_and_feel=Aussehen
+lower=klein
+Main_layout_file=Haupt-Layoutdatei
+Main_PDF_directory=Standard-Ordner_f\u00FCr_PDF-Dateien
+Main_PS_directory=Standard-Ordner_f\u00fcr_PS-Dateien
+Manage=Verwalten
+Manage_content_selectors=Wortauswahl_verwalten
+Manage_custom_exports=Verwalte_externe_Exportfilter
+Manage_custom_imports=Verwalte_externe_Importfilter
+Manage_journal_abbreviations=Abk\u00fcrzungen_der_Zeitschriften_verwalten
+Mark_entries=Eintr\u00E4ge_markieren
+Mark_entry=Eintrag_markieren
+Mark_new_entries_with_addition_date=Neue_Eintr\u00e4ge_mit_Datum_versehen
+Mark_new_entries_with_owner_name=Neue_Eintr\u00E4ge_mit_Namen_des_Besitzers_versehen
+# These are status line messages when marking/unmarking entries:
+Marked_selected=Ausgew\u00E4hlte_markiert
+Medline_entries_fetched=Medline-Eintr\u00E4ge_abgerufen
+Medline_XML=Medline_XML
+Medline_XML_File=Medline_XML_Datei
+Menu_and_label_font_size=Schriftgr\u00F6\u00DFe_in_Men\u00FCs
+Merged_external_changes=Externe_\u00C4nderungen_eingef\u00FCgt
+messages=Meldungen
+Messages=Mitteilungen
+Messages_and_Hints=Hinweise_und_Warnungen
+Miscellaneous=Verschiedenes
+Modification_of_field=\u00C4nderung_des_Felds
+Modified_group_"%0".=Gruppe_"%0"_ge\u00E4ndert.
+Modified_groups=Ge\u00e4nderte_Gruppen
+Modified_groups_tree=Baum_mit__modifizierten_Gruppen
+Modified_string=Ver\u00E4nderter_String
+Modify=Bearbeiten
+modify_group=Gruppe_bearbeiten
+MODS=MODS
+Move=Verschieben
+Move_down=Nach_unten
+Move_entries_in_group_selection_to_the_top=Sortiere_Eintr\u00E4ge_der_Gruppenauswahl_nach_oben
+move_group=Gruppe_verschieben
+Move_matching_entries_to_the_top=Treffer_nach_oben_sortieren
+Move_string_down=String_nach_unten
+Move_string_up=String_nach_oben
+Move_up=Nach_oben
+Moved_Group=Gruppe_verschoben
+Moved_group_"%0".=Gruppe_"%0"_verschoben.
+Name=Name
+Natbib_style=Natbib-Stil
+Ne_entries_imported.=Keine_Eintr\u00e4ge_importiert.
+nested_aux_files=referenzierte_AUX_Dateien
+New=Neu
+new=neu
+New_article=Neuer_Eintrag_'article'
+New_BibTeX_database=Neue_BibTeX_Datei
+New_BibTeX_entry=Neuer_BibTeX_Eintrag
+New_BibTeX_subdatabase=Neue_BibTeX_Teildatei
+New_book=Neuer_Eintrag_'book'
+New_content=Neuer_Inhalt
+New_database=Neue_Datei
+New_database_created.=Neue_Datei_angelegt.
+New_entry=Neuer_Eintrag
+New_entry...=Neuer_Eintrag...
+New_entry_from_plain_text=Neuer_Eintrag_aus_Klartext
+New_file=Neue_Datei
+New_group=Neue_Gruppe
+New_inbook=Neuer_Eintrag_'inbook'
+New_mastersthesis=Neuer_Eintrag_'masterthesis'
+New_phdthesis=Neuer_Eintrag_'phdthesis'
+New_proceedings=Neuer_Eintrag_'proceedings'
+New_string=Neuer_String
+New_subdatabase=Neue_Teildatei
+New_subdatabase_based_on_AUX_file=Neue_Teildatei_aus_AUX-Datei
+New_unpublished=Neuer_Eintrag_'unpublished'
+Next_entry=N\u00E4chster_Eintrag
+Next_tab=N\u00E4chster_Tab
+No_%0_found=Kein_%0_gefunden
+No_actual_changes_found.=Keine_aktuellen_\u00c4nderungen_gefunden.
+no_base-bibtex-file_specified=keine_Bibtex_Datenbank_angegeben!
+No_custom_imports_registered_yet.=Noch_keine_externen_Importfilter_registriert.
+no_database_generated=keine_Datenbank_erstellt_und_geschrieben
+No_duplicates_found=Keine_doppelten_Eintr\u00E4ge_gefunden
+No_entries_imported.=Keine_Eintr\u00E4ge_importiert.
+No_entries_or_multiple_entries_selected.=Keine_oder_mehrere_Eintr\u00e4ge_ausgew\u00e4hlt.
+No_entries_selected=Keine_Eintr\u00E4ge_ausgew\u00E4hlt.
+No_GUI._Only_process_command_line_options.=Kein_GUI._Nur_Kommandozeilenbefehle_ausf\u00FChren.
+No_journal_names_could_be_abbreviated.=Es_konnten_keine_Zeitschriftennamen_abgek\u00fcrzt_werden.
+No_journal_names_could_be_unabbreviated.=Das_Aufheben_der_Abk\u00fcrzung_konnte_bei_keiner_Zeitschrift_durchgef\u00fchrt_werden.
+No_Medline_entries_found.=Keine_Medline-Eintr\u00E4ge_gefunden.
+No_pdf_or_ps_defined,_and_no_file_matching_Bibtex_key_found=Sie_haben_keine_PDF-_oder_PS-Datei_angegeben_und_es_wurde_keine_Datei_gefunden,_die_mit_dem_BibTeX-Key_\u00FCbereinstimmt.
+No_references_found=Keine_Literaturangaben_gefunden
+No_saved_session_found.=Keine_gespeicherte_Sitzung_gefunden.
+No_url_defined=Keine_URL_angegeben
+non-Mac_only=nicht_f\u00FCr_Mac
+Normal=Normal
+not=nicht
+not_found=davon_nicht_gefunden
+Not_saved_(empty_session)=Nicht_gespeichert_(leere_Sitzung)
+Note_that_the_entry_causing_the_problem_has_been_selected.=Der_Eintrag,_der_das_Problem_verursacht,_wurde_ausgew\u00E4hlt.
+Note_that_the_new_definitions_will_not_be_compatible_with_previous_JabRef_versions.=Beachten_Sie,_da\u00DF_die_neuen_Definitionen_nicht_mit_fr\u00DCheren_Versionen_von_JabRef_kompatibel_sind.
+Note_that_you_must_specify_the_fully_qualified_class_name_for_the_look_and_feel,=Es_muss_der_volle_Klassenname_f\u00FCr_das_zu_verwendende_"look_and_feel"_angegeben_werden.
+Nothing_to_redo=Wiederholen_nicht_m\u00F6glich
+Nothing_to_undo=R\u00FCckg\u00E4ngig_nicht_m\u00F6glich
+# The next is used like in "References found: 1  Number of references to fetch?"
+Number_of_references_to_fetch?=Anzahl_der_abzurufenden_Literaturangaben?
+occurences=Ausdr\u00FCcke
+OK=OK
+Ok=OK
+One_or_more_keys_will_be_overwritten._Continue?=Einer_oder_mehrere_Keys_werden_\u00FCberschrieben._Fortsetzen?
+Open=\u00D6ffnen
+open=\u00F6ffnen
+Open_BibTeX_database=BibTeX_Datei_\u00F6ffnen
+Open_database=Datei_\u00F6ffnen
+Open_editor_when_a_new_entry_is_created=Editor_\u00F6ffnen,_wenn_ein_neuer_Eintrag_angelegt_wird
+Open_file=Datei_\u00F6ffnen
+Open_last_edited_databases_at_startup=Beim_Starten_von_JabRef_die_letzten_bearbeiteten_Dateien_\u00F6ffnen
+Open_PDF_or_PS=PDF_oder_PS_\u00F6ffnen
+Open_right-click_menu_with_Ctrl+left_button=Kontextmen\u00FC_mit_Strg_+_linker_Maustaste_\u00F6ffnen
+Open_URL_or_DOI=URL_oder_DOI_\u00F6ffnen
+Opened_database=Datei_ge\u00F6ffnet
+Opening=\u00D6ffne
+Opening_preferences...=\u00D6ffne_Voreinstellungen...
+Optional_fields=Optionale_Felder
+Options=Optionen
+or=oder
+out_of=von
+Output_or_export_file=Speichere_oder_exportiere_Datei
+Overlapping_groups=Sich_\u00fcberschneidende_Gruppen
+Override=\u00FCberschreiben
+override_the_bibtex_key_by_the_selected_text=BibTeX-Key_mit_ausgew\u00e4hltem_Text_\u00fcberschreiben
+Overwrite_keys=Keys_\u00FCberschreiben
+Ovid=Ovid
+pairs_processed=Paare_\u00FCberarbeitet
+Paste=Einf\u00FCgen
+paste_entries=Eintr\u00E4ge_einf\u00FCgen
+paste_entry=Eintrag_einf\u00FCgen
+Paste_from_clipboard=Text_aus_Zwischenablage_einf\u00FCgen
+Pasted=Eingef\u00FCgt
+Path_to_HTML_viewer=Pfad_zum_HTML-Browser
+Path_to_LyX_pipe=Pfad_zur_LyX_pipe
+Path_to_PDF_viewer=Pfad_zum_PDF-Anzeigeprogramm
+Path_to_PS_viewer=Pfad_zum_PS-Anzeigeprogramm
+Path_to_WinEdt.exe=Pfad_zu_WinEdt.exe
+Paths_to_external_programs=Pfad_zu_externen_Programmen
+PDF_links=PDF-Link
+Personal_journal_list=Pers\u00f6nliche_Zeitschriftenliste
+Pick_titles=Titel_w\u00e4hlen
+Plain_right_menu=Men\u00FC
+Plain_text=Einfacher_Text
+Plain_text_import=Klartext_importieren
+Please_check_your_network_connection_to_this_machine.=Bitte_\u00FCberpr\u00FCfen_Sie_die_Netzwerkverbindung_ihres_Computers.
+Please_define_BibTeX_key_first=Bitte_geben_Sie_zuerst_einen_BibTeX-Key_an
+Please_enter_a_name_for_the_group.=Bitte_geben_Sie_einen_Namen_f\u00FCr_die_Gruppe_ein.
+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>=Bitte_geben_Sie_einen_Suchausdruck_ein._Um_zum_Beispiel_alle_Felder_nach_<b>Smith</b>_zu_durchsuchen,_geben_Sie_ein%c<p><tt>smith</tt><p>Um_das_Feld_<b>Author</b>_nach_<b>Smith</b>_und_das_Feld_<b>Title</b>_nach_<b>electrical</b> [...]
+Please_enter_a_semicolon_or_comma_separated_list_of_Medline_IDs_(numbers).=Geben_Sie_bitte_eine_mit_Semikolon_oder_Komma_getrennte_Liste_der_Medline_IDs_(Nummern)_ein.
+Please_enter_the_field_to_search_(e.g._<b>keywords</b>)_and_the_keyword_to_search_it_for_(e.g._<b>electrical</b>).=Bitte_geben_Sie_das_zu_durchsuchende_Feld_(z.B._<b>keywords</b>)_und_das_darin_zu_suchende_Stichwort_(z.B._<b>elektrisch</b>)_ein.
+Please_enter_the_string's_label=Geben_Sie_bitte_den_Namen_des_Strings_ein.
+Please_refer_to_the_JabRef_help_manual_on_using_the_CiteSeer_tools.=Bitte_lesen_Sie_die_JabRef-Hilfe_f\u00FCr_Informationen,_wie_man_die_CiteSeer-Werkzeuge_benutzt.
+Please_select_an_importer=Bitte_Importer_ausw\u00E4hlen
+Please_select_an_importer.=Bitte_Importer_ausw\u00E4hlen.
+Please_select_exactly_one_group_to_move.=Bitte_genau_eine_zu_bewegende_Gruppe_ausw\u00E4hlen.
+Please_wait_until_it_has_finished.=Bitte_warten_Sie,_bis_die_Aktion_beendet_ist.
+Possible_duplicate_entries=M\u00F6gliche_doppelte_Eintr\u00E4ge
+Possible_duplicate_of_existing_entry._Click_to_resolve.=M\u00f6glicherweise_doppelter_Eintrag._Klicken_um_Konflikt_zu_l\u00f6sen
+Preamble=Pr\u00E4ambel
+Preamble_editor,_store_changes=Pr\u00E4ambel-Editor,_\u00C4nderungen_\u00FCbernehmen
+Preferences=Einstellungen
+Preferences_recorded=Einstellungen_ge\u00E4ndert
+Preferences_recorded.=Einstellungen_gespeichert.
+Preserve_formatting_of_non-BibTeX_fields=Formatierung_von_nicht-BibTeX-Feldern_beibehalten
+Preview=Vorschau
+Previous_entry=Vorheriger_Eintrag
+Previous_tab=Vorheriger_Tab
+Primary_sort_criterion=Prim\u00e4res_Sortierkriterium
+Problem_with_parsing_entry=Problem_beim_Analysieren_des_Eintrags
+PS_links=PS_Links
+Push_selection_to_LyX/Kile=Auswahl_in_LyX/Kile_einf\u00FCgen
+Push_selection_to_WinEdt=Auswahl_in_WinEdt_einf\u00FCgen
+Push_to_LyX=In_LyX_einf\u00FCgen
+Push_to_WinEdt=In_WinEdt_einf\u00FCgen
+Pushed_citations_to_WinEdt=Literaturangaben_in_WinEdt_eingef\u00fcgt
+Pushed_the_citations_for_the_following_rows_to=Literaturangaben_der_folgenden_Zeilen_eingef\u00FCgt_in
+Query_author(s)=Autor(en)_abfragen
+Quit=Beenden
+Quit_JabRef=JabRef_beenden
+Quit_synchronization=Synchronisation_beenden
+Raw_source=Importtext
+Really_delete_the_selected=Wirklich_l\u00F6schen:
+Recent_files=Zuletzt_ge\u00F6ffnete_Dateien
+Redo=Wiederholen
+Refer/Endnote=Refer/Endnote
+Reference_database=Referenz-Datenbank
+# The next two lines are used like in "References found: 1  Number of references to fetch?"
+References_found=Literaturangaben_gefunden
+Refine_supergroup\:_When_selected,_view_entries_contained_in_both_this_group_and_its_supergroup=Obergruppe_verfeinern:_Wenn_ausgew\u00e4hlt,_werden_Eintr\u00e4ge_aus_dieser_Gruppe_und_ihrer_\u00fcbergeordneten_Gruppe_angezeigt
+Refresh_view=Ansicht_aktualisieren
+Regexp=Regexp
+Regular_Expression=Regul\u00E4rer_Ausdruck
+Remember_these_entry_types?=Diese_Eintragstypen_behalten?
+Remote_operation=Externer_Zugriff
+Remote_server_port=Externer_Server-Port
+Remove=L\u00F6schen
+Remove_all?=Alle_l\u00f6schen?
+Remove_all_subgroups=Untergruppen_entfernen
+Remove_all_subgroups_of_"%0"?=Alle_Untergruppen_von_"%0"_entfernen?
+Remove_double_braces_around_BibTeX_fields_when_loading.=Beim_Laden_doppelte_geschweifte_Klammern_um_BibTeX-Felder_entfernen
+Remove_duplicates=Doppelte_Eintr\u00E4ge_l\u00F6schen
+Remove_entry_from_import=Eintrag_von_Importierung_entfernen
+Remove_entry_type=Eintragstyp_l\u00F6schen
+remove_from_group=aus_der_Gruppe_entfernen
+Remove_from_group=Aus_Gruppe_entfernen
+Remove_group=Gruppe_l\u00F6schen
+Remove_group,_keep_subgroups=Gruppe_l\u00F6schen,_Untergruppen_behalten
+Remove_group_"%0"?=Gruppe_"%0"_l\u00F6schen?
+Remove_group_"%0"_and_its_subgroups?=Gruppe_"%0"_inklusive_Untergruppen_l\u00F6schen?
+remove_group_(keep_subgroups)=Gruppe_l\u00F6schen_(Untergruppen_behalten)
+remove_group_and_subgroups=Gruppe_inklusive_Untergruppen_l\u00F6schen
+Remove_group_and_subgroups=Gruppe_und_Untergruppen_l\u00F6schen
+Remove_old_entry=Alten_Eintrag_entfernen
+Remove_selected_strings=Ausgew\u00E4hlte_Strings_entfernen
+remove_string=String_l\u00F6schen
+remove_string_=String_l\u00F6schen_
+Removed_entry_type.=Eintragstyp_gel\u00F6scht.
+Removed_group=Gruppe_gel\u00F6scht
+Removed_group_"%0".=Gruppe_"%0"_gel\u00F6scht.
+Removed_group_"%0"_and_its_subgroups.=Gruppe_"%0"_inklusive_Untergruppen_gel\u00F6scht.
+Removed_string=String_gel\u00F6scht
+Renamed_string=String_umbenannt
+Repeat_incremental_search=Direkte_Suche_wiederholen
+Replace=Ersetzen
+Replace_string=String_ersetzen
+Replace_with=Ersetzen_mit
+Replaced=Ersetzt:
+Required_fields=Ben\u00F6tigte_Felder
+Reset_all=Alle_zur\u00FCcksetzen
+resolved=davon_aufgel\u00F6st
+Results=Ergebnisse
+Revert_to_original_source=Original_wiederherstellen
+Review=\u00dcberpr\u00fcfung
+Review_changes=\u00c4nderungen_\u00fcberpr\u00fcfen
+Right=Rechts
+RIS=RIS
+Save=Speichern
+Save_before_closing=Speichern_vor_dem_Beenden
+Save_database=Datei_speichern
+Save_database_as_...=Datei_speichern_unter_...
+Save_failed=Fehler_beim_Speichern
+Save_failed_during_backup_creation=W\u00e4hrend_der_Erstellung_des_Backups_ist_das_Speichern_fehlgeschlagen
+Save_failed_while_committing_changes=W\u00e4hrend_die_\u00c4nderungen_\u00fcbermittelt_wurden,_ist_das_Speichern_fehlgeschlagen
+Save_selected_as_...=Auswahl_speichern_unter_...
+Save_session=Sitzung_speichern
+Saved_database=Datei_gespeichert
+Saved_selected_to=Auswahl_gespeichert_unter
+Saved_session=Sitzung_gespeichert
+Saving=Speichere
+Saving_database=Speichere_Datei
+Scan=\u00DCberpr\u00FCfen
+SciFinder=SciFinder
+Search=Suchen
+Search_All_Fields=Durchsuche_alle_Felder
+Search_all_fields=Alle_Felder_durchsuchen
+Search_error=Suchfehler
+Search_expression=Suchausdruck
+Search_for=Suchen_nach
+Search_General_Fields=Allgemeine_Felder_durchsuchen
+Search_general_fields=Allgemeine_Felder_durchsuchen
+Search_Optional_Fields=Optionale_Felder_durchsuchen
+Search_optional_fields=Optionale_Felder_durchsuchen
+Search_Required_Fields=Ben\u00f6tigte_Felder_durchsuchen
+Search_required_fields=Ben\u00f6tigte_Felder_durchsuchen
+Search_Specified_Field(s)=Durchsuche_diese(s)_Feld(er)
+Search_term=Suchbegriff
+Searched_database._Number_of_hits=Datei_durchsucht._Anzahl_der_Treffer
+Searching_for_%0_file=Suche_nach_%0-Datei
+Searching_for_duplicates...=Suche_nach_doppelten_Eintr\u00E4gen...
+Secondary_sort_criterion=Zweites_Sortierkriterium
+Select=Ausw\u00E4hlen
+Select_a_Zip-archive=ZIP-Archiv_ausw\u00E4hlen
+Select_action=Aktion_w\u00e4hlen
+Select_all=Alle_ausw\u00E4hlen
+Select_Classpath_of_New_Importer=Klassenpfad_ausw\u00E4hlen
+Select_encoding=Kodierung_w\u00e4hlen
+Select_entries_in_group_selection=W\u00E4hle_Eintr\u00E4ge_in_Gruppenauswahl
+Select_entry_type=Eintragstyp_ausw\u00E4hlen
+Select_file_from_ZIP-archive=Eintrag_aus_der_ZIP-Archiv_ausw\u00E4hlen
+Select_format=Format_w\u00E4hlen
+Select_matches=Treffer_ausw\u00E4hlen
+Select_matching_entries=Treffer_ausw\u00E4hlen
+Select_new_ImportFormat_Subclass=Klasse_ausw\u00E4hlen
+Select_the_tree_nodes_to_view_and_accept_or_reject_changes=W\u00E4hlen_Sie_die_drei_Knoten_aus,_um_die_\u00C4nderungen_zu_sehen_und_anzunehmen_oder_zu_verwerfen
+Selector_enabled_fields=Felder_mit_Wortliste
+Set_general_fields=Allgemeine_Felder_festlegen
+Set_table_font=Tabellenschriftart_ausw\u00E4hlen
+Set_up_general_fields=Allgemeine_Felder_festlegen
+Settings=Einstellungen
+Setup_selectors=Wortlisten_verwalten
+Short_form=Kurzform
+Shortcut=Tastenk\u00FCrzel
+Show/edit_BibTeX_source=BibTeX_Quelltext_anzeigen
+Show_'Firstname_Lastname'='Vorname_Nachname'_anzeigen
+Show_'Lastname,_Firstname'='Nachname,_Vorname'_anzeigen
+Show_abstract=Zeige_abstract
+Show_BibTeX_source_by_default=Quelltext_standardm\u00E4\u00DFig_anzeigen
+Show_BibTeX_source_panel=BibTeX_Quelltextpanel_anzeigen
+Show_CiteSeer_column=CiteSeer-Spalte_anzeigen
+Show_confirmation_dialog_when_deleting_entries=Dialog_zum_L\u00F6schen_von_Eintr\u00E4gen_anzeigen
+Show_description=Beschreibung_anzeigen
+Show_dynamic_groups_in_<i>italics</i>=Dynamische_Gruppen_<i>kursiv</i>_anzeigen
+Show_entries_*not*_in_group_selection=Zeige_Eintr\u00E4ge,_die_*nicht*_in_der_Gruppenauswahl_sind
+Show_general_fields=Allgemeine_Felder_anzeigen
+Show_groups_matching_all=Gruppen_anzeigen,_die_alle_enthalten
+Show_groups_matching_any=Gruppen_anzeigen,_die_mindestens_einen_enthalten
+Show_icons_for_groups=Gruppen-Icon_anzeigen
+Show_names_unchanged=Namen_unver\u00E4ndert_anzeigen
+Show_one_less_rows=Zeige_eine_Zeile_weniger
+Show_one_more_row=Zeige_eine_Zeile_mehr
+Show_optional_fields=Optionale_Felder_anzeigen
+Show_overlapping_groups=Sich_\u00fcberschneidende_Gruppen_anzeigen
+Show_PDF/PS_column=PDF/PS-Spalte_anzeigen
+Show_required_fields=Ben\u00F6tigte_Felder_anzeigen
+Show_URL/DOI_column=URL/DOI-Spalte_anzeigen
+Show_warning_dialog_when_a_duplicate_BibTeX_key_is_entered=Warnmeldung_anzeigen,_wenn_ein_doppelter_BibTeX-Key_eingegeben_wird.
+Show_warning_dialog_when_an_empty_BibTeX_key_is_entered=Warnung_anzeigen_wenn_ein_leerer_BibTeX-Key_angegeben_wird
+Simple_HTML=Einfaches_HTML
+Sixpack=Sixpack
+Size=Gr\u00F6\u00DFe
+Size_of_groups_interface_(rows)=Gr\u00F6\u00DFe_der_Gruppenansicht_(Reihen)
+Skip=\u00dcberspringen
+Sort_alphabetically=Alphabetisch_sortieren
+Sort_Automatically=Automatisch_sortieren
+Sort_options=Sortieroptionen
+sort_subgroups=Untergruppen_sortieren
+Sorted_all_subgroups_recursively=Alle_Untergruppen_rekursiv_sortiert
+Sorted_all_subgroups_recursively.=Alle_Untergruppen_rekursiv_sortiert.
+Sorted_immediate_subgroups=Direkte_Untergruppen_sortiert
+Sorted_immediate_subgroups.=Alle_direkten_Untergruppen_sortiert.
+source_edit=Quelltextbearbeitung
+Special_table_columns=Spezielle_Spalten
+Start=Starten
+Start_incremental_search=Weitersuchen_(bei_direkter_Suche)
+Start_search=Suche_starten
+Statically_group_entries_by_manual_assignment=Statisches_Gruppieren_der_Eintr\u00E4ge_durch_manuelle_Zuweisung
+Status=Status
+Stop=Stop
+Store=Speichern
+Store_fields_with_double_braces,_and_remove_extra_braces_when_loading.<BR>Double_braces_signal_that_BibTeX_should_preserve_character_case.=Felder_mit_geschweiften_Klammern_speichern_und_\u00fcberz\u00e4hlige_Klammern_beim_Laden_entfernen.<BR>Geschweifte_Klammern_zeigen_an,_dass_BibTeX_die_Gro\u00df-/Kleinschreibung_beibehalten_soll.
+Store_journal_abbreviations=Abk\u00fcrzungen_der_Zeitschriften_speichern
+Store_string=String_speichern
+Store_the_following_fields_with_braces_around_capital_letters=Die_folgenden_Felder_mit_geschweiften_Klammern_um_die_Gro\u00dfbuchstaben_speichern
+Stored_definition_for_type=Typ-Definition_gespeichert
+Stored_entry=Eintrag_gespeichert
+Stored_entry.=Eintrag_gespeichert.
+Strings=Ersetzen
+Strings_for_database=Strings_f\u00FCr_die_Datei
+subdatabase_from_aux=Datenbank_aus_LaTeX_aux
+Subdatabase_from_aux=Teildatenbank_aus_aux-Datei
+Suggest=Vorschlag
+Switch_preview_layout=Layout_der_Vorschau_wechseln
+Synchronize_%0_links=%0-Links_synchronisieren
+Synchronizing_%0_links...=Synchronisiere_%0-Links...
+Table=Tabelle
+Table_appearance=Erscheinungsbild_der_Tabelle
+Table_background_color=Hintergrundfarbe_der_Tabelle
+Table_grid_color=Farbe_des_Tabellenrasters
+Table_text_color=Textfarbe_der_Tabelle
+Tabname=Tab-Name
+Tertiary_sort_criterion=Drittes_Sortierkriterium
+Test=Test
+Text_Input_Area=Text_einf\u00FCgen
+The_#_character_is_not_allowed_in_BibTeX_fields=Das_Zeichen_#_ist_in_BibTeX-Feldern_nicht_erlaubt
+The_chosen_date_format_for_new_entries_is_not_valid=Das_Datumsformat_f\u00fcr_neue_Eintr\u00e4ge_ist_nicht_g\u00fcltig
+The_CiteSeer_fetch_operation_returned_zero_results.=Das_Importieren_von_CiteSeer_ergab_keine_Ergebnisse.
+the_field_<b>%0</b>=das_Feld_<b>%0</b>
+The_file<BR>'%0'<BR>has_been_modified<BR>externally!=Die_Datei<BR>_'%0'_<BR>wurde_von_einem_externen_Programm_ver\u00e4ndert!
+The_group_"%0"_already_contains_the_selection.=Die_Gruppe_"%0"_enth\u00e4lt_bereits_diese_Auswahl.
+The_group_"%0"_does_not_support_the_adding_of_entries.=Die_Gruppe_"%0"_unterst\u00FCtzt_das_manuelle_Hinzuf\u00FCgen_von_Eintr\u00E4gen_nicht.
+The_group_"%0"_does_not_support_the_removal_of_entries.=Die_Gruppe_"%0"_unterst\u00FCtzt_das_manuelle_Entfernen_von_Eintr\u00E4gen_nicht.
+The_label_of_the_string_can_not_be_a_number.=Der_Name_des_Strings_darf_keine_Zahl_sein.
+The_label_of_the_string_can_not_contain_spaces.=Der_Name_des_Strings_darf_keine_Leerzeichen_enthalten.
+The_label_of_the_string_can_not_contain_the_'#'_character.=Der_Name_des_Strings_darf_nicht_das_Zeichen_'#'_enthalten.
+The_output_option_depends_on_a_valid_import_option.=Die_Ausgabe-Option_beruht_auf_einer_g\u00fcltigen_Import-Option.
+The_regular_expression_<b>%0</b>_is_invalid%c=Der_Regul\u00E4re_Ausdruck_<b>%0</b>_ist_ung\u00FCltig%c
+The_search_is_case_insensitive.=Gro\u00DF-/Kleinschreibung_wird_nicht_unterschieden.
+The_search_is_case_sensitive.=Gro\u00DF-/Kleinschreibung_wird_unterschieden.
+The_string_has_been_removed_locally=Der_String_wurde_lokal_entfernt
+The_type_name_can_not_contain_spaces.=Der_Name_des_Typs_darf_keine_Leerzeichen_enthalten.
+The_URL_field_appears_to_be_empty_on_entry_number_=Das_URL-Feld_scheint_leer_zu_sein_bei_Eintrag_Nummer_
+There_are_possible_duplicates_(marked_with_a_'D'_icon)_that_haven't_been_resolved._Continue?=Es_gibt_m\u00f6gliche_Duplikate_(markiert_mit_'D'),_die_nicht_gekl\u00e4rt_werden_konnten._Fortfahren?
+There_is_no_entry_type=Es_exisitiert_kein_Eintragstyp
+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?=Dies_ver\u00E4ndert_das_Feld_"%0"_Ihrer_Eintr\u00E4ge.nDas_k\u00F6nnte_zu_ungewollten_\u00C4nderungen_Ihrer_Eintr\u00E4ge_f\u00FChren.nDeshalb_ist_es_erforderlich,_dass_Sie_in_Ihrer_Gruppendefinition_das_Feld_"keywords"nangeben_oder_einen_Nam [...]
+this_button_will_update=Dieser_Button_\u00E4ndert_die_verwendete<BR>Spaltenbreite_in_der_Tabelle_der_Eintr\u00E4ge
+this_button_will_update_the_column_width_settings<BR>to_match_the_current_widths_in_your_table=diese_Schaltfl\u00E4che_setzt_die_Einstellungen_der_Spaltenbreite<BR>auf_die_aktuellen_Spaltenbreiten_Ihrer_Tabelle
+This_entry_is_incomplete=Dieser_Eintrag_ist_unvollst\u00E4ndig
+This_entry_type_cannot_be_removed.=Dieser_Eintragstyp_kann_nicht_entfernt_werden.
+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.=Diese_Gruppe_enth\u00E4lt_manuell_zugewiesene_Eintr\u00E4ge._Eintr\u00E4ge_k\u00F6nnen_dieser_Gruppe_zugewiesen_werde [...]
+This_group_contains_entries_in_which=Diese_Gruppe_enth\u00E4lt_Eintr\u00E4ge,_bei_denen
+This_group_contains_entries_in_which_any_field_contains_the_regular_expression_<b>%0</b>=Diese_Gruppe_enth\u00E4lt_Eintr\u00E4ge,_in_denen_ein_beliebiges_Feld_den_Regul\u00E4ren_Ausdruck_<b>%0</b>_enth\u00E4lt.
+This_group_contains_entries_in_which_any_field_contains_the_term_<b>%0</b>=Diese_Gruppe_enth\u00E4lt_Eintr\u00E4ge,_in_denen_ein_beliebiges_Feld_den_Ausdruck_<b>%0</b>_enth\u00E4lt.
+This_group_contains_entries_whose_<b>%0</b>_field_contains_the_keyword_<b>%1</b>=Diese_Gruppe_enth\u00e4lt_Eintrage,_deren_Feld_<b>%0</b>_das_Stichwort_<b>%1</b>_enth\u00e4lt
+This_group_contains_entries_whose_<b>%0</b>_field_contains_the_regular_expression_<b>%1</b>=Diese_Gruppe_enth\u00E4lt_Eintrage,_deren_Feld_<b>%0</b>_den_Regul\u00E4ren_Ausdruck_<b>%1</b>_enth\u00E4lt
+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.=Dies_ist_ein_einfacher_Copy_&_Paste-Dialog._F\u00FCgen_sie_zun\u00E4chst_Text_in_das_Eingabefeld_ein._Anschlie\u00DFend_k\u00F6nen_Sie_Textstellen_markieren_und_einem_BibTeX-Feld_zuordnen.
+This_is_a_simple_copy_and_paste_dialog_for_import_some_fields_from_normal_text.=Dies_ist_ein_einfacher_Copy_&_Paste_Dialog_zum_Einf\u00fcgen_von_Feldern_aus_normalem_Text.
+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.=Veranlasst_JabRef_dazu,_jedem_%0-Link_zu_folgen_und_zu_\u00fcberpr\u00fcfen,_ob_die_entsprechende_Datei_existiert._Wenn_nicht,_werden_M\u00f6glichkeiten_angegeben,_das_Problem_zu_l\u00f6sen.
+This_operation_cannot_work_on_multiple_rows.=Diese_Aktion_kann_nicht_mit_mehreren_Zeilen_durchgef\u00FChrt_werden.
+Toggle_abbreviation=Abk\u00fcrzung_an-/abschalten
+Toggle_entry_preview=Eintragsvorschau_ein-/ausblenden
+Toggle_groups_interface=Gruppenansicht_ein-/ausblenden
+Toggle_search_panel=Suchdialog_ein-/ausblenden
+Tools=Extras
+Try_different_encoding=Versuchen_Sie_es_mit_einer_anderen_Kodierung
+Type=Typ
+Type_set_to_'other'=Typ_als_'other'_deklariert
+Unabbreviate_journal_names_of_the_selected_entries=Abk\u00fcrzung_der_Zeitschriftennamen_der_ausgew\u00e4hlten_Eintr\u00e4ge_aufheben
+unable_to_access_LyX-pipe=LyX-pipe_nicht_gefunden
+Unable_to_create_graphical_interface=Grafische_Benutzeroberfl\u00E4che_konnte_nicht_erzeugt_werden
+Unable_to_parse_clipboard_text_as_Bibtex_entries.=Der_Text_der_Zwischenablage_konnte_nicht_als_BibTeX-Format_analysiert_werden.
+Unable_to_parse_the_following_URL=Folgende_URL_konnte_nicht_analysiert_werden
+unable_to_write_to=konnte_nicht_speichern_auf
+Undo=R\u00FCckg\u00E4ngig
+Union=Vereinigung
+unknown_bibtex_entries=unbekannte_BibTeX-Eintr\u00E4ge
+Unknown_bibtex_entries=Fehlende_BibTeX_Eintr\u00E4ge
+unknown_edit=unbekannter_Bearbeitungsschritt
+unknown_entry_type=unbekannter_Eintragstyp
+Unknown_export_format=Unbekanntes_Export-Format
+Unmark_all=S\u00E4mtliche_Markierungen_aufheben
+Unmark_entries=Markierung_aufheben
+Unmark_entry=Markierung_aufheben
+Unmarked_selected=Markierung_f\u00fcr_ausgew\u00e4hlte_Eintr\u00e4ge_aufgehoben
+Unpack_EndNote_filter_set=Entpacke_EndNote_Filter-Set
+Unpacked_file=Entpackte_Datei
+Unpacked_file.=Datei_entpackt.
+Unsupported_version_of_class_%0:_%1=Nicht_unterst\u00FCtzte_Version_der_Klasse_%0:_%1
+untitled=ohne_Titel
+Up=Hoch
+Update_to_current_column_widths=Aktuelle_Spaltenbreiten_verwenden
+Updated_group_selection=Gruppenauswahl_aktualisiert
+Updating_entries...=Eintr\u00E4ge_werden_aktualisiert...
+UPPER=GROSS
+Upper_Each_First=Jeden_Ersten_Gro\u00DF
+Upper_first=Ersten_gro\u00DF
+usage=Benutzung
+Use_antialiasing_font=Antialias-Schrift_benutzen
+Use_antialiasing_font_in_table=Gegl\u00E4ttete_Schriftart_verwenden_(in_der_Tabelle)
+Use_inspection_window_also_when_a_single_entry_is_imported.=Kontrollfenster_benutzen,_auch_wenn_nur_ein_Eintrag_importiert_wird.
+Use_other_look_and_feel=anderes_"look_and_feel"_benutzen
+Use_regular_expressions=Regul\u00E4re_Ausdr\u00FCcke_benutzen
+Use_the_following_delimiter=Benutzen_Sie_das_folgende_Trennzeichen
+Use_the_following_delimiter_character(s)=Folgende(s)_Trennzeichen_benutzen
+Uses_default_application=Benutze_Standardprogramm
+Value_cleared_externally=Wert_extern_gel\u00F6scht
+Value_set_externally=Wert_extern_gesetzt
+verify_that_LyX_is_running_and_that_the_lyxpipe_is_valid=\u00FCberpr\u00FCfen_Sie,_ob_LyX_l\u00E4uft_und_ob_die_Angaben_zur_lyxpipe_stimmen
+View=Ansicht
+Visible_fields=Angezeigte_Felder
+Warn_about_unresolved_duplicates_when_closing_inspection_window=Warnung_zu_ungekl\u00e4rten_Duplikaten_ausgeben,_wenn_das_Kontrollfenster_geschlossen_wird
+Warn_before_overwriting_existing_keys=Vor_dem_\u00dcberschreiben_von_existierenden_Keys_warnen
+Warning=Warnung
+Warning_there_is_a_duplicate_key=Achtung!_Es_ist_ein_doppelter_Key_vorhanden
+Warnings=Warnungen
+web_link=Web-Link
+When_adding/removing_keywords,_separate_them_by=Beim_Hinzuf\u00fcgen_oder_L\u00f6schen_von_Stichw\u00f6rtern_folgendes_Trennzeichen_benutzen
+with=mit
+Word=Wort
+Wrong_file_format=Falsches_Dateiformat
+You_have_changed_the_language_setting._You_must_restart_JabRef_for_this_to_come_into_effect.=Sie_haben_die_Spracheinstellung_ge\u00E4ndert._Sie_m\u00FCssen_JabRef_neu_starten,_damit_die_\u00C4nderungen_in_Kraft_treten.
+You_have_cleared_this_field._Original_value=Sie_haben_dieses_Feld_gel\u00F6scht._Urspr\u00FCnglicher_Wert
+You_must_choose_a_file_name_to_store_journal_abbreviations=Sie_m\u00fcssen_einen_Dateinamen_w\u00e4hlen,_um_die_Abk\u00fcrzungen_der_Zeitschriften_zu_speichern
+You_must_enter_an_integer_value_in_the_text_field_for=Sie_m\u00fcssen_eine_Ganzzahl_verwenden_im_Textfeld_f\u00fcr
+You_must_fill_in_a_name_for_the_entry_type.=Sie_m\u00FCssen_einen_Namen_f\u00FCr_den_Eintragstyp_eingeben.
+You_must_provide_a_name,_a_search_string_and_a_field_name_for_this_group.=Sie_m\u00FCssen_einen_Namen,_einen_Suchbegriff_und_einen_Feldnamen_f\u00FCr_die_Gruppe_angeben.
+You_must_restart_JabRef_for_the_new_key_bindings_to_work_properly.=Sie_m\u00FCssen_JabRef_neu_starten,_damit_die_Tastenk\u00FCrzel_funktionieren.
+You_must_select_a_row_to_perform_this_operation.=Sie_m\u00FCssen_eine_Zeile_ausw\u00E4hlen,_um_diese_Aktion_durchf\u00FChren_zu_k\u00F6nnen.
+You_must_select_at_least_one_row_to_perform_this_operation.=Sie_m\u00FCssen_mindestens_eine_Zeile_ausw\u00E4hlen,_um_diesen_Vorgang_durchzuf\u00FChren.
+You_must_set_both_BibTeX_key_and_%0_directory=Sie_m\u00FCssen_sowohl_den_BibTeX-Key_als_auch_den_%0-Ordner_angeben
+You_must_set_both_bibtex_key_and_PDF_directory=Sie_m\u00fcssen_sowohl_den_BibTeX-Key,_als_auch_das_PDF-Verzeichnis_angeben
+Your_new_key_bindings_have_been_stored.=Ihre_neuen_Tastenk\u00FCrzel_wurden_gespeichert.
+Arguments_passed_on_to_running_JabRef_instance._Shutting_down.=Argumente_wurden_der_laufenden_JabRef-Instanz_\u00fcbergeben._Schlie\u00dfen_l\u00e4uft.
+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').=Konnte_zu_keinem_aktiven_gnuserv-Prozess_verbinden._Vergewissern_Sie_sich,_dass_(X)Emacs_l\u00e4uft,<BR>und_dass_der_Server_gestartet_wurde_(mit_dem_Befehl_'gnuserv-start').
+Push_selection_to_Emacs=Auswahl_in_Emacs_einf\u00fcgen
+Pushed_citations_to_Emacs=Literaturangaben_in_Emacs_eingef\u00fcgt
+Filter=Filter
+Hide_non-matching_entries=Nicht-Treffer_ausblenden
+Replace_(regular_expression)=Ersetzen_(Regul\u00e4rer_Ausdruck)
+Cite_command_(for_Emacs/WinEdt)=Cite-Kommando_(f\u00fcr_Emacs/WinEdt)
+Could_not_instantiate_%0_%1._Have_you_chosen_the_correct_package_path?=Konnte_%0_%1_nicht_realisieren._Haben_Sie_den_richtigen_Paket-Pfad_angegeben?
+No_entries_found._Please_make_sure_you_are_using_the_correct_import_filter.=Keine_Eintr\u00e4ge_gefunden._Bitte_vergewissern_Sie_sich,_dass_Sie_den_richtigen_Importfilter_benutzen.
+
+#### These lines were changed:
+Switches_between_full_and_abbreviated_journal_name_if_the_journal_name_is_known.=
+To_set_up,_go_to_<B>Tools_->_Manage_journal_abbreviations</B>=
+#####Switches_between_full_and_abbreviated_journal_name=Wechselt_zwischen_kompletten_und_abgek\u00fcrzten_Zeitschriftennamen
+#####if_the_journal_name_is_known._Go_to_(...............)=falls_der_Zeitschriftenname_bekannt_ist._Gehe_zu_(...............)
+
+Could_not_run_the_'gnuclient'_program._Make_sure_you_have_the_gnuserv/gnuclient_programs_installed.=
+
+Hierarchical_context=
+Add_entry_selection_to_this_group=
+Assign_entry_selection_exclusively_to_this_group=
+Remove_entry_selection_from_this_group=
diff --git a/src/resource/JabRef_de.properties.orig b/src/resource/JabRef_de.properties.orig
new file mode 100644
index 0000000..ebbe365
--- /dev/null
+++ b/src/resource/JabRef_de.properties.orig
@@ -0,0 +1,1029 @@
+#! created/edited by Popeye version 0.51 sunshine (popeye.sourceforge.net)
+
+!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.=Dies_ist_ein_einfacher_Copy_&_Paste-Dialog._Nachdem_Text_in_das_Texteingabefeld_geladen_oder_kopiert_wurde,_k\u00f6nnen_Sie_Textteile_markieren_und_ihnen_ein_BibTeX-Feld_zuordnen.
+%0_contains_the_Regular_Expression_<b>%1</b>=%0_den_Regul\u00E4ren_Ausdruck_<b>%1</b>_enth\u00E4lt
+%0_contains_the_term_<b>%1</b>=%0_den_Ausdruck_<b>%1</b>_enth\u00E4lt
+%0_doesn't_contain_the_Regular_Expression_<b>%1</b>=%0_nicht_den_Regul\u00E4ren_Ausdruck_<b>%1</b>_enth\u00E4lt
+%0_doesn't_contain_the_term_<b>%1</b>=%0_nicht_den_Ausdruck_<b>%1</b>_enth\u00E4lt
+%0_doesn't_match_the_Regular_Expression_<b>%1</b>=%0_nicht_exakt_dem_Regul\u00E4ren_Ausdruck_<b>%1</b>_entspricht
+%0_doesn't_match_the_term_<b>%1</b>=%0_nicht_exakt_dem_Ausdruck_<b>%1</b>_entspricht
+%0_field_set=%0-Feld_erstellt
+%0_import_cancelled.=%0_Importierung_abgebrochen
+%0_matches_the_Regular_Expression_<b>%1</b>=%0_exakt_dem_Regul\u00E4ren_Ausdruck_<b>%1</b>_entspricht
+%0_matches_the_term_<b>%1</b>=%0_exakt_dem_Ausdruck_<b>%1</b>_entspricht
+<field_name>=<Feldname>
+<HTML>Unpack_the_zip_file_containing_import/export_filters_for_Endnote,<BR>for_optimal_interoperability_with_JabRef</HTML>=<HTML>Entpacke_die_zip-Datei_mit_den_Import/Export-Filtern_f\u00FCr_EndNote,<BR>um_die_bestm\u00F6gliche_Kompatibilit\u00E4t_mit_JabRef_zu_gew\u00E4hrleisten</HTML>
+<no_field>=<kein_Feld>
+<select>=<ausw\u00E4hlen>
+<select_word>=<Wort_ausw\u00E4hlen>
+_on_entry_number_=_bei_Eintrag_Nummer_
+A_CiteSeer_fetch_operation_is_currently_in_progress.=CiteSeer-Abruf_ist_in_Bearbeitung.
+A_CiteSeer_import_operation_is_currently_in_progress.=Ein_CiteSeer-Import_ist_gerade_in_Bearbeitung.
+A_string_with_that_label_already_exists=Ein_String_mit_diesem_Namen_exisitiert_bereits
+Abbreviate_journal_names_of_the_selected_entries_(ISO_abbreviation)=Zeitschriftennamen_der_ausgew\u00e4hlten_Eintr\u00e4ge_abk\u00fcrzen_(ISO-Abk\u00fcrzung)
+Abbreviate_journal_names_of_the_selected_entries_(MEDLINE_abbreviation)=Zeitschriftennamen_der_ausgew\u00e4hlten_Eintr\u00e4ge_abk\u00fcrzen_(MEDLINE-Abk\u00fcrzung)
+Abbreviate_names=Namen_abk\u00fcrzen
+Abbreviation=Abk\u00fcrzung
+About_JabRef=\u00DCber_JabRef
+Abstract=Zusammenfassung
+Accept=\u00DCbernehmen
+Accept_change=\u00C4nderung_akzeptieren
+Action=Aktion
+Add=Hinzuf\u00FCgen
+Add_a_(compiled)_custom_ImportFormat_class_from_a_class_path._\nThe_path_need_not_be_on_the_classpath_of_JabRef.=F\u00FCge_(kompilierten)_externe_ImportFormat_Klasse_aus_Verzeichnis_hinzu._\nDas_Verzeichnis_mu\u00DF_nicht_im_Klassenpfad_von_JabRef_enthalten_sein.
+Add_a_(compiled)_custom_ImportFormat_class_from_a_Zip-archive.\nThe_Zip-archive_need_not_be_on_the_classpath_of_JabRef.=F\u00FCge_(kompilierten)_externe_ImportFormat_Klasse_aus_Verzeichnis_hinzu._\nDas_Verzeichnis_mu\u00DF_nicht_im_Klassenpfad_von_JabRef_enthalten_sein.
+add_entries_to_group=Eintr\u00E4ge_zu_Gruppe_hinzuf\u00FCgen
+Add_from_folder=Aus_Klassenpfad_hinzuf\u00FCgen
+Add_from_jar=Aus_Archiv-Datei_hinzuf\u00FCgen
+add_group=Gruppe_hinzuf\u00FCgen
+Add_Group=Gruppe_hinzuf\u00FCgen
+Add_new=Neu
+Add_Subgroup=Untergruppe_hinzuf\u00FCgen
+Add_to_group=Zu_Gruppe_hinzuf\u00FCgen
+Added_entry=Eintrag_hinzugef\u00FCgt
+Added_group=Gruppe_hinzugef\u00FCgt
+Added_group_"%0".=Gruppe_"%0"_hinzugef\u00FCgt.
+Added_new=Neu_hinzugef\u00FCgt
+Added_string=String_hinzugef\u00FCgt
+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.=Zus\u00E4tzlich_k\u00F6nnen_Eintr\u00E4ge,_deren_Feld_<b>%0</b>_nicht_< [...]
+Advanced=Erweitert
+Advanced_options_for_setting...=Erweiterte_Optionen_f\u00fcr_Einstellung...
+All_Entries=Alle_Eintr\u00E4ge
+All_entries=Alle_Eintr\u00E4ge
+All_entries_of_this_type_will_be_declared_typeless._Continue?=Alle_Eintr\u00E4ge_dieses_Typs_werden_als_typlos_eingestuft._Fortfahren?
+All_fields=Alle_Felder
+All_subgroups_(recursively)=Alle_Untergruppen_(rekursiv)
+Allow_editing_in_table_cells=Bearbeiten_in_der_Tabelle_zulassen
+Always_save_database_ordered_by_author_name=Datei_immer_nach_Autorennamen_sortiert_abspeichern
+and=und
+and_the_class_must_be_available_in_your_classpath_next_time_you_start_JabRef.=Au\u00DFerdem_muss_die_Klasse_beim_n\u00E4chsten_Start_von_JabRef_durch_den_"Classpath"_erreichbar_sein.
+any_field_that_matches_the_regular_expression_<b>%0</b>=ein_beliebiges_Feld,_auf_das_der_Regul\u00E4re_Ausdruck_<b>%0</b>_passt,
+Appearance=Erscheinungsbild
+Append=anf\u00FCgen
+Append_contents_from_a_BibTeX_database_into_the_currently_viewed_database=Inhalt_einer_BibTeX-Datei_an_die_aktuelle_Datei_anh\u00E4ngen
+Append_database=Datei_anh\u00E4ngen
+append_the_selected_text_to_bibtex_key=ausgew\u00e4hlten_Text_an_BibTeX-Key_anh\u00e4ngen
+Apply=\u00DCbernehmen
+Assign_entries_based_on:=Eintr\u00e4ge_zuweisen_basierend_auf:
+Assign_new_file=Neue_Datei_zuordnen
+Assign_the_original_group's_entries_to_this_group?=Eintr\u00E4ge_der_urspr\u00FCnglichen_Gruppe_zu_dieser_Gruppe_hinzuf\u00FCgen?
+Assigned_%0_entries_to_group_"%1".=%0_Eintr\u00E4ge_zu_Gruppe_"%1"_hinzugef\u00FCgt.
+Assigned_1_entry_to_group_"%0".=1_Eintrag_zu_Gruppe_"%0"_hinzugef\u00FCgt.
+Attach_%0_file=Datei_%0_anf\u00fcgen
+Attach_URL=URL_anf\u00fcgen
+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.=Versucht,_%0-Links_f\u00fcr_die_Eintr\u00e4ge_automatisch_zuzuordnen._Dies_funktioniert,_wenn_der_Name_einer_%0-Datei_im_%0-Verzeichnis_oder_einem_Unterverzeichnis<BR>identisch_ist_mit_dem_BibTeX-Key_eines_Eintrags_(erweitert_um_die_jeweilige_Dateiendung).
+Auto=Auto
+Autodetect_format=Format_automatisch_erkennen
+Autogenerate_BibTeX_key=BibTeX-Key_automatisch_generieren
+Autogenerate_BibTeX_keys=BibTeX-Keys_automatisch_generieren
+Autogenerate_groups=Gruppen_automatisch_erstellen
+autogenerate_keys=BibTeX-Keys_automatisch_generieren
+Automatically_create_groups=Gruppen_automatisch_erstellen
+Automatically_create_groups_for_database.=Automatisch_Gruppen_f\u00FCr_die_Datei_anlegen.
+Automatically_created_groups=Automatisch_erzeugte_Gruppen
+Automatically_hide_groups_interface_when_switching_to_a_database_that_contains_no_groups=Gruppenansicht_automatisch_ausblenden,_wenn_zu_einer_Datei_ohne_Gruppen_gewechselt_wird
+Automatically_show_groups_interface_when_switching_to_a_database_that_contains_groups=Gruppenansicht_automatisch_einblenden,_wenn_zu_einer_Datei_mit_Gruppen_gewechselt_wird
+Autoset=Automatisch_zuordnen
+Autoset_%0_field=Feld_%0_automatisch_setzen
+Autoset_%0_links._Allow_overwriting_existing_links.=%0_Links_automatisch_zuordnen._Vorhandene_Links_\u00fcberschreiben.
+Autoset_%0_links._Do_not_overwrite_existing_links.=%0_Links_automatisch_zuordnen._Vorhandene_Links_nicht_\u00fcberschreiben.
+Autosetting_%0_field...=Automatisches_Setzen_von_Feld_%0...
+AUX_File_import=Teildatenbank_aus_AUX_Datei_erstellen
+AUX_file_import=AUX_Datei_Import
+Available_export_formats=Verf\u00FCgbare_Exportformate
+Available_fields=verf\u00FCgbare_BibTeX_Felder
+Available_import_formats=Verf\u00FCgbare_Importformate
+Background_color_for_marked_entries=Hintergrundfarbe_f\u00fcr_markierte_Eintr\u00e4ge
+Background_color_for_optional_fields=Hintergrundfarbe_f\u00fcr_optionale_Felder
+Background_color_for_required_fields=Hintergrundfarbe_f\u00fcr_ben\u00f6tigte_Felder
+Backup_old_file_when_saving=Beim_Speichern_ein_Backup_der_alten_Datei_anlegen
+Bibkey_to_filename_conversion=Konvertierung_von_BibTeX-Key_zu_Dateiname
+Biblioscape_Tag_file=Biblioscape_Tag-Datei
+BibTeX=BibTeX
+BibTeX_key=BibTeX-Key
+BibTeX_key_is_unique.=Der_BibTeX-Key_ist_eindeutig.
+BibTeX_key_not_set._Enter_a_name_for_the_downloaded_file=Kein_BibTeX-Key_vorhanden._Bitte_Dateinamen_zum_Download_angeben
+BibTeX_source=BibTeX_Quelltext
+BibTeXML=BibTeXML
+BibTeXML_File=BibTeXML_Datei
+Binding=Tastenk\u00FCrzel
+Broken_link=Fehlerhafter_Link
+Browse=Durchsuchen
+by=von
+Calling_external_viewer...=Externes_Anzeigeprogramm_wird_aufgerufen
+Cancel=Abbrechen
+Cannot_add_entries_to_group_without_generating_keys._Generate_keys_now?=Eintr\u00e4ge_k\u00f6nnen_einer_Gruppe_nicht_hinzugef\u00fcgt_werden,_ohne_Keys_zu_generieren._Sollen_die_Keys_jetzt_generiert_werden?
+Cannot_merge_this_change=Kann_diese_\u00C4nderung_nicht_einf\u00FCgen
+Cannot_move_group=Gruppe_kann_nicht_verschoben_werden
+Cannot_move_group_"%0"_down.=Gruppe_"%0"_kann_nicht_nach_unten_bewegt_werden.
+Cannot_move_group_"%0"_left.=Gruppe_"%0"_kann_nicht_nach_links_bewegt_werden.
+Cannot_move_group_"%0"_right.=Gruppe_"%0"_kann_nicht_nach_rechts_bewegt_werden.
+Cannot_move_group_"%0"_up.=Gruppe_"%0"_kann_nicht_nach_oben_bewegt_werden.
+case_insensitive=Gro\u00DF-/Kleinschreibung_wird_nicht_unterschieden
+case_sensitive=Gro\u00DF-/Kleinschreibung_wird_unterschieden
+Case_sensitive=Gro\u00DF-/Kleinschreibung_unterscheiden
+change_assignment_of_entries=\u00C4nderung_der_zugewiesenen_Eintr\u00E4ge
+# The following are for case change in right-click menu in entry editor. The last four
+# illustrate the four variations of capitalization
+Change_case=Gro\u00DF-_und_Kleinschreibung
+Change_entry_type=Eintragstyp_\u00E4ndern
+change_key=BibTeX-Key_\u00E4ndern
+Change_of_Grouping_Method=\u00C4ndern_der_Gruppierungsmethode
+change_preamble=Pr\u00E4ambel_\u00E4ndern
+change_string_content=Inhalt_des_Strings_\u00E4ndern
+change_string_name=Namen_des_Strings_\u00E4ndern
+change_type=Typ_\u00E4ndern
+changed_=ge\u00E4ndert_
+Changed_font_settings=Schrifteinstellungen_ge\u00E4ndert
+Changed_language_settings=Spracheinstellungen_ge\u00E4ndert.
+Changed_look_and_feel_settings="Look_and_Feel"-Einstellungen_ge\u00E4ndert
+Changed_preamble=Pr\u00E4ambel_ge\u00E4ndert
+Changed_type_to=Typ_ge\u00E4ndert_zu
+Characters_to_ignore=Folgende_Buchstaben_ignorieren
+Check_existing_%0_links=Existierende_%0-Links_\u00fcberpr\u00fcfen
+Check_links=Links_\u00fcberpr\u00fcfen
+Choose_the_URL_to_download._The_default_value_points_to_a_list_provided_by_the_JabRef_developers.=URL_zum_Herunterladen_ausw\u00e4hlen._Der_Standardwert_f\u00fchrt_zu_einer_Liste,_die_von_den_JabRef-Entwicklern_zur_Verf\u00fcgung_gestellt_wird.
+Citation_import_from_CiteSeer_failed.=Fehler_beim_Import_von_CiteSeer.
+CiteSeer_Error=CiteSeer-Fehler
+CiteSeer_Fetch_Error=Fehler_beim_Abrufen_von_CiteSeer
+CiteSeer_import_entries=CiteSeer_Eintr\u00E4ge_importieren
+CiteSeer_Import_Error=Fehler_beim_Import_von_CiteSeer
+CiteSeer_Import_Fields=CiteSeer_Import-Felder
+CiteSeer_Transfer=CiteSeer-Transfer
+CiteSeer_Warning=CiteSeer_Warnung
+Class_name=Klassenname
+Clear=Zur\u00FCcksetzen
+clear_all_groups=Alle_Gruppen_l\u00F6schen
+Clear_field=Feld_l\u00f6schen
+Clear_highlight=Markierten_l\u00f6schen
+Clear_highlighted=Markierte_l\u00f6schen
+Clear_highlighted_groups=Markierte_Gruppen_l\u00f6schen
+Clear_inputarea=gesamten_Text_entfernen
+Clear_search=Suche_l\u00f6schen
+Close=Schlie\u00DFen
+Close_database=Datei_schlie\u00DFen
+Close_dialog=Dialog_schlie\u00DFen
+# The following lines correspond to names of key bindings:
+Close_entry_editor=Eintragseditor_schlie\u00DFen
+Close_preamble_editor=Pr\u00E4ambel-Editor_schlie\u00DFen
+Close_the_current_database=Aktuelle_Datei_schlie\u00DFen
+Close_the_help_window=Hilfefenster_schlie\u00DFen
+Close_window=Fenster_schlie\u00DFen
+Closed_database=Datei_geschlossen
+Collapse_subtree=Unterbaum_zuklappen
+Color_codes_for_required_and_optional_fields=Farbanzeige_f\u00FCr_ben\u00F6tigte_und_optionale_Felder
+Color_for_marking_incomplete_entries=Farbe_zum_Markieren_unvollst\u00e4ndiger_Eintr\u00e4ge
+Column_width=Spaltenbreite
+Command_line_id=Kommandozeilen_ID
+Complete_record=Kompletter_Eintrag
+Completed_citation_import_from_CiteSeer.=Import_von_CiteSeer_abgeschlossen.
+Completed_Import_Fields_from_CiteSeer.=Die_Felder_wurden_aus_CiteSeer_importiert.
+Completed_import_from_CiteSeer.=Import_von_CiteSeer_abgeschlossen
+Contained_in=Enthalten_in
+Content=Inhalt
+Copied=Kopiert
+Copied_cell_contents=Zelleninhalt_kopiert
+Copied_key=BibTeX-Key_kopiert
+Copied_keys=BibTeX-Keys_kopiert
+Copy=Kopieren
+Copy_BibTeX_key=BibTeX-Key_kopieren
+Copy_\\cite{BibTeX_key}=Kopiere_\\cite{BibTeX-Key}
+Copy_to_clipboard=Text_in_Zwischenablage_kopieren
+Could_not_call_executable=Konnte_das_Programm_nicht_aufrufen
+Could_not_connect_to_host=Verbindung_zum_Host_fehlgeschlagen
+# I have reformulated the following lines, because the 1st person form is not suitable:
+Could_not_connect_to_host_=Verbindung_zum_Host_fehlgeschlagen
+Could_not_export_entry_types=Eintragstypen_konnten_nicht_exportiert_werden
+Could_not_export_file=Konnte_Datei_nicht_exportieren
+Could_not_export_preferences=Einstellungen_konnten_nicht_exportiert_werden
+Could_not_find_a_suitable_import_format.=Kein_passendes_Importformat_gefunden.
+Could_not_find_layout_file=Keine_Layoutdatei_gefunden
+Could_not_import_entry_types=Eintragstypen_konnten_nicht_importiert_werden
+Could_not_import_preferences=Einstellungen_konnten_nicht_importiert_werden
+Could_not_instantiate_%0_%1=Konnte_Importer_nicht_erzeugen_%0_%1
+Could_not_resolve_import_format=Das_Importformat_konnte_nicht_bestimmt_werden.
+Could_not_save_file=Datei_konnte_nicht_gespeichert_werden
+Couldn't_find_an_entry_associated_with_this_URL=Es_konnte_kein_Eintrag_gefunden_werden,_der_mit_dieser_URL_verkn\u00FCpft_ist
+Couldn't_parse_the_'citeseerurl'_field_of_the_following_entries=Die_'citeseerurl'_der_folgenden_Eintr\u00E4ge_konnte_nicht_analysiert_werden
+Create_group=Gruppe_anlegen
+Created_group=Gruppe_erstellen
+Created_group_"%0".=Gruppe_"%0"_erstellt.
+Created_groups.=Gruppen_erstellt.
+Curly_braces_{_and_}_must_be_balanced.=Geschweifte_Klammern_{_und_}_m\u00FCssen_sich_ausgleichen.
+Current_content=Aktueller_Inhalt
+Current_value=Aktueller_Wert
+Custom_entry_types=Benutzerdefinierte_Eintragstypen
+Custom_entry_types_found_in_file=Benutzerdefinierte_Eintragstypen_gefunden
+Custom_export=Externe_Exportfilter
+Custom_importers=Externe_Importfilter
+Customize_entry_types=Eintragstypen_anpassen
+Customize_key_bindings=Tastenk\u00FCrzel_anpassen
+Cut=Ausschneiden
+cut_entries=Eintr\u00E4ge_ausschneiden
+cut_entry=Eintrag_ausschneiden
+Cut_pr=Ausschneiden
+Database_encoding=Zeichenkodierung_der_Datei
+Database_has_changed._Do_you_want_to_save_before_closing?=Die_Datei_wurde_ge\u00E4ndert._Wollen_Sie_vor_dem_Beenden_speichern?
+Database_properties=Eigenschaften_der_Datei
+Date_format=Datumsformat
+Default=Standard
+Default_encoding=Standard_Zeichenkodierung
+Default_grouping_field=Standard_Gruppierungs-Feld
+Default_look_and_feel=Standard_"look_and_feel"
+Default_owner=Standard-Besitzer
+Default_pattern=Standardmuster
+Default_sort_criteria=Standard-Sortierkriterium
+defined.=definiert.
+Delete=L\u00F6schen
+Delete_custom=Eintragstyp_l\u00F6schen
+Delete_custom_format=Format_des_Eintragstyps_l\u00F6schen
+# I have reformulated the following lines, because the 1st person form is not suitable:
+# (Folgende_URL_konnte_nicht_analysiert_werden)
+delete_entries=Eintr\u00E4ge_l\u00F6schen
+Delete_entry=Eintrag_l\u00F6schen
+delete_entry=Eintrag_l\u00F6schen
+Delete_multiple_entries=Mehrere_Eintr\u00E4ge_l\u00F6schen
+Delete_rows=Zeilen_l\u00F6schen
+Delete_strings=Strings_l\u00F6schen
+Deleted=Gel\u00F6scht
+Deleted_entry=Eintrag_gel\u00F6scht
+Delimit_fields_with_semicolon,_ex.=Felder_mit_Semikolon_abgrenzen,_z.B.
+Descending=Absteigend
+Description=Beschreibung
+Deselect_all=Auswahl_aufheben
+Details=Details
+Disable_entry_editor_when_multiple_entries_are_selected=Eintragseditor_sperren,_wenn_mehrere_Eintr\u00E4ge_ausgew\u00E4hlt_sind
+Disable_this_confirmation_dialog=Diesen_Best\u00E4tigungsdialog_deaktivieren
+Disable_this_warning_dialog=Diese_Warnmeldung_deaktivieren
+Display_all_entries_belonging_to_one_or_more_of_the_selected_groups.=Alle_Eintr\u00E4ge_anzeigen,_die_zu_einer_oder_mehreren_der_ausgew\u00E4hlten_Gruppen_geh\u00F6ren.
+Display_help_on_command_line_options=Zeige_Kommandozeilenhilfe
+Display_imported_entries_in_an_inspection_window_before_they_are_added.=Importierte_Eintr\u00e4ge_im_Kontrollfenster_anzeigen_bevor_sie_hinzugef\u00fcgt_werden.
+Display_only_entries_belonging_to_all_selected_groups.=Nur_Eintr\u00E4ge_anzeigen,_die_zu_allen_ausgew\u00E4hlten_Gruppen_geh\u00F6ren.
+Displaying_no_groups=Keine_Gruppen_anzeigen
+Do_not_abbreviate_names=Namen_nicht_abk\u00fcrzen
+Do_not_autoset=Nicht_automatisch_zuordnen
+Do_not_import_entry=Eintrag_nicht_importieren
+Do_not_open_any_files_at_startup=Keine_Dateien_beim_Start_\u00f6ffnen
+Do_not_overwrite_existing_keys=Existierende_Keys_nicht_\u00fcberschreiben
+Do_not_wrap_the_following_fields_when_saving=Beim_Speichern_keinen_Zeilenumbruch_in_den_folgenden_Feldern_einf\u00fcgen
+Docbook=Docbook
+Done=Fertig
+Down=Abw\u00e4rts
+Download=Herunterladen
+Download_completed=Download_beendet
+Download_file=Datei_herunterladen
+Downloading...=Download_l\u00E4uft
+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.=Aufgrund_des_doppelten_BibTeX-Keys_kann_die_Gruppenzuordnung_dieses_Eintrags_beim_n\u00E4chstenn\u00D6ffnen_nicht_wiederhergestellt_werden._Es_wird_empfohlen,_von_JabRef_jetzt_einen_eindeutigennKey_automatisch_generieren_zu_lassen,_um_dieses_Problem_zu_verhindern.
+dummy=dummy
+Duplicate_BibTeX_key=Doppelter_BibTeX-Key
+duplicate_BibTeX_key=doppelter_BibTeX-Key
+Duplicate_BibTeX_key.=Doppelter_BibTeX-Key.
+duplicate_BibTeX_key.=doppelter_BibTeX-Key
+Duplicate_BibTeX_key._Grouping_may_not_work_for_this_entry.=Doppelter_BibTeX-Key._Es_kann_sein,_dass_die_Gruppierung_f\u00fcr_diesen_Eintrag_nicht_funktioniert.
+Duplicate_Key_Warning=Warnung:_Key_bereits_vorhanden
+Duplicate_pairs_found=Doppelte_Eintr\u00E4ge_gefunden
+duplicate_removal=Duplikate_entfernen
+Duplicate_string_name=Doppelter_String-Name
+Duplicates_found=Doppelte_Eintr\u00E4ge_gefunden
+Duplicates_removed=Doppelte_Eintr\u00E4ge_gel\u00F6scht
+Dynamic_groups=Dynamische_Gruppen
+Dynamically_group_entries_by_a_free-form_search_expression=Dynamisches_Gruppieren_der_Eintr\u00E4ge_anhand_eines_beliebigen_Suchausdrucks
+Dynamically_group_entries_by_searching_a_field_for_a_keyword=Dynamisches_Gruppieren_der_Eintr\u00e4ge_anhand_eines_Stichworts_in_einem_Feld
+Each_line_must_be_on_the_following_form=Jede_Zeile_muss_das_folgende_Format_aufweisen
+Edit=Bearbeiten
+Edit_custom_export=Bearbeite_externen_Exportfilter
+Edit_entry=Eintrag_bearbeiten
+Edit_group=Gruppe_bearbeiten
+Edit_journal=Zeitschrift_bearbeiten
+Edit_preamble=Pr\u00E4ambel_bearbeiten
+Edit_strings=Strings_bearbeiten
+empty_BibTeX_key=leerer_BibTeX-Key
+Empty_BibTeX_key.=Leerer_BibTeX-Key.
+Empty_BibTeX_key._Grouping_may_not_work_for_this_entry.=Leerer_BibTeX-Key._Es_kann_sein,_dass_die_Gruppierung_f\u00fcr_diesen_Eintrag_nicht_funktioniert.
+Empty_database=Leere_Datei
+empty_database=leere_Datenbank
+Enable source_editing=Bearbeiten_von_Sourcecode_zulassen
+Enable_source_editing=Quelltextbearbeitung_aktivieren
+Endnote=Endnote
+Enter_URL=URL_eingeben
+Enter_URL_to_download=URL_f\u00FCr_den_Download_eingeben
+entries=Eintr\u00E4ge
+Entries_cannot_be_manually_assigned_to_or_removed_from_this_group.=Ein_manuelles_Hinzuf\u00FCgen_oder_Entfernen_von_Eintr\u00E4gen_ist_f\u00FCr_diese_Gruppe_nicht_m\u00F6glich.
+Entries_exported_to_clipboard=Eintr\u00E4ge_in_die_Zwischenablage_kopiert
+entries_have_undefined_BibTeX_key=Eintr\u00E4ge_haben_einen_unbestimmten_BibTeX-Key
+entries_into_new_database=Eintr\u00E4ge_in_neue_Datei
+entry=Eintrag
+Entry_editor=Editor
+# The following lines correspond to names of key bindings:
+Entry_editor,_next_entry=Eintragseditor,_n\u00E4chster_Eintrag
+Entry_editor,_next_panel=Eintragseditor,_n\u00E4chstes_Panel
+Entry_editor,_previous_entry=Eintragseditor,_voriger_Eintrag
+Entry_editor,_previous_panel=Eintragseditor,_voriges_Panel
+Entry_editor,_store_field=Eintragseditor,_Feld_speichern
+Entry_in_current_database=Eintrag_in_aktueller_Datenbank
+Entry_in_import=Eintrag_in_Importierung
+Entry_is_incomplete=Eintrag_ist_nicht_vollst\u00E4ndig
+Entry_preview=Eintragsvorschau
+Entry_table=Tabellenansicht
+Entry_table_columns=Spaltenanordnung
+Entry_type=Eintragstyp
+Entry_type_names_are_not_allowed_to_contain_white_space_or_the_following_characters=Namen_von_Eintragstypen_d\u00FCrfen_weder_Leerzeichen_noch_die_folgenden_Zeichen_enthalten
+Entry_types=Eintragstypen
+EOF_in_mid-string=EOF_in_mid-string
+Error=Fehler
+##Error:_check_your_External_viewer_settings_in_Preferences=Fehler:_\u00FCberpr\u00FCfen_Sie_Ihre_Einstellungen_zu_Externen_Programmen
+Error_in_field=Fehler_in_Feld
+Error_in_line=Fehler_in_Zeile
+Error_opening_file=Fehler_beim_\u00D6ffnen_der_Datei
+Error_setting_field=Fehler_beim_Erstellen_des_Feldes
+Existing_file=Bestehende_Datei
+exists._Overwrite?=Existiert._\u00DCberschreiben?
+exists._Overwrite_file?=existiert._Ersetzen?
+Exit=Beenden
+Expand_subtree=Unterbaum_aufklappen
+Explicit=Explizit
+Export=Exportieren
+Export_entry_types=Eintragstypen_exportieren
+Export_name=Filtername
+Export_preferences=Einstellungen_exportieren
+Export_preferences_to_file=Exportiere_Einstellungen_in_Datei
+Export_properties=Eigenschaften_f\u00FCr_Exportfilter
+Export_selected_to_clipboard=Ausgew\u00E4hlte_in_die_Zwischenablage_kopieren
+Export_to_clipboard=In_die_Zwischenablage_kopieren
+Exported_database_to_file=Datei_exportiert_nach
+Exporting=Exportiere
+External_changes=Externe_\u00C4nderungen
+External_files=Externe_Dateien
+External_programs=Externe_Programme
+External_viewer_called=Externer_Betrachter_aufgerufen
+Failed_to_read_groups_data_(unsupported_version:_%0)=Gruppen_konnten_nicht_eingelesen_werden_(nicht_unterst\u00FCtzte_Version:_%0)
+Fetch=Abrufen
+Fetch_Articles_Citing_your_Database=Literaturangaben_abrufen,_die_mit_Datens\u00E4tzen_ihrer_Datei_\u00FCbereinstimmen
+Fetch_Citations_from_CiteSeer=Literaturangaben_von_CiteSeer_abrufen
+Fetch_citations_from_CiteSeer=Eintr\u00E4ge_von_CiteSeer_holen
+Fetch_CiteSeer=CiteSeer_abrufen
+Fetch_Medline=Medline_abrufen
+fetch_Medline=Medline_abrufen
+Fetch_Medline_by_author=Medline_mittels_Autor_abrufen
+Fetch_Medline_by_ID=Medline_mittels_ID_abrufen
+Fetched_all_citations_from_target_database.=Alle_Literaturangaben_von_der_Zieldatenbank_abgerufen.
+Fetching_Citations=Literaturangaben_werden_abgerufen
+Fetching_Identifiers=Bezeichner_werden_abgerufen
+Fetching_Medline...=Rufe_Medline_ab...
+Fetching_Medline_by_ID...=Rufe_Medline_mittels_ID_ab...
+Fetching_Medline_by_id_...=Rufe_Medline_mittels_ID_ab...
+Fetching_Medline_by_term_...=Rufe_Medline_mittels_Suchbegriff_ab...
+Field=Feld
+field=Feld
+# 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=Feldinhalt
+Field_name=Feldname
+Field_names_are_not_allowed_to_contain_white_space_or_the_following_characters=Der_Feldname_darf_weder_Leerzeichen_noch_eines_der_folgenden_Zeichen_enthalten
+Field_sizes=Feldgr\u00f6\u00dfen
+Field_to_group_by=Sortierfeld
+Field_to_search=Zu_durchsuchendes_Feld
+Fields=Felder
+File=Datei
+file=Datei
+File_'%0'_not_found=Datei_'%0'_nicht_gefunden
+File_changed=Datei_ge\u00E4ndert
+File_extension=Dateiendung
+File_has_been_updated_externally._Are_you_sure_you_want_to_save?=Die_Datei_wurde_extern_ver\u00E4ndert._Sind_Sie_sicher,_dass_Sie_abspeichern_m\u00F6chten?
+File_not_found=Datei_nicht_gefunden
+File_updated_externally=Datei_extern_ge\u00E4ndert
+filename=Dateiname
+Files_opened=Dateien_ge\u00F6ffnet
+Find_duplicates=Nach_doppelten_Eintr\u00E4gen_suchen
+Finished_autosetting_%0_field._Entries_changed:_%1.=Automatisches_Setzen_von_Feld_%0_abgeschlossen._Ge\u00e4nderte_Eintr\u00e4ge:_%1.
+Finished_synchronizing_%0_links._Entries_changed%c_%1.=Synchronisierung_von_%0_Links_abgeschlossen._Ge\u00e4nderte_Eintr\u00e4ge%c_%1.
+First_select_the_entries_you_want_keys_to_be_generated_for.=W\u00E4hlen_Sie_zuerst_die_Eintr\u00E4ge_aus,_f\u00FCr_die_Keys_erstellt_werden_sollen.
+Fit_table_horizontally_on_screen=Tabelle_horizontal_dem_Bildschirm_anpassen
+Float=Oben_einsortieren
+Font_Family=Schriftart
+Font_Preview=Vorschau
+Font_Size=Schriftgr\u00F6\u00DFe
+Font_Style=Schriftstil
+FontSelector=Schriften_w\u00E4hlen
+for=f\u00FCr
+Format_of_author_and_editor_names=Format_der_Autoren-_und_Hrsg.-Namen
+Format_used=benutztes_Format
+Formatter_not_found=Formatierer_nicht_gefunden
+found=gefunden
+found_in_aux_file=gefundene_Schl\u00FCssel_in_AUX_Datei
+Full_name=Kompletter_Name
+General=Allgemein
+General_fields=Allgemeine_Felder
+Generate=Erzeugen
+Generate_BibTeX_key=BibTeX-Key_generieren
+Generate_keys=Erstelle_Key
+Generate_now=Jetzt_generieren
+Generated_BibTeX_key_for=BibTeX-Key_erzeugt_f\u00FCr
+Generating_BibTeX_key_for=Erzeuge_BibTeX-Key_f\u00FCr
+Grab=Tastenk\u00FCrzel_holen
+Gray_out_entries_not_in_group_selection=Eintr\u00E4ge_ausblenden,_die_nicht_in_der_Gruppenauswahl_sind
+Gray_out_non-hits=Nicht-Treffer_grau_einf\u00E4rben
+Gray_out_non-matching_entries=Nicht_\u00FCbereinstimmende_Eintr\u00E4ge_ausblenden
+Group_definitions_have_been_converted_to_JabRef_1.7_format.=Die_Gruppendefinitionen_wurden_zum_JabRef_1.7-Format_konvertiert.
+Group_name=Name_der_Gruppe
+Group_properties=Gruppeneigenschaften
+Groups=Gruppen
+Harvard_RTF=Harvard_RTF
+Help=Hilfe
+Help_contents=Hilfe_-_Inhalt
+Help_on_groups=Hilfe_zu_Gruppen
+Help_on_key_patterns=Hilfe_zu_BibTeX-Key-Mustern
+Hide_non-hits=Nicht-Treffer_ausblenden
+Highlight=Markieren
+Highlight_groups_matching_all_selected_entries=Gruppen_markieren,_die_alle_selektierten_Eintr\u00e4ge_enthalten
+Highlight_groups_matching_any_selected_entry=Gruppen_markieren,_die_mindestens_einen_der_selektierten_Eintr\u00e4ge_enthalten
+Highlight_groups_that_contain_entries_contained_in_any_currently_selected_group=Gruppen_markieren,_die_Eintr\u00e4ge_enthalten,_die_in_einer_der_gerade_markierten_Gruppen_enthalten_sind
+Highlight_overlapping_groups=Sich_\u00fcberschneidende_Gruppen_markieren
+Hint%c_To_search_specific_fields_only,_enter_for_example%c<p><tt>author%esmith_and_title%eelectrical</tt>=Hinweis%c_Um_ausschlie\u00DFlich_bestimmte_Felder_zu_durchsuchen,_geben_Sie_z.B._ein%c<p><tt>author%esmith_and_title%eelectrical</tt>
+HTML=HTML
+Ignore=Ignorieren
+Illegal_type_name=Ung\u00FCltiger_Typ
+Immediate_subgroups=Direkte_Untergruppen
+Import=Importieren
+Import_and_append=Importieren_und_anh\u00E4ngen
+Import_and_keep_old_entry=Importieren_und_alten_Eintrag_behalten
+Import_and_remove_old_entry=Importieren_und_alten_Eintrag_l\u00F6schen
+Import_cancelled.=Importierung_abgebrochen.
+Import_Data_from_CiteSeer=Daten_von_CiteSeer_importieren
+Import_Data_from_CiteSeer_Database=Daten_aus_CiteSeer-Datenbank_importieren
+Import_database=Datei_importieren
+Import_entries=Eintr\u00E4ge_importieren
+Import_entry_types=Eintragstypen_importieren
+Import_failed=Import_fehlgeschlagen
+Import_Fields_from_CiteSeer=Felder_von_CiteSeer_importieren
+Import_fields_from_CiteSeer=Felder_von_CiteSeer_importieren
+Import_fields_from_CiteSeer_Database=Import_fields_from_CiteSeer_Database
+Import_Fields_from_CiteSeer_Database=Felder_aus_CiteSeer-Datenbank_importieren
+Import_file=Importiere_Datei
+Import_group_definitions=Gruppendefinitionen_importieren
+Import_name=Importer_Name
+Import_plain_text=Klartext_importieren
+Import_preferences=Einstellungen_importieren
+Import_preferences_from_file=Importiere_Einstellungen_aus_Datei
+Import_strings=Strings_importieren
+Import_to_open_tab=In_ge\u00f6ffnetes_Tab_importieren
+Import_word_selector_definitions=Wortauswahldefinitionen_importieren
+Imported_database=Datei_importiert
+Imported_entries=Eintr\u00E4ge_importiert
+Imported_entry_types=Eintragstypen_importiert
+Imported_file=Importierte_Datei
+Imported_from_database=Importiert_aus_Datei
+ImportFormat_class=ImportFormat_Klasse
+Importing=Importiere
+Importing_file=importiere_Datei
+Importing_in_unknown_format=Importiere_ein_unbekanntes_Format
+In_JabRef,_use_pairs_of_#_characters_to_indicate_a_string.=Benutzen_Sie_in_JabRef_das_Zeichen_#_paarweise,_um_einen_String_(Abk\u00FCrzung)_anzugeben.
+Include_subgroups=Untergruppen_ber\u00fccksichtigen
+Include_subgroups:_When_selected,_view_entries_contained_in_this_group_or_its_subgroups=Untergruppen_ber\u00fccksichtigen:_Wenn_ausgew\u00e4hlt,_werden_Eintr\u00e4ge_dieser_Gruppe_und_ihrer_Untergruppen_angezeigt
+Incremental=Direkt
+Incremental_search=Weitersuchen
+Incremental_search_failed._Repeat_to_search_from_top.=Direkte_Suche_fehlgeschlagen._Wiederhole_die_Suche_vom_Anfang_der_Datenbank.
+Independent=Unabh\u00E4ngig
+Independent_group:_When_selected,_view_only_this_group's_entries=Unabh\u00e4ngige_Gruppen:_Wenn_ausgew\u00e4hlt,_werden_nur_die_Eintr\u00e4ge_dieser_Gruppe_angezeigt
+Initially_show_groups_tree_expanded=Baumansicht_der_Gruppen_standardm\u00e4\u00dfig_aufklappen
+Input=Bearbeitungsoptionen
+Input_error=Eingabefehler
+Insert=einf\u00FCgen
+Insert_rows=Zeilen_einf\u00FCgen
+Insert_selected_citations_into_LyX=Ausgew\u00E4hlte_Literaturangaben_in_LyX_einf\u00FCgen
+Insert_selected_citations_into_WinEdt=Ausgew\u00E4hlte_Literaturangaben_in_WinEdt_einf\u00FCgen
+insert_string_=String_einf\u00FCgen_
+Insert_URL=URL_einf\u00fcgen
+INSPEC=INSPEC
+integrity=Integrit\u00E4t
+# 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=Integrit\u00E4ts\u00FCberpr\u00FCfung
+Intersection=Schnittmenge
+Intersection_with_supergroups=Schnittmenge_mit_Obergruppen
+Invalid_BibTeX_key=Ung\u00fcltiger_BibTeX-Key
+Invalid_date_format=Ung\u00fcltiges_Datumsformat
+Invalid_URL=Ung\u00FCltige_URL
+Inverted=Invertiert
+is_a_standard_type.=ist_ein_Standardtyp
+ISI=ISI
+ISO_abbreviation=ISO-Abk\u00fcrzung
+Item_list_for_field=Wortliste_f\u00FCr_Feld
+JabRef_help=JabRef_Hilfe
+JabRef_preferences=JabRef_Einstellungen
+Journal_abbreviations=Abk\u00fcrzung_der_Zeitschriftennamen
+Journal_list_preview=Vorschau_der_Zeitschriftenliste
+Journal_name=Zeitschriftenname
+Journal_names=Zeitschriftennamen
+JStor_file=JStor_Datei
+Keep=Behalten
+Keep_both=Beide_behalten
+Keep_lower=Unteren_behalten
+Keep_upper=Oberen_behalten
+Key_bindings=Tastenk\u00FCrzel
+Key_bindings_changed=Tastenk\u00FCrzel_ge\u00E4ndert
+Key_generator_settings=Einstellungen_des_Key-Generators
+Key_pattern=BibTeX-Key-Muster
+keys_in_database=Keys_in_der_Datenbank
+Keyword=Stichwort
+Label=Name
+Language=Sprache
+Last_modified=zuletzt_ge\u00E4ndert
+Latex_AUX_file=LaTeX_AUX_Datei
+LaTeX_AUX_file=LaTeX_AUX-Datei
+Left=Links
+License=Lizenz
+Limit_to_fields=Auf_folgende_Felder_begrenzen
+Limit_to_selected_entries=Auf_ausgew\u00E4hlte_Eintr\u00E4ge_begrenzen
+Listen_for_remote_operation_on_port=Port_nach_externem_Zugriff_abh\u00f6ren
+Load_session=Sitzung_laden
+Loading_session...=Lade_Sitzung...
+Look_and_feel=Aussehen
+lower=klein
+Main_layout_file=Haupt-Layoutdatei
+Main_PDF_directory=Standard-Ordner_f\u00FCr_PDF-Dateien
+Main_PS_directory=Standard-Ordner_f\u00fcr_PS-Dateien
+Manage=Verwalten
+Manage_content_selectors=Wortauswahl_verwalten
+Manage_custom_exports=Verwalte_externe_Exportfilter
+Manage_custom_imports=Verwalte_externe_Importfilter
+Manage_journal_abbreviations=Abk\u00fcrzungen_der_Zeitschriften_verwalten
+Mark_entries=Eintr\u00E4ge_markieren
+Mark_entry=Eintrag_markieren
+Mark_new_entries_with_addition_date=Neue_Eintr\u00e4ge_mit_Datum_versehen
+Mark_new_entries_with_owner_name=Neue_Eintr\u00E4ge_mit_Namen_des_Besitzers_versehen
+# These are status line messages when marking/unmarking entries:
+Marked_selected=Ausgew\u00E4hlte_markiert
+Medline_entries_fetched=Medline-Eintr\u00E4ge_abgerufen
+Medline_XML=Medline_XML
+Medline_XML_File=Medline_XML_Datei
+Menu_and_label_font_size=Schriftgr\u00F6\u00DFe_in_Men\u00FCs
+Merged_external_changes=Externe_\u00C4nderungen_eingef\u00FCgt
+messages=Meldungen
+Messages=Mitteilungen
+Messages_and_Hints=Hinweise_und_Warnungen
+Miscellaneous=Verschiedenes
+Modification_of_field=\u00C4nderung_des_Felds
+Modified_group_"%0".=Gruppe_"%0"_ge\u00E4ndert.
+Modified_groups=Ge\u00e4nderte_Gruppen
+Modified_groups_tree=Baum_mit__modifizierten_Gruppen
+Modified_string=Ver\u00E4nderter_String
+Modify=Bearbeiten
+modify_group=Gruppe_bearbeiten
+MODS=MODS
+Move=Verschieben
+Move_down=Nach_unten
+Move_entries_in_group_selection_to_the_top=Sortiere_Eintr\u00E4ge_der_Gruppenauswahl_nach_oben
+move_group=Gruppe_verschieben
+Move_matching_entries_to_the_top=Treffer_nach_oben_sortieren
+Move_string_down=String_nach_unten
+Move_string_up=String_nach_oben
+Move_up=Nach_oben
+Moved_Group=Gruppe_verschoben
+Moved_group_"%0".=Gruppe_"%0"_verschoben.
+Name=Name
+Natbib_style=Natbib-Stil
+Ne_entries_imported.=Keine_Eintr\u00e4ge_importiert.
+nested_aux_files=referenzierte_AUX_Dateien
+New=Neu
+new=neu
+New_article=Neuer_Eintrag_'article'
+New_BibTeX_database=Neue_BibTeX_Datei
+New_BibTeX_entry=Neuer_BibTeX_Eintrag
+New_BibTeX_subdatabase=Neue_BibTeX_Teildatei
+New_book=Neuer_Eintrag_'book'
+New_content=Neuer_Inhalt
+New_database=Neue_Datei
+New_database_created.=Neue_Datei_angelegt.
+New_entry=Neuer_Eintrag
+New_entry...=Neuer_Eintrag...
+New_entry_from_plain_text=Neuer_Eintrag_aus_Klartext
+New_file=Neue_Datei
+New_group=Neue_Gruppe
+New_inbook=Neuer_Eintrag_'inbook'
+New_mastersthesis=Neuer_Eintrag_'masterthesis'
+New_phdthesis=Neuer_Eintrag_'phdthesis'
+New_proceedings=Neuer_Eintrag_'proceedings'
+New_string=Neuer_String
+New_subdatabase=Neue_Teildatei
+New_subdatabase_based_on_AUX_file=Neue_Teildatei_aus_AUX-Datei
+New_unpublished=Neuer_Eintrag_'unpublished'
+Next_entry=N\u00E4chster_Eintrag
+Next_tab=N\u00E4chster_Tab
+No_%0_found=Kein_%0_gefunden
+No_actual_changes_found.=Keine_aktuellen_\u00c4nderungen_gefunden.
+no_base-bibtex-file_specified=keine_Bibtex_Datenbank_angegeben!
+No_custom_imports_registered_yet.=Noch_keine_externen_Importfilter_registriert.
+no_database_generated=keine_Datenbank_erstellt_und_geschrieben
+No_duplicates_found=Keine_doppelten_Eintr\u00E4ge_gefunden
+No_entries_imported.=Keine_Eintr\u00E4ge_importiert.
+No_entries_or_multiple_entries_selected.=Keine_oder_mehrere_Eintr\u00e4ge_ausgew\u00e4hlt.
+No_entries_selected=Keine_Eintr\u00E4ge_ausgew\u00E4hlt.
+No_GUI._Only_process_command_line_options.=Kein_GUI._Nur_Kommandozeilenbefehle_ausf\u00FChren.
+No_journal_names_could_be_abbreviated.=Es_konnten_keine_Zeitschriftennamen_abgek\u00fcrzt_werden.
+No_journal_names_could_be_unabbreviated.=Das_Aufheben_der_Abk\u00fcrzung_konnte_bei_keiner_Zeitschrift_durchgef\u00fchrt_werden.
+No_Medline_entries_found.=Keine_Medline-Eintr\u00E4ge_gefunden.
+No_pdf_or_ps_defined,_and_no_file_matching_Bibtex_key_found=Sie_haben_keine_PDF-_oder_PS-Datei_angegeben_und_es_wurde_keine_Datei_gefunden,_die_mit_dem_BibTeX-Key_\u00FCbereinstimmt.
+No_references_found=Keine_Literaturangaben_gefunden
+No_saved_session_found.=Keine_gespeicherte_Sitzung_gefunden.
+No_url_defined=Keine_URL_angegeben
+non-Mac_only=nicht_f\u00FCr_Mac
+Normal=Normal
+not=nicht
+not_found=davon_nicht_gefunden
+Not_saved_(empty_session)=Nicht_gespeichert_(leere_Sitzung)
+Note_that_the_entry_causing_the_problem_has_been_selected.=Der_Eintrag,_der_das_Problem_verursacht,_wurde_ausgew\u00E4hlt.
+Note_that_the_new_definitions_will_not_be_compatible_with_previous_JabRef_versions.=Beachten_Sie,_da\u00DF_die_neuen_Definitionen_nicht_mit_fr\u00DCheren_Versionen_von_JabRef_kompatibel_sind.
+Note_that_you_must_specify_the_fully_qualified_class_name_for_the_look_and_feel,=Es_muss_der_volle_Klassenname_f\u00FCr_das_zu_verwendende_"look_and_feel"_angegeben_werden.
+Nothing_to_redo=Wiederholen_nicht_m\u00F6glich
+Nothing_to_undo=R\u00FCckg\u00E4ngig_nicht_m\u00F6glich
+# The next is used like in "References found: 1  Number of references to fetch?"
+Number_of_references_to_fetch?=Anzahl_der_abzurufenden_Literaturangaben?
+occurences=Ausdr\u00FCcke
+OK=OK
+Ok=OK
+One_or_more_keys_will_be_overwritten._Continue?=Einer_oder_mehrere_Keys_werden_\u00FCberschrieben._Fortsetzen?
+Open=\u00D6ffnen
+open=\u00F6ffnen
+Open_BibTeX_database=BibTeX_Datei_\u00F6ffnen
+Open_database=Datei_\u00F6ffnen
+Open_editor_when_a_new_entry_is_created=Editor_\u00F6ffnen,_wenn_ein_neuer_Eintrag_angelegt_wird
+Open_file=Datei_\u00F6ffnen
+Open_last_edited_databases_at_startup=Beim_Starten_von_JabRef_die_letzten_bearbeiteten_Dateien_\u00F6ffnen
+Open_PDF_or_PS=PDF_oder_PS_\u00F6ffnen
+Open_right-click_menu_with_Ctrl+left_button=Kontextmen\u00FC_mit_Strg_+_linker_Maustaste_\u00F6ffnen
+Open_URL_or_DOI=URL_oder_DOI_\u00F6ffnen
+Opened_database=Datei_ge\u00F6ffnet
+Opening=\u00D6ffne
+Opening_preferences...=\u00D6ffne_Voreinstellungen...
+Optional_fields=Optionale_Felder
+Options=Optionen
+or=oder
+out_of=von
+Output_or_export_file=Speichere_oder_exportiere_Datei
+Overlapping_groups=Sich_\u00fcberschneidende_Gruppen
+Override=\u00FCberschreiben
+override_the_bibtex_key_by_the_selected_text=BibTeX-Key_mit_ausgew\u00e4hltem_Text_\u00fcberschreiben
+Overwrite_keys=Keys_\u00FCberschreiben
+Ovid=Ovid
+pairs_processed=Paare_\u00FCberarbeitet
+Paste=Einf\u00FCgen
+paste_entries=Eintr\u00E4ge_einf\u00FCgen
+paste_entry=Eintrag_einf\u00FCgen
+Paste_from_clipboard=Text_aus_Zwischenablage_einf\u00FCgen
+Pasted=Eingef\u00FCgt
+Path_to_HTML_viewer=Pfad_zum_HTML-Browser
+Path_to_LyX_pipe=Pfad_zur_LyX_pipe
+Path_to_PDF_viewer=Pfad_zum_PDF-Anzeigeprogramm
+Path_to_PS_viewer=Pfad_zum_PS-Anzeigeprogramm
+Path_to_WinEdt.exe=Pfad_zu_WinEdt.exe
+Paths_to_external_programs=Pfad_zu_externen_Programmen
+PDF_links=PDF-Link
+Personal_journal_list=Pers\u00f6nliche_Zeitschriftenliste
+Pick_titles=Titel_w\u00e4hlen
+Plain_right_menu=Men\u00FC
+Plain_text=Einfacher_Text
+Plain_text_import=Klartext_importieren
+Please_check_your_network_connection_to_this_machine.=Bitte_\u00FCberpr\u00FCfen_Sie_die_Netzwerkverbindung_ihres_Computers.
+Please_define_BibTeX_key_first=Bitte_geben_Sie_zuerst_einen_BibTeX-Key_an
+Please_enter_a_name_for_the_group.=Bitte_geben_Sie_einen_Namen_f\u00FCr_die_Gruppe_ein.
+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>=Bitte_geben_Sie_einen_Suchausdruck_ein._Um_zum_Beispiel_alle_Felder_nach_<b>Smith</b>_zu_durchsuchen,_geben_Sie_ein%c<p><tt>smith</tt><p>Um_das_Feld_<b>Author</b>_nach_<b>Smith</b>_und_das_Feld_<b>Title</b>_nach_<b>electrical</b> [...]
+Please_enter_a_semicolon_or_comma_separated_list_of_Medline_IDs_(numbers).=Geben_Sie_bitte_eine_mit_Semikolon_oder_Komma_getrennte_Liste_der_Medline_IDs_(Nummern)_ein.
+Please_enter_the_field_to_search_(e.g._<b>keywords</b>)_and_the_keyword_to_search_it_for_(e.g._<b>electrical</b>).=Bitte_geben_Sie_das_zu_durchsuchende_Feld_(z.B._<b>keywords</b>)_und_das_darin_zu_suchende_Stichwort_(z.B._<b>elektrisch</b>)_ein.
+Please_enter_the_string's_label=Geben_Sie_bitte_den_Namen_des_Strings_ein.
+Please_refer_to_the_JabRef_help_manual_on_using_the_CiteSeer_tools.=Bitte_lesen_Sie_die_JabRef-Hilfe_f\u00FCr_Informationen,_wie_man_die_CiteSeer-Werkzeuge_benutzt.
+Please_select_an_importer=Bitte_Importer_ausw\u00E4hlen
+Please_select_an_importer.=Bitte_Importer_ausw\u00E4hlen.
+Please_select_exactly_one_group_to_move.=Bitte_genau_eine_zu_bewegende_Gruppe_ausw\u00E4hlen.
+Please_wait_until_it_has_finished.=Bitte_warten_Sie,_bis_die_Aktion_beendet_ist.
+Possible_duplicate_entries=M\u00F6gliche_doppelte_Eintr\u00E4ge
+Possible_duplicate_of_existing_entry._Click_to_resolve.=M\u00f6glicherweise_doppelter_Eintrag._Klicken_um_Konflikt_zu_l\u00f6sen
+Preamble=Pr\u00E4ambel
+Preamble_editor,_store_changes=Pr\u00E4ambel-Editor,_\u00C4nderungen_\u00FCbernehmen
+Preferences=Einstellungen
+Preferences_recorded=Einstellungen_ge\u00E4ndert
+Preferences_recorded.=Einstellungen_gespeichert.
+Preserve_formatting_of_non-BibTeX_fields=Formatierung_von_nicht-BibTeX-Feldern_beibehalten
+Preview=Vorschau
+Previous_entry=Vorheriger_Eintrag
+Previous_tab=Vorheriger_Tab
+Primary_sort_criterion=Prim\u00e4res_Sortierkriterium
+Problem_with_parsing_entry=Problem_beim_Analysieren_des_Eintrags
+PS_links=PS_Links
+push_selection_to_lyx=Auswahl_in_LyX_einf\u00FCgen
+Push_selection_to_WinEdt=Auswahl_in_WinEdt_einf\u00FCgen
+Push_to_LyX=In_LyX_einf\u00FCgen
+Push_to_WinEdt=In_WinEdt_einf\u00FCgen
+Pushed_citations_to_WinEdt=Literaturangaben_in_WinEdt_eingef\u00fcgt
+Pushed_the_citations_for_the_following_rows_to=Literaturangaben_der_folgenden_Zeilen_eingef\u00FCgt_in
+Query_author(s)=Autor(en)_abfragen
+Quit=Beenden
+Quit_JabRef=JabRef_beenden
+Quit_synchronization=Synchronisation_beenden
+Raw_source=Importtext
+Really_delete_the_selected=Wirklich_l\u00F6schen:
+Recent_files=Zuletzt_ge\u00F6ffnete_Dateien
+Redo=Wiederholen
+Refer/Endnote=Refer/Endnote
+Reference_database=Referenz-Datenbank
+# The next two lines are used like in "References found: 1  Number of references to fetch?"
+References_found=Literaturangaben_gefunden
+Refine_supergroup:_When_selected,_view_entries_contained_in_both_this_group_and_its_supergroup=Obergruppe_verfeinern:_Wenn_ausgew\u00e4hlt,_werden_Eintr\u00e4ge_aus_dieser_Gruppe_und_ihrer_\u00fcbergeordneten_Gruppe_angezeigt
+Refresh_view=Ansicht_aktualisieren
+Regexp=Regexp
+Regular_Expression=Regul\u00E4rer_Ausdruck
+Remember_these_entry_types?=Diese_Eintragstypen_behalten?
+Remote_operation=Externer_Zugriff
+Remote_server_port=Externer_Server-Port
+Remove=L\u00F6schen
+Remove_all?=Alle_l\u00f6schen?
+Remove_all_subgroups=Untergruppen_entfernen
+Remove_all_subgroups_of_"%0"?=Alle_Untergruppen_von_"%0"_entfernen?
+Remove_double_braces_around_BibTeX_fields_when_loading.=Beim_Laden_doppelte_geschweifte_Klammern_um_BibTeX-Felder_entfernen
+Remove_duplicates=Doppelte_Eintr\u00E4ge_l\u00F6schen
+Remove_entry_from_import=Eintrag_von_Importierung_entfernen
+Remove_entry_type=Eintragstyp_l\u00F6schen
+remove_from_group=aus_der_Gruppe_entfernen
+Remove_from_group=Aus_Gruppe_entfernen
+Remove_group=Gruppe_l\u00F6schen
+Remove_group,_keep_subgroups=Gruppe_l\u00F6schen,_Untergruppen_behalten
+Remove_group_"%0"?=Gruppe_"%0"_l\u00F6schen?
+Remove_group_"%0"_and_its_subgroups?=Gruppe_"%0"_inklusive_Untergruppen_l\u00F6schen?
+remove_group_(keep_subgroups)=Gruppe_l\u00F6schen_(Untergruppen_behalten)
+remove_group_and_subgroups=Gruppe_inklusive_Untergruppen_l\u00F6schen
+Remove_group_and_subgroups=Gruppe_und_Untergruppen_l\u00F6schen
+Remove_old_entry=Alten_Eintrag_entfernen
+Remove_selected_strings=Ausgew\u00E4hlte_Strings_entfernen
+remove_string=String_l\u00F6schen
+remove_string_=String_l\u00F6schen_
+Removed_entry_type.=Eintragstyp_gel\u00F6scht.
+Removed_group=Gruppe_gel\u00F6scht
+Removed_group_"%0".=Gruppe_"%0"_gel\u00F6scht.
+Removed_group_"%0"_and_its_subgroups.=Gruppe_"%0"_inklusive_Untergruppen_gel\u00F6scht.
+Removed_string=String_gel\u00F6scht
+Renamed_string=String_umbenannt
+Repeat_incremental_search=Direkte_Suche_wiederholen
+Replace=Ersetzen
+Replace_string=String_ersetzen
+Replace_with=Ersetzen_mit
+Replaced=Ersetzt:
+Required_fields=Ben\u00F6tigte_Felder
+Reset_all=Alle_zur\u00FCcksetzen
+resolved=davon_aufgel\u00F6st
+Results=Ergebnisse
+Revert_to_original_source=Original_wiederherstellen
+Review=\u00dcberpr\u00fcfung
+Review_changes=\u00c4nderungen_\u00fcberpr\u00fcfen
+Right=Rechts
+RIS=RIS
+Save=Speichern
+Save_before_closing=Speichern_vor_dem_Beenden
+Save_database=Datei_speichern
+Save_database_as_...=Datei_speichern_unter_...
+Save_failed=Fehler_beim_Speichern
+Save_failed_during_backup_creation=W\u00e4hrend_der_Erstellung_des_Backups_ist_das_Speichern_fehlgeschlagen
+Save_failed_while_committing_changes=W\u00e4hrend_die_\u00c4nderungen_\u00fcbermittelt_wurden,_ist_das_Speichern_fehlgeschlagen
+Save_selected_as_...=Auswahl_speichern_unter_...
+Save_session=Sitzung_speichern
+Saved_database=Datei_gespeichert
+Saved_selected_to=Auswahl_gespeichert_unter
+Saved_session=Sitzung_gespeichert
+Saving=Speichere
+Saving_database=Speichere_Datei
+Scan=\u00DCberpr\u00FCfen
+SciFinder=SciFinder
+Search=Suchen
+Search_All_Fields=Durchsuche_alle_Felder
+Search_all_fields=Alle_Felder_durchsuchen
+Search_error=Suchfehler
+Search_expression=Suchausdruck
+Search_for=Suchen_nach
+Search_General_Fields=Allgemeine_Felder_durchsuchen
+Search_general_fields=Allgemeine_Felder_durchsuchen
+Search_Optional_Fields=Optionale_Felder_durchsuchen
+Search_optional_fields=Optionale_Felder_durchsuchen
+Search_Required_Fields=Ben\u00f6tigte_Felder_durchsuchen
+Search_required_fields=Ben\u00f6tigte_Felder_durchsuchen
+Search_Specified_Field(s)=Durchsuche_diese(s)_Feld(er)
+Search_term=Suchbegriff
+Searched_database._Number_of_hits=Datei_durchsucht._Anzahl_der_Treffer
+Searching_for_%0_file=Suche_nach_%0-Datei
+Searching_for_duplicates...=Suche_nach_doppelten_Eintr\u00E4gen...
+Secondary_sort_criterion=Zweites_Sortierkriterium
+Select=Ausw\u00E4hlen
+Select_a_Zip-archive=ZIP-Archiv_ausw\u00E4hlen
+Select_action=Aktion_w\u00e4hlen
+Select_all=Alle_ausw\u00E4hlen
+Select_Classpath_of_New_Importer=Klassenpfad_ausw\u00E4hlen
+Select_encoding=Kodierung_w\u00e4hlen
+Select_entries_in_group_selection=W\u00E4hle_Eintr\u00E4ge_in_Gruppenauswahl
+Select_entry_type=Eintragstyp_ausw\u00E4hlen
+Select_file_from_ZIP-archive=Eintrag_aus_der_ZIP-Archiv_ausw\u00E4hlen
+Select_format=Format_w\u00E4hlen
+Select_matches=Treffer_ausw\u00E4hlen
+Select_matching_entries=Treffer_ausw\u00E4hlen
+Select_new_ImportFormat_Subclass=Klasse_ausw\u00E4hlen
+Select_the_tree_nodes_to_view_and_accept_or_reject_changes=W\u00E4hlen_Sie_die_drei_Knoten_aus,_um_die_\u00C4nderungen_zu_sehen_und_anzunehmen_oder_zu_verwerfen
+Selector_enabled_fields=Felder_mit_Wortliste
+Set_general_fields=Allgemeine_Felder_festlegen
+Set_table_font=Tabellenschriftart_ausw\u00E4hlen
+Set_up_general_fields=Allgemeine_Felder_festlegen
+Settings=Einstellungen
+Setup_selectors=Wortlisten_verwalten
+Short_form=Kurzform
+Shortcut=Tastenk\u00FCrzel
+Show/edit_BibTeX_source=BibTeX_Quelltext_anzeigen
+Show_'Firstname_Lastname'='Vorname_Nachname'_anzeigen
+Show_'Lastname,_Firstname'='Nachname,_Vorname'_anzeigen
+Show_abstract=Zeige_abstract
+Show_BibTeX_source_by_default=Quelltext_standardm\u00E4\u00DFig_anzeigen
+Show_BibTeX_source_panel=BibTeX_Quelltextpanel_anzeigen
+Show_CiteSeer_column=CiteSeer-Spalte_anzeigen
+Show_confirmation_dialog_when_deleting_entries=Dialog_zum_L\u00F6schen_von_Eintr\u00E4gen_anzeigen
+Show_description=Beschreibung_anzeigen
+Show_dynamic_groups_in_<i>italics</i>=Dynamische_Gruppen_<i>kursiv</i>_anzeigen
+Show_entries_*not*_in_group_selection=Zeige_Eintr\u00E4ge,_die_*nicht*_in_der_Gruppenauswahl_sind
+Show_general_fields=Allgemeine_Felder_anzeigen
+Show_groups_matching_all=Gruppen_anzeigen,_die_alle_enthalten
+Show_groups_matching_any=Gruppen_anzeigen,_die_mindestens_einen_enthalten
+Show_icons_for_groups=Gruppen-Icon_anzeigen
+Show_names_unchanged=Namen_unver\u00E4ndert_anzeigen
+Show_one_less_rows=Zeige_eine_Zeile_weniger
+Show_one_more_row=Zeige_eine_Zeile_mehr
+Show_optional_fields=Optionale_Felder_anzeigen
+Show_overlapping_groups=Sich_\u00fcberschneidende_Gruppen_anzeigen
+Show_PDF/PS_column=PDF/PS-Spalte_anzeigen
+Show_required_fields=Ben\u00F6tigte_Felder_anzeigen
+Show_URL/DOI_column=URL/DOI-Spalte_anzeigen
+Show_warning_dialog_when_a_duplicate_BibTeX_key_is_entered=Warnmeldung_anzeigen,_wenn_ein_doppelter_BibTeX-Key_eingegeben_wird.
+Show_warning_dialog_when_an_empty_BibTeX_key_is_entered=Warnung_anzeigen_wenn_ein_leerer_BibTeX-Key_angegeben_wird
+Simple_HTML=Einfaches_HTML
+Sixpack=Sixpack
+Size=Gr\u00F6\u00DFe
+Size_of_groups_interface_(rows)=Gr\u00F6\u00DFe_der_Gruppenansicht_(Reihen)
+Skip=\u00dcberspringen
+Sort_alphabetically=Alphabetisch_sortieren
+Sort_Automatically=Automatisch_sortieren
+Sort_options=Sortieroptionen
+sort_subgroups=Untergruppen_sortieren
+Sorted_all_subgroups_recursively=Alle_Untergruppen_rekursiv_sortiert
+Sorted_all_subgroups_recursively.=Alle_Untergruppen_rekursiv_sortiert.
+Sorted_immediate_subgroups=Direkte_Untergruppen_sortiert
+Sorted_immediate_subgroups.=Alle_direkten_Untergruppen_sortiert.
+source_edit=Quelltextbearbeitung
+Special_table_columns=Spezielle_Spalten
+Start=Starten
+Start_incremental_search=Weitersuchen_(bei_direkter_Suche)
+Start_search=Suche_starten
+Statically_group_entries_by_manual_assignment=Statisches_Gruppieren_der_Eintr\u00E4ge_durch_manuelle_Zuweisung
+Status=Status
+Stop=Stop
+Store=Speichern
+Store_fields_with_double_braces,_and_remove_extra_braces_when_loading.<BR>Double_braces_signal_that_BibTeX_should_preserve_character_case.=Felder_mit_geschweiften_Klammern_speichern_und_\u00fcberz\u00e4hlige_Klammern_beim_Laden_entfernen.<BR>Geschweifte_Klammern_zeigen_an,_dass_BibTeX_die_Gro\u00df-/Kleinschreibung_beibehalten_soll.
+Store_journal_abbreviations=Abk\u00fcrzungen_der_Zeitschriften_speichern
+Store_string=String_speichern
+Store_the_following_fields_with_braces_around_capital_letters=Die_folgenden_Felder_mit_geschweiften_Klammern_um_die_Gro\u00dfbuchstaben_speichern
+Stored_definition_for_type=Typ-Definition_gespeichert
+Stored_entry=Eintrag_gespeichert
+Stored_entry.=Eintrag_gespeichert.
+Strings=Ersetzen
+Strings_for_database=Strings_f\u00FCr_die_Datei
+subdatabase_from_aux=Datenbank_aus_LaTeX_aux
+Subdatabase_from_aux=Teildatenbank_aus_aux-Datei
+Suggest=Vorschlag
+Switch_preview_layout=Layout_der_Vorschau_wechseln
+Synchronize_%0_links=%0-Links_synchronisieren
+Synchronizing_%0_links...=Synchronisiere_%0-Links...
+Table=Tabelle
+Table_appearance=Erscheinungsbild_der_Tabelle
+Table_background_color=Hintergrundfarbe_der_Tabelle
+Table_grid_color=Farbe_des_Tabellenrasters
+Table_text_color=Textfarbe_der_Tabelle
+Tabname=Tab-Name
+Tertiary_sort_criterion=Drittes_Sortierkriterium
+Test=Test
+Text_Input_Area=Text_einf\u00FCgen
+The_#_character_is_not_allowed_in_BibTeX_fields=Das_Zeichen_#_ist_in_BibTeX-Feldern_nicht_erlaubt
+The_chosen_date_format_for_new_entries_is_not_valid=Das_Datumsformat_f\u00fcr_neue_Eintr\u00e4ge_ist_nicht_g\u00fcltig
+The_CiteSeer_fetch_operation_returned_zero_results.=Das_Importieren_von_CiteSeer_ergab_keine_Ergebnisse.
+the_field_<b>%0</b>=das_Feld_<b>%0</b>
+The_file<BR>'%0'<BR>has_been_modified<BR>externally!=Die_Datei<BR>_'%0'_<BR>wurde_von_einem_externen_Programm_ver\u00e4ndert!
+The_group_"%0"_already_contains_the_selection.=Die_Gruppe_"%0"_enth\u00e4lt_bereits_diese_Auswahl.
+The_group_"%0"_does_not_support_the_adding_of_entries.=Die_Gruppe_"%0"_unterst\u00FCtzt_das_manuelle_Hinzuf\u00FCgen_von_Eintr\u00E4gen_nicht.
+The_group_"%0"_does_not_support_the_removal_of_entries.=Die_Gruppe_"%0"_unterst\u00FCtzt_das_manuelle_Entfernen_von_Eintr\u00E4gen_nicht.
+The_label_of_the_string_can_not_be_a_number.=Der_Name_des_Strings_darf_keine_Zahl_sein.
+The_label_of_the_string_can_not_contain_spaces.=Der_Name_des_Strings_darf_keine_Leerzeichen_enthalten.
+The_label_of_the_string_can_not_contain_the_'#'_character.=Der_Name_des_Strings_darf_nicht_das_Zeichen_'#'_enthalten.
+The_output_option_depends_on_a_valid_import_option.=Die_Ausgabe-Option_beruht_auf_einer_g\u00fcltigen_Import-Option.
+The_regular_expression_<b>%0</b>_is_invalid%c=Der_Regul\u00E4re_Ausdruck_<b>%0</b>_ist_ung\u00FCltig%c
+The_search_is_case_insensitive.=Gro\u00DF-/Kleinschreibung_wird_nicht_unterschieden.
+The_search_is_case_sensitive.=Gro\u00DF-/Kleinschreibung_wird_unterschieden.
+The_string_has_been_removed_locally=Der_String_wurde_lokal_entfernt
+The_type_name_can_not_contain_spaces.=Der_Name_des_Typs_darf_keine_Leerzeichen_enthalten.
+The_URL_field_appears_to_be_empty_on_entry_number_=Das_URL-Feld_scheint_leer_zu_sein_bei_Eintrag_Nummer_
+There_are_possible_duplicates_(marked_with_a_'D'_icon)_that_haven't_been_resolved._Continue?=Es_gibt_m\u00f6gliche_Duplikate_(markiert_mit_'D'),_die_nicht_gekl\u00e4rt_werden_konnten._Fortfahren?
+There_is_no_entry_type=Es_exisitiert_kein_Eintragstyp
+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?=Dies_ver\u00E4ndert_das_Feld_"%0"_Ihrer_Eintr\u00E4ge.nDas_k\u00F6nnte_zu_ungewollten_\u00C4nderungen_Ihrer_Eintr\u00E4ge_f\u00FChren.nDeshalb_ist_es_erforderlich,_dass_Sie_in_Ihrer_Gruppendefinition_das_Feld_"keywords"nangeben_oder_einen_Nam [...]
+this_button_will_update=Dieser_Button_\u00E4ndert_die_verwendete<BR>Spaltenbreite_in_der_Tabelle_der_Eintr\u00E4ge
+this_button_will_update_the_column_width_settings<BR>to_match_the_current_widths_in_your_table=diese_Schaltfl\u00E4che_setzt_die_Einstellungen_der_Spaltenbreite<BR>auf_die_aktuellen_Spaltenbreiten_Ihrer_Tabelle
+This_entry_is_incomplete=Dieser_Eintrag_ist_unvollst\u00E4ndig
+This_entry_type_cannot_be_removed.=Dieser_Eintragstyp_kann_nicht_entfernt_werden.
+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.=Diese_Gruppe_enth\u00E4lt_manuell_zugewiesene_Eintr\u00E4ge._Eintr\u00E4ge_k\u00F6nnen_dieser_Gruppe_zugewiesen_werde [...]
+This_group_contains_entries_in_which=Diese_Gruppe_enth\u00E4lt_Eintr\u00E4ge,_bei_denen
+This_group_contains_entries_in_which_any_field_contains_the_regular_expression_<b>%0</b>=Diese_Gruppe_enth\u00E4lt_Eintr\u00E4ge,_in_denen_ein_beliebiges_Feld_den_Regul\u00E4ren_Ausdruck_<b>%0</b>_enth\u00E4lt.
+This_group_contains_entries_in_which_any_field_contains_the_term_<b>%0</b>=Diese_Gruppe_enth\u00E4lt_Eintr\u00E4ge,_in_denen_ein_beliebiges_Feld_den_Ausdruck_<b>%0</b>_enth\u00E4lt.
+This_group_contains_entries_whose_<b>%0</b>_field_contains_the_keyword_<b>%1</b>=Diese_Gruppe_enth\u00e4lt_Eintrage,_deren_Feld_<b>%0</b>_das_Stichwort_<b>%1</b>_enth\u00e4lt
+This_group_contains_entries_whose_<b>%0</b>_field_contains_the_regular_expression_<b>%1</b>=Diese_Gruppe_enth\u00E4lt_Eintrage,_deren_Feld_<b>%0</b>_den_Regul\u00E4ren_Ausdruck_<b>%1</b>_enth\u00E4lt
+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.=Dies_ist_ein_einfacher_Copy_&_Paste-Dialog._F\u00FCgen_sie_zun\u00E4chst_Text_in_das_Eingabefeld_ein._Anschlie\u00DFend_k\u00F6nen_Sie_Textstellen_markieren_und_einem_BibTeX-Feld_zuordnen.
+This_is_a_simple_copy_and_paste_dialog_for_import_some_fields_from_normal_text.=Dies_ist_ein_einfacher_Copy_&_Paste_Dialog_zum_Einf\u00fcgen_von_Feldern_aus_normalem_Text.
+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.=Veranlasst_JabRef_dazu,_jedem_%0-Link_zu_folgen_und_zu_\u00fcberpr\u00fcfen,_ob_die_entsprechende_Datei_existiert._Wenn_nicht,_werden_M\u00f6glichkeiten_angegeben,_das_Problem_zu_l\u00f6sen.
+This_operation_cannot_work_on_multiple_rows.=Diese_Aktion_kann_nicht_mit_mehreren_Zeilen_durchgef\u00FChrt_werden.
+Toggle_abbreviation=Abk\u00fcrzung_an-/abschalten
+Toggle_entry_preview=Eintragsvorschau_ein-/ausblenden
+Toggle_groups_interface=Gruppenansicht_ein-/ausblenden
+Toggle_search_panel=Suchdialog_ein-/ausblenden
+Tools=Extras
+Try_different_encoding=Versuchen_Sie_es_mit_einer_anderen_Kodierung
+Type=Typ
+Type_set_to_'other'=Typ_als_'other'_deklariert
+Unabbreviate_journal_names_of_the_selected_entries=Abk\u00fcrzung_der_Zeitschriftennamen_der_ausgew\u00e4hlten_Eintr\u00e4ge_aufheben
+unable_to_access_LyX-pipe=LyX-pipe_nicht_gefunden
+Unable_to_create_graphical_interface=Grafische_Benutzeroberfl\u00E4che_konnte_nicht_erzeugt_werden
+Unable_to_parse_clipboard_text_as_Bibtex_entries.=Der_Text_der_Zwischenablage_konnte_nicht_als_BibTeX-Format_analysiert_werden.
+Unable_to_parse_the_following_URL=Folgende_URL_konnte_nicht_analysiert_werden
+unable_to_write_to=konnte_nicht_speichern_auf
+Undo=R\u00FCckg\u00E4ngig
+Union=Vereinigung
+unknown_bibtex_entries=unbekannte_BibTeX-Eintr\u00E4ge
+Unknown_bibtex_entries=Fehlende_BibTeX_Eintr\u00E4ge
+unknown_edit=unbekannter_Bearbeitungsschritt
+unknown_entry_type=unbekannter_Eintragstyp
+Unknown_export_format=Unbekanntes_Export-Format
+Unmark_all=S\u00E4mtliche_Markierungen_aufheben
+Unmark_entries=Markierung_aufheben
+Unmark_entry=Markierung_aufheben
+Unmarked_selected=Markierung_f\u00fcr_ausgew\u00e4hlte_Eintr\u00e4ge_aufgehoben
+Unpack_EndNote_filter_set=Entpacke_EndNote_Filter-Set
+Unpacked_file=Entpackte_Datei
+Unpacked_file.=Datei_entpackt.
+Unsupported_version_of_class_%0:_%1=Nicht_unterst\u00FCtzte_Version_der_Klasse_%0:_%1
+untitled=ohne_Titel
+Up=Hoch
+Update_to_current_column_widths=Aktuelle_Spaltenbreiten_verwenden
+Updated_group_selection=Gruppenauswahl_aktualisiert
+Updating_entries...=Eintr\u00E4ge_werden_aktualisiert...
+UPPER=GROSS
+Upper_Each_First=Jeden_Ersten_Gro\u00DF
+Upper_first=Ersten_gro\u00DF
+usage=Benutzung
+Use_antialiasing_font=Antialias-Schrift_benutzen
+Use_antialiasing_font_in_table=Gegl\u00E4ttete_Schriftart_verwenden_(in_der_Tabelle)
+Use_inspection_window_also_when_a_single_entry_is_imported.=Kontrollfenster_benutzen,_auch_wenn_nur_ein_Eintrag_importiert_wird.
+Use_other_look_and_feel=anderes_"look_and_feel"_benutzen
+Use_regular_expressions=Regul\u00E4re_Ausdr\u00FCcke_benutzen
+Use_the_following_delimiter=Benutzen_Sie_das_folgende_Trennzeichen
+Use_the_following_delimiter_character(s)=Folgende(s)_Trennzeichen_benutzen
+Uses_default_application=Benutze_Standardprogramm
+Value_cleared_externally=Wert_extern_gel\u00F6scht
+Value_set_externally=Wert_extern_gesetzt
+verify_that_LyX_is_running_and_that_the_lyxpipe_is_valid=\u00FCberpr\u00FCfen_Sie,_ob_LyX_l\u00E4uft_und_ob_die_Angaben_zur_lyxpipe_stimmen
+View=Ansicht
+Visible_fields=Angezeigte_Felder
+Warn_about_unresolved_duplicates_when_closing_inspection_window=Warnung_zu_ungekl\u00e4rten_Duplikaten_ausgeben,_wenn_das_Kontrollfenster_geschlossen_wird
+Warn_before_overwriting_existing_keys=Vor_dem_\u00dcberschreiben_von_existierenden_Keys_warnen
+Warning=Warnung
+Warning_there_is_a_duplicate_key=Achtung!_Es_ist_ein_doppelter_Key_vorhanden
+Warnings=Warnungen
+web_link=Web-Link
+When_adding/removing_keywords,_separate_them_by=Beim_Hinzuf\u00fcgen_oder_L\u00f6schen_von_Stichw\u00f6rtern_folgendes_Trennzeichen_benutzen
+with=mit
+Word=Wort
+Wrong_file_format=Falsches_Dateiformat
+You_have_changed_the_language_setting._You_must_restart_JabRef_for_this_to_come_into_effect.=Sie_haben_die_Spracheinstellung_ge\u00E4ndert._Sie_m\u00FCssen_JabRef_neu_starten,_damit_die_\u00C4nderungen_in_Kraft_treten.
+You_have_cleared_this_field._Original_value=Sie_haben_dieses_Feld_gel\u00F6scht._Urspr\u00FCnglicher_Wert
+You_must_choose_a_file_name_to_store_journal_abbreviations=Sie_m\u00fcssen_einen_Dateinamen_w\u00e4hlen,_um_die_Abk\u00fcrzungen_der_Zeitschriften_zu_speichern
+You_must_enter_an_integer_value_in_the_text_field_for=Sie_m\u00fcssen_eine_Ganzzahl_verwenden_im_Textfeld_f\u00fcr
+You_must_fill_in_a_name_for_the_entry_type.=Sie_m\u00FCssen_einen_Namen_f\u00FCr_den_Eintragstyp_eingeben.
+You_must_provide_a_name,_a_search_string_and_a_field_name_for_this_group.=Sie_m\u00FCssen_einen_Namen,_einen_Suchbegriff_und_einen_Feldnamen_f\u00FCr_die_Gruppe_angeben.
+You_must_restart_JabRef_for_the_new_key_bindings_to_work_properly.=Sie_m\u00FCssen_JabRef_neu_starten,_damit_die_Tastenk\u00FCrzel_funktionieren.
+You_must_select_a_row_to_perform_this_operation.=Sie_m\u00FCssen_eine_Zeile_ausw\u00E4hlen,_um_diese_Aktion_durchf\u00FChren_zu_k\u00F6nnen.
+You_must_select_at_least_one_row_to_perform_this_operation.=Sie_m\u00FCssen_mindestens_eine_Zeile_ausw\u00E4hlen,_um_diesen_Vorgang_durchzuf\u00FChren.
+You_must_set_both_BibTeX_key_and_%0_directory=Sie_m\u00FCssen_sowohl_den_BibTeX-Key_als_auch_den_%0-Ordner_angeben
+You_must_set_both_bibtex_key_and_PDF_directory=Sie_m\u00fcssen_sowohl_den_BibTeX-Key,_als_auch_das_PDF-Verzeichnis_angeben
+Your_new_key_bindings_have_been_stored.=Ihre_neuen_Tastenk\u00FCrzel_wurden_gespeichert.
+Arguments_passed_on_to_running_JabRef_instance._Shutting_down.=Argumente_wurden_der_laufenden_JabRef-Instanz_\u00fcbergeben._Schlie\u00dfen_l\u00e4uft.
+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').=Konnte_zu_keinem_aktiven_gnuserv-Prozess_verbinden._Vergewissern_Sie_sich,_dass_(X)Emacs_l\u00e4uft,<BR>und_dass_der_Server_gestartet_wurde_(mit_dem_Befehl_'gnuserv-start').
+Push_selection_to_Emacs=Auswahl_in_Emacs_einf\u00fcgen
+Pushed_citations_to_Emacs=Literaturangaben_in_Emacs_eingef\u00fcgt
+Filter=Filter
+Hide_non-matching_entries=Nicht-Treffer_ausblenden
+Replace_(regular_expression)=Ersetzen_(Regul\u00e4rer_Ausdruck)
+Cite_command_(for_Emacs/WinEdt)=Cite-Kommando_(f\u00fcr_Emacs/WinEdt)
+Could_not_instantiate_%0_%1._Have_you_chosen_the_correct_package_path?=Konnte_%0_%1_nicht_realisieren._Haben_Sie_den_richtigen_Paket-Pfad_angegeben?
+No_entries_found._Please_make_sure_you_are_using_the_correct_import_filter.=Keine_Eintr\u00e4ge_gefunden._Bitte_vergewissern_Sie_sich,_dass_Sie_den_richtigen_Importfilter_benutzen.
+
+#### These lines were changed:
+Switches_between_full_and_abbreviated_journal_name_if_the_journal_name_is_known.=
+To_set_up,_go_to_<B>Tools_->_Manage_journal_abbreviations</B>=
+#####Switches_between_full_and_abbreviated_journal_name=Wechselt_zwischen_kompletten_und_abgek\u00fcrzten_Zeitschriftennamen
+#####if_the_journal_name_is_known._Go_to_(...............)=falls_der_Zeitschriftenname_bekannt_ist._Gehe_zu_(...............)
+
+Could_not_run_the_'gnuclient'_program._Make_sure_you_have_the_gnuserv/gnuclient_programs_installed.=
diff --git a/src/resource/JabRef_en.properties b/src/resource/JabRef_en.properties
new file mode 100644
index 0000000..efc8f66
--- /dev/null
+++ b/src/resource/JabRef_en.properties
@@ -0,0 +1,1036 @@
+#! created/edited by Popeye version 0.51 sunshine (popeye.sourceforge.net)
+
+!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.=!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.
+%0_contains_the_Regular_Expression_<b>%1</b>=%0_contains_the_Regular_Expression_<b>%1</b>
+%0_contains_the_term_<b>%1</b>=%0_contains_the_term_<b>%1</b>
+%0_doesn't_contain_the_Regular_Expression_<b>%1</b>=%0_doesn't_contain_the_Regular_Expression_<b>%1</b>
+%0_doesn't_contain_the_term_<b>%1</b>=%0_doesn't_contain_the_term_<b>%1</b>
+%0_doesn't_match_the_Regular_Expression_<b>%1</b>=%0_doesn't_match_the_Regular_Expression_<b>%1</b>
+%0_doesn't_match_the_term_<b>%1</b>=%0_doesn't_match_the_term_<b>%1</b>
+%0_field_set=%0_field_set
+%0_import_cancelled.=%0_import_cancelled.
+%0_matches_the_Regular_Expression_<b>%1</b>=%0_matches_the_Regular_Expression_<b>%1</b>
+%0_matches_the_term_<b>%1</b>=%0_matches_the_term_<b>%1</b>
+<field_name>=<field_name>
+<HTML>Unpack_the_zip_file_containing_import/export_filters_for_Endnote,<BR>for_optimal_interoperability_with_JabRef</HTML>=<HTML>Unpack_the_zip_file_containing_import/export_filters_for_Endnote,<BR>for_optimal_interoperability_with_JabRef</HTML>
+<no_field>=<no_field>
+<select>=<select>
+<select_word>=<select_word>
+_on_entry_number_=_on_entry_number_
+A_CiteSeer_fetch_operation_is_currently_in_progress.=A_CiteSeer_fetch_operation_is_currently_in_progress.
+A_CiteSeer_import_operation_is_currently_in_progress.=A_CiteSeer_import_operation_is_currently_in_progress.
+A_string_with_that_label_already_exists=A_string_with_that_label_already_exists
+About_JabRef=About_JabRef
+Abstract=Abstract
+Accept=Accept
+Accept_change=Accept_change
+Action=Action
+Add=Add
+add_entries_to_group=add_entries_to_group
+add_group=add_group
+Add_Group=Add_group
+Add_new=Add_new
+Add_Subgroup=Add_subgroup
+Add_to_group=Add_to_group
+Added_entry=Added_entry
+Added_group=Added_group
+Added_group_"%0".=Added_group_"%0".
+Added_new=Added_new
+Added_string=Added_string
+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.=Additionally,_entries_whose_<b>%0</b>_field_does_not_contain_<b>%1</b>_ [...]
+Advanced=Advanced
+Advanced_options_for_setting...=Advanced_options_for_setting...
+All_Entries=All_Entries
+All_entries=All_entries
+All_entries_of_this_type_will_be_declared_typeless._Continue?=All_entries_of_this_type_will_be_declared_typeless._Continue?
+All_fields=All_fields
+All_subgroups_(recursively)=All_subgroups_(recursively)
+Allow_editing_in_table_cells=Allow_editing_in_table_cells
+Always_save_database_ordered_by_author_name=Always_save_database_ordered_by_author_name
+and=and
+and_the_class_must_be_available_in_your_classpath_next_time_you_start_JabRef.=and_the_class_must_be_available_in_your_classpath_next_time_you_start_JabRef.
+any_field_that_matches_the_regular_expression_<b>%0</b>=any_field_that_matches_the_Regular_Expression_<b>%0</b>
+Appearance=Appearance
+Append=Append
+Append_contents_from_a_BibTeX_database_into_the_currently_viewed_database=Append_contents_from_a_BibTeX_database_into_the_currently_viewed_database
+Append_database=Append_database
+append_the_selected_text_to_bibtex_key=append_the_selected_text_to_bibtex_key
+Apply=Apply
+Assign_entries_based_on:=Assign_entries_based_on:
+Assign_new_file=Assign_new_file
+Assign_the_original_group's_entries_to_this_group?=Assign_the_original_group's_entries_to_this_group?
+Assigned_%0_entries_to_group_"%1".=Assigned_%0_entries_to_group_"%1".
+Assigned_1_entry_to_group_"%0".=Assigned_1_entry_to_group_"%0".
+Attach_%0_file=Attach_%0_file
+Attach_URL=Attach_URL
+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.=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.
+Auto=Auto
+Autodetect_format=Autodetect_format
+Autogenerate_BibTeX_key=Autogenerate_BibTeX_key
+Autogenerate_BibTeX_keys=Autogenerate_BibTeX_keys
+Autogenerate_groups=Autogenerate_groups
+autogenerate_keys=autogenerate_keys
+Automatically_create_groups=Automatically_create_groups
+Automatically_create_groups_for_database.=Automatically_create_groups_for_database.
+Automatically_created_groups=Automatically_created_groups
+Automatically_hide_groups_interface_when_switching_to_a_database_that_contains_no_groups=Automatically_hide_groups_interface_when_switching_to_a_database_that_contains_no_groups
+Automatically_show_groups_interface_when_switching_to_a_database_that_contains_groups=Automatically_show_groups_interface_when_switching_to_a_database_that_contains_groups
+Autoset=Autoset
+Autoset_%0_field=Autoset_%0_field
+Autoset_%0_links._Allow_overwriting_existing_links.=Autoset_%0_links._Allow_overwriting_existing_links.
+Autoset_%0_links._Do_not_overwrite_existing_links.=Autoset_%0_links._Do_not_overwrite_existing_links.
+Autosetting_%0_field...=Autosetting_%0_field...
+AUX_File_import=generate_subdatabase_from_aux
+AUX_file_import=AUX_file_import
+Available_export_formats=Available_export_formats
+Available_fields=Allowed_BibTeX_fields
+Available_import_formats=Available_import_formats
+Backup_old_file_when_saving=Backup_old_file_when_saving
+Bibkey_to_filename_conversion=Bibkey_to_filename_conversion
+Biblioscape_Tag_file=Biblioscape_Tag_file
+BibTeX=BibTeX
+BibTeX_key=BibTeX_key
+BibTeX_key_is_unique.=BibTeX_key_is_unique.
+BibTeX_key_not_set._Enter_a_name_for_the_downloaded_file=BibTeX_key_not_set._Enter_a_name_for_the_downloaded_file
+BibTeX_source=BibTeX_source
+BibTeXML=BibTeXML
+BibTeXML_File=BibTeXML_File
+Binding=Binding
+Broken_link=Broken_link
+Browse=Browse
+by=by
+Calling_external_viewer...=Calling_external_viewer...
+Cancel=Cancel
+Cannot_add_entries_to_group_without_generating_keys._Generate_keys_now?=Cannot_add_entries_to_group_without_generating_keys._Generate_keys_now?
+Cannot_merge_this_change=Cannot_merge_this_change
+Cannot_move_group=Cannot_move_group
+Cannot_move_group_"%0"_down.=Cannot_move_group_"%0"_down.
+Cannot_move_group_"%0"_left.=Cannot_move_group_"%0"_left.
+Cannot_move_group_"%0"_right.=Cannot_move_group_"%0"_right.
+Cannot_move_group_"%0"_up.=Cannot_move_group_"%0"_up.
+case_insensitive=case_insensitive
+case_sensitive=case_sensitive
+Case_sensitive=Case_sensitive
+change_assignment_of_entries=change_assignment_of_entries
+Change_case=Change_case
+Change_entry_type=Change_entry_type
+change_key=change_key
+Change_of_Grouping_Method=Change_of_Grouping_Method
+change_preamble=change_preamble
+change_string_content=change_string_content
+change_string_name=change_string_name
+change_type=change_type
+changed_=changed_
+Changed_font_settings=Changed_font_settings
+Changed_language_settings=Changed_language_settings
+Changed_look_and_feel_settings=Changed_look_and_feel_settings
+Changed_preamble=Changed_preamble
+Changed_type_to=Changed_type_to
+Characters_to_ignore=Characters_to_ignore
+Check_existing_%0_links=Check_existing_%0_links
+Check_links=Check_links
+Citation_import_from_CiteSeer_failed.=Citation_import_from_CiteSeer_failed.
+CiteSeer_Error=CiteSeer_Error
+CiteSeer_Fetch_Error=CiteSeer_Fetch_Error
+CiteSeer_import_entries=CiteSeer_import_entries
+CiteSeer_Import_Error=CiteSeer_Import_Error
+CiteSeer_Import_Fields=CiteSeer_Import_Fields
+CiteSeer_Transfer=CiteSeer_Transfer
+CiteSeer_Warning=CiteSeer_Warning
+Class_name=Class_name
+Clear=Clear
+clear_all_groups=clear_all_groups
+Clear_field=Clear_field
+Clear_highlight=Clear_highlight
+Clear_highlighted=Clear_highlighted
+Clear_highlighted_groups=Clear_highlighted_groups
+Clear_inputarea=Clear_text_input_area
+Clear_search=Clear_search
+Close=Close
+Close_database=Close_database
+Close_dialog=Close_dialog
+# The following lines correspond to names of key bindings:
+Close_entry_editor=Close_entry_editor
+Close_preamble_editor=Close_preamble_editor
+Close_the_current_database=Close_the_current_database
+Close_the_help_window=Close_the_help_window
+Close_window=Close_window
+Closed_database=Closed_database
+Collapse_subtree=Collapse_subtree
+Color_codes_for_required_and_optional_fields=Color_codes_for_required_and_optional_fields
+Column_width=Column_width
+Complete_record=Complete_record
+Completed_citation_import_from_CiteSeer.=Completed_citation_import_from_CiteSeer.
+Completed_Import_Fields_from_CiteSeer.=Completed_Import_Fields_from_CiteSeer.
+Completed_import_from_CiteSeer.=Completed_import_from_CiteSeer.
+Content=Content
+Copied=Copied
+Copied_cell_contents=Copied_cell_contents
+Copied_key=Copied_key
+Copied_keys=Copied_keys
+Copy=Copy
+Copy_BibTeX_key=Copy_BibTeX_key
+Copy_\\cite{BibTeX_key}=Copy_cite\\{BibTeX_key}
+Copy_to_clipboard=Copy_to_clipboard
+Could_not_call_executable=Could_not_call_executable
+Could_not_connect_to_host=Could_not_connect_to_host
+Could_not_connect_to_host_=Could_not_connect_to_host_
+Could_not_export_entry_types=Could_not_export_entry_types
+Could_not_export_file=Could_not_export_file
+Could_not_export_preferences=Could_not_export_preferences
+Could_not_find_a_suitable_import_format.=Could_not_find_a_suitable_import_format.
+Could_not_find_layout_file=Could_not_find_layout_file
+Could_not_import_entry_types=Could_not_import_entry_types
+Could_not_import_preferences=Could_not_import_preferences
+Could_not_resolve_import_format=Could_not_resolve_import_format
+Could_not_save_file=Could_not_save_file
+Couldn't_find_an_entry_associated_with_this_URL=Couldn't_find_an_entry_associated_with_this_URL
+Couldn't_parse_the_'citeseerurl'_field_of_the_following_entries=Couldn't_parse_the_'citeseerurl'_field_of_the_following_entries
+Create_group=Create_group
+Created_group=Created_group
+Created_group_"%0".=Created_group_"%0".
+Created_groups.=Created_groups.
+Curly_braces_{_and_}_must_be_balanced.=Curly_braces_{_and_}_must_be_balanced.
+Current_content=Current_content
+Current_value=Current_value
+Custom_entry_types=Custom_entry_types
+Custom_entry_types_found_in_file=Custom_entry_types_found_in_file
+Custom_export=Custom_export
+Customize_entry_types=Customize_entry_types
+Customize_key_bindings=Customize_key_bindings
+Cut=Cut
+cut_entries=cut_entries
+cut_entry=cut_entry
+Cut_pr=Cut
+Database_has_changed._Do_you_want_to_save_before_closing?=Database_has_changed._Do_you_want_to_save_before_closing?
+Date_format=Date_format
+Default=Default
+Default_encoding=Default_encoding
+Default_grouping_field=Default_grouping_field
+Default_look_and_feel=Default_look_and_feel
+Default_owner=Default_owner
+Default_pattern=Default_pattern
+defined.=defined.
+Delete=Delete
+Delete_custom=Delete_custom
+Delete_custom_format=Delete_custom_format
+delete_entries=delete_entries
+Delete_entry=Delete_entry
+delete_entry=delete_entry
+Delete_multiple_entries=Delete_multiple_entries
+Delete_rows=Delete_rows
+Delete_strings=Delete_strings
+Deleted=Deleted
+Deleted_entry=Deleted_entry
+Delimit_fields_with_semicolon,_ex.=Delimit_fields_with_semicolon,_ex.
+Descending=Descending
+Description=Description
+Deselect_all=Deselect_all
+Details=Details
+Disable_entry_editor_when_multiple_entries_are_selected=Disable_entry_editor_when_multiple_entries_are_selected
+Disable_this_confirmation_dialog=Disable_this_confirmation_dialog
+Disable_this_warning_dialog=Disable_this_warning_dialog
+Display_all_entries_belonging_to_one_or_more_of_the_selected_groups.=Display_all_entries_belonging_to_one_or_more_of_the_selected_groups.
+Display_help_on_command_line_options=Display_help_on_command_line_options
+Display_imported_entries_in_an_inspection_window_before_they_are_added.=Display_imported_entries_in_an_inspection_window_before_they_are_added.
+Display_only_entries_belonging_to_all_selected_groups.=Display_only_entries_belonging_to_all_selected_groups.
+Displaying_no_groups=Displaying_no_groups
+Do_not_autoset=Do_not_autoset
+Do_not_import_entry=Do_not_import_entry
+Do_not_open_any_files_at_startup=Do_not_open_any_files_at_startup
+Do_not_overwrite_existing_keys=Do_not_overwrite_existing_keys
+Docbook=Docbook
+Done=Done
+Down=Down
+Download=Download
+Download_completed=Download_completed
+Download_file=Download_file
+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.=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.
+dummy=dummy
+Duplicate_BibTeX_key=duplicate_BibTeX_key
+duplicate_BibTeX_key=duplicate_BibTeX_key
+Duplicate_BibTeX_key.=Duplicate_BibTeX_key.
+duplicate_BibTeX_key.=duplicate_BibTeX_key.
+Duplicate_BibTeX_key._Grouping_may_not_work_for_this_entry.=Duplicate_BibTeX_key._Grouping_may_not_work_for_this_entry.
+Duplicate_Key_Warning=Duplicate_Key_Warning
+Duplicate_pairs_found=Duplicate_pairs_found
+duplicate_removal=duplicate_removal
+Duplicate_string_name=Duplicate_string_name
+Duplicates_found=Duplicates_found
+Duplicates_removed=Duplicates_removed
+Dynamic_groups=Dynamic_groups
+Dynamically_group_entries_by_a_free-form_search_expression=Dynamically_group_entries_by_a_free-form_search_expression
+Dynamically_group_entries_by_searching_a_field_for_a_keyword=Dynamically_group_entries_by_searching_a_field_for_a_keyword
+Each_line_must_be_on_the_following_form=Each_line_must_be_on_the_following_form
+Edit=Edit
+Edit_custom_export=Edit_custom_export
+Edit_entry=Edit_entry
+Edit_group=Edit_Group
+Edit_preamble=Edit_preamble
+Edit_strings=Edit_strings
+empty_BibTeX_key=empty_BibTeX_key
+Empty_BibTeX_key.=Empty_BibTeX_key.
+Empty_BibTeX_key._Grouping_may_not_work_for_this_entry.=Empty_BibTeX_key._Grouping_may_not_work_for_this_entry.
+Empty_database=Empty_database
+empty_database=empty_database
+Enable source_editing=Enable source_editing
+Enable_source_editing=Enable_source_editing
+Endnote=Endnote
+Enter_URL=Enter_URL
+Enter_URL_to_download=Enter_URL_to_download
+entries=entries
+Entries_cannot_be_manually_assigned_to_or_removed_from_this_group.=Entries_cannot_be_manually_assigned_to_or_removed_from_this_group.
+Entries_exported_to_clipboard=Entries_exported_to_clipboard
+entries_have_undefined_BibTeX_key=entries_have_undefined_BibTeX_key
+entries_into_new_database=entries_into_new_database
+entry=entry
+Entry_editor=Entry_editor
+# The following lines correspond to names of key bindings:
+Entry_editor,_next_entry=Entry_editor,_next_entry
+Entry_editor,_next_panel=Entry_editor,_next_panel
+Entry_editor,_previous_entry=Entry_editor,_previous_entry
+Entry_editor,_previous_panel=Entry_editor,_previous_panel
+Entry_editor,_store_field=Entry_editor,_store_field
+Entry_in_current_database=Entry_in_current_database
+Entry_in_import=Entry_in_import
+Entry_is_incomplete=Entry_is_incomplete
+Entry_preview=Entry_preview
+Entry_table=Entry_table
+Entry_table_columns=Entry_table_columns
+Entry_type=Entry_type
+Entry_type_names_are_not_allowed_to_contain_white_space_or_the_following_characters=Entry_type_names_are_not_allowed_to_contain_white_space_or_the_following_characters
+Entry_types=Entry_types
+EOF_in_mid-string=EOF_in_mid-string
+Error=Error
+##Error:_check_your_External_viewer_settings_in_Preferences=Error:_check_your_External_viewer_settings_in_Preferences
+Error_in_field=Error_in_field
+Error_in_line=Error_in_line
+Error_opening_file=Error_opening_file
+Error_setting_field=Error_setting_field
+exists._Overwrite?=exists._Overwrite?
+exists._Overwrite_file?=exists._Overwrite_file?
+Exit=Exit
+Expand_subtree=Expand_subtree
+Explicit=Explicit
+#previous entry not translated. To view it, open Group interface and click on the "new group" button
+Export=Export
+Export_entry_types=Export_entry_types
+Export_name=Export_name
+Export_preferences=Export_preferences
+Export_preferences_to_file=Export_preferences_to_file
+Export_properties=Export_properties
+Export_selected_to_clipboard=Export_selected_to_clipboard
+Export_to_clipboard=Export_to_clipboard
+Exported_database_to_file=Exported_database_to_file
+Exporting=Exporting
+External_changes=External_changes
+External_programs=External_programs
+External_viewer_called=External_viewer_called
+Failed_to_read_groups_data_(unsupported_version:_%0)=Failed_to_read_groups_data_(unsupported_version:_%0)
+Fetch=Fetch
+Fetch_Articles_Citing_your_Database=Fetch_Articles_Citing_your_Database
+Fetch_Citations_from_CiteSeer=Fetch_Citations_from_CiteSeer
+Fetch_citations_from_CiteSeer=Fetch_citations_from_CiteSeer
+Fetch_CiteSeer=Fetch_CiteSeer
+Fetch_Medline=Fetch_Medline
+fetch_Medline=fetch_Medline
+Fetch_Medline_by_author=Fetch_Medline_by_author
+Fetch_Medline_by_ID=Fetch_Medline_by_ID
+Fetched_all_citations_from_target_database.=Fetched_all_citations_from_target_database.
+Fetching_Citations=Fetching_Citations
+Fetching_Identifiers=Fetching_Identifiers
+Fetching_Medline...=Fetching_Medline...
+Fetching_Medline_by_ID...=Fetching_Medline_by_ID...
+Fetching_Medline_by_id_...=Fetching_Medline_by_id_...
+Fetching_Medline_by_term_...=Fetching_Medline_by_term_...
+Field=Field
+field=field
+# 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=Field_content
+Field_name=Field_name
+Field_names_are_not_allowed_to_contain_white_space_or_the_following_characters=Field_names_are_not_allowed_to_contain_white_space_or_the_following_characters
+Field_sizes=Field_sizes
+Field_to_group_by=Field_to_group_by
+Field_to_search=Field_to_search
+Fields=Fields
+File=File
+file=file
+File_changed=File_changed
+File_extension=File_extension
+File_has_been_updated_externally._Are_you_sure_you_want_to_save?=File_has_been_updated_externally._Are_you_sure_you_want_to_save?
+File_not_found=File_not_found
+File_updated_externally=File_updated_externally
+filename=filename
+Files_opened=Files_opened
+Find_duplicates=Find_duplicates
+Finished_autosetting_%0_field._Entries_changed:_%1.=Finished_autosetting_%0_field._Entries_changed:_%1.
+Finished_synchronizing_%0_links._Entries_changed%c_%1.=Finished_synchronizing_%0_links._Entries_changed%c_%1.
+First_select_the_entries_you_want_keys_to_be_generated_for.=First_select_the_entries_you_want_keys_to_be_generated_for.
+Fit_table_horizontally_on_screen=Fit_table_horizontally_on_screen
+Float=Float
+Font_Family=Font_Family
+Font_Preview=Font_Preview
+Font_Size=Font_Size
+Font_Style=Font_Style
+FontSelector=FontSelector
+for=for
+Format_of_author_and_editor_names=Format_of_author_and_editor_names
+Format_used=Format_used
+Formatter_not_found=Formatter_not_found
+found=found
+found_in_aux_file=found_in_aux_file
+General=General
+General_fields=General_fields
+Generate=Generate
+Generate_BibTeX_key=Generate_BibTeX_key
+Generate_keys=Generate_keys
+Generate_now=Generate_now
+Generated_BibTeX_key_for=Generated_BibTeX_key_for
+Generating_BibTeX_key_for=Generating_BibTeX_key_for
+Grab=Grab
+Gray_out_entries_not_in_group_selection=Gray_out_entries_not_in_group_selection
+Gray_out_non-hits=Gray_out_non-hits
+Gray_out_non-matching_entries=Gray_out_non-matching_entries
+Group_definitions_have_been_converted_to_JabRef_1.7_format.=Group_definitions_have_been_converted_to_JabRef_1.7_format.
+Group_name=Group_name
+Group_properties=Group_properties
+Groups=Groups
+Harvard_RTF=Harvard_RTF
+Help=Help
+Help_contents=Help_contents
+Help_on_groups=Help_on_groups
+Help_on_key_patterns=Help_on_key_patterns
+Hide_non-hits=Hide_non-hits
+Highlight=Highlight
+Highlight_groups_matching_all_selected_entries=Highlight_groups_matching_all_selected_entries
+Highlight_groups_matching_any_selected_entry=Highlight_groups_matching_any_selected_entry
+Highlight_groups_that_contain_entries_contained_in_any_currently_selected_group=Highlight_groups_that_contain_entries_contained_in_any_currently_selected_group
+Highlight_overlapping_groups=Highlight_overlapping_groups
+Hint%c_To_search_specific_fields_only,_enter_for_example%c<p><tt>author%esmith_and_title%eelectrical</tt>=Hint%c_To_search_specific_fields_only,_enter_for_example%c<p><tt>author%esmith_and_title%eelectrical</tt>
+HTML=HTML
+Ignore=Ignore
+Illegal_type_name=Illegal_type_name
+Immediate_subgroups=Immediate_subgroups
+Import=Import
+Import_and_append=Import_and_append
+Import_and_keep_old_entry=Import_and_keep_old_entry
+Import_and_remove_old_entry=Import_and_remove_old_entry
+Import_cancelled.=Import_cancelled.
+Import_Data_from_CiteSeer=Import_Data_from_CiteSeer
+Import_Data_from_CiteSeer_Database=Import_Data_from_CiteSeer_Database
+Import_database=Import_database
+Import_entries=Import_entries
+Import_entry_types=Import_entry_types
+Import_failed=Import_failed
+Import_Fields_from_CiteSeer=Import_Fields_from_CiteSeer
+# I have reformulated the following lines, because the 1st person form is not suitable:
+# (Folgende_URL_konnte_nicht_analysiert_werden)
+Import_fields_from_CiteSeer=Import_fields_from_CiteSeer
+Import_fields_from_CiteSeer_Database=Import_fields_from_CiteSeer_Database
+Import_Fields_from_CiteSeer_Database=Import_Fields_from_CiteSeer_Database
+Import_file=Import_file
+Import_group_definitions=Import_group_definitions
+Import_plain_text=Import_fields_from_plain_text
+Import_preferences=Import_preferences
+Import_preferences_from_file=Import_preferences_from_file
+Import_strings=Import_strings
+Import_to_open_tab=Import_to_open_tab
+Import_word_selector_definitions=Import_word_selector_definitions
+Imported_database=Imported_database
+Imported_entries=Imported_entries
+Imported_entry_types=Imported_entry_types
+Imported_file=Imported_file
+Imported_from_database=Imported_from_database
+Importing=Importing
+Importing_file=Importing_file
+Importing_in_unknown_format=Importing_in_unknown_format
+In_JabRef,_use_pairs_of_#_characters_to_indicate_a_string.=In_JabRef,_use_pairs_of_#_characters_to_indicate_a_string.
+Include_subgroups=Include_subgroups
+Include_subgroups\:_When_selected,_view_entries_contained_in_this_group_or_its_subgroups=Include_subgroups:_When_selected,_view_entries_contained_in_this_group_or_its_subgroups
+Incremental=Incremental
+Incremental_search=Incremental_search
+Incremental_search_failed._Repeat_to_search_from_top.=Incremental_search_failed._Repeat_to_search_from_top.
+Independent=Independent
+Independent_group\:_When_selected,_view_only_this_group's_entries=Independent_group:_When_selected,_view_only_this_group's_entries
+Initially_show_groups_tree_expanded=Initially_show_groups_tree_expanded
+Input=Work_options
+Input_error=Input_error
+Insert=Insert
+Insert_rows=Insert_rows
+Insert_selected_citations_into_LyX/Kile=Insert_selected_citations_into_LyX/Kile
+Insert_selected_citations_into_WinEdt=Insert_selected_citations_into_WinEdt
+insert_string_=insert_string_
+Insert_URL=Insert_URL
+INSPEC=INSPEC
+integrity=integrity
+# 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=Integrity_check
+Intersection=Intersection
+Intersection_with_supergroups=Intersection_with_supergroups
+Invalid_BibTeX_key=Invalid_BibTeX_key
+Invalid_URL=Invalid_URL
+Inverted=Inverted
+is_a_standard_type.=is_a_standard_type.
+ISI=ISI
+Item_list_for_field=Item_list_for_field
+JabRef_help=JabRef_help
+JabRef_preferences=JabRef_preferences
+JStor_file=JStor_file
+Keep=Keep
+Keep_both=Keep_both
+Keep_lower=Keep_lower
+Keep_upper=Keep_upper
+Key_bindings=Key_bindings
+Key_bindings_changed=Key_bindings_changed
+Key_generator_settings=Key_generator_settings
+Key_pattern=Key_pattern
+keys_in_database=keys_in_database
+#not translated. To view it, use menu "Tools|New BibTeX file from AUx file", and launch the action on a non-existant aux file.
+Keyword=Keyword
+Label=Label
+Language=Language
+Latex_AUX_file=LaTeX_AUX_file
+LaTeX_AUX_file=LaTeX_AUX_file
+Left=Left
+License=License
+Limit_to_fields=Limit_to_fields
+Limit_to_selected_entries=Limit_to_selected_entries
+Listen_for_remote_operation_on_port=Listen_for_remote_operation_on_port
+Load_session=Load_session
+Loading_session...=Loading_session...
+Look_and_feel=Look_and_feel
+lower=lower
+Main_layout_file=Main_layout_file
+Main_PDF_directory=Main_PDF_directory
+Main_PS_directory=Main_PS_directory
+Manage=Manage
+Manage_content_selectors=Manage_content_selectors
+Manage_custom_exports=Manage_custom_exports
+Mark_entries=Mark_entries
+Mark_entry=Mark_entry
+Mark_new_entries_with_addition_date=Mark_new_entries_with_addition_date
+Mark_new_entries_with_owner_name=Mark_new_entries_with_owner_name
+Marked_selected=Marked_selected
+Medline_entries_fetched=Medline_entries_fetched
+Medline_XML=Medline_XML
+Medline_XML_File=Medline_XML_File
+Menu_and_label_font_size=Menu_and_label_font_size
+Merged_external_changes=Merged_external_changes
+messages=messages
+Messages=Messages
+Messages_and_Hints=Hints_and_Warnings
+Miscellaneous=Miscellaneous
+Modification_of_field=Modification_of_field
+Modified_group_"%0".=Modified_group_"%0".
+Modified_groups=Modified_groups
+Modified_groups_tree=Modified_groups_tree
+Modified_string=Modified_string
+Modify=Modify
+modify_group=modify_group
+MODS=MODS
+Move=Move
+Move_down=Move_down
+Move_entries_in_group_selection_to_the_top=Move_entries_in_group_selection_to_the_top
+move_group=move_group
+Move_matching_entries_to_the_top=Move_matching_entries_to_the_top
+Move_string_down=Move_string_down
+Move_string_up=Move_string_up
+Move_up=Move_up
+Moved_Group=Moved_Group
+Moved_group_"%0".=Moved_group_"%0".
+Name=Name
+Ne_entries_imported.=Ne_entries_imported.
+nested_aux_files=nested_aux_files
+New=New
+new=new
+New_article=New_article
+New_BibTeX_database=New_BibTeX_database
+New_BibTeX_entry=New_BibTeX_entry
+New_BibTeX_subdatabase=New_BibTeX_subdatabase
+New_book=New_book
+New_content=New_content
+New_database=New_database
+New_database_created.=New_database_created.
+New_entry=New_entry
+New_entry...=New_entry...
+New_entry_from_plain_text=New_entry_from_plain_text
+New_group=New_group
+New_inbook=New_inbook
+New_mastersthesis=New_mastersthesis
+New_phdthesis=New_phdthesis
+New_proceedings=New_proceedings
+New_string=New_string
+New_subdatabase=New_subdatabase
+New_subdatabase_based_on_AUX_file=New_subdatabase_based_on_AUX_file
+New_unpublished=New_unpublished
+Next_entry=Next_entry
+Next_tab=Next_tab
+No_%0_found=No_%0_found
+No_actual_changes_found.=No_actual_changes_found.
+no_base-bibtex-file_specified=no_base-bibtex-file_specified!
+no_database_generated=no_database_generated
+No_duplicates_found=No_duplicates_found
+No_entries_imported.=No_entries_imported.
+No_entries_or_multiple_entries_selected.=No_entries_or_multiple_entries_selected.
+No_entries_selected=No_entries_selected
+No_GUI._Only_process_command_line_options.=No_GUI._Only_process_command_line_options.
+No_Medline_entries_found.=No_Medline_entries_found.
+No_pdf_or_ps_defined,_and_no_file_matching_Bibtex_key_found=No_pdf_or_ps_defined,_and_no_file_matching_Bibtex_key_found
+No_references_found=No_references_found
+No_saved_session_found.=No_saved_session_found.
+No_url_defined=No_url_defined
+non-Mac_only=non-Mac_only
+not=not
+not_found=not_found
+Not_saved_(empty_session)=Not_saved_(empty_session)
+Note_that_the_entry_causing_the_problem_has_been_selected.=Note_that_the_entry_causing_the_problem_has_been_selected.
+Note_that_the_new_definitions_will_not_be_compatible_with_previous_JabRef_versions.=Note_that_the_new_definitions_will_not_be_compatible_with_previous_JabRef_versions.
+Note_that_you_must_specify_the_fully_qualified_class_name_for_the_look_and_feel,=Note_that_you_must_specify_the_fully_qualified_class_name_for_the_look_and_feel,
+Nothing_to_redo=Nothing_to_redo
+Nothing_to_undo=Nothing_to_undo
+# The next is used like in "References found: 1  Number of references to fetch?"
+Number_of_references_to_fetch?=Number_of_references_to_fetch?
+occurences=occurences
+OK=OK
+Ok=OK
+One_or_more_keys_will_be_overwritten._Continue?=One_or_more_keys_will_be_overwritten._Continue?
+Open=Open
+open=open
+Open_BibTeX_database=Open_BibTeX_database
+Open_database=Open_database
+Open_editor_when_a_new_entry_is_created=Open_editor_when_a_new_entry_is_created
+Open_file=Open_file
+Open_last_edited_databases_at_startup=Open_last_edited_databases_at_startup
+Open_PDF_or_PS=Open_PDF_or_PS
+Open_right-click_menu_with_Ctrl+left_button=Open_right-click_menu_with_Ctrl+left_button
+Open_URL_or_DOI=Open_URL_or_DOI
+Opened_database=Opened_database
+Opening=Opening
+Opening_preferences...=Opening_preferences...
+Optional_fields=Optional_fields
+Options=Options
+or=or
+out_of=out_of
+Output_or_export_file=Output_or_export_file
+Overlapping_groups=Overlapping_groups
+Override=Override
+override_the_bibtex_key_by_the_selected_text=override_the_bibtex_key_by_the_selected_text
+Overwrite_keys=Overwrite_keys
+Ovid=Ovid
+pairs_processed=pairs_processed
+Paste=Paste
+paste_entries=paste_entries
+paste_entry=paste_entry
+Paste_from_clipboard=Paste_from_clipboard
+Pasted=Pasted
+Path_to_HTML_viewer=Path_to_HTML_viewer
+Path_to_LyX_pipe=Path_to_LyX_pipe
+Path_to_PDF_viewer=Path_to_PDF_viewer
+Path_to_PS_viewer=Path_to_PS_viewer
+Path_to_WinEdt.exe=Path_to_WinEdt.exe
+Paths_to_external_programs=Paths_to_external_programs
+PDF_links=PDF_links
+Pick_titles=Pick_titles
+Plain_right_menu=Plain_right_menu
+Plain_text=Plain_text
+Plain_text_import=Plain_text_import
+Please_check_your_network_connection_to_this_machine.=Please_check_your_network_connection_to_this_machine.
+Please_define_BibTeX_key_first=Please_define_BibTeX_key_first
+Please_enter_a_name_for_the_group.=Please_enter_a_name_for_the_group.
+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>=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% [...]
+Please_enter_a_semicolon_or_comma_separated_list_of_Medline_IDs_(numbers).=Please_enter_a_semicolon_or_comma_separated_list_of_Medline_IDs_(numbers).
+Please_enter_the_field_to_search_(e.g._<b>keywords</b>)_and_the_keyword_to_search_it_for_(e.g._<b>electrical</b>).=Please_enter_the_field_to_search_(e.g._<b>keywords</b>)_and_the_keyword_to_search_it_for_(e.g._<b>electrical</b>).
+Please_enter_the_string's_label=Please_enter_the_string's_label
+Please_refer_to_the_JabRef_help_manual_on_using_the_CiteSeer_tools.=Please_refer_to_the_JabRef_help_manual_on_using_the_CiteSeer_tools.
+Please_select_exactly_one_group_to_move.=Please_select_exactly_one_group_to_move.
+Please_wait_until_it_has_finished.=Please_wait_until_it_has_finished.
+Possible_duplicate_entries=Possible_duplicate_entries
+Possible_duplicate_of_existing_entry._Click_to_resolve.=Possible_duplicate_of_existing_entry._Click_to_resolve.
+Preamble=Preamble
+Preamble_editor,_store_changes=Preamble_editor,_store_changes
+Preferences=Preferences
+Preferences_recorded=Preferences_recorded
+Preferences_recorded.=Preferences_recorded.
+Preserve_formatting_of_non-BibTeX_fields=Preserve_formatting_of_non-BibTeX_fields
+Preview=Preview
+Previous_entry=Previous_entry
+Previous_tab=Previous_tab
+Problem_with_parsing_entry=Problem_with_parsing_entry
+PS_links=PS_links
+Push_selection_to_LyX/Kile=Push_selection_to_LyX/Kile
+Push_selection_to_WinEdt=Push_selection_to_WinEdt
+Push_to_LyX=Push_to_LyX
+Push_to_WinEdt=Push_to_WinEdt
+Pushed_the_citations_for_the_following_rows_to=Pushed_the_citations_for_the_following_rows_to
+Query_author(s)=Query_author(s)
+Quit=Quit
+Quit_JabRef=Quit_JabRef
+Quit_synchronization=Quit_synchronization
+Raw_source=Raw_source
+Really_delete_the_selected=Really_delete_the_selected
+Recent_files=Recent_files
+Redo=Redo
+Refer/Endnote=Refer/Endnote
+Reference_database=Reference_database
+# The next two lines are used like in "References found: 1  Number of references to fetch?"
+References_found=References_found
+Refine_supergroup\:_When_selected,_view_entries_contained_in_both_this_group_and_its_supergroup=Refine_supergroup:_When_selected,_view_entries_contained_in_both_this_group_and_its_supergroup
+Refresh_view=Refresh_view
+Regexp=Regexp
+Regular_Expression=Regular_Expression
+Remember_these_entry_types?=Remember_these_entry_types?
+Remote_operation=Remote_operation
+Remote_server_port=Remote_server_port
+Remove=Remove
+Remove_all?=Remove_all?
+Remove_all_subgroups=Remove_subgroups
+Remove_all_subgroups_of_"%0"?=Remove_all_subgroups_of_"%0"?
+Remove_duplicates=Remove_duplicates
+Remove_entry_from_import=Remove_entry_from_import
+Remove_entry_type=Remove_entry_type
+remove_from_group=remove_from_group
+Remove_from_group=Remove_from_group
+Remove_group=Remove_group
+Remove_group,_keep_subgroups=Remove_group,_keep_subgroups
+Remove_group_"%0"?=Remove_group_"%0"?
+Remove_group_"%0"_and_its_subgroups?=Remove_group_"%0"_and_its_subgroups?
+remove_group_(keep_subgroups)=remove_group_(keep_subgroups)
+remove_group_and_subgroups=remove_group_and_subgroups
+Remove_group_and_subgroups=Remove_group_and_subgroups
+Remove_old_entry=Remove_old_entry
+Remove_selected_strings=Remove_selected_strings
+remove_string=remove_string
+remove_string_=remove_string_
+Removed_entry_type.=Removed_entry_type.
+Removed_group=Removed_group
+Removed_group_"%0".=Removed_group_"%0".
+Removed_group_"%0"_and_its_subgroups.=Removed_group_"%0"_and_its_subgroups.
+Removed_string=Removed_string
+Renamed_string=Renamed_string
+Repeat_incremental_search=Repeat_incremental_search
+Replace=Replace
+Replace_string=Replace_string
+Replace_with=Replace_with
+Replaced=Replaced
+Required_fields=Required_fields
+Reset_all=Reset_all
+resolved=resolved
+Results=Results
+Revert_to_original_source=Revert_to_original_source
+Review_changes=Review_changes
+Right=Right
+RIS=RIS
+Save=Save
+Save_before_closing=Save_before_closing
+Save_database=Save_database
+Save_database_as_...=Save_database_as_...
+Save_selected_as_...=Save_selected_as_...
+Save_session=Save_session
+Saved_database=Saved_database
+Saved_selected_to=Saved_selected_to
+Saved_session=Saved_session
+Saving=Saving
+Scan=Scan
+SciFinder=SciFinder
+Search=Search
+Search_All_Fields=Search_All_Fields
+Search_all_fields=Search_all_fields
+Search_error=Search_error
+Search_expression=Search_expression
+Search_for=Search_for
+Search_General_Fields=Search_General_Fields
+Search_general_fields=Search_general_fields
+Search_Optional_Fields=Search_Optional_Fields
+Search_optional_fields=Search_optional_fields
+Search_Required_Fields=Search_Required_Fields
+Search_required_fields=Search_required_fields
+Search_Specified_Field(s)=Search_Specified_Field(s)
+Search_term=Search_term
+Searched_database._Number_of_hits=Searched_database._Number_of_hits
+Searching_for_%0_file=Searching_for_%0_file
+Searching_for_duplicates...=Searching_for_duplicates...
+Secondary_sort_criterion=Secondary_sort_criterion
+Select=Select
+Select_action=Select_action
+Select_all=Select_all
+Select_entries_in_group_selection=Select_entries_in_group_selection
+Select_entry_type=Select_entry_type
+Select_format=Select_format
+Select_matches=Select_matches
+Select_matching_entries=Select_matching_entries
+Select_the_tree_nodes_to_view_and_accept_or_reject_changes=Select_the_tree_nodes_to_view_and_accept_or_reject_changes
+Selector_enabled_fields=Selector_enabled_fields
+Set_general_fields=Set_general_fields
+Set_table_font=Set_table_font
+Set_up_general_fields=Set_up_general_fields
+Settings=Settings
+Setup_selectors=Setup_selectors
+Short_form=Short_form
+Shortcut=Shortcut
+Show/edit_BibTeX_source=Show/edit_BibTeX_source
+Show_'Firstname_Lastname'=Show_'Firstname_Lastname'
+Show_'Lastname,_Firstname'=Show_'Lastname,_Firstname'
+Show_abstract=Show_abstract
+Show_BibTeX_source_by_default=Show_BibTeX_source_by_default
+Show_BibTeX_source_panel=Show_BibTeX_source_panel
+Show_CiteSeer_column=Show_CiteSeer_column
+Show_confirmation_dialog_when_deleting_entries=Show_confirmation_dialog_when_deleting_entries
+Show_dynamic_groups_in_<i>italics</i>=Show_dynamic_groups_in_<i>italics</i>
+Show_entries_*not*_in_group_selection=Show_entries_*not*_in_group_selection
+Show_general_fields=Show_general_field
+Show_groups_matching_all=Show_groups_matching_all
+Show_groups_matching_any=Show_groups_matching_any
+Show_icons_for_groups=Show_icons_for_groups
+Show_names_unchanged=Show_names_unchanged
+Show_one_less_rows=Show_one_less_rows
+Show_one_more_row=Show_one_more_row
+Show_optional_fields=Show_optional_field
+Show_overlapping_groups=Show_overlapping_groups
+Show_PDF/PS_column=Show_PDF/PS_column
+Show_required_fields=Show_required_fields
+Show_URL/DOI_column=Show_URL/DOI_column
+Show_warning_dialog_when_a_duplicate_BibTeX_key_is_entered=Show_warning_dialog_when_a_duplicate_BibTeX_key_is_entered
+Show_warning_dialog_when_an_empty_BibTeX_key_is_entered=Show_warning_dialog_when_an_empty_BibTeX_key_is_entered
+Simple_HTML=Simple_HTML
+Sixpack=Sixpack
+Size_of_groups_interface_(rows)=Size_of_groups_interface_(rows)
+Skip=Skip
+Sort_alphabetically=Sort_alphabetically
+Sort_Automatically=Sort_automatically
+Sort_options=Sort_options
+sort_subgroups=sort_subgroups
+Sorted_all_subgroups_recursively=Sorted_all_subgroups_recursively
+Sorted_all_subgroups_recursively.=Sorted_all_subgroups_recursively.
+Sorted_immediate_subgroups=Sorted_immediate_subgroups
+Sorted_immediate_subgroups.=Sorted_immediate_subgroups.
+source_edit=source_edit
+Special_table_columns=Special_table_columns
+Start=Start
+Start_incremental_search=Start_incremental_search
+Start_search=Start_search
+Statically_group_entries_by_manual_assignment=Statically_group_entries_by_manual_assignment
+Status=Status
+Stop=Stop
+Store=Store
+Store_fields_with_double_braces,_and_remove_extra_braces_when_loading.<BR>Double_braces_signal_that_BibTeX_should_preserve_character_case.=Store_fields_with_double_braces,_and_remove_extra_braces_when_loading.<BR>Double_braces_signal_that_BibTeX_should_preserve_character_case.
+Store_string=Store_string
+Stored_definition_for_type=Stored_definition_for_type
+Stored_entry=Stored_entry
+Stored_entry.=Stored_entry.
+Strings=Strings
+Strings_for_database=Strings_for_database
+subdatabase_from_aux=bibtex_from_LaTex_aux
+Subdatabase_from_aux=Subdatabase_from_aux
+Suggest=Suggest
+Switch_preview_layout=Switch_preview_layout
+Synchronize_%0_links=Synchronize_%0_links
+Synchronizing_%0_links...=Synchronizing_%0_links...
+Table=Table
+Table_appearance=Table_appearance
+Tabname=Tabname
+Tertiary_sort_criterion=Tertiary_sort_criterion
+Test=Test
+Text_Input_Area=paste_text_here
+The_#_character_is_not_allowed_in_BibTeX_fields=The_#_character_is_not_allowed_in_BibTeX_fields
+The_CiteSeer_fetch_operation_returned_zero_results.=The_CiteSeer_fetch_operation_returned_zero_results.
+the_field_<b>%0</b>=the_field_<b>%0</b>
+The_file<BR>'%0'<BR>has_been_modified<BR>externally!=The_file<BR>'%0'<BR>has_been_modified<BR>externally!
+The_group_"%0"_already_contains_the_selection.=The_group_"%0"_already_contains_the_selection.
+The_group_"%0"_does_not_support_the_adding_of_entries.=The_group_"%0"_does_not_support_the_adding_of_entries.
+The_group_"%0"_does_not_support_the_removal_of_entries.=The_group_"%0"_does_not_support_the_removal_of_entries.
+The_label_of_the_string_can_not_be_a_number.=The_label_of_the_string_can_not_be_a_number.
+The_label_of_the_string_can_not_contain_spaces.=The_label_of_the_string_can_not_contain_spaces.
+The_label_of_the_string_can_not_contain_the_'#'_character.=The_label_of_the_string_can_not_contain_the_'#'_character.
+The_output_option_depends_on_a_valid_import_option.=The_output_option_depends_on_a_valid_import_option.
+The_regular_expression_<b>%0</b>_is_invalid%c=The_Regular_Expression_<b>%0</b>_is_invalid%c
+The_search_is_case_insensitive.=The_search_is_case_insensitive.
+The_search_is_case_sensitive.=The_search_is_case_sensitive.
+The_string_has_been_removed_locally=The_string_has_been_removed_locally
+The_type_name_can_not_contain_spaces.=The_type_name_can_not_contain_spaces.
+The_URL_field_appears_to_be_empty_on_entry_number_=The_URL_field_appears_to_be_empty_on_entry_number_
+There_are_possible_duplicates_(marked_with_a_'D'_icon)_that_haven't_been_resolved._Continue?=There_are_possible_duplicates_(marked_with_a_'D'_icon)_that_haven't_been_resolved._Continue?
+There_is_no_entry_type=There_is_no_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?=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?
+this_button_will_update=this_button_will_update
+this_button_will_update_the_column_width_settings<BR>to_match_the_current_widths_in_your_table=this_button_will_update_the_column_width_settings<BR>to_match_the_current_widths_in_your_table
+This_entry_is_incomplete=This_entry_is_incomplete
+This_entry_type_cannot_be_removed.=This_entry_type_cannot_be_removed.
+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.=This_group_contains_entries_based_on_manual_assignment._Entries_can_be_assigned_to_this_group_by_selecting_them_then_ [...]
+This_group_contains_entries_in_which=This_group_contains_entries_in_which
+This_group_contains_entries_in_which_any_field_contains_the_regular_expression_<b>%0</b>=This_group_contains_entries_in_which_any_field_contains_the_Regular_Expression_<b>%0</b>
+This_group_contains_entries_in_which_any_field_contains_the_term_<b>%0</b>=This_group_contains_entries_in_which_any_field_contains_the_term_<b>%0</b>
+This_group_contains_entries_whose_<b>%0</b>_field_contains_the_keyword_<b>%1</b>=This_group_contains_entries_whose_<b>%0</b>_field_contains_the_keyword_<b>%1</b>
+This_group_contains_entries_whose_<b>%0</b>_field_contains_the_regular_expression_<b>%1</b>=This_group_contains_entries_whose_<b>%0</b>_field_contains_the_Regular_Expression_<b>%1</b>
+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.=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.
+This_is_a_simple_copy_and_paste_dialog_for_import_some_fields_from_normal_text.=This_is_a_simple_copy_and_paste_dialog_for_import_some_fields_from_normal_text.
+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.=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.
+This_operation_cannot_work_on_multiple_rows.=This_operation_cannot_work_on_multiple_rows.
+Toggle_entry_preview=Toggle_entry_preview
+Toggle_groups_interface=Toggle_groups_interface
+Toggle_search_panel=Toggle_search_panel
+Tools=Tools
+Type=Type
+Type_set_to_'other'=Type_set_to_'other'
+unable_to_access_LyX-pipe=unable_to_access_LyX-pipe
+Unable_to_create_graphical_interface=Unable_to_create_graphical_interface
+Unable_to_parse_clipboard_text_as_Bibtex_entries.=Unable_to_parse_clipboard_text_as_Bibtex_entries.
+Unable_to_parse_the_following_URL=Unable_to_parse_the_following_URL
+unable_to_write_to=unable_to_write_to
+Undo=Undo
+Union=Union
+unknown_bibtex_entries=unknown_bibtex_entries
+Unknown_bibtex_entries=Unknown_bibtex_entries
+unknown_edit=unknown_edit
+unknown_entry_type=unknown_entry_type
+Unknown_export_format=Unknown_export_format
+Unmark_all=Unmark_all
+Unmark_entries=Unmark_entries
+Unmark_entry=Unmark_entry
+Unmarked_selected=Unmarked_selected
+Unpack_EndNote_filter_set=Unpack_EndNote_filter_set
+Unpacked_file=Unpacked_file
+Unpacked_file.=Unpacked_file.
+Unsupported_version_of_class_%0:_%1=Unsupported_version_of_class_%0:_%1
+untitled=untitled
+Up=Up
+Update_to_current_column_widths=Update_to_current_column_widths
+Updated_group_selection=Updated_group_selection
+Updating_entries...=Updating_entries...
+UPPER=UPPER
+Upper_Each_First=Upper_Each_First
+Upper_first=Upper_first
+usage=usage
+Use_antialiasing_font_in_table=Use_antialiasing_font_in_table
+Use_inspection_window_also_when_a_single_entry_is_imported.=Use_inspection_window_also_when_a_single_entry_is_imported.
+Use_other_look_and_feel=Use_other_look_and_feel
+Use_regular_expressions=Use_Regular_Expressions
+#the previous entry is translated in the menu "Tools" but is not in the file Menu_fr.properties!!!
+Use_the_following_delimiter=Use_the_following_delimiter
+Use_the_following_delimiter_character(s)=Use_the_following_delimiter_character(s)
+Uses_default_application=Uses_default_application
+Value_cleared_externally=Value_cleared_externally
+Value_set_externally=Value_set_externally
+verify_that_LyX_is_running_and_that_the_lyxpipe_is_valid=verify_that_LyX_is_running_and_that_the_lyxpipe_is_valid
+View=View
+Visible_fields=Visible_fields
+Warn_about_unresolved_duplicates_when_closing_inspection_window=Warn_about_unresolved_duplicates_when_closing_inspection_window
+Warn_before_overwriting_existing_keys=Warn_before_overwriting_existing_keys
+Warning=Warning
+Warning_there_is_a_duplicate_key=Warning_there_is_a_duplicate_key
+Warnings=Warnings
+web_link=web_link
+When_adding/removing_keywords,_separate_them_by=When_adding/removing_keywords,_separate_them_by
+with=with
+Word=Word
+Wrong_file_format=Wrong_file_format
+You_have_changed_the_language_setting._You_must_restart_JabRef_for_this_to_come_into_effect.=You_have_changed_the_language_setting._You_must_restart_JabRef_for_this_to_come_into_effect.
+You_have_cleared_this_field._Original_value=You_have_cleared_this_field._Original_value
+You_must_enter_an_integer_value_in_the_text_field_for=You_must_enter_an_integer_value_in_the_text_field_for
+You_must_fill_in_a_name_for_the_entry_type.=You_must_fill_in_a_name_for_the_entry_type.
+You_must_provide_a_name,_a_search_string_and_a_field_name_for_this_group.=You_must_provide_a_name,_a_search_string_and_a_field_name_for_this_group.
+You_must_restart_JabRef_for_the_new_key_bindings_to_work_properly.=You_must_restart_JabRef_for_the_new_key_bindings_to_work_properly.
+You_must_select_a_row_to_perform_this_operation.=You_must_select_a_row_to_perform_this_operation.
+You_must_select_at_least_one_row_to_perform_this_operation.=You_must_select_at_least_one_row_to_perform_this_operation.
+You_must_set_both_BibTeX_key_and_%0_directory=You_must_set_both_BibTeX_key_and_%0_directory
+You_must_set_both_bibtex_key_and_PDF_directory=You_must_set_both_bibtex_key_and_PDF_directory
+Your_new_key_bindings_have_been_stored.=Your_new_key_bindings_have_been_stored.
+Manage_custom_imports=Manage_custom_imports
+Select_Classpath_of_New_Importer=Select_Classpath_of_New_Importer
+Select_new_ImportFormat_Subclass=Select_new_ImportFormat_Subclass
+Could_not_instantiate_%0_%1=Could_not_instantiate_%0_%1
+Add_a_(compiled)_custom_ImportFormat_class_from_a_class_path._\nThe_path_need_not_be_on_the_classpath_of_JabRef.=Add_a_(compiled)_custom_ImportFormat_class_from_a_class_path._\nThe_path_need_not_be_on_the_classpath_of_JabRef.
+Please_select_an_importer=Please_select_an_importer
+Import_name=Import_name
+Command_line_id=Command_line_id
+ImportFormat_class=ImportFormat_class
+Contained_in=Contained_in
+Show_description=Show_description
+Add_from_folder=Add_from_folder
+Custom_importers=Custom_importers
+No_custom_imports_registered_yet.=No_custom_imports_registered_yet.
+Abbreviate_journal_names_of_the_selected_entries_(ISO_abbreviation)=Abbreviate_journal_names_of_the_selected_entries_(ISO_abbreviation)
+Abbreviate_journal_names_of_the_selected_entries_(MEDLINE_abbreviation)=Abbreviate_journal_names_of_the_selected_entries_(MEDLINE_abbreviation)
+Background_color_for_marked_entries=Background_color_for_marked_entries
+Background_color_for_optional_fields=Background_color_for_optional_fields
+Background_color_for_required_fields=Background_color_for_required_fields
+Choose_the_URL_to_download._The_default_value_points_to_a_list_provided_by_the_JabRef_developers.=Choose_the_URL_to_download._The_default_value_points_to_a_list_provided_by_the_JabRef_developers.
+Color_for_marking_incomplete_entries=Color_for_marking_incomplete_entries
+Do_not_abbreviate_names=Do_not_abbreviate_names
+Do_not_wrap_the_following_fields_when_saving=Do_not_wrap_the_following_fields_when_saving
+External_files=External_files
+File_'%0'_not_found=File_'%0'_not_found
+Journal_abbreviations=Journal_abbreviations
+Journal_name=Journal_name
+Manage_journal_abbreviations=Manage_journal_abbreviations
+Natbib_style=Natbib_style
+New_file=New_file
+Personal_journal_list=Personal_journal_list
+Remove_double_braces_around_BibTeX_fields_when_loading.=Remove_double_braces_around_BibTeX_fields_when_loading.
+Store_the_following_fields_with_braces_around_capital_letters=Store_the_following_fields_with_braces_around_capital_letters
+Table_background_color=Table_background_color
+Table_grid_color=Table_grid_color
+Table_text_color=Table_text_color
+Toggle_abbreviation=Toggle_abbreviation
+Unabbreviate_journal_names_of_the_selected_entries=Unabbreviate_journal_names_of_the_selected_entries
+Use_antialiasing_font=Use_antialiasing_font
+Abbreviate_names=Abbreviate_names
+Abbreviation=Abbreviation
+ISO_abbreviation=ISO_abbreviation
+Edit_journal=Edit_journal
+Existing_file=Existing_file
+Saving_database=Saving_database
+Normal=Normal
+Default_sort_criteria=Default_sort_criteria
+Primary_sort_criterion=Primary_sort_criterion
+Database_properties=Database_properties
+Database_encoding=Database_encoding
+
+No_journal_names_could_be_abbreviated.=No_journal_names_could_be_abbreviated.
+No_journal_names_could_be_unabbreviated.=No_journal_names_could_be_unabbreviated.
+Save_failed=Save_failed
+Pushed_citations_to_WinEdt=Pushed_citations_to_WinEdt
+Try_different_encoding=Try_different_encoding
+Select_encoding=Select_encoding
+The_chosen_date_format_for_new_entries_is_not_valid=The_chosen_date_format_for_new_entries_is_not_valid
+Invalid_date_format=Invalid_date_format
+Review=Review
+Journal_names=Journal_names
+Save_failed_during_backup_creation=Save_failed_during_backup_creation
+Save_failed_while_committing_changes=Save_failed_while_committing_changes
+Full_name=Full_name
+Store_journal_abbreviations=Store_journal_abbreviations
+You_must_choose_a_file_name_to_store_journal_abbreviations=You_must_choose_a_file_name_to_store_journal_abbreviations
+Journal_list_preview=Journal_list_preview
+
+Add_from_jar=Add_from_jar
+Add_a_(compiled)_custom_ImportFormat_class_from_a_Zip-archive.\nThe_Zip-archive_need_not_be_on_the_classpath_of_JabRef.=Add_a_(compiled)_custom_ImportFormat_class_from_a_Zip-archive.\nThe_Zip-archive_need_not_be_on_the_classpath_of_JabRef.
+Select_a_Zip-archive=Select_a_Zip-archive
+Select_file_from_ZIP-archive=Select_file_from_ZIP-archive
+Last_modified=Last_modified
+Size=Size
+Please_select_an_importer.=Please_select_an_importer.
+
+Arguments_passed_on_to_running_JabRef_instance._Shutting_down.=Arguments_passed_on_to_running_JabRef_instance._Shutting_down.
+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').=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').
+Pushed_citations_to_Emacs=Pushed_citations_to_Emacs
+Push_selection_to_Emacs=Push_selection_to_Emacs
+
+Filter=Filter
+Hide_non-matching_entries=Hide_non-matching_entries
+Replace_(regular_expression)=Replace_(regular_expression)
+Cite_command_(for_Emacs/WinEdt)=Cite_command_(for_Emacs/WinEdt)
+No_entries_found._Please_make_sure_you_are_using_the_correct_import_filter.=No_entries_found._Please_make_sure_you_are_using_the_correct_import_filter.
+
+Could_not_instantiate_%0_%1._Have_you_chosen_the_correct_package_path?=Could_not_instantiate_%0_%1._Have_you_chosen_the_correct_package_path?
+
+Switches_between_full_and_abbreviated_journal_name_if_the_journal_name_is_known.=Switches_between_full_and_abbreviated_journal_name_if_the_journal_name_is_known.
+To_set_up,_go_to_<B>Tools_->_Manage_journal_abbreviations</B>=To_set_up,_go_to_<B>Tools_->_Manage_journal_abbreviations</B>
+
+Could_not_run_the_'gnuclient'_program._Make_sure_you_have_the_gnuserv/gnuclient_programs_installed.=Could_not_run_the_'gnuclient'_program._Make_sure_you_have_the_gnuserv/gnuclient_programs_installed.
+
+Hierarchical_context=Hierarchical_context
+
+Remove_entry_selection_from_this_group=Remove_entry_selection_from_this_group
+Assign_entry_selection_exclusively_to_this_group=Assign_entry_selection_exclusively_to_this_group
+Add_entry_selection_to_this_group=Add_entry_selection_to_this_group
\ No newline at end of file
diff --git a/src/resource/JabRef_en.properties.orig b/src/resource/JabRef_en.properties.orig
new file mode 100644
index 0000000..82f8146
--- /dev/null
+++ b/src/resource/JabRef_en.properties.orig
@@ -0,0 +1,1030 @@
+#! created/edited by Popeye version 0.51 sunshine (popeye.sourceforge.net)
+
+!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.=!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.
+%0_contains_the_Regular_Expression_<b>%1</b>=%0_contains_the_Regular_Expression_<b>%1</b>
+%0_contains_the_term_<b>%1</b>=%0_contains_the_term_<b>%1</b>
+%0_doesn't_contain_the_Regular_Expression_<b>%1</b>=%0_doesn't_contain_the_Regular_Expression_<b>%1</b>
+%0_doesn't_contain_the_term_<b>%1</b>=%0_doesn't_contain_the_term_<b>%1</b>
+%0_doesn't_match_the_Regular_Expression_<b>%1</b>=%0_doesn't_match_the_Regular_Expression_<b>%1</b>
+%0_doesn't_match_the_term_<b>%1</b>=%0_doesn't_match_the_term_<b>%1</b>
+%0_field_set=%0_field_set
+%0_import_cancelled.=%0_import_cancelled.
+%0_matches_the_Regular_Expression_<b>%1</b>=%0_matches_the_Regular_Expression_<b>%1</b>
+%0_matches_the_term_<b>%1</b>=%0_matches_the_term_<b>%1</b>
+<field_name>=<field_name>
+<HTML>Unpack_the_zip_file_containing_import/export_filters_for_Endnote,<BR>for_optimal_interoperability_with_JabRef</HTML>=<HTML>Unpack_the_zip_file_containing_import/export_filters_for_Endnote,<BR>for_optimal_interoperability_with_JabRef</HTML>
+<no_field>=<no_field>
+<select>=<select>
+<select_word>=<select_word>
+_on_entry_number_=_on_entry_number_
+A_CiteSeer_fetch_operation_is_currently_in_progress.=A_CiteSeer_fetch_operation_is_currently_in_progress.
+A_CiteSeer_import_operation_is_currently_in_progress.=A_CiteSeer_import_operation_is_currently_in_progress.
+A_string_with_that_label_already_exists=A_string_with_that_label_already_exists
+About_JabRef=About_JabRef
+Abstract=Abstract
+Accept=Accept
+Accept_change=Accept_change
+Action=Action
+Add=Add
+add_entries_to_group=add_entries_to_group
+add_group=add_group
+Add_Group=Add_group
+Add_new=Add_new
+Add_Subgroup=Add_subgroup
+Add_to_group=Add_to_group
+Added_entry=Added_entry
+Added_group=Added_group
+Added_group_"%0".=Added_group_"%0".
+Added_new=Added_new
+Added_string=Added_string
+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.=Additionally,_entries_whose_<b>%0</b>_field_does_not_contain_<b>%1</b>_ [...]
+Advanced=Advanced
+Advanced_options_for_setting...=Advanced_options_for_setting...
+All_Entries=All_Entries
+All_entries=All_entries
+All_entries_of_this_type_will_be_declared_typeless._Continue?=All_entries_of_this_type_will_be_declared_typeless._Continue?
+All_fields=All_fields
+All_subgroups_(recursively)=All_subgroups_(recursively)
+Allow_editing_in_table_cells=Allow_editing_in_table_cells
+Always_save_database_ordered_by_author_name=Always_save_database_ordered_by_author_name
+and=and
+and_the_class_must_be_available_in_your_classpath_next_time_you_start_JabRef.=and_the_class_must_be_available_in_your_classpath_next_time_you_start_JabRef.
+any_field_that_matches_the_regular_expression_<b>%0</b>=any_field_that_matches_the_Regular_Expression_<b>%0</b>
+Appearance=Appearance
+Append=Append
+Append_contents_from_a_BibTeX_database_into_the_currently_viewed_database=Append_contents_from_a_BibTeX_database_into_the_currently_viewed_database
+Append_database=Append_database
+append_the_selected_text_to_bibtex_key=append_the_selected_text_to_bibtex_key
+Apply=Apply
+Assign_entries_based_on:=Assign_entries_based_on:
+Assign_new_file=Assign_new_file
+Assign_the_original_group's_entries_to_this_group?=Assign_the_original_group's_entries_to_this_group?
+Assigned_%0_entries_to_group_"%1".=Assigned_%0_entries_to_group_"%1".
+Assigned_1_entry_to_group_"%0".=Assigned_1_entry_to_group_"%0".
+Attach_%0_file=Attach_%0_file
+Attach_URL=Attach_URL
+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.=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.
+Auto=Auto
+Autodetect_format=Autodetect_format
+Autogenerate_BibTeX_key=Autogenerate_BibTeX_key
+Autogenerate_BibTeX_keys=Autogenerate_BibTeX_keys
+Autogenerate_groups=Autogenerate_groups
+autogenerate_keys=autogenerate_keys
+Automatically_create_groups=Automatically_create_groups
+Automatically_create_groups_for_database.=Automatically_create_groups_for_database.
+Automatically_created_groups=Automatically_created_groups
+Automatically_hide_groups_interface_when_switching_to_a_database_that_contains_no_groups=Automatically_hide_groups_interface_when_switching_to_a_database_that_contains_no_groups
+Automatically_show_groups_interface_when_switching_to_a_database_that_contains_groups=Automatically_show_groups_interface_when_switching_to_a_database_that_contains_groups
+Autoset=Autoset
+Autoset_%0_field=Autoset_%0_field
+Autoset_%0_links._Allow_overwriting_existing_links.=Autoset_%0_links._Allow_overwriting_existing_links.
+Autoset_%0_links._Do_not_overwrite_existing_links.=Autoset_%0_links._Do_not_overwrite_existing_links.
+Autosetting_%0_field...=Autosetting_%0_field...
+AUX_File_import=generate_subdatabase_from_aux
+AUX_file_import=AUX_file_import
+Available_export_formats=Available_export_formats
+Available_fields=Allowed_BibTeX_fields
+Available_import_formats=Available_import_formats
+Backup_old_file_when_saving=Backup_old_file_when_saving
+Bibkey_to_filename_conversion=Bibkey_to_filename_conversion
+Biblioscape_Tag_file=Biblioscape_Tag_file
+BibTeX=BibTeX
+BibTeX_key=BibTeX_key
+BibTeX_key_is_unique.=BibTeX_key_is_unique.
+BibTeX_key_not_set._Enter_a_name_for_the_downloaded_file=BibTeX_key_not_set._Enter_a_name_for_the_downloaded_file
+BibTeX_source=BibTeX_source
+BibTeXML=BibTeXML
+BibTeXML_File=BibTeXML_File
+Binding=Binding
+Broken_link=Broken_link
+Browse=Browse
+by=by
+Calling_external_viewer...=Calling_external_viewer...
+Cancel=Cancel
+Cannot_add_entries_to_group_without_generating_keys._Generate_keys_now?=Cannot_add_entries_to_group_without_generating_keys._Generate_keys_now?
+Cannot_merge_this_change=Cannot_merge_this_change
+Cannot_move_group=Cannot_move_group
+Cannot_move_group_"%0"_down.=Cannot_move_group_"%0"_down.
+Cannot_move_group_"%0"_left.=Cannot_move_group_"%0"_left.
+Cannot_move_group_"%0"_right.=Cannot_move_group_"%0"_right.
+Cannot_move_group_"%0"_up.=Cannot_move_group_"%0"_up.
+case_insensitive=case_insensitive
+case_sensitive=case_sensitive
+Case_sensitive=Case_sensitive
+change_assignment_of_entries=change_assignment_of_entries
+Change_case=Change_case
+Change_entry_type=Change_entry_type
+change_key=change_key
+Change_of_Grouping_Method=Change_of_Grouping_Method
+change_preamble=change_preamble
+change_string_content=change_string_content
+change_string_name=change_string_name
+change_type=change_type
+changed_=changed_
+Changed_font_settings=Changed_font_settings
+Changed_language_settings=Changed_language_settings
+Changed_look_and_feel_settings=Changed_look_and_feel_settings
+Changed_preamble=Changed_preamble
+Changed_type_to=Changed_type_to
+Characters_to_ignore=Characters_to_ignore
+Check_existing_%0_links=Check_existing_%0_links
+Check_links=Check_links
+Citation_import_from_CiteSeer_failed.=Citation_import_from_CiteSeer_failed.
+CiteSeer_Error=CiteSeer_Error
+CiteSeer_Fetch_Error=CiteSeer_Fetch_Error
+CiteSeer_import_entries=CiteSeer_import_entries
+CiteSeer_Import_Error=CiteSeer_Import_Error
+CiteSeer_Import_Fields=CiteSeer_Import_Fields
+CiteSeer_Transfer=CiteSeer_Transfer
+CiteSeer_Warning=CiteSeer_Warning
+Class_name=Class_name
+Clear=Clear
+clear_all_groups=clear_all_groups
+Clear_field=Clear_field
+Clear_highlight=Clear_highlight
+Clear_highlighted=Clear_highlighted
+Clear_highlighted_groups=Clear_highlighted_groups
+Clear_inputarea=Clear_text_input_area
+Clear_search=Clear_search
+Close=Close
+Close_database=Close_database
+Close_dialog=Close_dialog
+# The following lines correspond to names of key bindings:
+Close_entry_editor=Close_entry_editor
+Close_preamble_editor=Close_preamble_editor
+Close_the_current_database=Close_the_current_database
+Close_the_help_window=Close_the_help_window
+Close_window=Close_window
+Closed_database=Closed_database
+Collapse_subtree=Collapse_subtree
+Color_codes_for_required_and_optional_fields=Color_codes_for_required_and_optional_fields
+Column_width=Column_width
+Complete_record=Complete_record
+Completed_citation_import_from_CiteSeer.=Completed_citation_import_from_CiteSeer.
+Completed_Import_Fields_from_CiteSeer.=Completed_Import_Fields_from_CiteSeer.
+Completed_import_from_CiteSeer.=Completed_import_from_CiteSeer.
+Content=Content
+Copied=Copied
+Copied_cell_contents=Copied_cell_contents
+Copied_key=Copied_key
+Copied_keys=Copied_keys
+Copy=Copy
+Copy_BibTeX_key=Copy_BibTeX_key
+Copy_\\cite{BibTeX_key}=Copy_cite\\{BibTeX_key}
+Copy_to_clipboard=Copy_to_clipboard
+Could_not_call_executable=Could_not_call_executable
+Could_not_connect_to_host=Could_not_connect_to_host
+Could_not_connect_to_host_=Could_not_connect_to_host_
+Could_not_export_entry_types=Could_not_export_entry_types
+Could_not_export_file=Could_not_export_file
+Could_not_export_preferences=Could_not_export_preferences
+Could_not_find_a_suitable_import_format.=Could_not_find_a_suitable_import_format.
+Could_not_find_layout_file=Could_not_find_layout_file
+Could_not_import_entry_types=Could_not_import_entry_types
+Could_not_import_preferences=Could_not_import_preferences
+Could_not_resolve_import_format=Could_not_resolve_import_format
+Could_not_save_file=Could_not_save_file
+Couldn't_find_an_entry_associated_with_this_URL=Couldn't_find_an_entry_associated_with_this_URL
+Couldn't_parse_the_'citeseerurl'_field_of_the_following_entries=Couldn't_parse_the_'citeseerurl'_field_of_the_following_entries
+Create_group=Create_group
+Created_group=Created_group
+Created_group_"%0".=Created_group_"%0".
+Created_groups.=Created_groups.
+Curly_braces_{_and_}_must_be_balanced.=Curly_braces_{_and_}_must_be_balanced.
+Current_content=Current_content
+Current_value=Current_value
+Custom_entry_types=Custom_entry_types
+Custom_entry_types_found_in_file=Custom_entry_types_found_in_file
+Custom_export=Custom_export
+Customize_entry_types=Customize_entry_types
+Customize_key_bindings=Customize_key_bindings
+Cut=Cut
+cut_entries=cut_entries
+cut_entry=cut_entry
+Cut_pr=Cut
+Database_has_changed._Do_you_want_to_save_before_closing?=Database_has_changed._Do_you_want_to_save_before_closing?
+Date_format=Date_format
+Default=Default
+Default_encoding=Default_encoding
+Default_grouping_field=Default_grouping_field
+Default_look_and_feel=Default_look_and_feel
+Default_owner=Default_owner
+Default_pattern=Default_pattern
+defined.=defined.
+Delete=Delete
+Delete_custom=Delete_custom
+Delete_custom_format=Delete_custom_format
+delete_entries=delete_entries
+Delete_entry=Delete_entry
+delete_entry=delete_entry
+Delete_multiple_entries=Delete_multiple_entries
+Delete_rows=Delete_rows
+Delete_strings=Delete_strings
+Deleted=Deleted
+Deleted_entry=Deleted_entry
+Delimit_fields_with_semicolon,_ex.=Delimit_fields_with_semicolon,_ex.
+Descending=Descending
+Description=Description
+Deselect_all=Deselect_all
+Details=Details
+Disable_entry_editor_when_multiple_entries_are_selected=Disable_entry_editor_when_multiple_entries_are_selected
+Disable_this_confirmation_dialog=Disable_this_confirmation_dialog
+Disable_this_warning_dialog=Disable_this_warning_dialog
+Display_all_entries_belonging_to_one_or_more_of_the_selected_groups.=Display_all_entries_belonging_to_one_or_more_of_the_selected_groups.
+Display_help_on_command_line_options=Display_help_on_command_line_options
+Display_imported_entries_in_an_inspection_window_before_they_are_added.=Display_imported_entries_in_an_inspection_window_before_they_are_added.
+Display_only_entries_belonging_to_all_selected_groups.=Display_only_entries_belonging_to_all_selected_groups.
+Displaying_no_groups=Displaying_no_groups
+Do_not_autoset=Do_not_autoset
+Do_not_import_entry=Do_not_import_entry
+Do_not_open_any_files_at_startup=Do_not_open_any_files_at_startup
+Do_not_overwrite_existing_keys=Do_not_overwrite_existing_keys
+Docbook=Docbook
+Done=Done
+Down=Down
+Download=Download
+Download_completed=Download_completed
+Download_file=Download_file
+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.=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.
+dummy=dummy
+Duplicate_BibTeX_key=duplicate_BibTeX_key
+duplicate_BibTeX_key=duplicate_BibTeX_key
+Duplicate_BibTeX_key.=Duplicate_BibTeX_key.
+duplicate_BibTeX_key.=duplicate_BibTeX_key.
+Duplicate_BibTeX_key._Grouping_may_not_work_for_this_entry.=Duplicate_BibTeX_key._Grouping_may_not_work_for_this_entry.
+Duplicate_Key_Warning=Duplicate_Key_Warning
+Duplicate_pairs_found=Duplicate_pairs_found
+duplicate_removal=duplicate_removal
+Duplicate_string_name=Duplicate_string_name
+Duplicates_found=Duplicates_found
+Duplicates_removed=Duplicates_removed
+Dynamic_groups=Dynamic_groups
+Dynamically_group_entries_by_a_free-form_search_expression=Dynamically_group_entries_by_a_free-form_search_expression
+Dynamically_group_entries_by_searching_a_field_for_a_keyword=Dynamically_group_entries_by_searching_a_field_for_a_keyword
+Each_line_must_be_on_the_following_form=Each_line_must_be_on_the_following_form
+Edit=Edit
+Edit_custom_export=Edit_custom_export
+Edit_entry=Edit_entry
+Edit_group=Edit_Group
+Edit_preamble=Edit_preamble
+Edit_strings=Edit_strings
+empty_BibTeX_key=empty_BibTeX_key
+Empty_BibTeX_key.=Empty_BibTeX_key.
+Empty_BibTeX_key._Grouping_may_not_work_for_this_entry.=Empty_BibTeX_key._Grouping_may_not_work_for_this_entry.
+Empty_database=Empty_database
+empty_database=empty_database
+Enable source_editing=Enable source_editing
+Enable_source_editing=Enable_source_editing
+Endnote=Endnote
+Enter_URL=Enter_URL
+Enter_URL_to_download=Enter_URL_to_download
+entries=entries
+Entries_cannot_be_manually_assigned_to_or_removed_from_this_group.=Entries_cannot_be_manually_assigned_to_or_removed_from_this_group.
+Entries_exported_to_clipboard=Entries_exported_to_clipboard
+entries_have_undefined_BibTeX_key=entries_have_undefined_BibTeX_key
+entries_into_new_database=entries_into_new_database
+entry=entry
+Entry_editor=Entry_editor
+# The following lines correspond to names of key bindings:
+Entry_editor,_next_entry=Entry_editor,_next_entry
+Entry_editor,_next_panel=Entry_editor,_next_panel
+Entry_editor,_previous_entry=Entry_editor,_previous_entry
+Entry_editor,_previous_panel=Entry_editor,_previous_panel
+Entry_editor,_store_field=Entry_editor,_store_field
+Entry_in_current_database=Entry_in_current_database
+Entry_in_import=Entry_in_import
+Entry_is_incomplete=Entry_is_incomplete
+Entry_preview=Entry_preview
+Entry_table=Entry_table
+Entry_table_columns=Entry_table_columns
+Entry_type=Entry_type
+Entry_type_names_are_not_allowed_to_contain_white_space_or_the_following_characters=Entry_type_names_are_not_allowed_to_contain_white_space_or_the_following_characters
+Entry_types=Entry_types
+EOF_in_mid-string=EOF_in_mid-string
+Error=Error
+##Error:_check_your_External_viewer_settings_in_Preferences=Error:_check_your_External_viewer_settings_in_Preferences
+Error_in_field=Error_in_field
+Error_in_line=Error_in_line
+Error_opening_file=Error_opening_file
+Error_setting_field=Error_setting_field
+exists._Overwrite?=exists._Overwrite?
+exists._Overwrite_file?=exists._Overwrite_file?
+Exit=Exit
+Expand_subtree=Expand_subtree
+Explicit=Explicit
+#previous entry not translated. To view it, open Group interface and click on the "new group" button
+Export=Export
+Export_entry_types=Export_entry_types
+Export_name=Export_name
+Export_preferences=Export_preferences
+Export_preferences_to_file=Export_preferences_to_file
+Export_properties=Export_properties
+Export_selected_to_clipboard=Export_selected_to_clipboard
+Export_to_clipboard=Export_to_clipboard
+Exported_database_to_file=Exported_database_to_file
+Exporting=Exporting
+External_changes=External_changes
+External_programs=External_programs
+External_viewer_called=External_viewer_called
+Failed_to_read_groups_data_(unsupported_version:_%0)=Failed_to_read_groups_data_(unsupported_version:_%0)
+Fetch=Fetch
+Fetch_Articles_Citing_your_Database=Fetch_Articles_Citing_your_Database
+Fetch_Citations_from_CiteSeer=Fetch_Citations_from_CiteSeer
+Fetch_citations_from_CiteSeer=Fetch_citations_from_CiteSeer
+Fetch_CiteSeer=Fetch_CiteSeer
+Fetch_Medline=Fetch_Medline
+fetch_Medline=fetch_Medline
+Fetch_Medline_by_author=Fetch_Medline_by_author
+Fetch_Medline_by_ID=Fetch_Medline_by_ID
+Fetched_all_citations_from_target_database.=Fetched_all_citations_from_target_database.
+Fetching_Citations=Fetching_Citations
+Fetching_Identifiers=Fetching_Identifiers
+Fetching_Medline...=Fetching_Medline...
+Fetching_Medline_by_ID...=Fetching_Medline_by_ID...
+Fetching_Medline_by_id_...=Fetching_Medline_by_id_...
+Fetching_Medline_by_term_...=Fetching_Medline_by_term_...
+Field=Field
+field=field
+# 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=Field_content
+Field_name=Field_name
+Field_names_are_not_allowed_to_contain_white_space_or_the_following_characters=Field_names_are_not_allowed_to_contain_white_space_or_the_following_characters
+Field_sizes=Field_sizes
+Field_to_group_by=Field_to_group_by
+Field_to_search=Field_to_search
+Fields=Fields
+File=File
+file=file
+File_changed=File_changed
+File_extension=File_extension
+File_has_been_updated_externally._Are_you_sure_you_want_to_save?=File_has_been_updated_externally._Are_you_sure_you_want_to_save?
+File_not_found=File_not_found
+File_updated_externally=File_updated_externally
+filename=filename
+Files_opened=Files_opened
+Find_duplicates=Find_duplicates
+Finished_autosetting_%0_field._Entries_changed:_%1.=Finished_autosetting_%0_field._Entries_changed:_%1.
+Finished_synchronizing_%0_links._Entries_changed%c_%1.=Finished_synchronizing_%0_links._Entries_changed%c_%1.
+First_select_the_entries_you_want_keys_to_be_generated_for.=First_select_the_entries_you_want_keys_to_be_generated_for.
+Fit_table_horizontally_on_screen=Fit_table_horizontally_on_screen
+Float=Float
+Font_Family=Font_Family
+Font_Preview=Font_Preview
+Font_Size=Font_Size
+Font_Style=Font_Style
+FontSelector=FontSelector
+for=for
+Format_of_author_and_editor_names=Format_of_author_and_editor_names
+Format_used=Format_used
+Formatter_not_found=Formatter_not_found
+found=found
+found_in_aux_file=found_in_aux_file
+General=General
+General_fields=General_fields
+Generate=Generate
+Generate_BibTeX_key=Generate_BibTeX_key
+Generate_keys=Generate_keys
+Generate_now=Generate_now
+Generated_BibTeX_key_for=Generated_BibTeX_key_for
+Generating_BibTeX_key_for=Generating_BibTeX_key_for
+Grab=Grab
+Gray_out_entries_not_in_group_selection=Gray_out_entries_not_in_group_selection
+Gray_out_non-hits=Gray_out_non-hits
+Gray_out_non-matching_entries=Gray_out_non-matching_entries
+Group_definitions_have_been_converted_to_JabRef_1.7_format.=Group_definitions_have_been_converted_to_JabRef_1.7_format.
+Group_name=Group_name
+Group_properties=Group_properties
+Groups=Groups
+Harvard_RTF=Harvard_RTF
+Help=Help
+Help_contents=Help_contents
+Help_on_groups=Help_on_groups
+Help_on_key_patterns=Help_on_key_patterns
+Hide_non-hits=Hide_non-hits
+Highlight=Highlight
+Highlight_groups_matching_all_selected_entries=Highlight_groups_matching_all_selected_entries
+Highlight_groups_matching_any_selected_entry=Highlight_groups_matching_any_selected_entry
+Highlight_groups_that_contain_entries_contained_in_any_currently_selected_group=Highlight_groups_that_contain_entries_contained_in_any_currently_selected_group
+Highlight_overlapping_groups=Highlight_overlapping_groups
+Hint%c_To_search_specific_fields_only,_enter_for_example%c<p><tt>author%esmith_and_title%eelectrical</tt>=Hint%c_To_search_specific_fields_only,_enter_for_example%c<p><tt>author%esmith_and_title%eelectrical</tt>
+HTML=HTML
+Ignore=Ignore
+Illegal_type_name=Illegal_type_name
+Immediate_subgroups=Immediate_subgroups
+Import=Import
+Import_and_append=Import_and_append
+Import_and_keep_old_entry=Import_and_keep_old_entry
+Import_and_remove_old_entry=Import_and_remove_old_entry
+Import_cancelled.=Import_cancelled.
+Import_Data_from_CiteSeer=Import_Data_from_CiteSeer
+Import_Data_from_CiteSeer_Database=Import_Data_from_CiteSeer_Database
+Import_database=Import_database
+Import_entries=Import_entries
+Import_entry_types=Import_entry_types
+Import_failed=Import_failed
+Import_Fields_from_CiteSeer=Import_Fields_from_CiteSeer
+# I have reformulated the following lines, because the 1st person form is not suitable:
+# (Folgende_URL_konnte_nicht_analysiert_werden)
+Import_fields_from_CiteSeer=Import_fields_from_CiteSeer
+Import_fields_from_CiteSeer_Database=Import_fields_from_CiteSeer_Database
+Import_Fields_from_CiteSeer_Database=Import_Fields_from_CiteSeer_Database
+Import_file=Import_file
+Import_group_definitions=Import_group_definitions
+Import_plain_text=Import_fields_from_plain_text
+Import_preferences=Import_preferences
+Import_preferences_from_file=Import_preferences_from_file
+Import_strings=Import_strings
+Import_to_open_tab=Import_to_open_tab
+Import_word_selector_definitions=Import_word_selector_definitions
+Imported_database=Imported_database
+Imported_entries=Imported_entries
+Imported_entry_types=Imported_entry_types
+Imported_file=Imported_file
+Imported_from_database=Imported_from_database
+Importing=Importing
+Importing_file=Importing_file
+Importing_in_unknown_format=Importing_in_unknown_format
+In_JabRef,_use_pairs_of_#_characters_to_indicate_a_string.=In_JabRef,_use_pairs_of_#_characters_to_indicate_a_string.
+Include_subgroups=Include_subgroups
+Include_subgroups:_When_selected,_view_entries_contained_in_this_group_or_its_subgroups=Include_subgroups:_When_selected,_view_entries_contained_in_this_group_or_its_subgroups
+Incremental=Incremental
+Incremental_search=Incremental_search
+Incremental_search_failed._Repeat_to_search_from_top.=Incremental_search_failed._Repeat_to_search_from_top.
+Independent=Independent
+Independent_group:_When_selected,_view_only_this_group's_entries=Independent_group:_When_selected,_view_only_this_group's_entries
+Initially_show_groups_tree_expanded=Initially_show_groups_tree_expanded
+Input=Work_options
+Input_error=Input_error
+Insert=Insert
+Insert_rows=Insert_rows
+Insert_selected_citations_into_LyX=Insert_selected_citations_into_LyX
+Insert_selected_citations_into_WinEdt=Insert_selected_citations_into_WinEdt
+insert_string_=insert_string_
+Insert_URL=Insert_URL
+INSPEC=INSPEC
+integrity=integrity
+# 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=Integrity_check
+Intersection=Intersection
+Intersection_with_supergroups=Intersection_with_supergroups
+Invalid_BibTeX_key=Invalid_BibTeX_key
+Invalid_URL=Invalid_URL
+Inverted=Inverted
+is_a_standard_type.=is_a_standard_type.
+ISI=ISI
+Item_list_for_field=Item_list_for_field
+JabRef_help=JabRef_help
+JabRef_preferences=JabRef_preferences
+JStor_file=JStor_file
+Keep=Keep
+Keep_both=Keep_both
+Keep_lower=Keep_lower
+Keep_upper=Keep_upper
+Key_bindings=Key_bindings
+Key_bindings_changed=Key_bindings_changed
+Key_generator_settings=Key_generator_settings
+Key_pattern=Key_pattern
+keys_in_database=keys_in_database
+#not translated. To view it, use menu "Tools|New BibTeX file from AUx file", and launch the action on a non-existant aux file.
+Keyword=Keyword
+Label=Label
+Language=Language
+Latex_AUX_file=LaTeX_AUX_file
+LaTeX_AUX_file=LaTeX_AUX_file
+Left=Left
+License=License
+Limit_to_fields=Limit_to_fields
+Limit_to_selected_entries=Limit_to_selected_entries
+Listen_for_remote_operation_on_port=Listen_for_remote_operation_on_port
+Load_session=Load_session
+Loading_session...=Loading_session...
+Look_and_feel=Look_and_feel
+lower=lower
+Main_layout_file=Main_layout_file
+Main_PDF_directory=Main_PDF_directory
+Main_PS_directory=Main_PS_directory
+Manage=Manage
+Manage_content_selectors=Manage_content_selectors
+Manage_custom_exports=Manage_custom_exports
+Mark_entries=Mark_entries
+Mark_entry=Mark_entry
+Mark_new_entries_with_addition_date=Mark_new_entries_with_addition_date
+Mark_new_entries_with_owner_name=Mark_new_entries_with_owner_name
+Marked_selected=Marked_selected
+Medline_entries_fetched=Medline_entries_fetched
+Medline_XML=Medline_XML
+Medline_XML_File=Medline_XML_File
+Menu_and_label_font_size=Menu_and_label_font_size
+Merged_external_changes=Merged_external_changes
+messages=messages
+Messages=Messages
+Messages_and_Hints=Hints_and_Warnings
+Miscellaneous=Miscellaneous
+Modification_of_field=Modification_of_field
+Modified_group_"%0".=Modified_group_"%0".
+Modified_groups=Modified_groups
+Modified_groups_tree=Modified_groups_tree
+Modified_string=Modified_string
+Modify=Modify
+modify_group=modify_group
+MODS=MODS
+Move=Move
+Move_down=Move_down
+Move_entries_in_group_selection_to_the_top=Move_entries_in_group_selection_to_the_top
+move_group=move_group
+Move_matching_entries_to_the_top=Move_matching_entries_to_the_top
+Move_string_down=Move_string_down
+Move_string_up=Move_string_up
+Move_up=Move_up
+Moved_Group=Moved_Group
+Moved_group_"%0".=Moved_group_"%0".
+Name=Name
+Ne_entries_imported.=Ne_entries_imported.
+nested_aux_files=nested_aux_files
+New=New
+new=new
+New_article=New_article
+New_BibTeX_database=New_BibTeX_database
+New_BibTeX_entry=New_BibTeX_entry
+New_BibTeX_subdatabase=New_BibTeX_subdatabase
+New_book=New_book
+New_content=New_content
+New_database=New_database
+New_database_created.=New_database_created.
+New_entry=New_entry
+New_entry...=New_entry...
+New_entry_from_plain_text=New_entry_from_plain_text
+New_group=New_group
+New_inbook=New_inbook
+New_mastersthesis=New_mastersthesis
+New_phdthesis=New_phdthesis
+New_proceedings=New_proceedings
+New_string=New_string
+New_subdatabase=New_subdatabase
+New_subdatabase_based_on_AUX_file=New_subdatabase_based_on_AUX_file
+New_unpublished=New_unpublished
+Next_entry=Next_entry
+Next_tab=Next_tab
+No_%0_found=No_%0_found
+No_actual_changes_found.=No_actual_changes_found.
+no_base-bibtex-file_specified=no_base-bibtex-file_specified!
+no_database_generated=no_database_generated
+No_duplicates_found=No_duplicates_found
+No_entries_imported.=No_entries_imported.
+No_entries_or_multiple_entries_selected.=No_entries_or_multiple_entries_selected.
+No_entries_selected=No_entries_selected
+No_GUI._Only_process_command_line_options.=No_GUI._Only_process_command_line_options.
+No_Medline_entries_found.=No_Medline_entries_found.
+No_pdf_or_ps_defined,_and_no_file_matching_Bibtex_key_found=No_pdf_or_ps_defined,_and_no_file_matching_Bibtex_key_found
+No_references_found=No_references_found
+No_saved_session_found.=No_saved_session_found.
+No_url_defined=No_url_defined
+non-Mac_only=non-Mac_only
+not=not
+not_found=not_found
+Not_saved_(empty_session)=Not_saved_(empty_session)
+Note_that_the_entry_causing_the_problem_has_been_selected.=Note_that_the_entry_causing_the_problem_has_been_selected.
+Note_that_the_new_definitions_will_not_be_compatible_with_previous_JabRef_versions.=Note_that_the_new_definitions_will_not_be_compatible_with_previous_JabRef_versions.
+Note_that_you_must_specify_the_fully_qualified_class_name_for_the_look_and_feel,=Note_that_you_must_specify_the_fully_qualified_class_name_for_the_look_and_feel,
+Nothing_to_redo=Nothing_to_redo
+Nothing_to_undo=Nothing_to_undo
+# The next is used like in "References found: 1  Number of references to fetch?"
+Number_of_references_to_fetch?=Number_of_references_to_fetch?
+occurences=occurences
+OK=OK
+Ok=OK
+One_or_more_keys_will_be_overwritten._Continue?=One_or_more_keys_will_be_overwritten._Continue?
+Open=Open
+open=open
+Open_BibTeX_database=Open_BibTeX_database
+Open_database=Open_database
+Open_editor_when_a_new_entry_is_created=Open_editor_when_a_new_entry_is_created
+Open_file=Open_file
+Open_last_edited_databases_at_startup=Open_last_edited_databases_at_startup
+Open_PDF_or_PS=Open_PDF_or_PS
+Open_right-click_menu_with_Ctrl+left_button=Open_right-click_menu_with_Ctrl+left_button
+Open_URL_or_DOI=Open_URL_or_DOI
+Opened_database=Opened_database
+Opening=Opening
+Opening_preferences...=Opening_preferences...
+Optional_fields=Optional_fields
+Options=Options
+or=or
+out_of=out_of
+Output_or_export_file=Output_or_export_file
+Overlapping_groups=Overlapping_groups
+Override=Override
+override_the_bibtex_key_by_the_selected_text=override_the_bibtex_key_by_the_selected_text
+Overwrite_keys=Overwrite_keys
+Ovid=Ovid
+pairs_processed=pairs_processed
+Paste=Paste
+paste_entries=paste_entries
+paste_entry=paste_entry
+Paste_from_clipboard=Paste_from_clipboard
+Pasted=Pasted
+Path_to_HTML_viewer=Path_to_HTML_viewer
+Path_to_LyX_pipe=Path_to_LyX_pipe
+Path_to_PDF_viewer=Path_to_PDF_viewer
+Path_to_PS_viewer=Path_to_PS_viewer
+Path_to_WinEdt.exe=Path_to_WinEdt.exe
+Paths_to_external_programs=Paths_to_external_programs
+PDF_links=PDF_links
+Pick_titles=Pick_titles
+Plain_right_menu=Plain_right_menu
+Plain_text=Plain_text
+Plain_text_import=Plain_text_import
+Please_check_your_network_connection_to_this_machine.=Please_check_your_network_connection_to_this_machine.
+Please_define_BibTeX_key_first=Please_define_BibTeX_key_first
+Please_enter_a_name_for_the_group.=Please_enter_a_name_for_the_group.
+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>=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% [...]
+Please_enter_a_semicolon_or_comma_separated_list_of_Medline_IDs_(numbers).=Please_enter_a_semicolon_or_comma_separated_list_of_Medline_IDs_(numbers).
+Please_enter_the_field_to_search_(e.g._<b>keywords</b>)_and_the_keyword_to_search_it_for_(e.g._<b>electrical</b>).=Please_enter_the_field_to_search_(e.g._<b>keywords</b>)_and_the_keyword_to_search_it_for_(e.g._<b>electrical</b>).
+Please_enter_the_string's_label=Please_enter_the_string's_label
+Please_refer_to_the_JabRef_help_manual_on_using_the_CiteSeer_tools.=Please_refer_to_the_JabRef_help_manual_on_using_the_CiteSeer_tools.
+Please_select_exactly_one_group_to_move.=Please_select_exactly_one_group_to_move.
+Please_wait_until_it_has_finished.=Please_wait_until_it_has_finished.
+Possible_duplicate_entries=Possible_duplicate_entries
+Possible_duplicate_of_existing_entry._Click_to_resolve.=Possible_duplicate_of_existing_entry._Click_to_resolve.
+Preamble=Preamble
+Preamble_editor,_store_changes=Preamble_editor,_store_changes
+Preferences=Preferences
+Preferences_recorded=Preferences_recorded
+Preferences_recorded.=Preferences_recorded.
+Preserve_formatting_of_non-BibTeX_fields=Preserve_formatting_of_non-BibTeX_fields
+Preview=Preview
+Previous_entry=Previous_entry
+Previous_tab=Previous_tab
+Problem_with_parsing_entry=Problem_with_parsing_entry
+PS_links=PS_links
+push_selection_to_lyx=Push_selection_to_LyX
+Push_selection_to_WinEdt=Push_selection_to_WinEdt
+Push_to_LyX=Push_to_LyX
+Push_to_WinEdt=Push_to_WinEdt
+Pushed_the_citations_for_the_following_rows_to=Pushed_the_citations_for_the_following_rows_to
+Query_author(s)=Query_author(s)
+Quit=Quit
+Quit_JabRef=Quit_JabRef
+Quit_synchronization=Quit_synchronization
+Raw_source=Raw_source
+Really_delete_the_selected=Really_delete_the_selected
+Recent_files=Recent_files
+Redo=Redo
+Refer/Endnote=Refer/Endnote
+Reference_database=Reference_database
+# The next two lines are used like in "References found: 1  Number of references to fetch?"
+References_found=References_found
+Refine_supergroup:_When_selected,_view_entries_contained_in_both_this_group_and_its_supergroup=Refine_supergroup:_When_selected,_view_entries_contained_in_both_this_group_and_its_supergroup
+Refresh_view=Refresh_view
+Regexp=Regexp
+Regular_Expression=Regular_Expression
+Remember_these_entry_types?=Remember_these_entry_types?
+Remote_operation=Remote_operation
+Remote_server_port=Remote_server_port
+Remove=Remove
+Remove_all?=Remove_all?
+Remove_all_subgroups=Remove_subgroups
+Remove_all_subgroups_of_"%0"?=Remove_all_subgroups_of_"%0"?
+Remove_duplicates=Remove_duplicates
+Remove_entry_from_import=Remove_entry_from_import
+Remove_entry_type=Remove_entry_type
+remove_from_group=remove_from_group
+Remove_from_group=Remove_from_group
+Remove_group=Remove_group
+Remove_group,_keep_subgroups=Remove_group,_keep_subgroups
+Remove_group_"%0"?=Remove_group_"%0"?
+Remove_group_"%0"_and_its_subgroups?=Remove_group_"%0"_and_its_subgroups?
+remove_group_(keep_subgroups)=remove_group_(keep_subgroups)
+remove_group_and_subgroups=remove_group_and_subgroups
+Remove_group_and_subgroups=Remove_group_and_subgroups
+Remove_old_entry=Remove_old_entry
+Remove_selected_strings=Remove_selected_strings
+remove_string=remove_string
+remove_string_=remove_string_
+Removed_entry_type.=Removed_entry_type.
+Removed_group=Removed_group
+Removed_group_"%0".=Removed_group_"%0".
+Removed_group_"%0"_and_its_subgroups.=Removed_group_"%0"_and_its_subgroups.
+Removed_string=Removed_string
+Renamed_string=Renamed_string
+Repeat_incremental_search=Repeat_incremental_search
+Replace=Replace
+Replace_string=Replace_string
+Replace_with=Replace_with
+Replaced=Replaced
+Required_fields=Required_fields
+Reset_all=Reset_all
+resolved=resolved
+Results=Results
+Revert_to_original_source=Revert_to_original_source
+Review_changes=Review_changes
+Right=Right
+RIS=RIS
+Save=Save
+Save_before_closing=Save_before_closing
+Save_database=Save_database
+Save_database_as_...=Save_database_as_...
+Save_selected_as_...=Save_selected_as_...
+Save_session=Save_session
+Saved_database=Saved_database
+Saved_selected_to=Saved_selected_to
+Saved_session=Saved_session
+Saving=Saving
+Scan=Scan
+SciFinder=SciFinder
+Search=Search
+Search_All_Fields=Search_All_Fields
+Search_all_fields=Search_all_fields
+Search_error=Search_error
+Search_expression=Search_expression
+Search_for=Search_for
+Search_General_Fields=Search_General_Fields
+Search_general_fields=Search_general_fields
+Search_Optional_Fields=Search_Optional_Fields
+Search_optional_fields=Search_optional_fields
+Search_Required_Fields=Search_Required_Fields
+Search_required_fields=Search_required_fields
+Search_Specified_Field(s)=Search_Specified_Field(s)
+Search_term=Search_term
+Searched_database._Number_of_hits=Searched_database._Number_of_hits
+Searching_for_%0_file=Searching_for_%0_file
+Searching_for_duplicates...=Searching_for_duplicates...
+Secondary_sort_criterion=Secondary_sort_criterion
+Select=Select
+Select_action=Select_action
+Select_all=Select_all
+Select_entries_in_group_selection=Select_entries_in_group_selection
+Select_entry_type=Select_entry_type
+Select_format=Select_format
+Select_matches=Select_matches
+Select_matching_entries=Select_matching_entries
+Select_the_tree_nodes_to_view_and_accept_or_reject_changes=Select_the_tree_nodes_to_view_and_accept_or_reject_changes
+Selector_enabled_fields=Selector_enabled_fields
+Set_general_fields=Set_general_fields
+Set_table_font=Set_table_font
+Set_up_general_fields=Set_up_general_fields
+Settings=Settings
+Setup_selectors=Setup_selectors
+Short_form=Short_form
+Shortcut=Shortcut
+Show/edit_BibTeX_source=Show/edit_BibTeX_source
+Show_'Firstname_Lastname'=Show_'Firstname_Lastname'
+Show_'Lastname,_Firstname'=Show_'Lastname,_Firstname'
+Show_abstract=Show_abstract
+Show_BibTeX_source_by_default=Show_BibTeX_source_by_default
+Show_BibTeX_source_panel=Show_BibTeX_source_panel
+Show_CiteSeer_column=Show_CiteSeer_column
+Show_confirmation_dialog_when_deleting_entries=Show_confirmation_dialog_when_deleting_entries
+Show_dynamic_groups_in_<i>italics</i>=Show_dynamic_groups_in_<i>italics</i>
+Show_entries_*not*_in_group_selection=Show_entries_*not*_in_group_selection
+Show_general_fields=Show_general_field
+Show_groups_matching_all=Show_groups_matching_all
+Show_groups_matching_any=Show_groups_matching_any
+Show_icons_for_groups=Show_icons_for_groups
+Show_names_unchanged=Show_names_unchanged
+Show_one_less_rows=Show_one_less_rows
+Show_one_more_row=Show_one_more_row
+Show_optional_fields=Show_optional_field
+Show_overlapping_groups=Show_overlapping_groups
+Show_PDF/PS_column=Show_PDF/PS_column
+Show_required_fields=Show_required_fields
+Show_URL/DOI_column=Show_URL/DOI_column
+Show_warning_dialog_when_a_duplicate_BibTeX_key_is_entered=Show_warning_dialog_when_a_duplicate_BibTeX_key_is_entered
+Show_warning_dialog_when_an_empty_BibTeX_key_is_entered=Show_warning_dialog_when_an_empty_BibTeX_key_is_entered
+Simple_HTML=Simple_HTML
+Sixpack=Sixpack
+Size_of_groups_interface_(rows)=Size_of_groups_interface_(rows)
+Skip=Skip
+Sort_alphabetically=Sort_alphabetically
+Sort_Automatically=Sort_automatically
+Sort_options=Sort_options
+sort_subgroups=sort_subgroups
+Sorted_all_subgroups_recursively=Sorted_all_subgroups_recursively
+Sorted_all_subgroups_recursively.=Sorted_all_subgroups_recursively.
+Sorted_immediate_subgroups=Sorted_immediate_subgroups
+Sorted_immediate_subgroups.=Sorted_immediate_subgroups.
+source_edit=source_edit
+Special_table_columns=Special_table_columns
+Start=Start
+Start_incremental_search=Start_incremental_search
+Start_search=Start_search
+Statically_group_entries_by_manual_assignment=Statically_group_entries_by_manual_assignment
+Status=Status
+Stop=Stop
+Store=Store
+Store_fields_with_double_braces,_and_remove_extra_braces_when_loading.<BR>Double_braces_signal_that_BibTeX_should_preserve_character_case.=Store_fields_with_double_braces,_and_remove_extra_braces_when_loading.<BR>Double_braces_signal_that_BibTeX_should_preserve_character_case.
+Store_string=Store_string
+Stored_definition_for_type=Stored_definition_for_type
+Stored_entry=Stored_entry
+Stored_entry.=Stored_entry.
+Strings=Strings
+Strings_for_database=Strings_for_database
+subdatabase_from_aux=bibtex_from_LaTex_aux
+Subdatabase_from_aux=Subdatabase_from_aux
+Suggest=Suggest
+Switch_preview_layout=Switch_preview_layout
+Synchronize_%0_links=Synchronize_%0_links
+Synchronizing_%0_links...=Synchronizing_%0_links...
+Table=Table
+Table_appearance=Table_appearance
+Tabname=Tabname
+Tertiary_sort_criterion=Tertiary_sort_criterion
+Test=Test
+Text_Input_Area=paste_text_here
+The_#_character_is_not_allowed_in_BibTeX_fields=The_#_character_is_not_allowed_in_BibTeX_fields
+The_CiteSeer_fetch_operation_returned_zero_results.=The_CiteSeer_fetch_operation_returned_zero_results.
+the_field_<b>%0</b>=the_field_<b>%0</b>
+The_file<BR>'%0'<BR>has_been_modified<BR>externally!=The_file<BR>'%0'<BR>has_been_modified<BR>externally!
+The_group_"%0"_already_contains_the_selection.=The_group_"%0"_already_contains_the_selection.
+The_group_"%0"_does_not_support_the_adding_of_entries.=The_group_"%0"_does_not_support_the_adding_of_entries.
+The_group_"%0"_does_not_support_the_removal_of_entries.=The_group_"%0"_does_not_support_the_removal_of_entries.
+The_label_of_the_string_can_not_be_a_number.=The_label_of_the_string_can_not_be_a_number.
+The_label_of_the_string_can_not_contain_spaces.=The_label_of_the_string_can_not_contain_spaces.
+The_label_of_the_string_can_not_contain_the_'#'_character.=The_label_of_the_string_can_not_contain_the_'#'_character.
+The_output_option_depends_on_a_valid_import_option.=The_output_option_depends_on_a_valid_import_option.
+The_regular_expression_<b>%0</b>_is_invalid%c=The_Regular_Expression_<b>%0</b>_is_invalid%c
+The_search_is_case_insensitive.=The_search_is_case_insensitive.
+The_search_is_case_sensitive.=The_search_is_case_sensitive.
+The_string_has_been_removed_locally=The_string_has_been_removed_locally
+The_type_name_can_not_contain_spaces.=The_type_name_can_not_contain_spaces.
+The_URL_field_appears_to_be_empty_on_entry_number_=The_URL_field_appears_to_be_empty_on_entry_number_
+There_are_possible_duplicates_(marked_with_a_'D'_icon)_that_haven't_been_resolved._Continue?=There_are_possible_duplicates_(marked_with_a_'D'_icon)_that_haven't_been_resolved._Continue?
+There_is_no_entry_type=There_is_no_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?=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?
+this_button_will_update=this_button_will_update
+this_button_will_update_the_column_width_settings<BR>to_match_the_current_widths_in_your_table=this_button_will_update_the_column_width_settings<BR>to_match_the_current_widths_in_your_table
+This_entry_is_incomplete=This_entry_is_incomplete
+This_entry_type_cannot_be_removed.=This_entry_type_cannot_be_removed.
+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.=This_group_contains_entries_based_on_manual_assignment._Entries_can_be_assigned_to_this_group_by_selecting_them_then_ [...]
+This_group_contains_entries_in_which=This_group_contains_entries_in_which
+This_group_contains_entries_in_which_any_field_contains_the_regular_expression_<b>%0</b>=This_group_contains_entries_in_which_any_field_contains_the_Regular_Expression_<b>%0</b>
+This_group_contains_entries_in_which_any_field_contains_the_term_<b>%0</b>=This_group_contains_entries_in_which_any_field_contains_the_term_<b>%0</b>
+This_group_contains_entries_whose_<b>%0</b>_field_contains_the_keyword_<b>%1</b>=This_group_contains_entries_whose_<b>%0</b>_field_contains_the_keyword_<b>%1</b>
+This_group_contains_entries_whose_<b>%0</b>_field_contains_the_regular_expression_<b>%1</b>=This_group_contains_entries_whose_<b>%0</b>_field_contains_the_Regular_Expression_<b>%1</b>
+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.=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.
+This_is_a_simple_copy_and_paste_dialog_for_import_some_fields_from_normal_text.=This_is_a_simple_copy_and_paste_dialog_for_import_some_fields_from_normal_text.
+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.=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.
+This_operation_cannot_work_on_multiple_rows.=This_operation_cannot_work_on_multiple_rows.
+Toggle_entry_preview=Toggle_entry_preview
+Toggle_groups_interface=Toggle_groups_interface
+Toggle_search_panel=Toggle_search_panel
+Tools=Tools
+Type=Type
+Type_set_to_'other'=Type_set_to_'other'
+unable_to_access_LyX-pipe=unable_to_access_LyX-pipe
+Unable_to_create_graphical_interface=Unable_to_create_graphical_interface
+Unable_to_parse_clipboard_text_as_Bibtex_entries.=Unable_to_parse_clipboard_text_as_Bibtex_entries.
+Unable_to_parse_the_following_URL=Unable_to_parse_the_following_URL
+unable_to_write_to=unable_to_write_to
+Undo=Undo
+Union=Union
+unknown_bibtex_entries=unknown_bibtex_entries
+Unknown_bibtex_entries=Unknown_bibtex_entries
+unknown_edit=unknown_edit
+unknown_entry_type=unknown_entry_type
+Unknown_export_format=Unknown_export_format
+Unmark_all=Unmark_all
+Unmark_entries=Unmark_entries
+Unmark_entry=Unmark_entry
+Unmarked_selected=Unmarked_selected
+Unpack_EndNote_filter_set=Unpack_EndNote_filter_set
+Unpacked_file=Unpacked_file
+Unpacked_file.=Unpacked_file.
+Unsupported_version_of_class_%0:_%1=Unsupported_version_of_class_%0:_%1
+untitled=untitled
+Up=Up
+Update_to_current_column_widths=Update_to_current_column_widths
+Updated_group_selection=Updated_group_selection
+Updating_entries...=Updating_entries...
+UPPER=UPPER
+Upper_Each_First=Upper_Each_First
+Upper_first=Upper_first
+usage=usage
+Use_antialiasing_font_in_table=Use_antialiasing_font_in_table
+Use_inspection_window_also_when_a_single_entry_is_imported.=Use_inspection_window_also_when_a_single_entry_is_imported.
+Use_other_look_and_feel=Use_other_look_and_feel
+Use_regular_expressions=Use_Regular_Expressions
+#the previous entry is translated in the menu "Tools" but is not in the file Menu_fr.properties!!!
+Use_the_following_delimiter=Use_the_following_delimiter
+Use_the_following_delimiter_character(s)=Use_the_following_delimiter_character(s)
+Uses_default_application=Uses_default_application
+Value_cleared_externally=Value_cleared_externally
+Value_set_externally=Value_set_externally
+verify_that_LyX_is_running_and_that_the_lyxpipe_is_valid=verify_that_LyX_is_running_and_that_the_lyxpipe_is_valid
+View=View
+Visible_fields=Visible_fields
+Warn_about_unresolved_duplicates_when_closing_inspection_window=Warn_about_unresolved_duplicates_when_closing_inspection_window
+Warn_before_overwriting_existing_keys=Warn_before_overwriting_existing_keys
+Warning=Warning
+Warning_there_is_a_duplicate_key=Warning_there_is_a_duplicate_key
+Warnings=Warnings
+web_link=web_link
+When_adding/removing_keywords,_separate_them_by=When_adding/removing_keywords,_separate_them_by
+with=with
+Word=Word
+Wrong_file_format=Wrong_file_format
+You_have_changed_the_language_setting._You_must_restart_JabRef_for_this_to_come_into_effect.=You_have_changed_the_language_setting._You_must_restart_JabRef_for_this_to_come_into_effect.
+You_have_cleared_this_field._Original_value=You_have_cleared_this_field._Original_value
+You_must_enter_an_integer_value_in_the_text_field_for=You_must_enter_an_integer_value_in_the_text_field_for
+You_must_fill_in_a_name_for_the_entry_type.=You_must_fill_in_a_name_for_the_entry_type.
+You_must_provide_a_name,_a_search_string_and_a_field_name_for_this_group.=You_must_provide_a_name,_a_search_string_and_a_field_name_for_this_group.
+You_must_restart_JabRef_for_the_new_key_bindings_to_work_properly.=You_must_restart_JabRef_for_the_new_key_bindings_to_work_properly.
+You_must_select_a_row_to_perform_this_operation.=You_must_select_a_row_to_perform_this_operation.
+You_must_select_at_least_one_row_to_perform_this_operation.=You_must_select_at_least_one_row_to_perform_this_operation.
+You_must_set_both_BibTeX_key_and_%0_directory=You_must_set_both_BibTeX_key_and_%0_directory
+You_must_set_both_bibtex_key_and_PDF_directory=You_must_set_both_bibtex_key_and_PDF_directory
+Your_new_key_bindings_have_been_stored.=Your_new_key_bindings_have_been_stored.
+Manage_custom_imports=Manage_custom_imports
+Select_Classpath_of_New_Importer=Select_Classpath_of_New_Importer
+Select_new_ImportFormat_Subclass=Select_new_ImportFormat_Subclass
+Could_not_instantiate_%0_%1=Could_not_instantiate_%0_%1
+Add_a_(compiled)_custom_ImportFormat_class_from_a_class_path._\nThe_path_need_not_be_on_the_classpath_of_JabRef.=Add_a_(compiled)_custom_ImportFormat_class_from_a_class_path._\nThe_path_need_not_be_on_the_classpath_of_JabRef.
+Please_select_an_importer=Please_select_an_importer
+Import_name=Import_name
+Command_line_id=Command_line_id
+ImportFormat_class=ImportFormat_class
+Contained_in=Contained_in
+Show_description=Show_description
+Add_from_folder=Add_from_folder
+Custom_importers=Custom_importers
+No_custom_imports_registered_yet.=No_custom_imports_registered_yet.
+Abbreviate_journal_names_of_the_selected_entries_(ISO_abbreviation)=Abbreviate_journal_names_of_the_selected_entries_(ISO_abbreviation)
+Abbreviate_journal_names_of_the_selected_entries_(MEDLINE_abbreviation)=Abbreviate_journal_names_of_the_selected_entries_(MEDLINE_abbreviation)
+Background_color_for_marked_entries=Background_color_for_marked_entries
+Background_color_for_optional_fields=Background_color_for_optional_fields
+Background_color_for_required_fields=Background_color_for_required_fields
+Choose_the_URL_to_download._The_default_value_points_to_a_list_provided_by_the_JabRef_developers.=Choose_the_URL_to_download._The_default_value_points_to_a_list_provided_by_the_JabRef_developers.
+Color_for_marking_incomplete_entries=Color_for_marking_incomplete_entries
+Do_not_abbreviate_names=Do_not_abbreviate_names
+Do_not_wrap_the_following_fields_when_saving=Do_not_wrap_the_following_fields_when_saving
+External_files=External_files
+File_'%0'_not_found=File_'%0'_not_found
+Journal_abbreviations=Journal_abbreviations
+Journal_name=Journal_name
+Manage_journal_abbreviations=Manage_journal_abbreviations
+Natbib_style=Natbib_style
+New_file=New_file
+Personal_journal_list=Personal_journal_list
+Remove_double_braces_around_BibTeX_fields_when_loading.=Remove_double_braces_around_BibTeX_fields_when_loading.
+Store_the_following_fields_with_braces_around_capital_letters=Store_the_following_fields_with_braces_around_capital_letters
+Table_background_color=Table_background_color
+Table_grid_color=Table_grid_color
+Table_text_color=Table_text_color
+Toggle_abbreviation=Toggle_abbreviation
+Unabbreviate_journal_names_of_the_selected_entries=Unabbreviate_journal_names_of_the_selected_entries
+Use_antialiasing_font=Use_antialiasing_font
+Abbreviate_names=Abbreviate_names
+Abbreviation=Abbreviation
+ISO_abbreviation=ISO_abbreviation
+Edit_journal=Edit_journal
+Existing_file=Existing_file
+Saving_database=Saving_database
+Normal=Normal
+Default_sort_criteria=Default_sort_criteria
+Primary_sort_criterion=Primary_sort_criterion
+Database_properties=Database_properties
+Database_encoding=Database_properties
+
+No_journal_names_could_be_abbreviated.=No_journal_names_could_be_abbreviated.
+No_journal_names_could_be_unabbreviated.=No_journal_names_could_be_unabbreviated.
+Save_failed=Save_failed
+Pushed_citations_to_WinEdt=Pushed_citations_to_WinEdt
+Try_different_encoding=Try_different_encoding
+Select_encoding=Select_encoding
+The_chosen_date_format_for_new_entries_is_not_valid=The_chosen_date_format_for_new_entries_is_not_valid
+Invalid_date_format=Invalid_date_format
+Review=Review
+Journal_names=Journal_names
+Save_failed_during_backup_creation=Save_failed_during_backup_creation
+Save_failed_while_committing_changes=Save_failed_while_committing_changes
+Full_name=Full_name
+Store_journal_abbreviations=Store_journal_abbreviations
+You_must_choose_a_file_name_to_store_journal_abbreviations=You_must_choose_a_file_name_to_store_journal_abbreviations
+Journal_list_preview=Journal_list_preview
+
+Add_from_jar=Add_from_jar
+Add_a_(compiled)_custom_ImportFormat_class_from_a_Zip-archive.\nThe_Zip-archive_need_not_be_on_the_classpath_of_JabRef.=Add_a_(compiled)_custom_ImportFormat_class_from_a_Zip-archive.\nThe_Zip-archive_need_not_be_on_the_classpath_of_JabRef.
+Select_a_Zip-archive=Select_a_Zip-archive
+Select_file_from_ZIP-archive=Select_file_from_ZIP-archive
+Last_modified=Last_modified
+Size=Size
+Please_select_an_importer.=Please_select_an_importer.
+
+Arguments_passed_on_to_running_JabRef_instance._Shutting_down.=Arguments_passed_on_to_running_JabRef_instance._Shutting_down.
+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').=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').
+Pushed_citations_to_Emacs=Pushed_citations_to_Emacs
+Push_selection_to_Emacs=Push_selection_to_Emacs
+
+Filter=Filter
+Hide_non-matching_entries=Hide_non-matching_entries
+Replace_(regular_expression)=Replace_(regular_expression)
+Cite_command_(for_Emacs/WinEdt)=Cite_command_(for_Emacs/WinEdt)
+No_entries_found._Please_make_sure_you_are_using_the_correct_import_filter.=No_entries_found._Please_make_sure_you_are_using_the_correct_import_filter.
+
+Could_not_instantiate_%0_%1._Have_you_chosen_the_correct_package_path?=Could_not_instantiate_%0_%1._Have_you_chosen_the_correct_package_path?
+
+Switches_between_full_and_abbreviated_journal_name_if_the_journal_name_is_known.=Switches_between_full_and_abbreviated_journal_name_if_the_journal_name_is_known.
+To_set_up,_go_to_<B>Tools_->_Manage_journal_abbreviations</B>=To_set_up,_go_to_<B>Tools_->_Manage_journal_abbreviations</B>
+
+Could_not_run_the_'gnuclient'_program._Make_sure_you_have_the_gnuserv/gnuclient_programs_installed.=Could_not_run_the_'gnuclient'_program._Make_sure_you_have_the_gnuserv/gnuclient_programs_installed.
diff --git a/src/resource/JabRef_fr.properties b/src/resource/JabRef_fr.properties
new file mode 100644
index 0000000..046a0f1
--- /dev/null
+++ b/src/resource/JabRef_fr.properties
@@ -0,0 +1,1025 @@
+#! created/edited by Popeye version 0.51 sunshine (popeye.sourceforge.net)
+
+!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.=!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.
+%0_contains_the_Regular_Expression_<b>%1</b>=%0_contient_l'expression_r\u00e9guli\u00e8re_<b>%1</b>
+%0_contains_the_term_<b>%1</b>=%0_contient_le_terme_<b>%1</b>
+%0_doesn't_contain_the_Regular_Expression_<b>%1</b>=%0_ne_contient_pas_l'expression_r\u00e9guli\u00e8re_<b>%1</b>
+%0_doesn't_contain_the_term_<b>%1</b>=%0_ne_contient_pas_le_terme_<b>%1</b>
+%0_doesn't_match_the_Regular_Expression_<b>%1</b>=%0_ne_correspond_pas_\u00e0_l'expression_r\u00e9guli\u00e8re_<b>%1</b>
+%0_doesn't_match_the_term_<b>%1</b>=%0_ne_correspond_pas_au_terme_<b>%1</b>
+%0_field_set=D\u00E9finition_du_champ_%0
+%0_import_cancelled.=%0_importation_interrompue.
+%0_matches_the_Regular_Expression_<b>%1</b>=%0_correspond_\u00e0_l'expression_r\u00e9guli\u00e8re_<b>%1</b>
+%0_matches_the_term_<b>%1</b>=%0_correspond_au_terme_<b>%1</b>
+<field_name>=<nom_de_champ>
+<HTML>Unpack_the_zip_file_containing_import/export_filters_for_Endnote,<BR>for_optimal_interoperability_with_JabRef</HTML>=<HTML>D\u00E9compacter_le_fichier_zip_contenant_les_filtres_import/export_pour_Endnote,<BR>pour_une_interop\u00E9rabilit\u00E9_optimale_avec_JabRef</HTML>
+<no_field>=<pas_de_champ>
+<select>=<s\u00E9lectionner>
+<select_word>=<entrer_le_mot-clef>
+_on_entry_number_=_pour_le_num\u00e9ro_d'entr\u00e9e_
+A_CiteSeer_fetch_operation_is_currently_in_progress.=Une_op\u00E9ration_de_recherche_sur_CiteSeer_est_en_cours.
+A_CiteSeer_import_operation_is_currently_in_progress.=Une_op\u00E9ration_d'importation_depuis_CiteSeer_est_en_cours.
+A_string_with_that_label_already_exists=Une_cha\u00EEne_avec_ce_nom_existe_d\u00E9j\u00E0
+About_JabRef=A_propos_de_JabRef
+Abstract=R\u00e9sum\u00e9
+Accept=Valider
+Accept_change=Accepter_la_modification
+Action=Action
+Add=Ajouter
+add_entries_to_group=ajouter_des_entr\u00e9es_au_groupe
+add_group=ajouter_un_groupe
+Add_Group=Ajouter_un_groupe
+Add_new=Ajouter_nouvelle
+Add_Subgroup=Ajouter_un_sous-groupe
+Add_to_group=Ajouter_au_groupe
+Added_entry=Entr\u00E9e_ajout\u00E9e
+Added_group=Groupe_ajout\u00e9
+Added_group_"%0".=Groupe_"%0"_ajout\u00e9.
+Added_new=Nouvel_ajout
+Added_string=Cha\u00EEne_ajout\u00E9e
+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.=De_plus,_des_entr\u00e9es_dont_le_champ_<b>%0</b>_ne_contient_pas_<b>%1 [...]
+Advanced=Avanc\u00E9
+Advanced_options_for_setting...=Options_avanc\u00e9es_pour_la_configuration...
+All_Entries=Toutes_les_entr\u00e9es
+All_entries=Toutes_les_entr\u00E9es
+All_entries_of_this_type_will_be_declared_typeless._Continue?=Toutes_les_entr\u00E9es_similaires_seront_consid\u00E9r\u00E9es_sans_type._Continuer_?
+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_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
+Append=Ajouter
+Append_contents_from_a_BibTeX_database_into_the_currently_viewed_database=Ajouter_le_contenu_d'une_base_BibTeX_\u00E0_la_base_actuelle
+Append_database=Joindre_\u00E0_la_base
+append_the_selected_text_to_bibtex_key=ajouter_le_texte_s\u00e9lectionn\u00e9_\u00e0_la_clef_BibTeX
+Apply=Appliquer
+Assign_entries_based_on:=Attribuer_les_entr\u00E9es_selon_:
+Assign_new_file=Assigner_un_nouveau_fichier
+Assign_the_original_group's_entries_to_this_group?=Assigner_les_entr\u00e9es_originales_du_groupe_\u00e0_ce_groupe ?
+Assigned_%0_entries_to_group_"%1".=%0_entr\u00e9es_ajout\u00e9es_au_groupe_"%1".
+Assigned_1_entry_to_group_"%0".=Une_entr\u00e9e_ajout\u00e9e_au_groupe_"%0".
+Attach_%0_file=Attacher_le_fichier_%0
+Attach_URL=Attacher_l'URL
+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.=Cela_tente_de_d\u00e9finir_automatiquement_les_liens_%0_de_vos_entr\u00e9es._La_d\u00e9finition_automatique_fonctionne_si_un_fichier_%0_dans_votre_r\u00e9pertoire_%0_ou_dans_un_sous-r\u00e9pertoire<BR>porte_le_m\u00eame_nom_que_la_clef_d'une_entr\u00e9e_BibTeX,_l'extension_en_plus.
+Auto=Auto
+Autodetect_format=D\u00E9tection_automatique_du_format
+Autogenerate_BibTeX_key=Cr\u00E9ation_automatique_des_clefs_BibTeX
+Autogenerate_BibTeX_keys=Cr\u00E9ation_automatique_des_clefs_BibTeX
+Autogenerate_groups=Cr\u00E9ation_automatique_des_groupes
+autogenerate_keys=cr\u00E9ation_automatique_des_clefs
+Automatically_create_groups=Cr\u00E9er_automatiquement_des_groupes
+Automatically_create_groups_for_database.=Cr\u00E9er_automatiquement_des_groupes_pour_la_base.
+Automatically_created_groups=Groupes_cr\u00e9\u00e9s_automatiquement
+Automatically_hide_groups_interface_when_switching_to_a_database_that_contains_no_groups=Masquer_automatiquement_l'interface_des_groupes_lors_de_l'affichage_d'une_base_de_donn\u00e9es_qui_ne_contient_pas_de_groupes
+Automatically_show_groups_interface_when_switching_to_a_database_that_contains_groups=Afficher_automatiquement_l'interface_des_groupes_lors_de_l'affichage_d'une_base_de_donn\u00e9es_qui_contient_des_groupes
+Autoset=D\u00e9finir_automatiquement
+Autoset_%0_field=Auto-d\u00e9finition_du_champ_%0
+Autoset_%0_links._Allow_overwriting_existing_links.=D\u00e9finir_automatiquement_les_liens_%0._Ecraser_les_liens_existants.
+Autoset_%0_links._Do_not_overwrite_existing_links.=D\u00e9finir_automatiquement_les_liens_%0._Ne_pas_\u00e9craser_les_liens_existants.
+Autosetting_%0_field...=Auto-param\u00e9trage_du_champ_%0...
+AUX_File_import=G\u00E9n\u00E9rer_un_fichier_BibTeX_\u00E0_partir_de_fichier_AUX
+AUX_file_import=Importation_de_fichier_AUX
+Available_export_formats=Formats_d'exportation_disponibles
+Available_fields=Champs_BibTeX_disponibles
+Available_import_formats=Formats_d'importation_disponibles
+Backup_old_file_when_saving=Cr\u00E9er_une_copie_de_sauvegarde_lors_de_l'enregistrement
+Bibkey_to_filename_conversion=Conversion_de_la_clef_BibTeX_en_nom_de_fichier
+Biblioscape_Tag_file=Biblioscape_Tag
+BibTeX=BibTeX
+BibTeX_key=Clef_BibTeX
+BibTeX_key_is_unique.=La_clef_BibTeX_est_unique.
+BibTeX_key_not_set._Enter_a_name_for_the_downloaded_file=Clef_BibTeX_ind\u00E9finie._Entrer_un_nom_pour_le_fichier_t\u00E9l\u00E9charg\u00E9
+BibTeX_source=Source_BibTeX
+BibTeXML=BibTeXML
+BibTeXML_File=BibTeXML
+Binding=Affectation
+Broken_link=Lien_rompu
+Browse=Explorer
+by=par
+Calling_external_viewer...=Lancement_de_l'afficheur_externe...
+Cancel=Annuler
+Cannot_add_entries_to_group_without_generating_keys._Generate_keys_now?=Les_entr\u00e9es_ne_peuvent_pas_\u00eatre_ajout\u00e9es_au_groupe_sans_g\u00e9n\u00e9rer_des_clefs._Voulez-vous_g\u00e9n\u00e9rer_des_clefs_maintenant_?
+Cannot_merge_this_change=Cette_modification_ne_peut_pas_\u00EAtre_fusionn\u00E9e
+Cannot_move_group=Le_groupe_"%0"_ne_peut_pas_\u00eatre_d\u00e9plac\u00e9
+Cannot_move_group_"%0"_down.=Le_groupe_"%0"_ne_peut_pas_\u00eatre_d\u00e9plac\u00e9_vers_le_bas.
+Cannot_move_group_"%0"_left.=Le_groupe_"%0"_ne_peut_pas_\u00eatre_d\u00e9plac\u00e9_vers_la_gauche.
+Cannot_move_group_"%0"_right.=Le_groupe_"%0"_ne_peut_pas_\u00eatre_d\u00e9plac\u00e9_vers_la_droite.
+Cannot_move_group_"%0"_up.=Le_groupe_"%0"_ne_peut_pas_\u00eatre_d\u00e9plac\u00e9_vers_le_haut
+case_insensitive=insensible_\u00e0_la_casse
+case_sensitive=sensible_\u00e0_la_casse
+Case_sensitive=Sensible_\u00e0_la_casse
+change_assignment_of_entries=changer_l'assignation_des_entr\u00e9es
+Change_case=Changer_la_casse
+Change_entry_type=Changer_le_type_d'entr\u00E9e
+change_key=changer_la_clef
+Change_of_Grouping_Method=Changement_de_la_M\u00e9thode_de_Groupement
+change_preamble=changer_le_pr\u00E9ambule
+change_string_content=changer_le_contenu_de_la_cha\u00EEne
+change_string_name=changer_le_nom_de_la_cha\u00EEne
+change_type=changer_le_type
+changed_=chang\u00e9_
+Changed_font_settings=Param\u00E8tres_de_police_modifi\u00E9s
+Changed_language_settings=Param\u00E8tres_linguistiques_modifi\u00E9s
+Changed_look_and_feel_settings=Changer_les_param\u00e8tres_d'apparence
+Changed_preamble=Pr\u00E9ambule_modifi\u00E9
+Changed_type_to=Type_modifi\u00E9_en
+Characters_to_ignore=Caract\u00E8res_\u00E0_ignorer_
+Check_existing_%0_links=V\u00e9rifier_les_liens_%0_existants
+Check_links=V\u00e9rifier_les_liens
+Citation_import_from_CiteSeer_failed.=L'importation_des_citations_depuis_CiteSeer_a_\u00E9chou\u00E9e.
+CiteSeer_Error=Erreur_CiteSeer
+CiteSeer_Fetch_Error=Erreur_de_recherche_sur_CiteSeer
+CiteSeer_import_entries=Entr\u00E9es_d'importation_depuis_CiteSeer
+CiteSeer_Import_Error=Erreur_d'importation_depuis_CiteSeer
+CiteSeer_Import_Fields=Champs_d'importation_de_CiteSeer
+CiteSeer_Transfer=Transfert_de_CiteSeer
+CiteSeer_Warning=Avertissement_CiteSeer
+Class_name=Nom_de_classe
+Clear=Vider
+clear_all_groups=Vider_tous_les_groupes
+Clear_field=Vider_le_champ
+Clear_highlight=Vider_surlignements
+Clear_highlighted=Vider_surlign\u00e9s
+Clear_highlighted_groups=Vider_les_groupes_surlign\u00e9s
+Clear_inputarea=Vider_la_zone_de_saisie
+Clear_search=Effacer_la_recherche
+Close=Fermer
+Close_database=Fermer_la_base
+Close_dialog=Fermer_la_fen\u00EAtre
+Close_entry_editor=Fermer_l'\u00E9diteur_d'entr\u00E9e
+Close_preamble_editor=Fermer_l'\u00E9diteur_de_pr\u00E9ambule
+Close_the_current_database=Fermer_la_base_courante
+Close_the_help_window=Fermer_la_fen\u00EAtre_d'aide
+Close_window=Fermer_la_fen\u00EAtre
+Closed_database=Base_ferm\u00E9e
+Collapse_subtree=Masquer_le_sous-arbre
+Color_codes_for_required_and_optional_fields=Codes_de_couleurs_pour_les_champs_requis_et_optionnels
+Column_width=Largeur_de_colonne
+Complete_record=Compl\u00E9ter_l'enregistrement
+Completed_citation_import_from_CiteSeer.=Importation_des_citations_depuis_CiteSeer_termin\u00E9e.
+Completed_Import_Fields_from_CiteSeer.=Importation_des_champs_depuis_CiteSeer_termin\u00E9e.
+Completed_import_from_CiteSeer.=Importation_depuis_CiteSeer_termin\u00e9e.
+Content=Contenu
+Copied=Copi\u00E9
+Copied_cell_contents=Contenu_des_cellules_copi\u00e9
+Copied_key=Clef_copi\u00E9e
+Copied_keys=Clefs_copi\u00E9es
+Copy=Copier
+Copy_BibTeX_key=Copier_la_clef_BibTeX
+Copy_\\cite{BibTeX_key}=Copier_\\cite{clef_BibTeX}
+Copy_to_clipboard=Copier_le_texte_vers_le_presse-papiers
+Could_not_call_executable=L'ex\u00E9cutable_n'a_pas_pu_\u00EAtre_lanc\u00E9
+Could_not_connect_to_host=La_connexion_\u00e0_l'ordinateur_h\u00f4te_a_\u00e9chou\u00e9
+Could_not_connect_to_host_=La_connexion_\u00e0_l'ordinateur_h\u00f4te_a_\u00e9chou\u00e9_
+Could_not_export_entry_types=L'exportation_des_types_d'entr\u00e9es_a_\u00e9chou\u00e9
+Could_not_export_file=Le_fichier_n'a_pas_pu_\u00EAtre_export\u00E9
+Could_not_export_preferences=L'exportation_des_pr\u00e9f\u00e9rences_a_\u00e9chou\u00e9
+Could_not_find_a_suitable_import_format.=Un_format_d'importation_convenable_n'a_pas_pu_\u00EAtre_trouv\u00E9
+Could_not_find_layout_file=Fichier_de_mise_en_page_non_trouv\u00E9
+Could_not_import_entry_types=L'importation_des_types_d'entr\u00e9es_a_\u00e9chou\u00e9_
+Could_not_import_preferences=L'importation_des_pr\u00e9f\u00e9rences_a_\u00e9chou\u00e9_
+Could_not_resolve_import_format=Le_format_d'importation_n'a_pas_\u00e9t\u00e9_d\u00e9cod\u00e9_
+Could_not_save_file=Le_fichier_n'a_pas_pu_\u00EAtre_sauvegard\u00E9_
+Couldn't_find_an_entry_associated_with_this_URL=Aucune_entr\u00E9e_associ\u00E9e_\u00E0_cette_URL_n'a_\u00E9t\u00E9_trouv\u00E9e_
+Couldn't_parse_the_'citeseerurl'_field_of_the_following_entries=Le_champ_'citeseerurl'_n'a_pas_pu_\u00EAtre_trait\u00E9_dans_les_entr\u00E9es_suivantes_
+Create_group=Cr\u00E9er_le_groupe
+Created_group=Groupe_cr\u00E9\u00E9
+Created_group_"%0".=Groupe_"%0"_cr\u00e9\u00e9.
+Created_groups.=Groupes_cr\u00E9\u00E9s.
+Curly_braces_{_and_}_must_be_balanced.=Les_accolades_{_et_}_doivent_\u00EAtre_\u00E9quilibr\u00E9es.
+Current_content=Contenu_actuel
+Current_value=Valeur_actuelle_
+Custom_entry_types=Types_d'entr\u00E9es_personnalis\u00E9es
+Custom_entry_types_found_in_file=Types_d'entr\u00E9es_personnalis\u00E9es_trouv\u00E9es_dans_le_fichier
+Custom_export=Exportation_personnalis\u00E9e
+Customize_entry_types=Personnaliser_les_types_d'entr\u00E9es
+Customize_key_bindings=Personnaliser_les_affectations_de_touches
+Cut=Couper
+cut_entries=Couper_les_entr\u00E9es
+cut_entry=supprimer_l'entr\u00E9e
+Cut_pr=Couper
+Database_has_changed._Do_you_want_to_save_before_closing?=Base_modifi\u00E9e._Voulez-vous_la_sauvegarder_avant_de_fermer_?
+Date_format=Format_de_date
+Default=D\u00E9faut
+Default_encoding=Encodage_par_d\u00E9faut_
+Default_grouping_field=Champ_par_d\u00E9faut_pour_les_groupes_
+Default_look_and_feel=Apparence_par_d\u00E9faut
+Default_owner=Propri\u00E9taire_par_d\u00E9faut
+Default_pattern=Mod\u00E8le_par_d\u00E9faut
+defined.=d\u00E9fini(e).
+Delete=Supprimer
+Delete_custom=Supprimer_les_d\u00E9finitions_personnalis\u00E9es
+Delete_custom_format=Supprimer_le_format_personnalis\u00E9
+delete_entries=effacer_les_entr\u00E9es
+Delete_entry=Supprimer_l'entr\u00E9e
+delete_entry=effacer_l'entr\u00E9e
+Delete_multiple_entries=Effacer_plusieurs_entr\u00E9es
+Delete_rows=Supprimer_des_lignes
+Delete_strings=Supprimer_les_cha\u00EEnes
+Deleted=Supprim\u00E9
+Deleted_entry=Supprimer_l'entr\u00E9e
+Delimit_fields_with_semicolon,_ex.=D\u00E9limiter_les_champs_par_des_points-virgules,_ex.
+Descending=Descendant
+Description=Description
+Deselect_all=Tout_d\u00e9s\u00e9lectionner
+Details=D\u00E9tails
+Disable_entry_editor_when_multiple_entries_are_selected=D\u00E9sactiver_l'\u00E9diteur_en_cas_de_s\u00E9lections_multiples
+Disable_this_confirmation_dialog=D\u00E9sactiver_cette_demande_de_confirmation
+Disable_this_warning_dialog=D\u00E9sactiver_ce_message_d'avertissement
+Display_all_entries_belonging_to_one_or_more_of_the_selected_groups.=Afficher_toutes_les_entr\u00E9es_appartenant_\u00E0_au_moins_un_des_groupes_s\u00E9lectionn\u00E9s.
+Display_help_on_command_line_options=Afficher_l'aide_sur_les_options_de_la_ligne_de_commande
+Display_imported_entries_in_an_inspection_window_before_they_are_added.=Afficher_les_entr\u00e9es_import\u00e9es_dans_une_fen\u00eatre_d'inspection_avant_de_les_ajouter.
+Display_only_entries_belonging_to_all_selected_groups.=Afficher_uniquement_les_entr\u00E9es_appartenant_\u00E0_tous_les_groupes_s\u00E9lectionn\u00E9s.
+Displaying_no_groups=Pas_de_groupes_\u00E0_afficher
+Do_not_autoset=Ne_pas_d\u00e9finir_automatiquement.
+Do_not_import_entry=Ne_pas_importer_l'entr\u00e9e
+Do_not_open_any_files_at_startup=N'ouvrir_aucun_fichier_au_d\u00E9marrage
+Do_not_overwrite_existing_keys=Ne_pas_\u00e9craser_de_clefs_existantes
+Docbook=Docbook
+Done=Termin\u00E9
+Down=Bas
+Download=T\u00E9l\u00E9chargement
+Download_completed=T\u00E9l\u00E9chargement_termin\u00E9
+Download_file=T\u00E9l\u00E9charger_le_fichier
+Downloading...=T\u00E9l\u00E9chargement...
+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.=A_cause_de_la_clef_BibTeX_dupliqu\u00e9e,_les_assignations_de_groupes_de_cette_entr\u00e9e_ne_pourront_pas_\u00eatre_restaur\u00e9e_correctement_\u00e0_la_r\u00e9ouverture_de_cette_base_de_donn\u00e9es._Il_est_recommand\u00e9_de_demand\u00e9_\u00e0_JabRef_de_g\u00e9n\u0 [...]
+dummy=nul
+Duplicate_BibTeX_key=Dupliquer_la_clef_BibTeX
+duplicate_BibTeX_key=dupliquer_la_clef_BibTeX
+Duplicate_BibTeX_key.=Dupliquer_la_clef_BibTeX.
+duplicate_BibTeX_key.=dupliquer_la_clef_BibTeX.
+Duplicate_BibTeX_key._Grouping_may_not_work_for_this_entry.=Clef_BibTeX_dupliqu\u00e9e._Les_groupes_pourraient_ne_pas_fonctionner_pour_cette_entr\u00e9e.
+Duplicate_Key_Warning=Avertissement :_Clef_dupliqu\u00e9e
+Duplicate_pairs_found=Doublons_trouv\u00E9s
+duplicate_removal=Suppression_des_doublons
+Duplicate_string_name=Dupliquer_le_nom_de_cha\u00EEne
+Duplicates_found=Doublons_trouv\u00e9s
+Duplicates_removed=Doublons_supprim\u00e9s
+Dynamic_groups=Groupes_dynamiques
+Dynamically_group_entries_by_a_free-form_search_expression=Grouper_dynamiquement_les_entr\u00e9es_en_utilisant_une_expression_de_recherche_de_forme_libre
+Dynamically_group_entries_by_searching_a_field_for_a_keyword=Grouper_dynamiquement_les_entr\u00e9es_en_cherchant_un_mot-clef_dans_un_champ
+Each_line_must_be_on_the_following_form=Chaque_ligne_doit_\u00EA_de_la_forme_suivante
+Edit=Editer
+Edit_custom_export=Editer_l'exportation_personnalis\u00E9e
+Edit_entry=Editer_l'entr\u00E9e
+Edit_group=Editer_le_groupe
+Edit_preamble=Editer_le_pr\u00E9ambule
+Edit_strings=Editer_les_cha\u00EEnes
+empty_BibTeX_key=Clef_BibTeX_vide
+Empty_BibTeX_key.=Clef_BibTeX_vide.
+Empty_BibTeX_key._Grouping_may_not_work_for_this_entry.=Vider_la_clef_BibTeX._La_gestion_des_groupes_pourrait_ne_plus_fonctionner_pour_cette_entr\u00e9e.
+Empty_database=Base_vide
+empty_database=base_vide
+Enable source_editing=Autoriser_l'\u00e9dition_du_source
+Enable_source_editing=Autoriser_l'\u00e9dition_du_source
+Endnote=Endnote
+Enter_URL=Entrer_l'URL
+Enter_URL_to_download=Entrer_l'URL_de_t\u00E9l\u00E9chargement
+entries=entr\u00E9es
+Entries_cannot_be_manually_assigned_to_or_removed_from_this_group.=Des_entr\u00e9es_ne_peuvent_pas_ajout\u00e9es_ou_supprim\u00e9es_manuellement_de_ce_groupe.
+Entries_exported_to_clipboard=Entr\u00E9es_export\u00E9es_vers_le_presse-papiers
+entries_have_undefined_BibTeX_key=Des_entr\u00e9es_ont_des_clef_BibTeX_non_d\u00e9finies
+entries_into_new_database=entr\u00E9es_dans_la_nouvelle_base
+entry=entr\u00E9e
+Entry_editor=Editeur_d'entr\u00E9e
+Entry_editor,_next_entry=Editeur_d'entr\u00E9e,_entr\u00E9e_suivante
+Entry_editor,_next_panel=Editeur_d'entr\u00E9e,_fen\u00EAtre_suivante
+Entry_editor,_previous_entry=Editeur_d'entr\u00E9e,_entr\u00E9e_pr\u00E9c\u00E9dente
+Entry_editor,_previous_panel=Editeur_d'entr\u00E9e,_fen\u00EAtre_pr\u00E9c\u00E9dente
+Entry_editor,_store_field=Editeur_d'entr\u00E9e,_sauver_le_champ
+Entry_in_current_database=Entr\u00e9e_dans_la_base_de_donn\u00e9es_actuelle
+Entry_in_import=Entr\u00e9e_dans_l'importation
+Entry_is_incomplete=L'entr\u00E9e_est_incompl\u00E8te
+Entry_preview=Aper\u00E7u_de_l'entr\u00E9e
+Entry_table=Table_des_entr\u00E9es
+Entry_table_columns=Colonnes_de_la_table_des_entr\u00E9es
+Entry_type=Type_d'entr\u00E9e
+Entry_type_names_are_not_allowed_to_contain_white_space_or_the_following_characters=Les_noms_de_type_d'entr\u00E9e_ne_peuvent_pas_contenir_d'espace_et_les_caract\u00E8res_suivants
+Entry_types=Types_d'entr\u00E9es
+EOF_in_mid-string=Fin_de_fichier_au_milieu_d'une_cha\u00EEne
+Error=Erreur
+##Error:_check_your_External_viewer_settings_in_Preferences=Erreur :_v\u00e9rifier_les_param\u00e9trage_de_votre_visionneur_externe_dans_les_Options
+Error_in_field=Erreur_dans_le_champ
+Error_in_line=Erreur_\u00E0_la_ligne
+Error_opening_file=Erreur_lors_de_l'ouverture_du_fichier
+Error_setting_field=Erreur_de_configuration_du_champ
+exists._Overwrite?=existe._Ecraser_le_fichier ?
+exists._Overwrite_file?=existe._Ecraser_le_fichier ?
+Exit=Quitter
+Expand_subtree=D\u00e9velopper_le_sous-arbre
+Explicit=Explicite
+Export=Exporter
+Export_entry_types=Exporter_les_types_d'entr\u00e9es
+Export_name=Nom_de_l'exportation
+Export_preferences=Exporter_les_pr\u00E9f\u00E9rences
+Export_preferences_to_file=Exporter_les_pr\u00E9f\u00E9rences_vers_un_fichier
+Export_properties=Propri\u00E9t\u00E9s_de_l'exportation
+Export_selected_to_clipboard=Exporter_la_s\u00E9lection_vers_le_presse-papiers
+Export_to_clipboard=Exporter_vers_le_presse-papiers
+Exported_database_to_file=Base_export\u00E9e_dans_le_fichier
+Exporting=Exportation_en_cours
+External_changes=Modifications_externes
+External_programs=Programmes_externes
+External_viewer_called=Editeur_externe_lanc\u00E9
+Failed_to_read_groups_data_(unsupported_version:_%0)=La_lecture_des_donn\u00e9es_des_groupes_a_\u00e9chou\u00e9_(version_non_support\u00e9e :_%0)
+Fetch=Rechercher
+Fetch_Articles_Citing_your_Database=Rechercher_les_articles_citant_votre_base
+Fetch_Citations_from_CiteSeer=Rechercher_des_citations_depuis_CiteSeer
+Fetch_citations_from_CiteSeer=Rechercher_des_citations_depuis_CiteSeer
+Fetch_CiteSeer=Recherche_CiteSeer
+Fetch_Medline=Recherche_Medline
+fetch_Medline=recherche_Medline
+Fetch_Medline_by_author=Rechercher_sur_Medline_par_auteur
+Fetch_Medline_by_ID=Recherche_Medline_par_ID
+Fetched_all_citations_from_target_database.=Toutes_les_citations_ont_\u00E9t\u00E9_r\u00E9cup\u00E9r\u00E9es_depuis_la_base_cible.
+Fetching_Citations=Recherche_des_citations_en_cours
+Fetching_Identifiers=Recherche_des_identifiants
+Fetching_Medline...=Recherche_Medline_en_cours...
+Fetching_Medline_by_ID...=Recherche_sur_Medline_par_ID...
+Fetching_Medline_by_id_...=Recherche_sur_Medline_par_id...
+Fetching_Medline_by_term_...=Recherche_sur_Medline_par_terme...
+Field=Champ
+field=Champ
+Field_content=Contenu_du_champ
+Field_name=Nom_de_champ
+Field_names_are_not_allowed_to_contain_white_space_or_the_following_characters=Les_noms_de_champ_ne_peuvent_pas_contenir_d'espace_et_les_caract\u00E8res_suivants
+Field_sizes=Tailles_des_champs
+Field_to_group_by=Champ_\u00E0_grouper_par
+Field_to_search=Champ_pour_la_recherche
+Fields=Champs
+File=Fichier
+file=fichier
+File_changed=Fichier_chang\u00e9
+File_extension=Extension_de_fichier
+File_has_been_updated_externally._Are_you_sure_you_want_to_save?=Le_fichier_a_\u00E9t\u00E9_mis_\u00E0_jour_externalement._Etes-vous_certain_de_vouloir_l'enregistrer ?
+File_not_found=Fichier_non_trouv\u00E9
+File_updated_externally=Fichier_mis_\u00E0_jour_externalement
+filename=nom_de_fichier
+Files_opened=Fichiers_ouverts
+Find_duplicates=Chercher_les_doublons
+Finished_autosetting_%0_field._Entries_changed:_%1.=Auto-param\u00e9trage_du_champ_%0_termin\u00e9._Entr\u00e9es_chang\u00e9es :_%1.
+Finished_synchronizing_%0_links._Entries_changed%c_%1.=Synchronisation_des_liens_%0_termin\u00e9e._Entr\u00e9es_modifi\u00e9es%c_%1.
+First_select_the_entries_you_want_keys_to_be_generated_for.=Commencez_par_s\u00E9lectionner_les_entr\u00E9es_pour_lesquelles_vous_voulez_que_des_clefs_soient_g\u00E9n\u00E9r\u00E9es.
+Fit_table_horizontally_on_screen=Ajuster_la_table_horizontalement_\u00E0_l'\u00E9cran
+Float=Flottante
+Font_Family=Famille_de_police
+Font_Preview=Pr\u00E9visualisation_de_la_police
+Font_Size=Taille_de_police
+Font_Style=Style_de_police
+FontSelector=S\u00E9lecteur_de_police
+for=pour
+Format_of_author_and_editor_names=Format_des_noms_d'auteurs_et_d'\u00E9diteurs
+Format_used=Format_utilis\u00E9
+Formatter_not_found=Formateur_non_trouv\u00E9
+found=trouv\u00E9
+found_in_aux_file=trouv\u00E9es_dans_le_fichier_aux
+General=G\u00e9n\u00e9ral
+General_fields=Champs_g\u00E9n\u00E9raux
+Generate=Cr\u00E9er
+Generate_BibTeX_key=Cr\u00E9er_la_clef_BibTeX
+Generate_keys=G\u00e9n\u00e9rer_les_clefs
+Generate_now=G\u00e9n\u00e9rer_maintenant
+Generated_BibTeX_key_for=Cr\u00E9ation_termin\u00E9e_de_la_clef_BibTeX_pour
+Generating_BibTeX_key_for=Cr\u00E9ation_en_cours_d'une_clef_BibTeX_pour
+Grab=Rechercher
+Gray_out_entries_not_in_group_selection=Griser_les_entr\u00E9es_hors_de_la_s\u00E9lection
+Gray_out_non-hits=Griser_les_entr\u00E9es_non_correspondantes
+Gray_out_non-matching_entries=Griser_les_entr\u00E9es_non_correspondantes
+Group_definitions_have_been_converted_to_JabRef_1.7_format.=Les_d\u00E9finitions_des_groupes_ont_\u00E9t\u00E9_converties_au_format_JabRef_1.7
+Group_name=Nom_du_groupe_
+Group_properties=Propri\u00E9t\u00E9s_du_groupe
+Groups=Groupes
+Harvard_RTF=Harvard_RTF
+Help=Aide
+Help_contents=Contenu_de_l'aide
+Help_on_groups=Aide_sur_les_groupes
+Help_on_key_patterns=Aide_sur_le_param\u00E9trage_des_clefs
+Hide_non-hits=Masquer_les_entr\u00E9es_non_correspondantes
+Highlight=Surlign\u00E9e
+Highlight_groups_matching_all_selected_entries=Surligner_les_groupes_correspondant_\u00e0_toutes_les_entr\u00e9es_s\u00e9lectionn\u00e9es
+Highlight_groups_matching_any_selected_entry=Surligner_les_groupes_correspondant_\u00e0_au_moins_une_des_entr\u00e9es_s\u00e9lectionn\u00e9es
+Highlight_groups_that_contain_entries_contained_in_any_currently_selected_group=Surligner_les_groupes_qui_contiennent_des_entr\u00e9es_contenues_dans_n'importe_quel_groupe_s\u00e9lectionn\u00e9
+Highlight_overlapping_groups=Surligner_les_groupes_se_chevauchant
+Hint%c_To_search_specific_fields_only,_enter_for_example%c<p><tt>author%esmith_and_title%eelectrical</tt>=Astuce%c_Pour_chercher_uniquement_dans_des_champs_sp\u00e9cifiques,_entrez_par_exemple%c<p><tt>author%esmith_and_title%e\u00e9lectrique</tt>
+HTML=HTML
+Ignore=Ignorer
+Illegal_type_name=Nom_de_type_ill\u00e9gal
+Immediate_subgroups=Sous-groupes_directs
+Import=Importer
+Import_and_append=Importer_et_joindre
+Import_and_keep_old_entry=Importer_et_conserver_l'ancienne_entr\u00e9e
+Import_and_remove_old_entry=Importer_et_supprimer_l'ancienne_entr\u00e9e
+Import_cancelled.=Importation_interrompue.
+Import_Data_from_CiteSeer=Importer_les_donn\u00E9es_depuis_CiteSeer
+Import_Data_from_CiteSeer_Database=Importer_les_donn\u00E9es_depuis_la_base_CiteSeer
+Import_database=Importer_une_base
+Import_entries=Importer_les_entr\u00E9es
+Import_entry_types=Types_d'entr\u00e9es_import\u00e9s
+Import_failed=L'importation_a_\u00e9chou\u00e9e
+Import_Fields_from_CiteSeer=Importer_les_champs_depuis_CiteSeer
+Import_fields_from_CiteSeer=Importation_des_champs_\u00E0_partir_de_CiteSeer
+Import_fields_from_CiteSeer_Database=Importation_des_champs_\u00E0_partir_de_la_base_CiteSeer
+Import_Fields_from_CiteSeer_Database=Importer_les_champs_depuis_la_base_CiteSeer
+Import_file=Fichier_\u00E0_importer
+Import_group_definitions=Importer_les_d\u00E9finitions_de_groupe
+Import_plain_text=Importer_des_champs_\u00E0_partir_de_texte_brut
+Import_preferences=Importer_les_pr\u00E9f\u00E9rences
+Import_preferences_from_file=Importer_les_pr\u00E9f\u00E9rences_depuis_un_fichier
+Import_strings=Importer_les_cha\u00EEnes
+Import_to_open_tab=Importer_dans_l'onglet_ouvert
+Import_word_selector_definitions=Importer_les_d\u00E9finitions_des_s\u00E9lecteurs_de_mots
+Imported_database=Base_import\u00E9e
+Imported_entries=Entr\u00E9es_import\u00E9es
+Imported_entry_types=Types_d'entr\u00e9es_import\u00e9s
+Imported_file=Fichier_import\u00E9
+Imported_from_database=Import\u00e9_\u00e0_partir_de_la_base_de_donn\u00e9es
+Importing=Importation_en_cours
+Importing_file=Importation_de_fichier_en_cours
+Importing_in_unknown_format=Importation_dans_un_format_inconnu
+In_JabRef,_use_pairs_of_#_characters_to_indicate_a_string.=Dans_JabRef,_utiliser_une_paire_de_#_pour_d\u00E9limiter_une_cha\u00EEne.
+Include_subgroups=Inclure_les_sous-groupes
+Include_subgroups\:_When_selected,_view_entries_contained_in_this_group_or_its_subgroups=Inclut_les_sous-groupes_\:_Quand_s\u00e9lectionn\u00e9,_afficher_les_entr\u00e9es_contenues_dans_ce_groupe_ou_ses_sous-groupes
+Incremental=Incr\u00E9mentale
+Incremental_search=Recherche_incr\u00E9mentale
+Incremental_search_failed._Repeat_to_search_from_top.=La_recherche_incr\u00E9mentale_n'a_pas_abouti._R\u00E9p\u00E9ter_depuis_le_d\u00E9but.
+Independent=Ind\u00E9pendant
+Independent_group\:_When_selected,_view_only_this_group's_entries=Groupe_ind\u00e9pendant_\:_Quand_s\u00e9lectionn\u00e9,_afficher_uniquement_les_entr\u00e9es_de_ce_groupe
+Initially_show_groups_tree_expanded=Afficher_au_d\u00e9part_l'arbre_des_groupes_d\u00e9velopp\u00e9
+Input=Attribution_des_champs
+Input_error=Entr\u00E9e_erron\u00E9e
+Insert=Ins\u00E9rer
+Insert_rows=Ins\u00E9rer_des_lignes
+Insert_selected_citations_into_LyX/Kile=Envoyer_les_citations_s\u00E9lectionn\u00E9es_dans_LyX/Kile
+Insert_selected_citations_into_WinEdt=Envoyer_les_citations_s\u00E9lectionn\u00E9es_dans_&WinEdt
+insert_string_=ins\u00e9rer_la_cha\u00eene
+Insert_URL=Ins\u00E9rer_l'URL
+INSPEC=INSPEC
+integrity=int\u00e9grit\u00e9
+Integrity_check=V\u00e9rification_d'int\u00e9grit\u00e9
+Intersection=Intersection
+Intersection_with_supergroups=_Intersection_avec_super-groupes
+Invalid_BibTeX_key=Clef_BibTeX_invalide
+Invalid_URL=URL_invalide
+Inverted=Compl\u00E9mentaire
+is_a_standard_type.=est_un_type_standard.
+ISI=ISI
+Item_list_for_field=Liste_des_choix_pour_le_champ
+JabRef_help=Aide_de_JabRef
+JabRef_preferences=Pr\u00E9f\u00E9rences_pour_JabRef
+JStor_file=JStor
+Keep=Garder
+Keep_both=Garder_les_deux
+Keep_lower=Garder_celui_du_bas
+Keep_upper=Garder_celui_du_haut
+Key_bindings=Affectations_des_touches
+Key_bindings_changed=Affectations_des_touches_modifi\u00E9es
+Key_generator_settings=Param\u00e9trage_du_g\u00e9n\u00e9rateur_de_clef
+Key_pattern=Param\u00E9trage_des_clefs
+keys_in_database=clefs_dans_la_base_de_donn\u00e9es
+Keyword=Mot-clef
+Label=Nom_du_champ
+Language=Langue_
+Latex_AUX_file=Fichier_LaTeX_AUX
+LaTeX_AUX_file=Fichier_LaTeX_AUX
+Left=Gauche
+License=Licence
+Limit_to_fields=Restreindre_aux_champs
+Limit_to_selected_entries=Restreindre_aux_seules_entr\u00E9es_s\u00E9lectionn\u00E9es
+Listen_for_remote_operation_on_port=Ecouter_le_port_pour_des_op\u00e9rations_\u00e0_distance
+Load_session=Charger_la_session
+Loading_session...=Chargement_de_la_session...
+Look_and_feel=Apparence
+lower=minuscule
+Main_layout_file=Principal_fichier_de_mise_en_page
+Main_PDF_directory=R\u00E9pertoire_PDF_principal_
+Main_PS_directory=R\u00e9pertoire_PS_principal_
+Manage=G\u00E9rer
+Manage_content_selectors=G\u00E9rer_les_s\u00E9lecteurs_de_contenu
+Manage_custom_exports=G\u00E9rer_les_exportations_personnalis\u00E9es
+Mark_entries=Etiqueter_des_entr\u00E9es
+Mark_entry=Etiqueter_l'entr\u00E9e
+Mark_new_entries_with_addition_date=Enregistrer_la_date_d'ajout_pour_les_nouvelles_entr\u00e9es
+Mark_new_entries_with_owner_name=Nouvelles_entr\u00E9es_attribu\u00E9es_au_propri\u00E9taire_
+Marked_selected=Etiquetage_de_la_s\u00E9lection
+Medline_entries_fetched=Entr\u00E9es_Medline_r\u00E9cup\u00E9r\u00E9es
+Medline_XML=Medline_XML
+Medline_XML_File=Medline_XML
+Menu_and_label_font_size=Taille_de_police_pour_les_menus_et_les_champs_
+Merged_external_changes=Fusionner_les_modifications_externes
+messages=messages
+Messages=Messages
+Messages_and_Hints=Avertissements_et_Suggestions
+Miscellaneous=Divers
+Modification_of_field=Modification_du_champ
+Modified_group_"%0".=Groupe_"%0"_modifi\u00e9.
+Modified_groups=Groupes_modifi\u00e9s
+Modified_groups_tree=Arborescence_des_groupes_modifi\u00e9e
+Modified_string=Cha\u00EEne_modifi\u00E9e
+Modify=Modifier
+modify_group=Modifier_le_groupe
+MODS=MODS
+Move=D\u00e9placer
+Move_down=D\u00E9placer_vers_le_bas
+Move_entries_in_group_selection_to_the_top=D\u00E9placer_les_entr\u00E9es_s\u00E9lectionn\u00E9es_en_haut
+move_group=d\u00e9placer_le_groupe
+Move_matching_entries_to_the_top=D\u00E9placer_en_haut_les_entr\u00E9es_correspondant_aux_crit\u00E8res_de_recherche
+Move_string_down=D\u00E9placer_la_cha\u00EEne_vers_le_bas
+Move_string_up=D\u00E9placer_la_cha\u00EEne_vers_le_haut
+Move_up=D\u00E9placer_vers_le_haut
+Moved_Group=Groupe_d\u00e9plac\u00e9
+Moved_group_"%0".=Groupe_"%0"_d\u00e9plac\u00e9.
+Name=Nom
+nested_aux_files=fichiers_AUX_imbriqu\u00E9s
+New=Nouveau
+new=Nouveau
+New_article=Nouveau_'article'
+New_BibTeX_database=Nouvelle_base_BibTeX
+New_BibTeX_entry=Nouvelle_entr\u00E9e_BibTeX
+New_BibTeX_subdatabase=Nouveau_fichier_BibTeX
+New_book=Nouveau_'book'
+New_content=Nouveau_contenu
+New_database=Nouvelle_base
+New_database_created.=Nouvelle_base_cr\u00E9\u00E9e.
+New_entry=Nouvelle_entr\u00E9e
+New_entry...=Nouvelle_entr\u00E9e...
+New_entry_from_plain_text=Nouvelle_entr\u00E9e_depuis_texte_brut
+New_group=Nouveau_groupe
+New_inbook=Nouveau_'inbook'
+New_mastersthesis=Nouveau_'mastersthesis'
+New_phdthesis=Nouveau_'phdthesis'
+New_proceedings=Nouveau_'proceedings'
+New_string=Nouvelle_cha\u00EEne
+New_subdatabase=Nouveau_fichier
+New_subdatabase_based_on_AUX_file=Nouveau_fichier_BibTeX_depuis_fichier_AUX
+New_unpublished=Nouveau_'unpublished'
+Next_entry=Entr\u00E9e_suivante
+Next_tab=Onglet_suivant
+No_%0_found=Pas_de_%0_trouv\u00e9
+No_actual_changes_found.=Pas_de_changements_trouv\u00e9s.
+no_base-bibtex-file_specified=fichier_BibTeX_non_sp\u00e9cifi\u00e9 !
+no_database_generated=pas_de_base_cr\u00E9\u00E9e
+No_duplicates_found=Pas_de_doublons_trouv\u00e9s
+No_entries_imported.=Pas_d'entr\u00e9es_import\u00e9es.
+No_entries_or_multiple_entries_selected.=Pas_d'entr\u00E9e_s\u00E9lectionn\u00E9e_ou_s\u00E9lection_de_plusieurs_entr\u00E9es.
+No_entries_selected=Pas_d'entr\u00e9es_s\u00e9lectionn\u00e9es
+No_GUI._Only_process_command_line_options.=Pas_d'interface_utilisateur._Traitement_limit\u00E9_aux_options_de_la_ligne_de_commande.
+No_Medline_entries_found.=Pas_d'entr\u00e9es_Medline_trouv\u00e9es
+No_pdf_or_ps_defined,_and_no_file_matching_Bibtex_key_found=PDF_ou_PS_non_d\u00E9fini_et_fichier_correspondant_\u00E0_la_clef_BibTeX_non_trouv\u00E9.
+No_references_found=Aucune_r\u00E9f\u00E9rence_trouv\u00E9e
+No_saved_session_found.=Pas_trouv\u00E9_de_session_sauvegard\u00E9e.
+No_url_defined=Pas_d'URL_d\u00E9finie
+non-Mac_only=Uniquement_pour_les_non-Mac
+not=non
+not_found=non_trouv\u00E9
+Not_saved_(empty_session)=Pas_de_sauvegarde_(session_vide)
+Note_that_the_entry_causing_the_problem_has_been_selected.=Noter_que_l'entr\u00E9e_responsable_du_probl\u00E8me_a_\u00E9t\u00E9_s\u00E9lectionn\u00E9e.
+Note_that_the_new_definitions_will_not_be_compatible_with_previous_JabRef_versions.=Notez_que_les_nouvelles_d\u00E9finitions_ne_seront_pas_compatibles_avec_les_pr\u00E9c\u00E9dentes_versions_de_JabRef.
+Note_that_you_must_specify_the_fully_qualified_class_name_for_the_look_and_feel,=Notez_que_vous_devez_sp\u00E9cifier_le_nom_de_classe_complet_pour_l'apparence,
+Nothing_to_redo=Rien_\u00E0_r\u00E9p\u00E9ter
+Nothing_to_undo=Rien_\u00E0_annuler
+Number_of_references_to_fetch?=Nombre_de_r\u00E9f\u00E9rences_\u00E0_r\u00E9cup\u00E9rer_?
+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=ouvre
+Open_BibTeX_database=Ouvrir_une_base_BibTeX
+Open_database=Ouvrir_une_base
+Open_editor_when_a_new_entry_is_created=Ouvrir_l'\u00E9diteur_quand_une_nouvelle_entr\u00E9e_est_cr\u00E9\u00E9e
+Open_file=Ouvrir_le_fichier
+Open_last_edited_databases_at_startup=Ouvrir_les_fichiers_de_la_derni\u00E8re_session_au_d\u00E9marrage
+Open_PDF_or_PS=Ouvrir_PDF_ou_PS
+Open_right-click_menu_with_Ctrl+left_button=D\u00E9rouler_le_menu_contextuel_avec_Ctrl+clic_gauche
+Open_URL_or_DOI=Ouvrir_URL_ou_DOI
+Opened_database=Base_ouverte
+Opening=Ouverture_en_cours
+Opening_preferences...=Ouverture_des_pr\u00E9f\u00E9rences_en_cours...
+Optional_fields=Champs_optionnels
+Options=Options
+or=ou
+out_of=sur
+Output_or_export_file=Fichier_de_sortie_ou_d'exportation
+Overlapping_groups=Groupes_se_chevauchant
+Override=Remplacer
+override_the_bibtex_key_by_the_selected_text=remplacer_la_clef_BibTeX_par_le_texte_s\u00e9lectionn\u00e9
+Overwrite_keys=Ecraser_les_clefs
+Ovid=Ovid
+pairs_processed=paires_trait\u00E9es
+Paste=Coller
+paste_entries=Coller_les_entr\u00E9es
+paste_entry=Coller_l'entr\u00E9e
+Paste_from_clipboard=Coller_le_texte_depuis_le_presse-papiers
+Pasted=Coll\u00E9
+Path_to_HTML_viewer=Chemin_du_visionneur_HTML_
+Path_to_LyX_pipe=Chemin_du_canal_de_transmission_LyX_
+Path_to_PDF_viewer=Chemin_du_visionneur_PDF_
+Path_to_PS_viewer=Chemin_du_visionneur_PS_
+Path_to_WinEdt.exe=Chemin_de_WinEdt.exe_
+Paths_to_external_programs=Chemins_vers_les_programmes_externes.
+PDF_links=Liens_PDF
+Pick_titles=S\u00e9lectionnez_des_titres[?]
+Plain_right_menu=Menu_droit_brut_[?]
+Plain_text=Texte_brut
+Plain_text_import=Importation_de_texte_brut
+Please_check_your_network_connection_to_this_machine.=SVP,_v\u00E9rifiez_votre_connexion_r\u00E9seau_\u00E0_cette_machine.
+Please_define_BibTeX_key_first=SVP,_commencez_par_d\u00E9finir_la_clef_BibTeX
+Please_enter_a_name_for_the_group.=SVP,_entrez_un_nom_pour_le_groupe.
+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>=SVP,_entrez_un_terme_\u00e0_recherche._Par_exemple,_pour_rechercher_<b>Smith</b>_dans_tout_les_champs,_entrez %c<p><tt>smith</tt><p>Pour_rechercher_<b>Smith</b>_dans_le_champ_<b>Author</b>_et_<b>\u00e9lectrique</b>_dans_le_c [...]
+Please_enter_a_semicolon_or_comma_separated_list_of_Medline_IDs_(numbers).=SVP,_entrez_une_liste_d'IDs_Medline_(num\u00E9riques)_s\u00E9par\u00E9s_par_un_point-virgule_ou_par_une_virgule
+Please_enter_the_field_to_search_(e.g._<b>keywords</b>)_and_the_keyword_to_search_it_for_(e.g._<b>electrical</b>).=SVP,_entrez_le_champ_de_recherche_(par_ex._<b>keywords</b>)_et_le_mot-clef_\u00e0_rechercher_(par_ex._<b>\u00e9lectrique</b>).
+Please_enter_the_string's_label=SVP,_entrez_le_nom_de_la_cha\u00EEne
+Please_refer_to_the_JabRef_help_manual_on_using_the_CiteSeer_tools.=SVP,_reportez-vous_au_manuel_d'aide_de_JabRef_\u00E0_propos_de_l'utilisation_des_outils_CiteSeer.
+Please_select_exactly_one_group_to_move.=SVP,_s\u00e9lectionnez_uniquement_un_groupe_\u00e0_d\u00e9placer.
+Please_wait_until_it_has_finished.=SVP,_attendez_la_fin_de_l'op\u00E9ration.
+Possible_duplicate_entries=Entr\u00E9es_potentiellement_dupliqu\u00E9es
+Possible_duplicate_of_existing_entry._Click_to_resolve.=Duplication_possible_d'une_entr\u00e9e_existante._Cliquer_pour_v\u00e9rification_pour_trancher.
+Preamble=Pr\u00E9ambule
+Preamble_editor,_store_changes=Editeur_de_pr\u00E9ambule,_sauver_les_changements
+Preferences=Pr\u00E9f\u00E9rences
+Preferences_recorded=Pr\u00E9f\u00E9rences_enregistr\u00E9es
+Preferences_recorded.=Pr\u00E9f\u00E9rences_enregistr\u00E9es.
+Preserve_formatting_of_non-BibTeX_fields=Pr\u00E9server_le_format_des_champs_non-BibTeX
+Preview=Aper\u00E7u
+Previous_entry=Entr\u00E9e_pr\u00E9c\u00E9dente
+Previous_tab=Onglet_pr\u00E9c\u00E9dent
+Problem_with_parsing_entry=Probl\u00E8me_de_traitement_d'une_entr\u00E9e
+PS_links=Liens_PS
+Push_selection_to_LyX/Kile=Envoyer_la_s\u00E9lection_dans_LyX/Kile
+Push_selection_to_WinEdt=Envoyer_la_s\u00E9lection_dans_WinEdt
+Push_to_LyX=Envoyer_vers_LyX
+Push_to_WinEdt=Envoyer_vers_WinEdt
+Pushed_the_citations_for_the_following_rows_to=Envoyer_les_citations_pour_les_lignes_suivantes_vers
+Query_author(s)=Requ\u00EAte_sur_les_auteurs
+Quit=Quitter
+Quit_JabRef=Quitter_JabRef
+Quit_synchronization=Quitter_la_synchronisation
+Raw_source=Texte_brut
+Really_delete_the_selected=Voulez-vous_vraiment_supprimer_cette
+Recent_files=Fichiers_r\u00E9cents
+Redo=R\u00E9p\u00E9ter
+Refer/Endnote=Refer/Endnote
+Reference_database=Base_de_r\u00E9f\u00E9rence
+References_found=R\u00E9f\u00E9rences_trouv\u00E9es
+Refine_supergroup\:_When_selected,_view_entries_contained_in_both_this_group_and_its_supergroup=Raffine_le_super-groupe \:_Quand_s\u00e9lectionn\u00e9,_afficher_les_entr\u00e9es_contenues_\u00e0_la_fois_dans_ce_groupe_et_son_super-groupe
+Refresh_view=Rafra\u00EEchir_la_vue
+Regexp=Exp._R\u00E9g.
+Regular_Expression=Expression_r\u00E9guli\u00E8re
+Remember_these_entry_types?=Se_souvenir_de_ces_types_d'entr\u00E9es_?
+Remote_operation=Acc\u00e8s_\u00e0_distance
+Remote_server_port=Port_du_serveur_d'acc\u00e8s_\u00e0_distance
+Remove=Supprimer
+Remove_all?=Tout_supprimer_?
+Remove_all_subgroups=Supprimer_les_sous-groupes
+Remove_all_subgroups_of_"%0"?=Supprimer_tous_les_sous-groupes_de_"%0"_?
+Remove_duplicates=Supprimer_les_doublons
+Remove_entry_from_import=Supprimer_l'entr\u00e9e_de_l'importation
+Remove_entry_type=Supprimer_le_type_d'entr\u00E9e
+remove_from_group=supprimer_du_groupe
+Remove_from_group=Supprimer_du_groupe
+Remove_group=Supprimer_le_groupe
+Remove_group,_keep_subgroups=Supprimer_le_groupe,_garder_les_sous-groupes
+Remove_group_"%0"?=Supprimer_le_groupe_"%0"_?
+Remove_group_"%0"_and_its_subgroups?=Supprimer_le_groupe_"%0"_et_ses_sous-groupes_?
+remove_group_(keep_subgroups)=supprimer_le_groupe_(garder_les_sous-groupes)
+remove_group_and_subgroups=supprimer_le_groupe_et_les_sous-groupes
+Remove_group_and_subgroups=Supprimer_le_groupe_et_les_sous-groupes
+Remove_old_entry=Supprimer_l'ancienne_entr\u00e9e
+Remove_selected_strings=Supprimer_les_cha\u00EEnes_s\u00E9lectionn\u00E9es
+remove_string=enlever_la_cha\u00EEne
+remove_string_=enlever_la_cha\u00eene_
+Removed_entry_type.=Type_d'entr\u00E9e_supprim\u00E9.
+Removed_group=Groupe_supprim\u00E9
+Removed_group_"%0".=Groupe_"%0"_supprim\u00e9.
+Removed_group_"%0"_and_its_subgroups.=Groupe_"%0"_et_ses_sous-groupes_supprim\u00e9s.
+Removed_string=Cha\u00EEne_supprim\u00E9e
+Renamed_string=Cha\u00eene_renomm\u00e9e
+Repeat_incremental_search=R\u00E9p\u00E9ter_la_recherche_incr\u00E9mentale
+Replace=Remplacer
+Replace_string=Remplacer_la_cha\u00EEne
+Replace_with=Remplacer_par
+Replaced=Remplac\u00E9
+Required_fields=Champs_requis
+Reset_all=R\u00E9tablir_les_options_pr\u00E9c\u00E9dentes
+resolved=r\u00E9solu
+Results=R\u00E9sultats
+Revert_to_original_source=R\u00E9tablir_le_contenu_initial
+Review_changes=Revoir_les_changements
+Right=Droite
+RIS=RIS
+Save=Sauver
+Save_before_closing=Sauvegarde_avant_fermeture
+Save_database=Sauvegarder_la_base
+Save_database_as_...=Sauvegarder_la_base_sous_...
+Save_selected_as_...=Sauvegarder_la_s\u00E9lection_sous_...
+Save_session=Sauvegarder_la_session
+Saved_database=Base_sauvegard\u00E9e
+Saved_selected_to=Sauvegarder_la_s\u00E9lection_de
+Saved_session=Session_sauvegard\u00E9e
+Saving=Enregistrement_en_cours
+Scan=D\u00E9marrer
+SciFinder=SciFinder
+Search=Recherche
+Search_All_Fields=Recherche_dans_tous_les_champs
+Search_all_fields=Recherche_dans_tous_les_champs
+Search_error=Erreur_de_recherche
+Search_expression=Expression_\u00E0_rechercher_
+Search_for=Rechercher
+Search_General_Fields=Recherche_dans_les_champs_g\u00E9n\u00E9raux
+Search_general_fields=Recherche_dans_les_champs_g\u00E9n\u00E9raux
+Search_Optional_Fields=Recherche_dans_les_champs_optionnels
+Search_optional_fields=Recherche_dans_les_champs_optionnels
+Search_Required_Fields=Recherche_dans_les_champs_requis
+Search_required_fields=Recherche_dans_les_champs_requis
+Search_Specified_Field(s)=Recherche_dans_les_champs_sp\u00E9cifi\u00E9s
+Search_term=Rechercher_le_terme
+Searched_database._Number_of_hits=Recherche_effectu\u00E9e._Nombre_de_r\u00E9sultats_trouv\u00E9s
+Searching_for_%0_file=Recherche_du_fichier_%0
+Searching_for_duplicates...=Recherche_des_doublons_en_cours...
+Secondary_sort_criterion=Crit\u00E8re_secondaire_de_tri
+Select=S\u00E9lectionner
+Select_action=S\u00E9lectionner_l'op\u00E9ration
+Select_all=Tout_s\u00E9lectionner
+Select_entries_in_group_selection=S\u00E9lectionner_les_entr\u00E9es_dans_la_s\u00E9lection
+Select_entry_type=S\u00E9lectionner_un_type_d'entr\u00E9e
+Select_format=S\u00E9lectionner_le_format
+Select_matches=S\u00E9lectionner_les_correspondances
+Select_matching_entries=S\u00E9lection_des_entr\u00E9es_correspondant_aux_crit\u00E8res_de_recherche
+Select_the_tree_nodes_to_view_and_accept_or_reject_changes=S\u00E9lectionner_les_noeuds_de_l'arborescence_pour_voir,_et_accepter_ou_rejeter,_les_modifications
+Selector_enabled_fields=Champs_de_s\u00E9lecteur_actifs
+Set_general_fields=D\u00E9finir_les_champs_g\u00E9n\u00E9raux
+Set_table_font=D\u00E9finir_la_police_de_la_table
+Set_up_general_fields=Configurer_les_champs_g\u00E9n\u00E9raux
+Settings=Param\u00E8tres
+Setup_selectors=G\u00E9rer_les_s\u00E9lecteurs
+Short_form=Forme_courte
+Shortcut=Raccourci
+Show/edit_BibTeX_source=Montrer/\u00E9diter_le_source_BibTeX
+Show_'Firstname_Lastname'=Ordre_d'affichage_'Pr\u00E9nom_Nom'
+Show_'Lastname,_Firstname'=Ordre_d'affichage_'Nom,_Pr\u00E9nom'
+Show_abstract=Montrer_le_r\u00E9sum\u00E9
+Show_BibTeX_source_by_default=Par_d\u00E9faut,_afficher_l'onglet_Source_BibTeX
+Show_BibTeX_source_panel=Afficher_l'onglet_"Source_BibTeX"
+Show_CiteSeer_column=Afficher_la_colonne_CiteSeer
+Show_confirmation_dialog_when_deleting_entries=Demander_une_confirmation_lors_de_la_suppression_d'entr\u00E9es
+Show_dynamic_groups_in_<i>italics</i>=Afficher_les_groupes_dynamiques_en_<i>italique</i>
+Show_entries_*not*_in_group_selection=Montrer_les_entr\u00E9es_*non*_s\u00E9lectionn\u00E9es
+Show_general_fields=Montrer_les_champs_g\u00E9n\u00E9raux
+Show_groups_matching_all=Montrer_les_groupes_correspondants_\u00e0_tous
+Show_groups_matching_any=Montrer_les_groupes_correspondants_\u00e0_n'importe_quel
+Show_icons_for_groups=Afficher_les_ic\u00f4nes_pour_les_groupes
+Show_names_unchanged=Ordre_des_noms_inchang\u00E9
+Show_one_less_rows=Afficher_une_ligne_de_moins
+Show_one_more_row=Afficher_une_ligne_de_plus
+Show_optional_fields=Montrer_les_champs_optionnels
+Show_overlapping_groups=Montrer_les_groupes_se_chevauchant
+Show_PDF/PS_column=Afficher_la_colonne_PDF/PS
+Show_required_fields=Montrer_les_champs_requis
+Show_URL/DOI_column=Afficher_la_colonne_URL/DOI
+Show_warning_dialog_when_a_duplicate_BibTeX_key_is_entered=Afficher_un_message_d'avertissement_quand_une_clef_BibTeX_d\u00E9j\u00E0_existante_est_entr\u00E9e
+Show_warning_dialog_when_an_empty_BibTeX_key_is_entered=Afficher_une_fen\u00eatre_d'avertissement_quand_une_clef_BibTeX_vide_est_entr\u00e9e
+Simple_HTML=HTML_(simple)
+Sixpack=Sixpack
+Size_of_groups_interface_(rows)=Taille_de_l'interface_des_groupes_(lignes)
+Skip=Passer
+Sort_alphabetically=Classer_alphab\u00e9tiquement
+Sort_Automatically=Trier_automatiquement
+Sort_options=Options_du_tri
+sort_subgroups=trier_les_sous-groupes
+Sorted_all_subgroups_recursively=Tous_les_sous-groupes_r\u00e9cursivement_tri\u00e9s
+Sorted_all_subgroups_recursively.=Tous_les_sous-groupes_r\u00e9cursivement_tri\u00e9s.
+Sorted_immediate_subgroups=Sous-groupes_directs_tri\u00e9s
+Sorted_immediate_subgroups.=Sous-groupes_directs_tri\u00e9s.
+source_edit=\u00E9dition_du_source
+Special_table_columns=Colonnes_de_tableau_particuli\u00E8res
+Start=D\u00E9marrer
+Start_incremental_search=D\u00E9marrer_la_recherche_incr\u00E9mentale
+Start_search=D\u00e9buter_la_recherche
+Statically_group_entries_by_manual_assignment=Grouper_manuellement_les_entr\u00E9es
+Status=Etat
+Stop=Arr\u00eat
+Store=Enregistrer
+Store_fields_with_double_braces,_and_remove_extra_braces_when_loading.<BR>Double_braces_signal_that_BibTeX_should_preserve_character_case.=Enregistrer_les_champs_avec_des_doubles_accolades_et_supprimer_les_accolades_suppl\u00e9mentaires_au_chargement._<BR>Les_doubles_accolades_signalent_que_BibTeX_doit_pr\u00e9server_la_casse_des_caract\u00e8res.
+Store_string=Enregistrer_la_cha\u00EEne
+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 :
+subdatabase_from_aux=BibTeX_\u00E0_partir_de_LaTex_aux
+Subdatabase_from_aux=BibTeX_\u00E0_partir_de_LaTex_aux
+Suggest=Sugg\u00E9rer
+Switch_preview_layout=Pr\u00E9visualiser_la_mise_en_page
+Synchronize_%0_links=Synchroniser_les_liens_%0
+Synchronizing_%0_links...=Synchronisation_des_liens_%0...
+Table=Table
+Table_appearance=Apparence_de_la_table
+Tabname=Nom_d'onglet
+Tertiary_sort_criterion=Crit\u00E8re_tertiaire_de_tri
+Test=Test
+Text_Input_Area=Zone_de_saisie_du_texte
+The_#_character_is_not_allowed_in_BibTeX_fields=Le_caract\u00E8re_#_est_interdit_dans_un_champ_BibTeX
+The_CiteSeer_fetch_operation_returned_zero_results.=La_recherche_CiteSeer_n'a_retourn\u00E9_aucun_r\u00E9sultat.
+the_field_<b>%0</b>=le_champ_<b>%0</b>
+The_file<BR>'%0'<BR>has_been_modified<BR>externally!=Le_fichier<BR>'%0'<BR>a_\u00e9t\u00e9_modifi\u00e9_<BR>externalement !
+The_group_"%0"_already_contains_the_selection.=Le_groupe_"%0"_contient_d\u00e9j\u00e0_la_s\u00e9lection.
+The_group_"%0"_does_not_support_the_adding_of_entries.=Le_groupe_"%0"_ne_supporte_pas_l'ajout_des_entr\u00e9es.
+The_group_"%0"_does_not_support_the_removal_of_entries.=Le_groupe_"%0"_ne_supporte_pas_la_suppression_des_entr\u00e9es.
+The_label_of_the_string_can_not_be_a_number.=L'intitul\u00E9_de_la_cha\u00EEne_ne_peut_\u00EAtre_un_nombre.
+The_label_of_the_string_can_not_contain_spaces.=Un_nom_de_cha\u00eene_ne_peut_pas_contenir_d'espaces.
+The_label_of_the_string_can_not_contain_the_'#'_character.=Le_nom_de_la_cha\u00eene_ne_peut_pas_contenir_le_caract\u00e8re_'#'.
+The_output_option_depends_on_a_valid_import_option.=L'option_de_sortie_d\u00e9pend_d'une_option_d'importation_valide.
+The_regular_expression_<b>%0</b>_is_invalid%c=L'expression_r\u00e9guli\u00e8re_<b>%0</b>_est_invalide%c
+The_search_is_case_insensitive.=La_recherche_n'est_pas_sensible_\u00e0_la_casse.
+The_search_is_case_sensitive.=La_recherche_est_sensible_\u00e0_la_casse.
+The_string_has_been_removed_locally=La_cha\u00EEne_a_\u00E9t\u00E9_supprim\u00E9e_localement
+The_type_name_can_not_contain_spaces.=Le_nom_d'un_type_ne_peut_pas_contenir_d'espaces.
+The_URL_field_appears_to_be_empty_on_entry_number_=Le_champ_URL_semble_\u00eatre_vide_pour_l'entr\u00e9e_num\u00e9ro_
+There_are_possible_duplicates_(marked_with_a_'D'_icon)_that_haven't_been_resolved._Continue?=Il_y_a_des_doublons_potentiels_(marqu\u00e9_avec_un_ic\u00f4ne_'D')_qui_n'ont_pas_\u00e9t\u00e9_r\u00e9solus._Continuer_?
+There_is_no_entry_type=Il_n'y_a_pas_de_type_d'entr\u00E9e
+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?=Cette_action_modifiera_le_champ_"%0"_de_vos_entr\u00e9es._Cela_pourrait_causer_des_changements_involontaires_dans_vos_entr\u00e9es,_aussi_il_n'est_pas_recommand\u00e9_que_vous_changiez_ce_champ_dans_votre_d\u00e9finition_de_groupe_par_"keywor [...]
+this_button_will_update=Ce_bouton_sera_mis_\u00e0_jour
+this_button_will_update_the_column_width_settings<BR>to_match_the_current_widths_in_your_table=ce_bouton_mettra_\u00E0_jour_les_param\u00E8tres_des_largeurs_des_colonnes<BR>pour_retenir_les_largeurs_actuelles_de_votre_table
+This_entry_is_incomplete=Cette_entr\u00E9e_est_incompl\u00E8te
+This_entry_type_cannot_be_removed.=Ce_type_d'entr\u00E9e_ne_peut_pas_\u00EAtre_supprim\u00E9.
+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.=Ce_groupe_contient_des_entr\u00e9es_bas\u00e9es_sur_un_ajout_manuel._Des_entr\u00e9es_peuvent_\u00eatre_ajout\u00e9es [...]
+This_group_contains_entries_in_which=Ce_groupe_contient_des_entr\u00e9es_pour_lesquelles
+This_group_contains_entries_in_which_any_field_contains_the_regular_expression_<b>%0</b>=Ce_groupe_contient_des_entr\u00e9es_dans_lesquelles_un_champ_contient_l'expression_r\u00e9guli\u00e8re_<b>%0</b>
+This_group_contains_entries_in_which_any_field_contains_the_term_<b>%0</b>=Ce_groupe_contient_des_entr\u00e9es_dans_lesquelles_un_champ_contient_le_terme_<b>%0</b>
+This_group_contains_entries_whose_<b>%0</b>_field_contains_the_keyword_<b>%1</b>=Ce_groupe_contient_des_entr\u00e9es_dont_le_champ_<b>%0</b>_contient_le_mot-clef_<b>%1</b>
+This_group_contains_entries_whose_<b>%0</b>_field_contains_the_regular_expression_<b>%1</b>=Ce_groupe_contient_des_entr\u00e9es_dont_le_champ_<b>%0</b>_contient_l'expression_r\u00e9guli\u00e8re_<b>%1</b>
+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.=Cette_fen\u00EAtre_fonctionne_par_copier-coller._Commencer_par_charger_ou_coller_du_texte_dans_la_zone_de_saisie_du_texte._Ensuite,_vous_pouvez_s\u00E9lectionner_le_texte_et_attribuer_\u00E0_un_champ_BibTeX.
+This_is_a_simple_copy_and_paste_dialog_for_import_some_fields_from_normal_text.=Ceci_est_simplement_une_fen\u00eatre_de_copier-coller_pour_importer_certains_champs_\u00e0_partir_d'un_texte_normal
+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.=Cela_conduit_JabRef_\u00e0_tester_chaque_lien_%0_et_\u00e0_v\u00e9rifier_si_le_fichier_existe._Dans_la_n\u00e9gative,_des_options_vous_seront_propos\u00e9es<BR>pour_r\u00e9soudre_le_probl\u00e8me.
+This_operation_cannot_work_on_multiple_rows.=Cette_op\u00E9ration_ne_peut_pas_\u00EAtre_effectu\u00E9e_sur_plusieurs_lignes.
+Toggle_entry_preview=Afficher/Masquer_l'aper\u00E7u
+Toggle_groups_interface=Afficher/Masquer_l'interface_des_groupes
+Toggle_search_panel=Afficher/Masquer_la_fen\u00EAtre_de_recherche
+Tools=Outils
+Type=Type
+Type_set_to_'other'=Type_configur\u00E9_comme_'other'_(autre)
+unable_to_access_LyX-pipe=Incapable_d'acc\u00E9der_au_canal_de_transmission_LyX
+Unable_to_create_graphical_interface=Incapable_de_cr\u00e9er_l'interface_graphique
+Unable_to_parse_clipboard_text_as_Bibtex_entries.=Incapable_de_traiter_le_texte_du_presse-papiers_comme_des_entr\u00e9es_BibTeX.
+Unable_to_parse_the_following_URL=Incapable_de_traiter_l'ULR_suivante
+unable_to_write_to=Incapable_d'\u00e9crire_sur
+Undo=Annuler
+Union=Union
+unknown_bibtex_entries=entr\u00e9es_BibTeX_inconnues
+Unknown_bibtex_entries=Entr\u00E9es_BibTeX_inconnues
+unknown_edit=\u00e9dition_inconnue
+unknown_entry_type=type_d'entr\u00E9e_inconnue
+Unknown_export_format=Format_d'exportation_inconnu
+Unmark_all=Tout_d\u00E9s\u00E9tiqueter
+Unmark_entries=D\u00E9s\u00E9tiqueter_des_entr\u00E9es
+Unmark_entry=D\u00E9s\u00E9tiqueter_l'entr\u00E9e
+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
+untitled=sans_titre
+Up=Haut
+Update_to_current_column_widths=Figer_les_largeurs_des_colonnes_actuelles
+Updated_group_selection=S\u00E9lection_de_groupe_mise_\u00E0_jour
+Updating_entries...=Mise_\u00E0_jour_des_entr\u00E9es...
+UPPER=MAJUSCULE
+Upper_Each_First=Chaque_Premi\u00E8re_Lettre_En_Majuscule
+Upper_first=Premi\u00E8re_lettre_en_majuscule
+usage=usage
+Use_antialiasing_font_in_table=Utiliser_une_police_liss\u00E9e_dans_la_table
+Use_inspection_window_also_when_a_single_entry_is_imported.=Utiliser_la_fen\u00eatre_d'inspection_m\u00eame_quand_une_seule_entr\u00e9e_est_import\u00e9e.
+Use_other_look_and_feel=Utiliser_une_autre_apparence
+Use_regular_expressions=Utiliser_les_expressions_r\u00E9guli\u00E8res
+Use_the_following_delimiter=Utiliser_le_d\u00E9limiteur_suivant
+Use_the_following_delimiter_character(s)=Utiliser_le(s)_caract\u00e8re(s)_de_s\u00E9paration_suivant(s)
+Uses_default_application=Utilise_l'application_par_d\u00e9faut
+Value_cleared_externally=Valeur_supprim\u00E9e_externalement
+Value_set_externally=Valeur_param\u00E9tr\u00E9e_externalement_
+verify_that_LyX_is_running_and_that_the_lyxpipe_is_valid=v\u00E9rifier_que_LyX_tourne_et_que_le_canal_de_transmission_LyX_est_valide
+View=Aper\u00E7u
+Visible_fields=Champs_visibles
+Warn_about_unresolved_duplicates_when_closing_inspection_window=Avertir_des_doublons_non_r\u00e9solus_lors_de_la_fermeture_de_la_fen\u00eatre_d'inspection
+Warn_before_overwriting_existing_keys=Avertir_avant_d'\u00E9craser_des_clefs_existantes
+Warning=Avertissement
+Warning_there_is_a_duplicate_key=Avertissement_%c_il_y_a_une_clef_dupliqu\u00e9e
+Warnings=Messages_d'avertissement
+web_link=Lien_internet
+When_adding/removing_keywords,_separate_them_by=Lors_de_l'ajout/suppression_de_mots-clef,_les_s\u00e9parer_avec
+with=avec
+Word=Mot
+Wrong_file_format=Format_de_fichier_incorrect
+You_have_changed_the_language_setting._You_must_restart_JabRef_for_this_to_come_into_effect.=Vous_avez_modifi\u00E9_la_langue._Vous_devez_red\u00E9marrer_JabRef_pour_que_ce_changement_prenne_effet.
+You_have_cleared_this_field._Original_value=Vous_avez_vid\u00e9_ce_champ._Valeur_originale
+You_must_enter_an_integer_value_in_the_text_field_for=Vous_devez_entrer_une_valeur_enti\u00e8re_dans_le_champ_texte_pour
+You_must_fill_in_a_name_for_the_entry_type.=Vous_devez_fournir_un_nom_pour_le_type_d'entr\u00E9e.
+You_must_provide_a_name,_a_search_string_and_a_field_name_for_this_group.=Vous_devez_fournir_un_nom,_une_cha\u00EEne_\u00E0_rechercher_et_un_nom_de_champ_pour_ce_groupe.
+You_must_restart_JabRef_for_the_new_key_bindings_to_work_properly.=Vous_devez_relancer_JabRef_pour_que_les_nouvelles_affectations_des_touches_soient_activ\u00E9es
+You_must_select_a_row_to_perform_this_operation.=Vous_devez_s\u00E9lectionner_une_ligne_pour_effectuer_cette_op\u00E9ration.
+You_must_select_at_least_one_row_to_perform_this_operation.=Vous_devez_s\u00E9lectionner_au_moins_une_colonne_pour_effectuer_cette_op\u00E9ration.
+You_must_set_both_BibTeX_key_and_%0_directory=Vous_devez_d\u00E9finir_\u00E0_la_fois_la_clef_BibTeX_et_le_r\u00E9pertoire_%0
+You_must_set_both_bibtex_key_and_PDF_directory=You_must_set_both_bibtex_key_and_PDF_directory
+Your_new_key_bindings_have_been_stored.=Votre_nouvelle_affectation_de_touche_a_\u00E9t\u00E9_sauvegard\u00E9e
+Manage_custom_imports=G\u00e9rer_les_importations_personnalis\u00e9es
+Select_Classpath_of_New_Importer=S\u00e9lectionner_le_chemin_de_classe_du_nouveau_filtre_d'importation
+Select_new_ImportFormat_Subclass=S\u00e9lectionner_une_nouvelle_sous-classe_ImportFormat
+Could_not_instantiate_%0_%1=N'a_pas_pu_initialiser_%0_%1
+Add_a_(compiled)_custom_ImportFormat_class_from_a_class_path._\nThe_path_need_not_be_on_the_classpath_of_JabRef.=Ajouter_une_classe_ImportFormat_personnalis\u00e9e_(compil\u00e9e)_\u00e0_partir_d'un_chemin_de_classe._\nLe_chemin_n'a_pas_besoin_d'\u00eatre_dans_le_chemin_de_classe_de_JabRef.
+Please_select_an_importer=S\u00e9lectionner_un_filtre_d'importation,_SVP
+Import_name=nom_Import
+Command_line_id=Identifiant_de_la_ligne_de_commande
+ImportFormat_class=Classe_ImportFormat
+Contained_in=Contenu_dans
+Show_description=Montrer_la_description
+Add_from_folder=Ajouter_\u00e0_partir_du_r\u00e9pertoire
+Custom_importers=Filtres_d'importation_personnalis\u00e9s
+No_custom_imports_registered_yet.=Pas_encore_d'importation_personnalis\u00e9e_enregistr\u00e9e
+Abbreviate_journal_names_of_the_selected_entries_(ISO_abbreviation)=Abr\u00e9ger_les_noms_de_journaux_des_entr\u00e9es_s\u00e9lectionn\u00e9es_(abr\u00e9viations_ISO)
+Abbreviate_journal_names_of_the_selected_entries_(MEDLINE_abbreviation)=Abr\u00e9ger_les_noms_de_journaux_des_entr\u00e9es_s\u00e9lectionn\u00e9es_(abr\u00e9viations_MEDLINE)
+Background_color_for_marked_entries=Couleur_d'arri\u00e8re-plan_pour_les_entr\u00e9es_marqu\u00e9es
+Background_color_for_optional_fields=Couleur_d'arri\u00e8re-plan_pour_les_champs_optionnels
+Background_color_for_required_fields=Couleur_d'arri\u00e8re-plan_pour_les_champs_requis
+Choose_the_URL_to_download._The_default_value_points_to_a_list_provided_by_the_JabRef_developers.=Choisir_l'URL_de_t\u00e9l\u00e9chargement._La_valeur_par_d\u00e9faut_pointe_vers_une_liste_fournie_par_les_d\u00e9veloppeurs_de_JabRef
+Color_for_marking_incomplete_entries=Couleur_pour_marque_les_entr\u00e9es_incompl\u00e8tes
+Do_not_abbreviate_names=Ne_pas_abr\u00e9ger_les_noms
+Do_not_wrap_the_following_fields_when_saving=Ne_pas_renvoyer_\u00e0_la_ligne_les_champs_suivants_lors_de_la_sauvegarde
+External_files=Fichiers_externes
+File_'%0'_not_found=Fichier_'%0'_non_trouv\u00e9
+Journal_abbreviations=Abr\u00e9viations_de_journaux
+Journal_name=Nom_du_journal
+Manage_journal_abbreviations=G\u00e9rer_les_abr\u00e9viations_de_journaux
+Natbib_style=Style_Natbib
+New_file=Nouveau_fichier
+Personal_journal_list=Liste_personnelle_de_journaux
+Remove_double_braces_around_BibTeX_fields_when_loading.=Supprimer_les_doubles_accolades_autour_des_champs_BibTeX_\u00e0_l'ouverture
+Store_the_following_fields_with_braces_around_capital_letters=Stocker_les_champs_suivants_avec_des_accolades_autour_des_lettres_capitales
+Table_background_color=Couleur_d'arri\u00e8re-plan_de_la_table
+Table_grid_color=Couleur_de_la_grille_de_la_table
+Table_text_color=Couleur_du_texte_de_la_table
+Toggle_abbreviation=Afficher/Masquer_l'abr\u00e9viation
+Unabbreviate_journal_names_of_the_selected_entries=D\u00e9velopper_les_noms_de_journaux_des_entr\u00e9es_s\u00e9lectionn\u00e9es
+Use_antialiasing_font=Utiliser_une_police_liss\u00e9e
+Abbreviate_names=Abr\u00e9ger_les_noms
+Abbreviation=Abr\u00e9viation
+ISO_abbreviation=Abr\u00e9viation_ISO
+Edit_journal=Editer_le_journal
+Existing_file=Fermeture_du_fichier_en_cours
+Saving_database=Sauvegarde_de_la_base_en_cours
+Normal=Normale
+Default_sort_criteria=Crit\u00e8re_de_tri_par_d\u00e9faut
+Primary_sort_criterion=Crit\u00e8re_de_tri_principal
+Database_properties=Propri\u00E9t\u00E9s_de la base de donn\u00e9es
+Database_encoding=Encodage_de_la_base_de_donn\u00e9es
+No_journal_names_could_be_abbreviated.=Aucun_nom_de_journal_n'a_pu_\u00eatre_abr\u00e9g\u00e9.
+No_journal_names_could_be_unabbreviated.=Aucun_nom_de_journal_n'a_pu_\u00eatre_d\u00e9velopp\u00e9.
+Save_failed=Echec_de_la_sauvegarde
+Pushed_citations_to_WinEdt=Citations_envoy\u00e9es_vers_WinEdt
+Try_different_encoding=Essayer_un_encodage_diff\u00e9rent
+Select_encoding=S\u00e9lectionner_l'encodage
+The_chosen_date_format_for_new_entries_is_not_valid=Le_format_de_date_choisi_pour_les_nouvelles_entr\u00e9es_n'est_pas_valide
+Invalid_date_format=Format_de_date_invalide
+Review=V\u00e9rification
+Journal_names=Noms_de_journaux
+Save_failed_during_backup_creation=La_sauvegarde_a_\u00e9chou\u00e9e_durant_la_cr\u00e9ation_de_la_copie_de_secours
+Save_failed_while_committing_changes=La_sauvegarde_a_\u00e9chou\u00e9e_lors_de_la_soumission_des_changements
+Full_name=Nom_complet
+Store_journal_abbreviations=Stocker_les_abr\u00e9viations_de_journaux
+You_must_choose_a_file_name_to_store_journal_abbreviations=Vous_devez_choisir_un_nom_de_fichier_pour_stocker_les_abr\u00e9viations_de_journaux
+Journal_list_preview=Pr\u00e9visualisation_de_la_liste_des_journaux
+
+Add_from_jar=Ajouter_\u00e0_partir_de_jar
+Add_a_(compiled)_custom_ImportFormat_class_from_a_Zip-archive.\nThe_Zip-archive_need_not_be_on_the_classpath_of_JabRef.=Ajouter_une_classe_ImportFormat_personnalis\u00e9e_(compil\u00e9e)_\u00e0_partir_d'une_archive_ZIP._\nL'archive_ZIP_n'a_pas_besoin_d'\u00eatre_dans_le_chemin_de_classe_de_JabRef.
+Select_a_Zip-archive=S\u00e9lectionner_une_archive_ZIP
+Select_file_from_ZIP-archive=S\u00e9lectionner_un_fichier_depuis_une_archive_ZIP
+Last_modified=Dernier_modifi\u00e9
+Size=Taille
+Please_select_an_importer.=S\u00e9lectionner_un_filtre_d'importation,_SVP.
+
+Arguments_passed_on_to_running_JabRef_instance._Shutting_down.=Arguments_transmis_\u00e0_l'instance_JabRef active.
+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').=La_connexion_\u00e0_un_processus gnuserv_actif_a_\u00e9chou\u00e9._Assurez-vous_qu'Emacs_ou_XEmacs_soit_actif,<BR>et_que_le_serveur_a_\u00e9t\u00e9_d\u00e9marr\u00e9_(avec_la_commande_'gnuserv-start').
+
+Push_selection_to_Emacs=Envoyer_la_s\u00E9lection_dans_Emacs
+Pushed_citations_to_Emacs=Envoyer_les_citations_dans_Emacs
+
+Filter=Filtre
+Hide_non-matching_entries=Masquer_les_entr\u00E9es_non_correspondantes
+Replace_(regular_expression)=Remplacer_(expression_r\u00e9guli\u00e8re)
+
+Cite_command_(for_Emacs/WinEdt)=Commande_de_citation_(pour_Emacs/WinEdt)
+
+Could_not_instantiate_%0_%1._Have_you_chosen_the_correct_package_path?=%0_%1_a_\u00e9chou\u00e9._Avez-vous_choisi_le_chemin_de_paquetage_correct_?
+No_entries_found._Please_make_sure_you_are_using_the_correct_import_filter.=Pas_d'entr\u00e9es_trouv\u00e9es._Assurez-vous,_SVP,_que_vous_utilisez_le_filtre_d'importation_appropri\u00e9.
+
+Switches_between_full_and_abbreviated_journal_name_if_the_journal_name_is_known.=Basculer_entre_les_noms_de_journaux_d\u00e9velopp\u00e9s_et_abr\u00e9g\u00e9s_si_le_nom_de_journal_est_connu. 
+To_set_up,_go_to_<B>Tools_->_Manage_journal_abbreviations</B>=Pour_configurer,_voir_<B>Outils_->_G\u00e9rer_les_abr\u00e9viations_de_journaux</B>
+
+Could_not_run_the_'gnuclient'_program._Make_sure_you_have_the_gnuserv/gnuclient_programs_installed.=Le_programme_'gnuclient'_n'a_pas_pu_\u00eatre_lanc\u00e9._Assurez-vous_que_les_programmes_gnuserv/gnuclient_sont_install\u00e9s.
+
+Hierarchical_context=Type de hi�rarchie
+Add_entry_selection_to_this_group=Ajouter_les_entr\u00e9es_s\u00e9lectionn\u00e9es_\u00e0_ce_groupe
+Assign_entry_selection_exclusively_to_this_group=Assigner_les_entr\u00e9es_s\u00e9lectionn\u00e9es_uniquement_\u00e0_ce_groupe
+Ne_entries_imported.=
+Remove_entry_selection_from_this_group=Supprimer_les_entr\u00e9es_s\u00e9lectionn\u00e9es_de_ce_groupe
diff --git a/src/resource/JabRef_fr.properties.orig b/src/resource/JabRef_fr.properties.orig
new file mode 100644
index 0000000..87f0242
--- /dev/null
+++ b/src/resource/JabRef_fr.properties.orig
@@ -0,0 +1,1019 @@
+#! created/edited by Popeye version 0.51 sunshine (popeye.sourceforge.net)
+
+!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.=!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.
+%0_contains_the_Regular_Expression_<b>%1</b>=%0_contient_l'expression_r\u00e9guli\u00e8re_<b>%1</b>
+%0_contains_the_term_<b>%1</b>=%0_contient_le_terme_<b>%1</b>
+%0_doesn't_contain_the_Regular_Expression_<b>%1</b>=%0_ne_contient_pas_l'expression_r\u00e9guli\u00e8re_<b>%1</b>
+%0_doesn't_contain_the_term_<b>%1</b>=%0_ne_contient_pas_le_terme_<b>%1</b>
+%0_doesn't_match_the_Regular_Expression_<b>%1</b>=%0_ne_correspond_pas_\u00e0_l'expression_r\u00e9guli\u00e8re_<b>%1</b>
+%0_doesn't_match_the_term_<b>%1</b>=%0_ne_correspond_pas_au_terme_<b>%1</b>
+%0_field_set=D\u00E9finition_du_champ_%0
+%0_import_cancelled.=%0_importation_interrompue.
+%0_matches_the_Regular_Expression_<b>%1</b>=%0_correspond_\u00e0_l'expression_r\u00e9guli\u00e8re_<b>%1</b>
+%0_matches_the_term_<b>%1</b>=%0_correspond_au_terme_<b>%1</b>
+<field_name>=<nom_de_champ>
+<HTML>Unpack_the_zip_file_containing_import/export_filters_for_Endnote,<BR>for_optimal_interoperability_with_JabRef</HTML>=<HTML>D\u00E9compacter_le_fichier_zip_contenant_les_filtres_import/export_pour_Endnote,<BR>pour_une_interop\u00E9rabilit\u00E9_optimale_avec_JabRef</HTML>
+<no_field>=<pas_de_champ>
+<select>=<s\u00E9lectionner>
+<select_word>=<entrer_le_mot-clef>
+_on_entry_number_=_pour_le_num\u00e9ro_d'entr\u00e9e_
+A_CiteSeer_fetch_operation_is_currently_in_progress.=Une_op\u00E9ration_de_recherche_sur_CiteSeer_est_en_cours.
+A_CiteSeer_import_operation_is_currently_in_progress.=Une_op\u00E9ration_d'importation_depuis_CiteSeer_est_en_cours.
+A_string_with_that_label_already_exists=Une_cha\u00EEne_avec_ce_nom_existe_d\u00E9j\u00E0
+About_JabRef=A_propos_de_JabRef
+Abstract=R\u00e9sum\u00e9
+Accept=Valider
+Accept_change=Accepter_la_modification
+Action=Action
+Add=Ajouter
+add_entries_to_group=ajouter_des_entr\u00e9es_au_groupe
+add_group=ajouter_un_groupe
+Add_Group=Ajouter_un_groupe
+Add_new=Ajouter_nouvelle
+Add_Subgroup=Ajouter_un_sous-groupe
+Add_to_group=Ajouter_au_groupe
+Added_entry=Entr\u00E9e_ajout\u00E9e
+Added_group=Groupe_ajout\u00e9
+Added_group_"%0".=Groupe_"%0"_ajout\u00e9.
+Added_new=Nouvel_ajout
+Added_string=Cha\u00EEne_ajout\u00E9e
+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.=De_plus,_des_entr\u00e9es_dont_le_champ_<b>%0</b>_ne_contient_pas_<b>%1 [...]
+Advanced=Avanc\u00E9
+Advanced_options_for_setting...=Options_avanc\u00e9es_pour_la_configuration...
+All_Entries=Toutes_les_entr\u00e9es
+All_entries=Toutes_les_entr\u00E9es
+All_entries_of_this_type_will_be_declared_typeless._Continue?=Toutes_les_entr\u00E9es_similaires_seront_consid\u00E9r\u00E9es_sans_type._Continuer_?
+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_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
+Append=Ajouter
+Append_contents_from_a_BibTeX_database_into_the_currently_viewed_database=Ajouter_le_contenu_d'une_base_BibTeX_\u00E0_la_base_actuelle
+Append_database=Joindre_\u00E0_la_base
+append_the_selected_text_to_bibtex_key=ajouter_le_texte_s\u00e9lectionn\u00e9_\u00e0_la_clef_BibTeX
+Apply=Appliquer
+Assign_entries_based_on:=Attribuer_les_entr\u00E9es_selon_:
+Assign_new_file=Assigner_un_nouveau_fichier
+Assign_the_original_group's_entries_to_this_group?=Assigner_les_entr\u00e9es_originales_du_groupe_\u00e0_ce_groupe ?
+Assigned_%0_entries_to_group_"%1".=%0_entr\u00e9es_ajout\u00e9es_au_groupe_"%1".
+Assigned_1_entry_to_group_"%0".=Une_entr\u00e9e_ajout\u00e9e_au_groupe_"%0".
+Attach_%0_file=Attacher_le_fichier_%0
+Attach_URL=Attacher_l'URL
+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.=Cela_tente_de_d\u00e9finir_automatiquement_les_liens_%0_de_vos_entr\u00e9es._La_d\u00e9finition_automatique_fonctionne_si_un_fichier_%0_dans_votre_r\u00e9pertoire_%0_ou_dans_un_sous-r\u00e9pertoire<BR>porte_le_m\u00eame_nom_que_la_clef_d'une_entr\u00e9e_BibTeX,_l'extension_en_plus.
+Auto=Auto
+Autodetect_format=D\u00E9tection_automatique_du_format
+Autogenerate_BibTeX_key=Cr\u00E9ation_automatique_des_clefs_BibTeX
+Autogenerate_BibTeX_keys=Cr\u00E9ation_automatique_des_clefs_BibTeX
+Autogenerate_groups=Cr\u00E9ation_automatique_des_groupes
+autogenerate_keys=cr\u00E9ation_automatique_des_clefs
+Automatically_create_groups=Cr\u00E9er_automatiquement_des_groupes
+Automatically_create_groups_for_database.=Cr\u00E9er_automatiquement_des_groupes_pour_la_base.
+Automatically_created_groups=Groupes_cr\u00e9\u00e9s_automatiquement
+Automatically_hide_groups_interface_when_switching_to_a_database_that_contains_no_groups=Masquer_automatiquement_l'interface_des_groupes_lors_de_l'affichage_d'une_base_de_donn\u00e9es_qui_ne_contient_pas_de_groupes
+Automatically_show_groups_interface_when_switching_to_a_database_that_contains_groups=Afficher_automatiquement_l'interface_des_groupes_lors_de_l'affichage_d'une_base_de_donn\u00e9es_qui_contient_des_groupes
+Autoset=D\u00e9finir_automatiquement
+Autoset_%0_field=Auto-d\u00e9finition_du_champ_%0
+Autoset_%0_links._Allow_overwriting_existing_links.=D\u00e9finir_automatiquement_les_liens_%0._Ecraser_les_liens_existants.
+Autoset_%0_links._Do_not_overwrite_existing_links.=D\u00e9finir_automatiquement_les_liens_%0._Ne_pas_\u00e9craser_les_liens_existants.
+Autosetting_%0_field...=Auto-param\u00e9trage_du_champ_%0...
+AUX_File_import=G\u00E9n\u00E9rer_un_fichier_BibTeX_\u00E0_partir_de_fichier_AUX
+AUX_file_import=Importation_de_fichier_AUX
+Available_export_formats=Formats_d'exportation_disponibles
+Available_fields=Champs_BibTeX_disponibles
+Available_import_formats=Formats_d'importation_disponibles
+Backup_old_file_when_saving=Cr\u00E9er_une_copie_de_sauvegarde_lors_de_l'enregistrement
+Bibkey_to_filename_conversion=Conversion_de_la_clef_BibTeX_en_nom_de_fichier
+Biblioscape_Tag_file=Biblioscape_Tag
+BibTeX=BibTeX
+BibTeX_key=Clef_BibTeX
+BibTeX_key_is_unique.=La_clef_BibTeX_est_unique.
+BibTeX_key_not_set._Enter_a_name_for_the_downloaded_file=Clef_BibTeX_ind\u00E9finie._Entrer_un_nom_pour_le_fichier_t\u00E9l\u00E9charg\u00E9
+BibTeX_source=Source_BibTeX
+BibTeXML=BibTeXML
+BibTeXML_File=BibTeXML
+Binding=Affectation
+Broken_link=Lien_rompu
+Browse=Explorer
+by=par
+Calling_external_viewer...=Lancement_de_l'afficheur_externe...
+Cancel=Annuler
+Cannot_add_entries_to_group_without_generating_keys._Generate_keys_now?=Les_entr\u00e9es_ne_peuvent_pas_\u00eatre_ajout\u00e9es_au_groupe_sans_g\u00e9n\u00e9rer_des_clefs._Voulez-vous_g\u00e9n\u00e9rer_des_clefs_maintenant_?
+Cannot_merge_this_change=Cette_modification_ne_peut_pas_\u00EAtre_fusionn\u00E9e
+Cannot_move_group=Le_groupe_"%0"_ne_peut_pas_\u00eatre_d\u00e9plac\u00e9
+Cannot_move_group_"%0"_down.=Le_groupe_"%0"_ne_peut_pas_\u00eatre_d\u00e9plac\u00e9_vers_le_bas.
+Cannot_move_group_"%0"_left.=Le_groupe_"%0"_ne_peut_pas_\u00eatre_d\u00e9plac\u00e9_vers_la_gauche.
+Cannot_move_group_"%0"_right.=Le_groupe_"%0"_ne_peut_pas_\u00eatre_d\u00e9plac\u00e9_vers_la_droite.
+Cannot_move_group_"%0"_up.=Le_groupe_"%0"_ne_peut_pas_\u00eatre_d\u00e9plac\u00e9_vers_le_haut
+case_insensitive=insensible_\u00e0_la_casse
+case_sensitive=sensible_\u00e0_la_casse
+Case_sensitive=Sensible_\u00e0_la_casse
+change_assignment_of_entries=changer_l'assignation_des_entr\u00e9es
+Change_case=Changer_la_casse
+Change_entry_type=Changer_le_type_d'entr\u00E9e
+change_key=changer_la_clef
+Change_of_Grouping_Method=Changement_de_la_M\u00e9thode_de_Groupement
+change_preamble=changer_le_pr\u00E9ambule
+change_string_content=changer_le_contenu_de_la_cha\u00EEne
+change_string_name=changer_le_nom_de_la_cha\u00EEne
+change_type=changer_le_type
+changed_=chang\u00e9_
+Changed_font_settings=Param\u00E8tres_de_police_modifi\u00E9s
+Changed_language_settings=Param\u00E8tres_linguistiques_modifi\u00E9s
+Changed_look_and_feel_settings=Changer_les_param\u00e8tres_d'apparence
+Changed_preamble=Pr\u00E9ambule_modifi\u00E9
+Changed_type_to=Type_modifi\u00E9_en
+Characters_to_ignore=Caract\u00E8res_\u00E0_ignorer_
+Check_existing_%0_links=V\u00e9rifier_les_liens_%0_existants
+Check_links=V\u00e9rifier_les_liens
+Citation_import_from_CiteSeer_failed.=L'importation_des_citations_depuis_CiteSeer_a_\u00E9chou\u00E9e.
+CiteSeer_Error=Erreur_CiteSeer
+CiteSeer_Fetch_Error=Erreur_de_recherche_sur_CiteSeer
+CiteSeer_import_entries=Entr\u00E9es_d'importation_depuis_CiteSeer
+CiteSeer_Import_Error=Erreur_d'importation_depuis_CiteSeer
+CiteSeer_Import_Fields=Champs_d'importation_de_CiteSeer
+CiteSeer_Transfer=Transfert_de_CiteSeer
+CiteSeer_Warning=Avertissement_CiteSeer
+Class_name=Nom_de_classe
+Clear=Vider
+clear_all_groups=Vider_tous_les_groupes
+Clear_field=Vider_le_champ
+Clear_highlight=Vider_surlignements
+Clear_highlighted=Vider_surlign\u00e9s
+Clear_highlighted_groups=Vider_les_groupes_surlign\u00e9s
+Clear_inputarea=Vider_la_zone_de_saisie
+Clear_search=Effacer_la_recherche
+Close=Fermer
+Close_database=Fermer_la_base
+Close_dialog=Fermer_la_fen\u00EAtre
+Close_entry_editor=Fermer_l'\u00E9diteur_d'entr\u00E9e
+Close_preamble_editor=Fermer_l'\u00E9diteur_de_pr\u00E9ambule
+Close_the_current_database=Fermer_la_base_courante
+Close_the_help_window=Fermer_la_fen\u00EAtre_d'aide
+Close_window=Fermer_la_fen\u00EAtre
+Closed_database=Base_ferm\u00E9e
+Collapse_subtree=Masquer_le_sous-arbre
+Color_codes_for_required_and_optional_fields=Codes_de_couleurs_pour_les_champs_requis_et_optionnels
+Column_width=Largeur_de_colonne
+Complete_record=Compl\u00E9ter_l'enregistrement
+Completed_citation_import_from_CiteSeer.=Importation_des_citations_depuis_CiteSeer_termin\u00E9e.
+Completed_Import_Fields_from_CiteSeer.=Importation_des_champs_depuis_CiteSeer_termin\u00E9e.
+Completed_import_from_CiteSeer.=Importation_depuis_CiteSeer_termin\u00e9e.
+Content=Contenu
+Copied=Copi\u00E9
+Copied_cell_contents=Contenu_des_cellules_copi\u00e9
+Copied_key=Clef_copi\u00E9e
+Copied_keys=Clefs_copi\u00E9es
+Copy=Copier
+Copy_BibTeX_key=Copier_la_clef_BibTeX
+Copy_\\cite{BibTeX_key}=Copier_\\cite{clef_BibTeX}
+Copy_to_clipboard=Copier_le_texte_vers_le_presse-papiers
+Could_not_call_executable=L'ex\u00E9cutable_n'a_pas_pu_\u00EAtre_lanc\u00E9
+Could_not_connect_to_host=La_connexion_\u00e0_l'ordinateur_h\u00f4te_a_\u00e9chou\u00e9
+Could_not_connect_to_host_=La_connexion_\u00e0_l'ordinateur_h\u00f4te_a_\u00e9chou\u00e9_
+Could_not_export_entry_types=L'exportation_des_types_d'entr\u00e9es_a_\u00e9chou\u00e9
+Could_not_export_file=Le_fichier_n'a_pas_pu_\u00EAtre_export\u00E9
+Could_not_export_preferences=L'exportation_des_pr\u00e9f\u00e9rences_a_\u00e9chou\u00e9
+Could_not_find_a_suitable_import_format.=Un_format_d'importation_convenable_n'a_pas_pu_\u00EAtre_trouv\u00E9
+Could_not_find_layout_file=Fichier_de_mise_en_page_non_trouv\u00E9
+Could_not_import_entry_types=L'importation_des_types_d'entr\u00e9es_a_\u00e9chou\u00e9_
+Could_not_import_preferences=L'importation_des_pr\u00e9f\u00e9rences_a_\u00e9chou\u00e9_
+Could_not_resolve_import_format=Le_format_d'importation_n'a_pas_\u00e9t\u00e9_d\u00e9cod\u00e9_
+Could_not_save_file=Le_fichier_n'a_pas_pu_\u00EAtre_sauvegard\u00E9_
+Couldn't_find_an_entry_associated_with_this_URL=Aucune_entr\u00E9e_associ\u00E9e_\u00E0_cette_URL_n'a_\u00E9t\u00E9_trouv\u00E9e_
+Couldn't_parse_the_'citeseerurl'_field_of_the_following_entries=Le_champ_'citeseerurl'_n'a_pas_pu_\u00EAtre_trait\u00E9_dans_les_entr\u00E9es_suivantes_
+Create_group=Cr\u00E9er_le_groupe
+Created_group=Groupe_cr\u00E9\u00E9
+Created_group_"%0".=Groupe_"%0"_cr\u00e9\u00e9.
+Created_groups.=Groupes_cr\u00E9\u00E9s.
+Curly_braces_{_and_}_must_be_balanced.=Les_accolades_{_et_}_doivent_\u00EAtre_\u00E9quilibr\u00E9es.
+Current_content=Contenu_actuel
+Current_value=Valeur_actuelle_
+Custom_entry_types=Types_d'entr\u00E9es_personnalis\u00E9es
+Custom_entry_types_found_in_file=Types_d'entr\u00E9es_personnalis\u00E9es_trouv\u00E9es_dans_le_fichier
+Custom_export=Exportation_personnalis\u00E9e
+Customize_entry_types=Personnaliser_les_types_d'entr\u00E9es
+Customize_key_bindings=Personnaliser_les_affectations_de_touches
+Cut=Couper
+cut_entries=Couper_les_entr\u00E9es
+cut_entry=supprimer_l'entr\u00E9e
+Cut_pr=Couper
+Database_has_changed._Do_you_want_to_save_before_closing?=Base_modifi\u00E9e._Voulez-vous_la_sauvegarder_avant_de_fermer_?
+Date_format=Format_de_date
+Default=D\u00E9faut
+Default_encoding=Encodage_par_d\u00E9faut_
+Default_grouping_field=Champ_par_d\u00E9faut_pour_les_groupes_
+Default_look_and_feel=Apparence_par_d\u00E9faut
+Default_owner=Propri\u00E9taire_par_d\u00E9faut
+Default_pattern=Mod\u00E8le_par_d\u00E9faut
+defined.=d\u00E9fini(e).
+Delete=Supprimer
+Delete_custom=Supprimer_les_d\u00E9finitions_personnalis\u00E9es
+Delete_custom_format=Supprimer_le_format_personnalis\u00E9
+delete_entries=effacer_les_entr\u00E9es
+Delete_entry=Supprimer_l'entr\u00E9e
+delete_entry=effacer_l'entr\u00E9e
+Delete_multiple_entries=Effacer_plusieurs_entr\u00E9es
+Delete_rows=Supprimer_des_lignes
+Delete_strings=Supprimer_les_cha\u00EEnes
+Deleted=Supprim\u00E9
+Deleted_entry=Supprimer_l'entr\u00E9e
+Delimit_fields_with_semicolon,_ex.=D\u00E9limiter_les_champs_par_des_points-virgules,_ex.
+Descending=Descendant
+Description=Description
+Deselect_all=Tout_d\u00e9s\u00e9lectionner
+Details=D\u00E9tails
+Disable_entry_editor_when_multiple_entries_are_selected=D\u00E9sactiver_l'\u00E9diteur_en_cas_de_s\u00E9lections_multiples
+Disable_this_confirmation_dialog=D\u00E9sactiver_cette_demande_de_confirmation
+Disable_this_warning_dialog=D\u00E9sactiver_ce_message_d'avertissement
+Display_all_entries_belonging_to_one_or_more_of_the_selected_groups.=Afficher_toutes_les_entr\u00E9es_appartenant_\u00E0_au_moins_un_des_groupes_s\u00E9lectionn\u00E9s.
+Display_help_on_command_line_options=Afficher_l'aide_sur_les_options_de_la_ligne_de_commande
+Display_imported_entries_in_an_inspection_window_before_they_are_added.=Afficher_les_entr\u00e9es_import\u00e9es_dans_une_fen\u00eatre_d'inspection_avant_de_les_ajouter.
+Display_only_entries_belonging_to_all_selected_groups.=Afficher_uniquement_les_entr\u00E9es_appartenant_\u00E0_tous_les_groupes_s\u00E9lectionn\u00E9s.
+Displaying_no_groups=Pas_de_groupes_\u00E0_afficher
+Do_not_autoset=Ne_pas_d\u00e9finir_automatiquement.
+Do_not_import_entry=Ne_pas_importer_l'entr\u00e9e
+Do_not_open_any_files_at_startup=N'ouvrir_aucun_fichier_au_d\u00E9marrage
+Do_not_overwrite_existing_keys=Ne_pas_\u00e9craser_de_clefs_existantes
+Docbook=Docbook
+Done=Termin\u00E9
+Down=Bas
+Download=T\u00E9l\u00E9chargement
+Download_completed=T\u00E9l\u00E9chargement_termin\u00E9
+Download_file=T\u00E9l\u00E9charger_le_fichier
+Downloading...=T\u00E9l\u00E9chargement...
+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.=A_cause_de_la_clef_BibTeX_dupliqu\u00e9e,_les_assignations_de_groupes_de_cette_entr\u00e9e_ne_pourront_pas_\u00eatre_restaur\u00e9e_correctement_\u00e0_la_r\u00e9ouverture_de_cette_base_de_donn\u00e9es._Il_est_recommand\u00e9_de_demand\u00e9_\u00e0_JabRef_de_g\u00e9n\u0 [...]
+dummy=nul
+Duplicate_BibTeX_key=Dupliquer_la_clef_BibTeX
+duplicate_BibTeX_key=dupliquer_la_clef_BibTeX
+Duplicate_BibTeX_key.=Dupliquer_la_clef_BibTeX.
+duplicate_BibTeX_key.=dupliquer_la_clef_BibTeX.
+Duplicate_BibTeX_key._Grouping_may_not_work_for_this_entry.=Clef_BibTeX_dupliqu\u00e9e._Les_groupes_pourraient_ne_pas_fonctionner_pour_cette_entr\u00e9e.
+Duplicate_Key_Warning=Avertissement :_Clef_dupliqu\u00e9e
+Duplicate_pairs_found=Doublons_trouv\u00E9s
+duplicate_removal=Suppression_des_doublons
+Duplicate_string_name=Dupliquer_le_nom_de_cha\u00EEne
+Duplicates_found=Doublons_trouv\u00e9s
+Duplicates_removed=Doublons_supprim\u00e9s
+Dynamic_groups=Groupes_dynamiques
+Dynamically_group_entries_by_a_free-form_search_expression=Grouper_dynamiquement_les_entr\u00e9es_en_utilisant_une_expression_de_recherche_de_forme_libre
+Dynamically_group_entries_by_searching_a_field_for_a_keyword=Grouper_dynamiquement_les_entr\u00e9es_en_cherchant_un_mot-clef_dans_un_champ
+Each_line_must_be_on_the_following_form=Chaque_ligne_doit_\u00EA_de_la_forme_suivante
+Edit=Editer
+Edit_custom_export=Editer_l'exportation_personnalis\u00E9e
+Edit_entry=Editer_l'entr\u00E9e
+Edit_group=Editer_le_groupe
+Edit_preamble=Editer_le_pr\u00E9ambule
+Edit_strings=Editer_les_cha\u00EEnes
+empty_BibTeX_key=Clef_BibTeX_vide
+Empty_BibTeX_key.=Clef_BibTeX_vide.
+Empty_BibTeX_key._Grouping_may_not_work_for_this_entry.=Vider_la_clef_BibTeX._La_gestion_des_groupes_pourrait_ne_plus_fonctionner_pour_cette_entr\u00e9e.
+Empty_database=Base_vide
+empty_database=base_vide
+Enable source_editing=Autoriser_l'\u00e9dition_du_source
+Enable_source_editing=Autoriser_l'\u00e9dition_du_source
+Endnote=Endnote
+Enter_URL=Entrer_l'URL
+Enter_URL_to_download=Entrer_l'URL_de_t\u00E9l\u00E9chargement
+entries=entr\u00E9es
+Entries_cannot_be_manually_assigned_to_or_removed_from_this_group.=Des_entr\u00e9es_ne_peuvent_pas_ajout\u00e9es_ou_supprim\u00e9es_manuellement_de_ce_groupe.
+Entries_exported_to_clipboard=Entr\u00E9es_export\u00E9es_vers_le_presse-papiers
+entries_have_undefined_BibTeX_key=Des_entr\u00e9es_ont_des_clef_BibTeX_non_d\u00e9finies
+entries_into_new_database=entr\u00E9es_dans_la_nouvelle_base
+entry=entr\u00E9e
+Entry_editor=Editeur_d'entr\u00E9e
+Entry_editor,_next_entry=Editeur_d'entr\u00E9e,_entr\u00E9e_suivante
+Entry_editor,_next_panel=Editeur_d'entr\u00E9e,_fen\u00EAtre_suivante
+Entry_editor,_previous_entry=Editeur_d'entr\u00E9e,_entr\u00E9e_pr\u00E9c\u00E9dente
+Entry_editor,_previous_panel=Editeur_d'entr\u00E9e,_fen\u00EAtre_pr\u00E9c\u00E9dente
+Entry_editor,_store_field=Editeur_d'entr\u00E9e,_sauver_le_champ
+Entry_in_current_database=Entr\u00e9e_dans_la_base_de_donn\u00e9es_actuelle
+Entry_in_import=Entr\u00e9e_dans_l'importation
+Entry_is_incomplete=L'entr\u00E9e_est_incompl\u00E8te
+Entry_preview=Aper\u00E7u_de_l'entr\u00E9e
+Entry_table=Table_des_entr\u00E9es
+Entry_table_columns=Colonnes_de_la_table_des_entr\u00E9es
+Entry_type=Type_d'entr\u00E9e
+Entry_type_names_are_not_allowed_to_contain_white_space_or_the_following_characters=Les_noms_de_type_d'entr\u00E9e_ne_peuvent_pas_contenir_d'espace_et_les_caract\u00E8res_suivants
+Entry_types=Types_d'entr\u00E9es
+EOF_in_mid-string=Fin_de_fichier_au_milieu_d'une_cha\u00EEne
+Error=Erreur
+##Error:_check_your_External_viewer_settings_in_Preferences=Erreur :_v\u00e9rifier_les_param\u00e9trage_de_votre_visionneur_externe_dans_les_Options
+Error_in_field=Erreur_dans_le_champ
+Error_in_line=Erreur_\u00E0_la_ligne
+Error_opening_file=Erreur_lors_de_l'ouverture_du_fichier
+Error_setting_field=Erreur_de_configuration_du_champ
+exists._Overwrite?=existe._Ecraser_le_fichier ?
+exists._Overwrite_file?=existe._Ecraser_le_fichier ?
+Exit=Quitter
+Expand_subtree=D\u00e9velopper_le_sous-arbre
+Explicit=Explicite
+Export=Exporter
+Export_entry_types=Exporter_les_types_d'entr\u00e9es
+Export_name=Nom_de_l'exportation
+Export_preferences=Exporter_les_pr\u00E9f\u00E9rences
+Export_preferences_to_file=Exporter_les_pr\u00E9f\u00E9rences_vers_un_fichier
+Export_properties=Propri\u00E9t\u00E9s_de_l'exportation
+Export_selected_to_clipboard=Exporter_la_s\u00E9lection_vers_le_presse-papiers
+Export_to_clipboard=Exporter_vers_le_presse-papiers
+Exported_database_to_file=Base_export\u00E9e_dans_le_fichier
+Exporting=Exportation_en_cours
+External_changes=Modifications_externes
+External_programs=Programmes_externes
+External_viewer_called=Editeur_externe_lanc\u00E9
+Failed_to_read_groups_data_(unsupported_version:_%0)=La_lecture_des_donn\u00e9es_des_groupes_a_\u00e9chou\u00e9_(version_non_support\u00e9e :_%0)
+Fetch=Rechercher
+Fetch_Articles_Citing_your_Database=Rechercher_les_articles_citant_votre_base
+Fetch_Citations_from_CiteSeer=Rechercher_des_citations_depuis_CiteSeer
+Fetch_citations_from_CiteSeer=Rechercher_des_citations_depuis_CiteSeer
+Fetch_CiteSeer=Recherche_CiteSeer
+Fetch_Medline=Recherche_Medline
+fetch_Medline=recherche_Medline
+Fetch_Medline_by_author=Rechercher_sur_Medline_par_auteur
+Fetch_Medline_by_ID=Recherche_Medline_par_ID
+Fetched_all_citations_from_target_database.=Toutes_les_citations_ont_\u00E9t\u00E9_r\u00E9cup\u00E9r\u00E9es_depuis_la_base_cible.
+Fetching_Citations=Recherche_des_citations_en_cours
+Fetching_Identifiers=Recherche_des_identifiants
+Fetching_Medline...=Recherche_Medline_en_cours...
+Fetching_Medline_by_ID...=Recherche_sur_Medline_par_ID...
+Fetching_Medline_by_id_...=Recherche_sur_Medline_par_id...
+Fetching_Medline_by_term_...=Recherche_sur_Medline_par_terme...
+Field=Champ
+field=Champ
+Field_content=Contenu_du_champ
+Field_name=Nom_de_champ
+Field_names_are_not_allowed_to_contain_white_space_or_the_following_characters=Les_noms_de_champ_ne_peuvent_pas_contenir_d'espace_et_les_caract\u00E8res_suivants
+Field_sizes=Tailles_des_champs
+Field_to_group_by=Champ_\u00E0_grouper_par
+Field_to_search=Champ_pour_la_recherche
+Fields=Champs
+File=Fichier
+file=fichier
+File_changed=Fichier_chang\u00e9
+File_extension=Extension_de_fichier
+File_has_been_updated_externally._Are_you_sure_you_want_to_save?=Le_fichier_a_\u00E9t\u00E9_mis_\u00E0_jour_externalement._Etes-vous_certain_de_vouloir_l'enregistrer ?
+File_not_found=Fichier_non_trouv\u00E9
+File_updated_externally=Fichier_mis_\u00E0_jour_externalement
+filename=nom_de_fichier
+Files_opened=Fichiers_ouverts
+Find_duplicates=Chercher_les_doublons
+Finished_autosetting_%0_field._Entries_changed:_%1.=Auto-param\u00e9trage_du_champ_%0_termin\u00e9._Entr\u00e9es_chang\u00e9es :_%1.
+Finished_synchronizing_%0_links._Entries_changed%c_%1.=Synchronisation_des_liens_%0_termin\u00e9e._Entr\u00e9es_modifi\u00e9es%c_%1.
+First_select_the_entries_you_want_keys_to_be_generated_for.=Commencez_par_s\u00E9lectionner_les_entr\u00E9es_pour_lesquelles_vous_voulez_que_des_clefs_soient_g\u00E9n\u00E9r\u00E9es.
+Fit_table_horizontally_on_screen=Ajuster_la_table_horizontalement_\u00E0_l'\u00E9cran
+Float=Flottante
+Font_Family=Famille_de_police
+Font_Preview=Pr\u00E9visualisation_de_la_police
+Font_Size=Taille_de_police
+Font_Style=Style_de_police
+FontSelector=S\u00E9lecteur_de_police
+for=pour
+Format_of_author_and_editor_names=Format_des_noms_d'auteurs_et_d'\u00E9diteurs
+Format_used=Format_utilis\u00E9
+Formatter_not_found=Formateur_non_trouv\u00E9
+found=trouv\u00E9
+found_in_aux_file=trouv\u00E9es_dans_le_fichier_aux
+General=G\u00e9n\u00e9ral
+General_fields=Champs_g\u00E9n\u00E9raux
+Generate=Cr\u00E9er
+Generate_BibTeX_key=Cr\u00E9er_la_clef_BibTeX
+Generate_keys=G\u00e9n\u00e9rer_les_clefs
+Generate_now=G\u00e9n\u00e9rer_maintenant
+Generated_BibTeX_key_for=Cr\u00E9ation_termin\u00E9e_de_la_clef_BibTeX_pour
+Generating_BibTeX_key_for=Cr\u00E9ation_en_cours_d'une_clef_BibTeX_pour
+Grab=Rechercher
+Gray_out_entries_not_in_group_selection=Griser_les_entr\u00E9es_hors_de_la_s\u00E9lection
+Gray_out_non-hits=Griser_les_entr\u00E9es_non_correspondantes
+Gray_out_non-matching_entries=Griser_les_entr\u00E9es_non_correspondantes
+Group_definitions_have_been_converted_to_JabRef_1.7_format.=Les_d\u00E9finitions_des_groupes_ont_\u00E9t\u00E9_converties_au_format_JabRef_1.7
+Group_name=Nom_du_groupe_
+Group_properties=Propri\u00E9t\u00E9s_du_groupe
+Groups=Groupes
+Harvard_RTF=Harvard_RTF
+Help=Aide
+Help_contents=Contenu_de_l'aide
+Help_on_groups=Aide_sur_les_groupes
+Help_on_key_patterns=Aide_sur_le_param\u00E9trage_des_clefs
+Hide_non-hits=Masquer_les_entr\u00E9es_non_correspondantes
+Highlight=Surlign\u00E9e
+Highlight_groups_matching_all_selected_entries=Surligner_les_groupes_correspondant_\u00e0_toutes_les_entr\u00e9es_s\u00e9lectionn\u00e9es
+Highlight_groups_matching_any_selected_entry=Surligner_les_groupes_correspondant_\u00e0_au_moins_une_des_entr\u00e9es_s\u00e9lectionn\u00e9es
+Highlight_groups_that_contain_entries_contained_in_any_currently_selected_group=Surligner_les_groupes_qui_contiennent_des_entr\u00e9es_contenues_dans_n'importe_quel_groupe_s\u00e9lectionn\u00e9
+Highlight_overlapping_groups=Surligner_les_groupes_se_chevauchant
+Hint%c_To_search_specific_fields_only,_enter_for_example%c<p><tt>author%esmith_and_title%eelectrical</tt>=Astuce%c_Pour_chercher_uniquement_dans_des_champs_sp\u00e9cifiques,_entrez_par_exemple%c<p><tt>author%esmith_and_title%e\u00e9lectrique</tt>
+HTML=HTML
+Ignore=Ignorer
+Illegal_type_name=Nom_de_type_ill\u00e9gal
+Immediate_subgroups=Sous-groupes_directs
+Import=Importer
+Import_and_append=Importer_et_joindre
+Import_and_keep_old_entry=Importer_et_conserver_l'ancienne_entr\u00e9e
+Import_and_remove_old_entry=Importer_et_supprimer_l'ancienne_entr\u00e9e
+Import_cancelled.=Importation_interrompue.
+Import_Data_from_CiteSeer=Importer_les_donn\u00E9es_depuis_CiteSeer
+Import_Data_from_CiteSeer_Database=Importer_les_donn\u00E9es_depuis_la_base_CiteSeer
+Import_database=Importer_une_base
+Import_entries=Importer_les_entr\u00E9es
+Import_entry_types=Types_d'entr\u00e9es_import\u00e9s
+Import_failed=L'importation_a_\u00e9chou\u00e9e
+Import_Fields_from_CiteSeer=Importer_les_champs_depuis_CiteSeer
+Import_fields_from_CiteSeer=Importation_des_champs_\u00E0_partir_de_CiteSeer
+Import_fields_from_CiteSeer_Database=Importation_des_champs_\u00E0_partir_de_la_base_CiteSeer
+Import_Fields_from_CiteSeer_Database=Importer_les_champs_depuis_la_base_CiteSeer
+Import_file=Fichier_\u00E0_importer
+Import_group_definitions=Importer_les_d\u00E9finitions_de_groupe
+Import_plain_text=Importer_des_champs_\u00E0_partir_de_texte_brut
+Import_preferences=Importer_les_pr\u00E9f\u00E9rences
+Import_preferences_from_file=Importer_les_pr\u00E9f\u00E9rences_depuis_un_fichier
+Import_strings=Importer_les_cha\u00EEnes
+Import_to_open_tab=Importer_dans_l'onglet_ouvert
+Import_word_selector_definitions=Importer_les_d\u00E9finitions_des_s\u00E9lecteurs_de_mots
+Imported_database=Base_import\u00E9e
+Imported_entries=Entr\u00E9es_import\u00E9es
+Imported_entry_types=Types_d'entr\u00e9es_import\u00e9s
+Imported_file=Fichier_import\u00E9
+Imported_from_database=Import\u00e9_\u00e0_partir_de_la_base_de_donn\u00e9es
+Importing=Importation_en_cours
+Importing_file=Importation_de_fichier_en_cours
+Importing_in_unknown_format=Importation_dans_un_format_inconnu
+In_JabRef,_use_pairs_of_#_characters_to_indicate_a_string.=Dans_JabRef,_utiliser_une_paire_de_#_pour_d\u00E9limiter_une_cha\u00EEne.
+Include_subgroups=Inclure_les_sous-groupes
+Include_subgroups:_When_selected,_view_entries_contained_in_this_group_or_its_subgroups=Inclure_les_sous-groupes :_Quand_s\u00e9lectionn\u00e9,_afficher_les_entr\u00e9es_contenu_dans_ce_groupe_et_ses_sous-groupes
+Incremental=Incr\u00E9mentale
+Incremental_search=Recherche_incr\u00E9mentale
+Incremental_search_failed._Repeat_to_search_from_top.=La_recherche_incr\u00E9mentale_n'a_pas_abouti._R\u00E9p\u00E9ter_depuis_le_d\u00E9but.
+Independent=Ind\u00E9pendant
+Independent_group:_When_selected,_view_only_this_group's_entries=Groupe_ind\u00e9pendant :_Quand_s\u00e9lectionn\u00e9,_affiche_uniquement_les_entr\u00e9es_de_ce_groupe
+Initially_show_groups_tree_expanded=Afficher_au_d\u00e9part_l'arbre_des_groupes_d\u00e9velopp\u00e9
+Input=Attribution_des_champs
+Input_error=Entr\u00E9e_erron\u00E9e
+Insert=Ins\u00E9rer
+Insert_rows=Ins\u00E9rer_des_lignes
+Insert_selected_citations_into_LyX=Envoyer_les_citations_s\u00E9lectionn\u00E9es_dans_LyX
+Insert_selected_citations_into_WinEdt=Envoyer_les_citations_s\u00E9lectionn\u00E9es_dans_&WinEdt
+insert_string_=ins\u00e9rer_la_cha\u00eene
+Insert_URL=Ins\u00E9rer_l'URL
+INSPEC=INSPEC
+integrity=int\u00e9grit\u00e9
+Integrity_check=V\u00e9rification_d'int\u00e9grit\u00e9
+Intersection=Intersection
+Intersection_with_supergroups=_Intersection_avec_super-groupes
+Invalid_BibTeX_key=Clef_BibTeX_invalide
+Invalid_URL=URL_invalide
+Inverted=Compl\u00E9mentaire
+is_a_standard_type.=est_un_type_standard.
+ISI=ISI
+Item_list_for_field=Liste_des_choix_pour_le_champ
+JabRef_help=Aide_de_JabRef
+JabRef_preferences=Pr\u00E9f\u00E9rences_pour_JabRef
+JStor_file=JStor
+Keep=Garder
+Keep_both=Garder_les_deux
+Keep_lower=Garder_celui_du_bas
+Keep_upper=Garder_celui_du_haut
+Key_bindings=Affectations_des_touches
+Key_bindings_changed=Affectations_des_touches_modifi\u00E9es
+Key_generator_settings=Param\u00e9trage_du_g\u00e9n\u00e9rateur_de_clef
+Key_pattern=Param\u00E9trage_des_clefs
+keys_in_database=clefs_dans_la_base_de_donn\u00e9es
+Keyword=Mot-clef
+Label=Nom_du_champ
+Language=Langue_
+Latex_AUX_file=Fichier_LaTeX_AUX
+LaTeX_AUX_file=Fichier_LaTeX_AUX
+Left=Gauche
+License=Licence
+Limit_to_fields=Restreindre_aux_champs
+Limit_to_selected_entries=Restreindre_aux_seules_entr\u00E9es_s\u00E9lectionn\u00E9es
+Listen_for_remote_operation_on_port=Ecouter_le_port_pour_des_op\u00e9rations_\u00e0_distance
+Load_session=Charger_la_session
+Loading_session...=Chargement_de_la_session...
+Look_and_feel=Apparence
+lower=minuscule
+Main_layout_file=Principal_fichier_de_mise_en_page
+Main_PDF_directory=R\u00E9pertoire_PDF_principal_
+Main_PS_directory=R\u00e9pertoire_PS_principal_
+Manage=G\u00E9rer
+Manage_content_selectors=G\u00E9rer_les_s\u00E9lecteurs_de_contenu
+Manage_custom_exports=G\u00E9rer_les_exportations_personnalis\u00E9es
+Mark_entries=Etiqueter_des_entr\u00E9es
+Mark_entry=Etiqueter_l'entr\u00E9e
+Mark_new_entries_with_addition_date=Enregistrer_la_date_d'ajout_pour_les_nouvelles_entr\u00e9es
+Mark_new_entries_with_owner_name=Nouvelles_entr\u00E9es_attribu\u00E9es_au_propri\u00E9taire_
+Marked_selected=Etiquetage_de_la_s\u00E9lection
+Medline_entries_fetched=Entr\u00E9es_Medline_r\u00E9cup\u00E9r\u00E9es
+Medline_XML=Medline_XML
+Medline_XML_File=Medline_XML
+Menu_and_label_font_size=Taille_de_police_pour_les_menus_et_les_champs_
+Merged_external_changes=Fusionner_les_modifications_externes
+messages=messages
+Messages=Messages
+Messages_and_Hints=Avertissements_et_Suggestions
+Miscellaneous=Divers
+Modification_of_field=Modification_du_champ
+Modified_group_"%0".=Groupe_"%0"_modifi\u00e9.
+Modified_groups=Groupes_modifi\u00e9s
+Modified_groups_tree=Arborescence_des_groupes_modifi\u00e9e
+Modified_string=Cha\u00EEne_modifi\u00E9e
+Modify=Modifier
+modify_group=Modifier_le_groupe
+MODS=MODS
+Move=D\u00e9placer
+Move_down=D\u00E9placer_vers_le_bas
+Move_entries_in_group_selection_to_the_top=D\u00E9placer_les_entr\u00E9es_s\u00E9lectionn\u00E9es_en_haut
+move_group=d\u00e9placer_le_groupe
+Move_matching_entries_to_the_top=D\u00E9placer_en_haut_les_entr\u00E9es_correspondant_aux_crit\u00E8res_de_recherche
+Move_string_down=D\u00E9placer_la_cha\u00EEne_vers_le_bas
+Move_string_up=D\u00E9placer_la_cha\u00EEne_vers_le_haut
+Move_up=D\u00E9placer_vers_le_haut
+Moved_Group=Groupe_d\u00e9plac\u00e9
+Moved_group_"%0".=Groupe_"%0"_d\u00e9plac\u00e9.
+Name=Nom
+nested_aux_files=fichiers_AUX_imbriqu\u00E9s
+New=Nouveau
+new=Nouveau
+New_article=Nouveau_'article'
+New_BibTeX_database=Nouvelle_base_BibTeX
+New_BibTeX_entry=Nouvelle_entr\u00E9e_BibTeX
+New_BibTeX_subdatabase=Nouveau_fichier_BibTeX
+New_book=Nouveau_'book'
+New_content=Nouveau_contenu
+New_database=Nouvelle_base
+New_database_created.=Nouvelle_base_cr\u00E9\u00E9e.
+New_entry=Nouvelle_entr\u00E9e
+New_entry...=Nouvelle_entr\u00E9e...
+New_entry_from_plain_text=Nouvelle_entr\u00E9e_depuis_texte_brut
+New_group=Nouveau_groupe
+New_inbook=Nouveau_'inbook'
+New_mastersthesis=Nouveau_'mastersthesis'
+New_phdthesis=Nouveau_'phdthesis'
+New_proceedings=Nouveau_'proceedings'
+New_string=Nouvelle_cha\u00EEne
+New_subdatabase=Nouveau_fichier
+New_subdatabase_based_on_AUX_file=Nouveau_fichier_BibTeX_depuis_fichier_AUX
+New_unpublished=Nouveau_'unpublished'
+Next_entry=Entr\u00E9e_suivante
+Next_tab=Onglet_suivant
+No_%0_found=Pas_de_%0_trouv\u00e9
+No_actual_changes_found.=Pas_de_changements_trouv\u00e9s.
+no_base-bibtex-file_specified=fichier_BibTeX_non_sp\u00e9cifi\u00e9 !
+no_database_generated=pas_de_base_cr\u00E9\u00E9e
+No_duplicates_found=Pas_de_doublons_trouv\u00e9s
+No_entries_imported.=Pas_d'entr\u00e9es_import\u00e9es.
+No_entries_or_multiple_entries_selected.=Pas_d'entr\u00E9e_s\u00E9lectionn\u00E9e_ou_s\u00E9lection_de_plusieurs_entr\u00E9es.
+No_entries_selected=Pas_d'entr\u00e9es_s\u00e9lectionn\u00e9es
+No_GUI._Only_process_command_line_options.=Pas_d'interface_utilisateur._Traitement_limit\u00E9_aux_options_de_la_ligne_de_commande.
+No_Medline_entries_found.=Pas_d'entr\u00e9es_Medline_trouv\u00e9es
+No_pdf_or_ps_defined,_and_no_file_matching_Bibtex_key_found=PDF_ou_PS_non_d\u00E9fini_et_fichier_correspondant_\u00E0_la_clef_BibTeX_non_trouv\u00E9.
+No_references_found=Aucune_r\u00E9f\u00E9rence_trouv\u00E9e
+No_saved_session_found.=Pas_trouv\u00E9_de_session_sauvegard\u00E9e.
+No_url_defined=Pas_d'URL_d\u00E9finie
+non-Mac_only=Uniquement_pour_les_non-Mac
+not=non
+not_found=non_trouv\u00E9
+Not_saved_(empty_session)=Pas_de_sauvegarde_(session_vide)
+Note_that_the_entry_causing_the_problem_has_been_selected.=Noter_que_l'entr\u00E9e_responsable_du_probl\u00E8me_a_\u00E9t\u00E9_s\u00E9lectionn\u00E9e.
+Note_that_the_new_definitions_will_not_be_compatible_with_previous_JabRef_versions.=Notez_que_les_nouvelles_d\u00E9finitions_ne_seront_pas_compatibles_avec_les_pr\u00E9c\u00E9dentes_versions_de_JabRef.
+Note_that_you_must_specify_the_fully_qualified_class_name_for_the_look_and_feel,=Notez_que_vous_devez_sp\u00E9cifier_le_nom_de_classe_complet_pour_l'apparence,
+Nothing_to_redo=Rien_\u00E0_r\u00E9p\u00E9ter
+Nothing_to_undo=Rien_\u00E0_annuler
+Number_of_references_to_fetch?=Nombre_de_r\u00E9f\u00E9rences_\u00E0_r\u00E9cup\u00E9rer_?
+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=ouvre
+Open_BibTeX_database=Ouvrir_une_base_BibTeX
+Open_database=Ouvrir_une_base
+Open_editor_when_a_new_entry_is_created=Ouvrir_l'\u00E9diteur_quand_une_nouvelle_entr\u00E9e_est_cr\u00E9\u00E9e
+Open_file=Ouvrir_le_fichier
+Open_last_edited_databases_at_startup=Ouvrir_les_fichiers_de_la_derni\u00E8re_session_au_d\u00E9marrage
+Open_PDF_or_PS=Ouvrir_PDF_ou_PS
+Open_right-click_menu_with_Ctrl+left_button=D\u00E9rouler_le_menu_contextuel_avec_Ctrl+clic_gauche
+Open_URL_or_DOI=Ouvrir_URL_ou_DOI
+Opened_database=Base_ouverte
+Opening=Ouverture_en_cours
+Opening_preferences...=Ouverture_des_pr\u00E9f\u00E9rences_en_cours...
+Optional_fields=Champs_optionnels
+Options=Options
+or=ou
+out_of=sur
+Output_or_export_file=Fichier_de_sortie_ou_d'exportation
+Overlapping_groups=Groupes_se_chevauchant
+Override=Remplacer
+override_the_bibtex_key_by_the_selected_text=remplacer_la_clef_BibTeX_par_le_texte_s\u00e9lectionn\u00e9
+Overwrite_keys=Ecraser_les_clefs
+Ovid=Ovid
+pairs_processed=paires_trait\u00E9es
+Paste=Coller
+paste_entries=Coller_les_entr\u00E9es
+paste_entry=Coller_l'entr\u00E9e
+Paste_from_clipboard=Coller_le_texte_depuis_le_presse-papiers
+Pasted=Coll\u00E9
+Path_to_HTML_viewer=Chemin_du_visionneur_HTML_
+Path_to_LyX_pipe=Chemin_du_canal_de_transmission_Lyx_
+Path_to_PDF_viewer=Chemin_du_visionneur_PDF_
+Path_to_PS_viewer=Chemin_du_visionneur_PS_
+Path_to_WinEdt.exe=Chemin_de_WinEdt.exe_
+Paths_to_external_programs=Chemins_vers_les_programmes_externes.
+PDF_links=Liens_PDF
+Pick_titles=S\u00e9lectionnez_des_titres[?]
+Plain_right_menu=Menu_droit_brut_[?]
+Plain_text=Texte_brut
+Plain_text_import=Importation_de_texte_brut
+Please_check_your_network_connection_to_this_machine.=SVP,_v\u00E9rifiez_votre_connexion_r\u00E9seau_\u00E0_cette_machine.
+Please_define_BibTeX_key_first=SVP,_commencez_par_d\u00E9finir_la_clef_BibTeX
+Please_enter_a_name_for_the_group.=SVP,_entrez_un_nom_pour_le_groupe.
+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>=SVP,_entrez_un_terme_\u00e0_recherche._Par_exemple,_pour_rechercher_<b>Smith</b>_dans_tout_les_champs,_entrez %c<p><tt>smith</tt><p>Pour_rechercher_<b>Smith</b>_dans_le_champ_<b>Author</b>_et_<b>\u00e9lectrique</b>_dans_le_c [...]
+Please_enter_a_semicolon_or_comma_separated_list_of_Medline_IDs_(numbers).=SVP,_entrez_une_liste_d'IDs_Medline_(num\u00E9riques)_s\u00E9par\u00E9s_par_un_point-virgule_ou_par_une_virgule
+Please_enter_the_field_to_search_(e.g._<b>keywords</b>)_and_the_keyword_to_search_it_for_(e.g._<b>electrical</b>).=SVP,_entrez_le_champ_de_recherche_(par_ex._<b>keywords</b>)_et_le_mot-clef_\u00e0_rechercher_(par_ex._<b>\u00e9lectrique</b>).
+Please_enter_the_string's_label=SVP,_entrez_le_nom_de_la_cha\u00EEne
+Please_refer_to_the_JabRef_help_manual_on_using_the_CiteSeer_tools.=SVP,_reportez-vous_au_manuel_d'aide_de_JabRef_\u00E0_propos_de_l'utilisation_des_outils_CiteSeer.
+Please_select_exactly_one_group_to_move.=SVP,_s\u00e9lectionnez_uniquement_un_groupe_\u00e0_d\u00e9placer.
+Please_wait_until_it_has_finished.=SVP,_attendez_la_fin_de_l'op\u00E9ration.
+Possible_duplicate_entries=Entr\u00E9es_potentiellement_dupliqu\u00E9es
+Possible_duplicate_of_existing_entry._Click_to_resolve.=Duplication_possible_d'une_entr\u00e9e_existante._Cliquer_pour_v\u00e9rification_pour_trancher.
+Preamble=Pr\u00E9ambule
+Preamble_editor,_store_changes=Editeur_de_pr\u00E9ambule,_sauver_les_changements
+Preferences=Pr\u00E9f\u00E9rences
+Preferences_recorded=Pr\u00E9f\u00E9rences_enregistr\u00E9es
+Preferences_recorded.=Pr\u00E9f\u00E9rences_enregistr\u00E9es.
+Preserve_formatting_of_non-BibTeX_fields=Pr\u00E9server_le_format_des_champs_non-BibTeX
+Preview=Aper\u00E7u
+Previous_entry=Entr\u00E9e_pr\u00E9c\u00E9dente
+Previous_tab=Onglet_pr\u00E9c\u00E9dent
+Problem_with_parsing_entry=Probl\u00E8me_de_traitement_d'une_entr\u00E9e
+PS_links=Liens_PS
+push_selection_to_lyx=Envoyer_la_s\u00E9lection_dans_LyX
+Push_selection_to_WinEdt=Envoyer_la_s\u00E9lection_dans_WinEdt
+Push_to_LyX=Envoyer_vers_LyX
+Push_to_WinEdt=Envoyer_vers_WinEdt
+Pushed_the_citations_for_the_following_rows_to=Envoyer_les_citations_pour_les_lignes_suivantes_vers
+Query_author(s)=Requ\u00EAte_sur_les_auteurs
+Quit=Quitter
+Quit_JabRef=Quitter_JabRef
+Quit_synchronization=Quitter_la_synchronisation
+Raw_source=Texte_brut
+Really_delete_the_selected=Voulez-vous_vraiment_supprimer_cette
+Recent_files=Fichiers_r\u00E9cents
+Redo=R\u00E9p\u00E9ter
+Refer/Endnote=Refer/Endnote
+Reference_database=Base_de_r\u00E9f\u00E9rence
+References_found=R\u00E9f\u00E9rences_trouv\u00E9es
+Refine_supergroup:_When_selected,_view_entries_contained_in_both_this_group_and_its_supergroup=Raffine_le_super-groupe :_Quand_s\u00e9lectionn\u00e9,_affiche_les_entr\u00e9es_contenues_\u00e0_la_fois_dans_ce_groupe_et_son_super-groupe
+Refresh_view=Rafra\u00EEchir_la_vue
+Regexp=Exp._R\u00E9g.
+Regular_Expression=Expression_r\u00E9guli\u00E8re
+Remember_these_entry_types?=Se_souvenir_de_ces_types_d'entr\u00E9es_?
+Remote_operation=Acc\u00e8s_\u00e0_distance
+Remote_server_port=Port_du_serveur_d'acc\u00e8s_\u00e0_distance
+Remove=Supprimer
+Remove_all?=Tout_supprimer_?
+Remove_all_subgroups=Supprimer_les_sous-groupes
+Remove_all_subgroups_of_"%0"?=Supprimer_tous_les_sous-groupes_de_"%0"_?
+Remove_duplicates=Supprimer_les_doublons
+Remove_entry_from_import=Supprimer_l'entr\u00e9e_de_l'importation
+Remove_entry_type=Supprimer_le_type_d'entr\u00E9e
+remove_from_group=supprimer_du_groupe
+Remove_from_group=Supprimer_du_groupe
+Remove_group=Supprimer_le_groupe
+Remove_group,_keep_subgroups=Supprimer_le_groupe,_garder_les_sous-groupes
+Remove_group_"%0"?=Supprimer_le_groupe_"%0"_?
+Remove_group_"%0"_and_its_subgroups?=Supprimer_le_groupe_"%0"_et_ses_sous-groupes_?
+remove_group_(keep_subgroups)=supprimer_le_groupe_(garder_les_sous-groupes)
+remove_group_and_subgroups=supprimer_le_groupe_et_les_sous-groupes
+Remove_group_and_subgroups=Supprimer_le_groupe_et_les_sous-groupes
+Remove_old_entry=Supprimer_l'ancienne_entr\u00e9e
+Remove_selected_strings=Supprimer_les_cha\u00EEnes_s\u00E9lectionn\u00E9es
+remove_string=enlever_la_cha\u00EEne
+remove_string_=enlever_la_cha\u00eene_
+Removed_entry_type.=Type_d'entr\u00E9e_supprim\u00E9.
+Removed_group=Groupe_supprim\u00E9
+Removed_group_"%0".=Groupe_"%0"_supprim\u00e9.
+Removed_group_"%0"_and_its_subgroups.=Groupe_"%0"_et_ses_sous-groupes_supprim\u00e9s.
+Removed_string=Cha\u00EEne_supprim\u00E9e
+Renamed_string=Cha\u00eene_renomm\u00e9e
+Repeat_incremental_search=R\u00E9p\u00E9ter_la_recherche_incr\u00E9mentale
+Replace=Remplacer
+Replace_string=Remplacer_la_cha\u00EEne
+Replace_with=Remplacer_par
+Replaced=Remplac\u00E9
+Required_fields=Champs_requis
+Reset_all=R\u00E9tablir_les_options_pr\u00E9c\u00E9dentes
+resolved=r\u00E9solu
+Results=R\u00E9sultats
+Revert_to_original_source=R\u00E9tablir_le_contenu_initial
+Review_changes=Revoir_les_changements
+Right=Droite
+RIS=RIS
+Save=Sauver
+Save_before_closing=Sauvegarde_avant_fermeture
+Save_database=Sauvegarder_la_base
+Save_database_as_...=Sauvegarder_la_base_sous_...
+Save_selected_as_...=Sauvegarder_la_s\u00E9lection_sous_...
+Save_session=Sauvegarder_la_session
+Saved_database=Base_sauvegard\u00E9e
+Saved_selected_to=Sauvegarder_la_s\u00E9lection_de
+Saved_session=Session_sauvegard\u00E9e
+Saving=Enregistrement_en_cours
+Scan=D\u00E9marrer
+SciFinder=SciFinder
+Search=Recherche
+Search_All_Fields=Recherche_dans_tous_les_champs
+Search_all_fields=Recherche_dans_tous_les_champs
+Search_error=Erreur_de_recherche
+Search_expression=Expression_\u00E0_rechercher_
+Search_for=Rechercher
+Search_General_Fields=Recherche_dans_les_champs_g\u00E9n\u00E9raux
+Search_general_fields=Recherche_dans_les_champs_g\u00E9n\u00E9raux
+Search_Optional_Fields=Recherche_dans_les_champs_optionnels
+Search_optional_fields=Recherche_dans_les_champs_optionnels
+Search_Required_Fields=Recherche_dans_les_champs_requis
+Search_required_fields=Recherche_dans_les_champs_requis
+Search_Specified_Field(s)=Recherche_dans_les_champs_sp\u00E9cifi\u00E9s
+Search_term=Rechercher_le_terme
+Searched_database._Number_of_hits=Recherche_effectu\u00E9e._Nombre_de_r\u00E9sultats_trouv\u00E9s
+Searching_for_%0_file=Recherche_du_fichier_%0
+Searching_for_duplicates...=Recherche_des_doublons_en_cours...
+Secondary_sort_criterion=Crit\u00E8re_secondaire_de_tri
+Select=S\u00E9lectionner
+Select_action=S\u00E9lectionner_l'op\u00E9ration
+Select_all=Tout_s\u00E9lectionner
+Select_entries_in_group_selection=S\u00E9lectionner_les_entr\u00E9es_dans_la_s\u00E9lection
+Select_entry_type=S\u00E9lectionner_un_type_d'entr\u00E9e
+Select_format=S\u00E9lectionner_le_format
+Select_matches=S\u00E9lectionner_les_correspondances
+Select_matching_entries=S\u00E9lection_des_entr\u00E9es_correspondant_aux_crit\u00E8res_de_recherche
+Select_the_tree_nodes_to_view_and_accept_or_reject_changes=S\u00E9lectionner_les_noeuds_de_l'arborescence_pour_voir,_et_accepter_ou_rejeter,_les_modifications
+Selector_enabled_fields=Champs_de_s\u00E9lecteur_actifs
+Set_general_fields=D\u00E9finir_les_champs_g\u00E9n\u00E9raux
+Set_table_font=D\u00E9finir_la_police_de_la_table
+Set_up_general_fields=Configurer_les_champs_g\u00E9n\u00E9raux
+Settings=Param\u00E8tres
+Setup_selectors=G\u00E9rer_les_s\u00E9lecteurs
+Short_form=Forme_courte
+Shortcut=Raccourci
+Show/edit_BibTeX_source=Montrer/\u00E9diter_le_source_BibTeX
+Show_'Firstname_Lastname'=Ordre_d'affichage_'Pr\u00E9nom_Nom'
+Show_'Lastname,_Firstname'=Ordre_d'affichage_'Nom,_Pr\u00E9nom'
+Show_abstract=Montrer_le_r\u00E9sum\u00E9
+Show_BibTeX_source_by_default=Par_d\u00E9faut,_afficher_l'onglet_Source_BibTeX
+Show_BibTeX_source_panel=Afficher_l'onglet_"Source_BibTeX"
+Show_CiteSeer_column=Afficher_la_colonne_CiteSeer
+Show_confirmation_dialog_when_deleting_entries=Demander_une_confirmation_lors_de_la_suppression_d'entr\u00E9es
+Show_dynamic_groups_in_<i>italics</i>=Afficher_les_groupes_dynamiques_en_<i>italique</i>
+Show_entries_*not*_in_group_selection=Montrer_les_entr\u00E9es_*non*_s\u00E9lectionn\u00E9es
+Show_general_fields=Montrer_les_champs_g\u00E9n\u00E9raux
+Show_groups_matching_all=Montrer_les_groupes_correspondants_\u00e0_tous
+Show_groups_matching_any=Montrer_les_groupes_correspondants_\u00e0_n'importe_quel
+Show_icons_for_groups=Afficher_les_ic\u00f4nes_pour_les_groupes
+Show_names_unchanged=Ordre_des_noms_inchang\u00E9
+Show_one_less_rows=Afficher_une_ligne_de_moins
+Show_one_more_row=Afficher_une_ligne_de_plus
+Show_optional_fields=Montrer_les_champs_optionnels
+Show_overlapping_groups=Montrer_les_groupes_se_chevauchant
+Show_PDF/PS_column=Afficher_la_colonne_PDF/PS
+Show_required_fields=Montrer_les_champs_requis
+Show_URL/DOI_column=Afficher_la_colonne_URL/DOI
+Show_warning_dialog_when_a_duplicate_BibTeX_key_is_entered=Afficher_un_message_d'avertissement_quand_une_clef_BibTeX_d\u00E9j\u00E0_existante_est_entr\u00E9e
+Show_warning_dialog_when_an_empty_BibTeX_key_is_entered=Afficher_une_fen\u00eatre_d'avertissement_quand_une_clef_BibTeX_vide_est_entr\u00e9e
+Simple_HTML=HTML_(simple)
+Sixpack=Sixpack
+Size_of_groups_interface_(rows)=Taille_de_l'interface_des_groupes_(lignes)
+Skip=Passer
+Sort_alphabetically=Classer_alphab\u00e9tiquement
+Sort_Automatically=Trier_automatiquement
+Sort_options=Options_du_tri
+sort_subgroups=trier_les_sous-groupes
+Sorted_all_subgroups_recursively=Tous_les_sous-groupes_r\u00e9cursivement_tri\u00e9s
+Sorted_all_subgroups_recursively.=Tous_les_sous-groupes_r\u00e9cursivement_tri\u00e9s.
+Sorted_immediate_subgroups=Sous-groupes_directs_tri\u00e9s
+Sorted_immediate_subgroups.=Sous-groupes_directs_tri\u00e9s.
+source_edit=\u00E9dition_du_source
+Special_table_columns=Colonnes_de_tableau_particuli\u00E8res
+Start=D\u00E9marrer
+Start_incremental_search=D\u00E9marrer_la_recherche_incr\u00E9mentale
+Start_search=D\u00e9buter_la_recherche
+Statically_group_entries_by_manual_assignment=Grouper_manuellement_les_entr\u00E9es
+Status=Etat
+Stop=Arr\u00eat
+Store=Enregistrer
+Store_fields_with_double_braces,_and_remove_extra_braces_when_loading.<BR>Double_braces_signal_that_BibTeX_should_preserve_character_case.=Enregistrer_les_champs_avec_des_doubles_accolades_et_supprimer_les_accolades_suppl\u00e9mentaires_au_chargement._<BR>Les_doubles_accolades_signalent_que_BibTeX_doit_pr\u00e9server_la_casse_des_caract\u00e8res.
+Store_string=Enregistrer_la_cha\u00EEne
+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 :
+subdatabase_from_aux=BibTeX_\u00E0_partir_de_LaTex_aux
+Subdatabase_from_aux=BibTeX_\u00E0_partir_de_LaTex_aux
+Suggest=Sugg\u00E9rer
+Switch_preview_layout=Pr\u00E9visualiser_la_mise_en_page
+Synchronize_%0_links=Synchroniser_les_liens_%0
+Synchronizing_%0_links...=Synchronisation_des_liens_%0...
+Table=Table
+Table_appearance=Apparence_de_la_table
+Tabname=Nom_d'onglet
+Tertiary_sort_criterion=Crit\u00E8re_tertiaire_de_tri
+Test=Test
+Text_Input_Area=Zone_de_saisie_du_texte
+The_#_character_is_not_allowed_in_BibTeX_fields=Le_caract\u00E8re_#_est_interdit_dans_un_champ_BibTeX
+The_CiteSeer_fetch_operation_returned_zero_results.=La_recherche_CiteSeer_n'a_retourn\u00E9_aucun_r\u00E9sultat.
+the_field_<b>%0</b>=le_champ_<b>%0</b>
+The_file<BR>'%0'<BR>has_been_modified<BR>externally!=Le_fichier<BR>'%0'<BR>a_\u00e9t\u00e9_modifi\u00e9_<BR>externalement !
+The_group_"%0"_already_contains_the_selection.=Le_groupe_"%0"_contient_d\u00e9j\u00e0_la_s\u00e9lection.
+The_group_"%0"_does_not_support_the_adding_of_entries.=Le_groupe_"%0"_ne_supporte_pas_l'ajout_des_entr\u00e9es.
+The_group_"%0"_does_not_support_the_removal_of_entries.=Le_groupe_"%0"_ne_supporte_pas_la_suppression_des_entr\u00e9es.
+The_label_of_the_string_can_not_be_a_number.=L'intitul\u00E9_de_la_cha\u00EEne_ne_peut_\u00EAtre_un_nombre.
+The_label_of_the_string_can_not_contain_spaces.=Un_nom_de_cha\u00eene_ne_peut_pas_contenir_d'espaces.
+The_label_of_the_string_can_not_contain_the_'#'_character.=Le_nom_de_la_cha\u00eene_ne_peut_pas_contenir_le_caract\u00e8re_'#'.
+The_output_option_depends_on_a_valid_import_option.=L'option_de_sortie_d\u00e9pend_d'une_option_d'importation_valide.
+The_regular_expression_<b>%0</b>_is_invalid%c=L'expression_r\u00e9guli\u00e8re_<b>%0</b>_est_invalide%c
+The_search_is_case_insensitive.=La_recherche_n'est_pas_sensible_\u00e0_la_casse.
+The_search_is_case_sensitive.=La_recherche_est_sensible_\u00e0_la_casse.
+The_string_has_been_removed_locally=La_cha\u00EEne_a_\u00E9t\u00E9_supprim\u00E9e_localement
+The_type_name_can_not_contain_spaces.=Le_nom_d'un_type_ne_peut_pas_contenir_d'espaces.
+The_URL_field_appears_to_be_empty_on_entry_number_=Le_champ_URL_semble_\u00eatre_vide_pour_l'entr\u00e9e_num\u00e9ro_
+There_are_possible_duplicates_(marked_with_a_'D'_icon)_that_haven't_been_resolved._Continue?=Il_y_a_des_doublons_potentiels_(marqu\u00e9_avec_un_ic\u00f4ne_'D')_qui_n'ont_pas_\u00e9t\u00e9_r\u00e9solus._Continuer_?
+There_is_no_entry_type=Il_n'y_a_pas_de_type_d'entr\u00E9e
+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?=Cette_action_modifiera_le_champ_"%0"_de_vos_entr\u00e9es._Cela_pourrait_causer_des_changements_involontaires_dans_vos_entr\u00e9es,_aussi_il_n'est_pas_recommand\u00e9_que_vous_changiez_ce_champ_dans_votre_d\u00e9finition_de_groupe_par_"keywor [...]
+this_button_will_update=Ce_bouton_sera_mis_\u00e0_jour
+this_button_will_update_the_column_width_settings<BR>to_match_the_current_widths_in_your_table=ce_bouton_mettra_\u00E0_jour_les_param\u00E8tres_des_largeurs_des_colonnes<BR>pour_retenir_les_largeurs_actuelles_de_votre_table
+This_entry_is_incomplete=Cette_entr\u00E9e_est_incompl\u00E8te
+This_entry_type_cannot_be_removed.=Ce_type_d'entr\u00E9e_ne_peut_pas_\u00EAtre_supprim\u00E9.
+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.=Ce_groupe_contient_des_entr\u00e9es_bas\u00e9es_sur_un_ajout_manuel._Des_entr\u00e9es_peuvent_\u00eatre_ajout\u00e9es [...]
+This_group_contains_entries_in_which=Ce_groupe_contient_des_entr\u00e9es_pour_lesquelles
+This_group_contains_entries_in_which_any_field_contains_the_regular_expression_<b>%0</b>=Ce_groupe_contient_des_entr\u00e9es_dans_lesquelles_un_champ_contient_l'expression_r\u00e9guli\u00e8re_<b>%0</b>
+This_group_contains_entries_in_which_any_field_contains_the_term_<b>%0</b>=Ce_groupe_contient_des_entr\u00e9es_dans_lesquelles_un_champ_contient_le_terme_<b>%0</b>
+This_group_contains_entries_whose_<b>%0</b>_field_contains_the_keyword_<b>%1</b>=Ce_groupe_contient_des_entr\u00e9es_dont_le_champ_<b>%0</b>_contient_le_mot-clef_<b>%1</b>
+This_group_contains_entries_whose_<b>%0</b>_field_contains_the_regular_expression_<b>%1</b>=Ce_groupe_contient_des_entr\u00e9es_dont_le_champ_<b>%0</b>_contient_l'expression_r\u00e9guli\u00e8re_<b>%1</b>
+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.=Cette_fen\u00EAtre_fonctionne_par_copier-coller._Commencer_par_charger_ou_coller_du_texte_dans_la_zone_de_saisie_du_texte._Ensuite,_vous_pouvez_s\u00E9lectionner_le_texte_et_attribuer_\u00E0_un_champ_BibTeX.
+This_is_a_simple_copy_and_paste_dialog_for_import_some_fields_from_normal_text.=Ceci_est_simplement_une_fen\u00eatre_de_copier-coller_pour_importer_certains_champs_\u00e0_partir_d'un_texte_normal
+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.=Cela_conduit_JabRef_\u00e0_tester_chaque_lien_%0_et_\u00e0_v\u00e9rifier_si_le_fichier_existe._Dans_la_n\u00e9gative,_des_options_vous_seront_propos\u00e9es<BR>pour_r\u00e9soudre_le_probl\u00e8me.
+This_operation_cannot_work_on_multiple_rows.=Cette_op\u00E9ration_ne_peut_pas_\u00EAtre_effectu\u00E9e_sur_plusieurs_lignes.
+Toggle_entry_preview=Afficher/Masquer_l'aper\u00E7u
+Toggle_groups_interface=Afficher/Masquer_l'interface_des_groupes
+Toggle_search_panel=Afficher/Masquer_la_fen\u00EAtre_de_recherche
+Tools=Outils
+Type=Type
+Type_set_to_'other'=Type_configur\u00E9_comme_'other'_(autre)
+unable_to_access_LyX-pipe=Incapable_d'acc\u00E9der_au_canal_de_transmission_LyX
+Unable_to_create_graphical_interface=Incapable_de_cr\u00e9er_l'interface_graphique
+Unable_to_parse_clipboard_text_as_Bibtex_entries.=Incapable_de_traiter_le_texte_du_presse-papiers_comme_des_entr\u00e9es_BibTeX.
+Unable_to_parse_the_following_URL=Incapable_de_traiter_l'ULR_suivante
+unable_to_write_to=Incapable_d'\u00e9crire_sur
+Undo=Annuler
+Union=Union
+unknown_bibtex_entries=entr\u00e9es_BibTeX_inconnues
+Unknown_bibtex_entries=Entr\u00E9es_BibTeX_inconnues
+unknown_edit=\u00e9dition_inconnue
+unknown_entry_type=type_d'entr\u00E9e_inconnue
+Unknown_export_format=Format_d'exportation_inconnu
+Unmark_all=Tout_d\u00E9s\u00E9tiqueter
+Unmark_entries=D\u00E9s\u00E9tiqueter_des_entr\u00E9es
+Unmark_entry=D\u00E9s\u00E9tiqueter_l'entr\u00E9e
+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
+untitled=sans_titre
+Up=Haut
+Update_to_current_column_widths=Figer_les_largeurs_des_colonnes_actuelles
+Updated_group_selection=S\u00E9lection_de_groupe_mise_\u00E0_jour
+Updating_entries...=Mise_\u00E0_jour_des_entr\u00E9es...
+UPPER=MAJUSCULE
+Upper_Each_First=Chaque_Premi\u00E8re_Lettre_En_Majuscule
+Upper_first=Premi\u00E8re_lettre_en_majuscule
+usage=usage
+Use_antialiasing_font_in_table=Utiliser_une_police_liss\u00E9e_dans_la_table
+Use_inspection_window_also_when_a_single_entry_is_imported.=Utiliser_la_fen\u00eatre_d'inspection_m\u00eame_quand_une_seule_entr\u00e9e_est_import\u00e9e.
+Use_other_look_and_feel=Utiliser_une_autre_apparence
+Use_regular_expressions=Utiliser_les_expressions_r\u00E9guli\u00E8res
+Use_the_following_delimiter=Utiliser_le_d\u00E9limiteur_suivant
+Use_the_following_delimiter_character(s)=Utiliser_le(s)_caract\u00e8re(s)_de_s\u00E9paration_suivant(s)
+Uses_default_application=Utilise_l'application_par_d\u00e9faut
+Value_cleared_externally=Valeur_supprim\u00E9e_externalement
+Value_set_externally=Valeur_param\u00E9tr\u00E9e_externalement_
+verify_that_LyX_is_running_and_that_the_lyxpipe_is_valid=v\u00E9rifier_que_LyX_tourne_et_que_le_canal_de_transmission_LyX_est_valide
+View=Aper\u00E7u
+Visible_fields=Champs_visibles
+Warn_about_unresolved_duplicates_when_closing_inspection_window=Avertir_des_doublons_non_r\u00e9solus_lors_de_la_fermeture_de_la_fen\u00eatre_d'inspection
+Warn_before_overwriting_existing_keys=Avertir_avant_d'\u00E9craser_des_clefs_existantes
+Warning=Avertissement
+Warning_there_is_a_duplicate_key=Avertissement_%c_il_y_a_une_clef_dupliqu\u00e9e
+Warnings=Messages_d'avertissement
+web_link=Lien_internet
+When_adding/removing_keywords,_separate_them_by=Lors_de_l'ajout/suppression_de_mots-clef,_les_s\u00e9parer_avec
+with=avec
+Word=Mot
+Wrong_file_format=Format_de_fichier_incorrect
+You_have_changed_the_language_setting._You_must_restart_JabRef_for_this_to_come_into_effect.=Vous_avez_modifi\u00E9_la_langue._Vous_devez_red\u00E9marrer_JabRef_pour_que_ce_changement_prenne_effet.
+You_have_cleared_this_field._Original_value=Vous_avez_vid\u00e9_ce_champ._Valeur_originale
+You_must_enter_an_integer_value_in_the_text_field_for=Vous_devez_entrer_une_valeur_enti\u00e8re_dans_le_champ_texte_pour
+You_must_fill_in_a_name_for_the_entry_type.=Vous_devez_fournir_un_nom_pour_le_type_d'entr\u00E9e.
+You_must_provide_a_name,_a_search_string_and_a_field_name_for_this_group.=Vous_devez_fournir_un_nom,_une_cha\u00EEne_\u00E0_rechercher_et_un_nom_de_champ_pour_ce_groupe.
+You_must_restart_JabRef_for_the_new_key_bindings_to_work_properly.=Vous_devez_relancer_JabRef_pour_que_les_nouvelles_affectations_des_touches_soient_activ\u00E9es
+You_must_select_a_row_to_perform_this_operation.=Vous_devez_s\u00E9lectionner_une_ligne_pour_effectuer_cette_op\u00E9ration.
+You_must_select_at_least_one_row_to_perform_this_operation.=Vous_devez_s\u00E9lectionner_au_moins_une_colonne_pour_effectuer_cette_op\u00E9ration.
+You_must_set_both_BibTeX_key_and_%0_directory=Vous_devez_d\u00E9finir_\u00E0_la_fois_la_clef_BibTeX_et_le_r\u00E9pertoire_%0
+You_must_set_both_bibtex_key_and_PDF_directory=You_must_set_both_bibtex_key_and_PDF_directory
+Your_new_key_bindings_have_been_stored.=Votre_nouvelle_affectation_de_touche_a_\u00E9t\u00E9_sauvegard\u00E9e
+Manage_custom_imports=G\u00e9rer_les_importations_personnalis\u00e9es
+Select_Classpath_of_New_Importer=S\u00e9lectionner_le_chemin_de_classe_du_nouveau_filtre_d'importation
+Select_new_ImportFormat_Subclass=S\u00e9lectionner_une_nouvelle_sous-classe_ImportFormat
+Could_not_instantiate_%0_%1=N'a_pas_pu_initialiser_%0_%1
+Add_a_(compiled)_custom_ImportFormat_class_from_a_class_path._\nThe_path_need_not_be_on_the_classpath_of_JabRef.=Ajouter_une_classe_ImportFormat_personnalis\u00e9e_(compil\u00e9e)_\u00e0_partir_d'un_chemin_de_classe._\nLe_chemin_n'a_pas_besoin_d'\u00eatre_dans_le_chemin_de_classe_de_JabRef.
+Please_select_an_importer=S\u00e9lectionner_un_filtre_d'importation,_SVP
+Import_name=nom_Import
+Command_line_id=Identifiant_de_la_ligne_de_commande
+ImportFormat_class=Classe_ImportFormat
+Contained_in=Contenu_dans
+Show_description=Montrer_la_description
+Add_from_folder=Ajouter_\u00e0_partir_du_r\u00e9pertoire
+Custom_importers=Filtres_d'importation_personnalis\u00e9s
+No_custom_imports_registered_yet.=Pas_encore_d'importation_personnalis\u00e9e_enregistr\u00e9e
+Abbreviate_journal_names_of_the_selected_entries_(ISO_abbreviation)=Abr\u00e9ger_les_noms_de_journaux_des_entr\u00e9es_s\u00e9lectionn\u00e9es_(abr\u00e9viations_ISO)
+Abbreviate_journal_names_of_the_selected_entries_(MEDLINE_abbreviation)=Abr\u00e9ger_les_noms_de_journaux_des_entr\u00e9es_s\u00e9lectionn\u00e9es_(abr\u00e9viations_MEDLINE)
+Background_color_for_marked_entries=Couleur_d'arri\u00e8re-plan_pour_les_entr\u00e9es_marqu\u00e9es
+Background_color_for_optional_fields=Couleur_d'arri\u00e8re-plan_pour_les_champs_optionnels
+Background_color_for_required_fields=Couleur_d'arri\u00e8re-plan_pour_les_champs_requis
+Choose_the_URL_to_download._The_default_value_points_to_a_list_provided_by_the_JabRef_developers.=Choisir_l'URL_de_t\u00e9l\u00e9chargement._La_valeur_par_d\u00e9faut_pointe_vers_une_liste_fournie_par_les_d\u00e9veloppeurs_de_JabRef
+Color_for_marking_incomplete_entries=Couleur_pour_marque_les_entr\u00e9es_incompl\u00e8tes
+Do_not_abbreviate_names=Ne_pas_abr\u00e9ger_les_noms
+Do_not_wrap_the_following_fields_when_saving=Ne_pas_renvoyer_\u00e0_la_ligne_les_champs_suivants_lors_de_la_sauvegarde
+External_files=Fichiers_externes
+File_'%0'_not_found=Fichier_'%0'_non_trouv\u00e9
+Journal_abbreviations=Abr\u00e9viations_de_journaux
+Journal_name=Nom_du_journal
+Manage_journal_abbreviations=G\u00e9rer_les_abr\u00e9viations_de_journaux
+Natbib_style=Style_Natbib
+New_file=Nouveau_fichier
+Personal_journal_list=Liste_personnelle_de_journaux
+Remove_double_braces_around_BibTeX_fields_when_loading.=Supprimer_les_doubles_accolades_autour_des_champs_BibTeX_\u00e0_l'ouverture
+Store_the_following_fields_with_braces_around_capital_letters=Stocker_les_champs_suivants_avec_des_accolades_autour_des_lettres_capitales
+Table_background_color=Couleur_d'arri\u00e8re-plan_de_la_table
+Table_grid_color=Couleur_de_la_grille_de_la_table
+Table_text_color=Couleur_du_texte_de_la_table
+Toggle_abbreviation=Afficher/Masquer_l'abr\u00e9viation
+Unabbreviate_journal_names_of_the_selected_entries=D\u00e9velopper_les_noms_de_journaux_des_entr\u00e9es_s\u00e9lectionn\u00e9es
+Use_antialiasing_font=Utiliser_une_police_liss\u00e9e
+Abbreviate_names=Abr\u00e9ger_les_noms
+Abbreviation=Abr\u00e9viation
+ISO_abbreviation=Abr\u00e9viation_ISO
+Edit_journal=Editer_le_journal
+Existing_file=Fermeture_du_fichier_en_cours
+Saving_database=Sauvegarde_de_la_base_en_cours
+Normal=Normale
+Default_sort_criteria=Crit\u00e8re_de_tri_par_d\u00e9faut
+Primary_sort_criterion=Crit\u00e8re_de_tri_principal
+Database_properties=Propri\u00E9t\u00E9s_de la base de donn\u00e9es
+Database_encoding=Encodage_de_la_base_de_donn\u00e9es
+No_journal_names_could_be_abbreviated.=Aucun_nom_de_journal_n'a_pu_\u00eatre_abr\u00e9g\u00e9.
+No_journal_names_could_be_unabbreviated.=Aucun_nom_de_journal_n'a_pu_\u00eatre_d\u00e9velopp\u00e9.
+Save_failed=Echec_de_la_sauvegarde
+Pushed_citations_to_WinEdt=Citations_envoy\u00e9es_vers_WinEdt
+Try_different_encoding=Essayer_un_encodage_diff\u00e9rent
+Select_encoding=S\u00e9lectionner_l'encodage
+The_chosen_date_format_for_new_entries_is_not_valid=Le_format_de_date_choisi_pour_les_nouvelles_entr\u00e9es_n'est_pas_valide
+Invalid_date_format=Format_de_date_invalide
+Review=V\u00e9rification
+Journal_names=Noms_de_journaux
+Save_failed_during_backup_creation=La_sauvegarde_a_\u00e9chou\u00e9e_durant_la_cr\u00e9ation_de_la_copie_de_secours
+Save_failed_while_committing_changes=La_sauvegarde_a_\u00e9chou\u00e9e_lors_de_la_soumission_des_changements
+Full_name=Nom_complet
+Store_journal_abbreviations=Stocker_les_abr\u00e9viations_de_journaux
+You_must_choose_a_file_name_to_store_journal_abbreviations=Vous_devez_choisir_un_nom_de_fichier_pour_stocker_les_abr\u00e9viations_de_journaux
+Journal_list_preview=Pr\u00e9visualisation_de_la_liste_des_journaux
+
+Add_from_jar=Ajouter_\u00e0_partir_de_jar
+Add_a_(compiled)_custom_ImportFormat_class_from_a_Zip-archive.\nThe_Zip-archive_need_not_be_on_the_classpath_of_JabRef.=Ajouter_une_classe_ImportFormat_personnalis\u00e9e_(compil\u00e9e)_\u00e0_partir_d'une_archive_ZIP._\nL'archive_ZIP_n'a_pas_besoin_d'\u00eatre_dans_le_chemin_de_classe_de_JabRef.
+Select_a_Zip-archive=S\u00e9lectionner_une_archive_ZIP
+Select_file_from_ZIP-archive=S\u00e9lectionner_un_fichier_depuis_une_archive_ZIP
+Last_modified=Dernier_modifi\u00e9
+Size=Taille
+Please_select_an_importer.=S\u00e9lectionner_un_filtre_d'importation,_SVP.
+
+Arguments_passed_on_to_running_JabRef_instance._Shutting_down.=Arguments_transmis_\u00e0_l'instance_JabRef active.
+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').=La_connexion_\u00e0_un_processus gnuserv_actif_a_\u00e9chou\u00e9._Assurez-vous_qu'Emacs_ou_XEmacs_soit_actif,<BR>et_que_le_serveur_a_\u00e9t\u00e9_d\u00e9marr\u00e9_(avec_la_commande_'gnuserv-start').
+
+Push_selection_to_Emacs=Envoyer_la_s\u00E9lection_dans_Emacs
+Pushed_citations_to_Emacs=Envoyer_les_citations_dans_Emacs
+
+Filter=Filtre
+Hide_non-matching_entries=Masquer_les_entr\u00E9es_non_correspondantes
+Replace_(regular_expression)=Remplacer_(expression_r\u00e9guli\u00e8re)
+
+Cite_command_(for_Emacs/WinEdt)=Commande_de_citation_(pour_Emacs/WinEdt)
+
+Could_not_instantiate_%0_%1._Have_you_chosen_the_correct_package_path?=%0_%1_a_\u00e9chou\u00e9._Avez-vous_choisi_le_chemin_de_paquetage_correct_?
+No_entries_found._Please_make_sure_you_are_using_the_correct_import_filter.=Pas_d'entr\u00e9es_trouv\u00e9es._Assurez-vous,_SVP,_que_vous_utilisez_le_filtre_d'importation_appropri\u00e9.
+
+Switches_between_full_and_abbreviated_journal_name_if_the_journal_name_is_known.=Basculer_entre_les_noms_de_journaux_d\u00e9velopp\u00e9s_et_abr\u00e9g\u00e9s_si_le_nom_de_journal_est_connu. 
+To_set_up,_go_to_<B>Tools_->_Manage_journal_abbreviations</B>=Pour_configurer,_voir_<B>Outils_->_G\u00e9rer_les_abr\u00e9viations_de_journaux</B>
+
+Could_not_run_the_'gnuclient'_program._Make_sure_you_have_the_gnuserv/gnuclient_programs_installed.=Le_programme_'gnuclient'_n'a_pas_pu_\u00eatre_lanc\u00e9._Assurez-vous_que_les_programmes_gnuserv/gnuclient_sont_install\u00e9s.
diff --git a/src/resource/JabRef_no.properties b/src/resource/JabRef_no.properties
new file mode 100644
index 0000000..3cec8ef
--- /dev/null
+++ b/src/resource/JabRef_no.properties
@@ -0,0 +1,1028 @@
+#! created/edited by Popeye version 0.51 sunshine (popeye.sourceforge.net)
+
+!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.=Dette_er_et_enkelt_klipp-og-lim-vindu._F\u00F8rst_last_inn_eller_kopier_tekst_til_inndatafeltet._Deretter_kan_du_merke_tekst_og_tildele_den_til_et_BibTeX-felt.
+%0_contains_the_Regular_Expression_<b>%1</b>=%0_inneholder_regul\u00e6ruttrykket_<b>%1</b>
+%0_contains_the_term_<b>%1</b>=%0_inneholder_uttrykket_<b>%1</b>
+%0_doesn't_contain_the_Regular_Expression_<b>%1</b>=%0_inneholder_ikke_regul\u00e6ruttrykket_<b>%1</b>
+%0_doesn't_contain_the_term_<b>%1</b>=%0_inneholder_ikke_uttrykket_<b>%1</b>
+%0_doesn't_match_the_Regular_Expression_<b>%1</b>=%0_matcher_ikke_regul\u00e6ruttrykket_<b>%1</b>
+%0_doesn't_match_the_term_<b>%1</b>=%0_matcher_ikke_uttrykket_<b>%1</b>
+%0_field_set=%0-felt_satt
+%0_import_cancelled.=%0-import_kansellert.
+%0_matches_the_Regular_Expression_<b>%1</b>=%0_matcher_regul\u00e6ruttrykket_<b>%1</b>
+%0_matches_the_term_<b>%1</b>=%0_matcher_uttrykket_<b>%1</b>
+<field_name>=<feltnavn>
+<HTML>Unpack_the_zip_file_containing_import/export_filters_for_Endnote,<BR>for_optimal_interoperability_with_JabRef</HTML>=<HTML>Pakk_ut_zip-filen_som_inneholder_import-_og_eksportfiltre_for<BR>EndNote,_for_best_mulig_kompatibilitet_med_JabRef</HTML>
+<no_field>=<ingen_felter>
+<select>=<velg>
+<select_word>=<velg_ord>
+_on_entry_number_=_ved_enhet_nummer_
+A_CiteSeer_fetch_operation_is_currently_in_progress.=En_henteoperasjon_fra_CiteSeer_p\u00E5g\u00E5r_allerede.
+A_CiteSeer_import_operation_is_currently_in_progress.=En_importoperasjon_fra_CiteSeer_p\u00E5g\u00E5r_allerede.
+A_string_with_that_label_already_exists=En_streng_med_det_navnet_finnes_allerede
+About_JabRef=Om_JabRef
+Abstract=Sammendrag
+Accept=Aksepter
+Accept_change=Aksepter_endring
+Action=Aksjon
+Add=Legg_til
+add_entries_to_group=legg_til_enheter_i_gruppe
+add_group=legg_til_gruppe
+Add_Group=Legg_til_gruppe
+Add_new=Legg_til_ny
+Add_Subgroup=Legg_til_undergruppe
+Add_to_group=Legg_til_i_gruppe
+Added_entry=La_til_enhet
+Added_group=La_til_gruppe
+Added_group_"%0".=La_til_gruppe_"%0".
+Added_new=La_til_ny
+Added_string=La_til_streng
+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.=Dessuten,_enheter_hvis_<b>%0</b>-felt_ikke_inneholder_<b>%1</b>_kan_leg [...]
+Advanced=Avansert
+Advanced_options_for_setting...=Advanced_options_for_setting...
+All_Entries=Alle_enheter
+All_entries=Alle_enheter
+All_entries_of_this_type_will_be_declared_typeless._Continue?=Alle_enheter_av_denne_typen_vil_bli_erkl\u00E6rt_typel\u00F8se._Fortsette?
+All_fields=Alle_felter
+All_subgroups_(recursively)=Alle_undergrupper_(rekursivt)
+Allow_editing_in_table_cells=Tillat_redigering_av_celler_i_tabellen
+Always_save_database_ordered_by_author_name=Lagre_alltid_sortert_p\u00E5_forfatternavn
+and=og
+and_the_class_must_be_available_in_your_classpath_next_time_you_start_JabRef.=og_klassen_m\u00E5_v\u00E6re_tilgjengelig_i_CLASSPATH_neste_gang_du_starter_JabRef.
+any_field_that_matches_the_regular_expression_<b>%0</b>=ethvert_felt_som_matcher_regul\u00e6ruttrykket_<b>%0</b>
+Appearance=Utseende
+Append=Legg_til
+Append_contents_from_a_BibTeX_database_into_the_currently_viewed_database=Legg_til_innhold_fra_en_BibTeX-database_i_den_\u00E5pne_database
+Append_database=Append_database
+append_the_selected_text_to_bibtex_key=
+Apply=Utf\u00F8r
+Assign_entries_based_on:=Assign_entries_based_on:
+Assign_new_file=Tilordne_ny_fil
+Assign_the_original_group's_entries_to_this_group?=Legg_den_opprinnelige_gruppens_enheter_til_denne_gruppen?
+Assigned_%0_entries_to_group_"%1".=La_til_%0_enheter_til_gruppen_"%1".
+Assigned_1_entry_to_group_"%0".=La_til_1_enhet_til_gruppen_"%0".
+Attach_%0_file=Tilordne_%0-fil
+Attach_URL=Tilordne_URL
+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.=Pr\u00F8v_\u00E5_sette_%0-linker_automatisk_for_dine_enheter._Dette_virker_dersom_en_%0-fil_i_%0-katalogen_din_eller_en_underkatalog<BR>har_navn_likt_en_enhets_BibTeX-n\u00F8kkel,_pluss_etternavn.
+Auto=Auto
+Autodetect_format=Autodetekter_format
+Autogenerate_BibTeX_key=Autogenerer_BibTeX-n\u00F8kkel
+Autogenerate_BibTeX_keys=Autogenerer_BibTeX-n\u00F8kler
+Autogenerate_groups=Autogenerer_grupper
+autogenerate_keys=autogenerer_n\u00F8kler
+Automatically_create_groups=Generer_grupper_automatisk
+Automatically_create_groups_for_database.=Generer_grupper_for_databasen.
+Automatically_created_groups=Genererte_grupper_automatisk
+Automatically_hide_groups_interface_when_switching_to_a_database_that_contains_no_groups=Skjul_automatisk_grupperingskontroll_n\u00e5_du_bytter_til_en_database_som_ikke_inneholder_grupper
+Automatically_show_groups_interface_when_switching_to_a_database_that_contains_groups=Vis_automatisk_grupperingskontroll_n\u00e5_du_bytter_til_en_database_som_inneholder_grupper
+Autoset=Sett_automatisk
+Autoset_%0_field=Automatisk_setting_av_%0-felt
+Autoset_%0_links._Allow_overwriting_existing_links.=Sett_%0-linker_automatisk._Tillat_overskriving_av_eksisterende_linker.
+Autoset_%0_links._Do_not_overwrite_existing_links.=Sett_%0-linker_automatisk._Skriv_ikke_over_eksisterende_linker.
+Autosetting_%0_field...=Setter_%0-felt_automatisk...
+AUX_File_import=AUX-import
+AUX_file_import=AUX-fil_import
+Available_export_formats=Tilgjengelige_eksportformater
+Available_fields=Tilgjengelige_felter
+Available_import_formats=Tilgjengelige_importformater
+Backup_old_file_when_saving=Lag_sikkerhetskopi_ved_lagring
+Bibkey_to_filename_conversion=
+Biblioscape_Tag_file=Biblioscape_tag-fil
+BibTeX=BibTeX
+BibTeX_key=
+BibTeX_key_is_unique.=BibTeX-n\u00F8kkelen_er_unik
+BibTeX_key_not_set._Enter_a_name_for_the_downloaded_file=BibTeX-n\u00F8kkel_er_ikke_satt._Angi_et_navn_for_den_nedlastede_filen
+BibTeX_source=BibTeX-kilde
+BibTeXML=BibTeXML
+BibTeXML_File=BibTeXML-fil
+Binding=Hurtigtast
+Broken_link=Ugyldig_link
+Browse=Bla_gjennom
+by=med
+Calling_external_viewer...=Kaller_opp_eksternt_program...
+Cancel=Avbryt
+Cannot_add_entries_to_group_without_generating_keys._Generate_keys_now?=Kan_ikke_legge_til_enheter_til_en_gruppe_uten_\u00e5_generere_n\u00f8kler._Vil_du_generer_n\u00f8kler_n\u00e5?
+Cannot_merge_this_change=Kan_ikke_inkorporere_denne_endringen
+Cannot_move_group=Kan_ikke_flytte_gruppen
+Cannot_move_group_"%0"_down.=Kan_ikke_flytte_gruppen_"%0"_ned.
+Cannot_move_group_"%0"_left.=Kan_ikke_flytte_gruppen_"%0"_til_venstre.
+Cannot_move_group_"%0"_right.=Kan_ikke_flytte_gruppen_"%0"_til_h\u00f8yre.
+Cannot_move_group_"%0"_up.=Kan_ikke_flytte_gruppen_"%0"_opp.
+case_insensitive=skiller_ikke_mellom_store_og_sm\u00e5_bokstaver
+case_sensitive=skiller_mellom_store_og_sm\u00e5_bokstaver
+Case_sensitive=Skill_store_og_sm\u00E5_bokstaver
+change_assignment_of_entries=endre_tilordning_av_enheter
+Change_case=Endre_store/sm\u00E5_bokstaver
+Change_entry_type=Endre_enhetstype
+change_key=sett_n\u00F8kkel
+Change_of_Grouping_Method=Endre_grupperingsm\u00E5te
+change_preamble=endre_'preamble'
+change_string_content=endre_strengdefinisjon
+change_string_name=endre_navn_p\u00E5_streng
+change_type=endre_type
+changed_=endret_
+Changed_font_settings=Endret_skriftoppsett
+Changed_language_settings=Endret_spr\u00E5koppsett
+Changed_look_and_feel_settings=Endret_oppsett_av_grensesnitt
+Changed_preamble=Endret_preamble
+Changed_type_to=Endret_type_til
+Characters_to_ignore=Ignorer_f\u00F8lgende_tegn
+Check_existing_%0_links=Sjekk_eksisterende_%0-linker
+Check_links=Sjekk_eksterne_linker
+Citation_import_from_CiteSeer_failed.=Import_av_referanser_fra_CiteSeer_mislyktes.
+CiteSeer_Error=CiteSeer-feil
+CiteSeer_Fetch_Error=Feil_ved_henting_fra_CiteSeer
+CiteSeer_import_entries=CiteSeer_importer_enheter
+CiteSeer_Import_Error=Feil_ved_import_fra_CiteSeer
+CiteSeer_Import_Fields=CiteSeer_importer_felter
+CiteSeer_Transfer=CiteSeer-overf\u00F8ring
+CiteSeer_Warning=CiteSeer-advarsel
+Class_name=Klassenavn
+Clear=Opphev
+clear_all_groups=fjern_alle_grupper
+Clear_field=Slett_felt
+Clear_highlight=Fjern_utheving
+Clear_highlighted=Fjern_utheving
+Clear_highlighted_groups=Fjern_utheving_av_grupper
+Clear_inputarea=Slett_inndata
+Clear_search=Opphev_s\u00F8k
+Close=Lukk
+Close_database=Lukk_database
+Close_dialog=Lukk_dialog
+# The following lines correspond to names of key bindings:
+Close_entry_editor=Lukk_enhetsskjema
+Close_preamble_editor=Lukk_preamble-skjema
+Close_the_current_database=Lukk_denne_databasen
+Close_the_help_window=Lukk_hjelpevinduet
+Close_window=Lukk_vindu
+Closed_database=Lukket_database
+Collapse_subtree=Lukk_forgrening
+Color_codes_for_required_and_optional_fields=Fargekoder_for_n\u00F8dvendige_og_valgfrie_felter
+Column_width=Kolonnebredde
+Complete_record=Komplett_form
+Completed_citation_import_from_CiteSeer.=Import_av_referanser_fra_CiteSeer_fullf\u00F8rt.
+Completed_Import_Fields_from_CiteSeer.=Fullf\u00F8rte_import_av_felter_fra_CiteSeer
+Completed_import_from_CiteSeer.=Fullf\u00F8rte_import_fra_CiteSeer
+Content=Innhold
+Copied=Kopierte
+Copied_cell_contents=Kopierte_innhold_av_cellen
+Copied_key=Kopierte_n\u00F8kkel
+Copied_keys=Kopierte_n\u00F8kler
+Copy=Kopier
+Copy_BibTeX_key=Kopier_BibTeX-n\u00F8kkel
+Copy_\\cite{BibTeX_key}=
+Copy_to_clipboard=Kopier
+Could_not_call_executable=Kunne_ikke_kalle_programfilen
+Could_not_connect_to_host=Kunne_ikke_koble_til_vert
+Could_not_connect_to_host_=Kunne_ikke_koble_opp_mot_vert
+Could_not_export_entry_types=Kunne_ikke_eksportere_enhetstyper
+Could_not_export_file=Kunne_ikke_eksportere
+Could_not_export_preferences=Kunne_ikke_eksportere_innstillinger
+# I have reformulated the following lines, because the 1st person form is not suitable:
+Could_not_find_a_suitable_import_format.=Fant_ikke_noe_passende_importformat.
+Could_not_find_layout_file=Fant_ikke_layoutfil
+Could_not_import_entry_types=Kunne_ikke_importere_enhetstyper
+Could_not_import_preferences=Kunne_ikke_importere_innstillinger
+Could_not_resolve_import_format=Kunne_ikke_bestemme_importformat
+Could_not_save_file=Kunne_ikke_lagre
+Couldn't_find_an_entry_associated_with_this_URL=Fant_ingen_enhet_for_f\u00F8lgende_URL
+Couldn't_parse_the_'citeseerurl'_field_of_the_following_entries=Kunne_ikke_tolke_'citeseerurl'-feltet_for_f\u00F8lgende_enheter
+Create_group=Opprett_gruppe
+Created_group=Opprettet_gruppe
+Created_group_"%0".=Opprettet_gruppe_"%0".
+Created_groups.=Opprettet_grupper.
+Curly_braces_{_and_}_must_be_balanced.=Kr\u00F8llparenteser_{_og_}_m\u00E5_v\u00E6re_balanserte.
+Current_content=N\u00E5v\u00E6rende_innhold
+Current_value=N\u00E5v\u00E6rende_verdi
+Custom_entry_types=Egendefinerte_enhetstyper
+Custom_entry_types_found_in_file=Fant_egendefinerte_enhetstyper_i_filen
+Custom_export=Eksterne_eksportfiltre
+Customize_entry_types=Tilpass_enhetstyper
+Customize_key_bindings=Sett_opp_hurtigtaster
+Cut=Klipp_ut
+cut_entries=klippet_ut
+cut_entry=klipp_ut_enhet
+Cut_pr=Klippet_ut
+Database_has_changed._Do_you_want_to_save_before_closing?=Databasen_er_endret._Vil_du_lagre_f\u00F8r_du_lukker_den?
+Date_format=
+Default=Tilbakestill
+Default_encoding=Standard_koding
+Default_grouping_field=Standardfelt_for_gruppering
+Default_look_and_feel=Standard_utseende
+Default_owner=Eier_av_nye_enheter
+Default_pattern=Default_pattern
+defined.=er_definert.
+Delete=Slett
+Delete_custom=Slett_tilpasset
+Delete_custom_format=Slett_tilpasset_type
+delete_entries=slett_enheter
+Delete_entry=Slett_enhet
+delete_entry=slett_enhet
+Delete_multiple_entries=Slett_flere_enheter
+Delete_rows=Slett_rader
+Delete_strings=Slett_strenger
+Deleted=Slettet
+Deleted_entry=Slettet_enhet
+Delimit_fields_with_semicolon,_ex.=Avgrens_felter_med_semikolon,_f.eks.
+Descending=Synkende
+Description=Beskrivelse
+Deselect_all=Velg_ingen
+Details=Details
+Disable_entry_editor_when_multiple_entries_are_selected=Sperr_enhetsskjema_n\u00E5r_flere_enheter_er_valgt
+Disable_this_confirmation_dialog=Deaktiver_denne_kontrolldialogen
+Disable_this_warning_dialog=Deaktiver_denne_advarselen
+Display_all_entries_belonging_to_one_or_more_of_the_selected_groups.=Vis_alle_enheter_inneholdt_i_minst_en_av_de_valgte_gruppene.
+Display_help_on_command_line_options=Vis_kommandolinjehjelp
+Display_imported_entries_in_an_inspection_window_before_they_are_added.=Vis_importerte_enheter_i_et_inspeksjonsvindu_f\u00F8r_de_legges_til.
+Display_only_entries_belonging_to_all_selected_groups.=Vis_kun_enheter_inneholdt_i_alle_valgte_grupper.
+Displaying_no_groups=Viser_ingen_grupper
+Do_not_autoset=Ikke_sett_linker_automatisk
+Do_not_import_entry=Ikke_importer_enhet
+Do_not_open_any_files_at_startup=\u00c5pne_ingen_filer_ved_oppstart
+Do_not_overwrite_existing_keys=Ikke_skriv_over_eksisterende_n�kler
+Docbook=Docbook
+Done=Ferdig
+Down=Ned
+Download=Last_ned
+Download_completed=Nedlasting_fullf\u00F8rt
+Download_file=Last_ned_fil
+Downloading...=Laster_ned...
+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.=P\u00e5_grunn_av_den_ikke-unike_BibTeX-n\u00f8kkelen_kan_ikke_gruppetilordningen(e)_for_denne_enheten_gjenopprettes_riktig_n\u00e5r_databasen_\u00e5pnes_igjen._Det_anbefales_at_du_lar_JabRef_generere_en_unik_n\u00f8kkel_for_\u00e5_unng\u00e5_dette_problemet.
+dummy=dummy
+Duplicate_BibTeX_key=Ikke_unik_BibTeX-n\u00F8kkel
+duplicate_BibTeX_key=ikke_unik_BibTeX-n\u00F8kkel
+Duplicate_BibTeX_key.=Duplicate_BibTeX_key.
+duplicate_BibTeX_key.=ikke_unik_n\u00F8kkel.
+Duplicate_BibTeX_key._Grouping_may_not_work_for_this_entry.=BibTeX-n\u00F8kkelen_er_ikke_unik._Gruppering_kan_feile_for_denne_enheten.
+Duplicate_Key_Warning=Advarsel:_ikke_unik_n\u00F8kkel
+Duplicate_pairs_found=Duplikatpar_funnet
+duplicate_removal=fjerning_av_duplikater
+Duplicate_string_name=Ikke_unikt_navn_p\u00E5_streng
+Duplicates_found=Duplikater_funnet
+Duplicates_removed=Duplikater_fjernet
+Dynamic_groups=Dynamiske_grupper
+Dynamically_group_entries_by_a_free-form_search_expression=Grupper_enheter_dynamisk_ved_hjelp_av_et_standard_s\u00f8keuttrykk
+Dynamically_group_entries_by_searching_a_field_for_a_keyword=Grupper_enheter_dynamisk_ved_\u00e5_s\u00f8ke_etter_n\u00f8kkelord_i_et_felt
+Each_line_must_be_on_the_following_form=Hver_av_linjene_m\u00E5_v\u00E6re_p\u00E5_den_f\u00F8lgende_formen
+Edit=Rediger
+Edit_custom_export=Rediger_eksternt_eksportfilter
+Edit_entry=Rediger_enhet
+Edit_group=Rediger_gruppe
+Edit_preamble=Rediger_'preamble'
+Edit_strings=Rediger_strenger
+empty_BibTeX_key=tom_BibTeX-n\u00F8kkeldfasdfdsafads
+Empty_BibTeX_key.=Tom_BibTeX-n\u00F8kkel
+Empty_BibTeX_key._Grouping_may_not_work_for_this_entry.=Tom_BibTeX-n\u00F8kkel._Gruppering_kan_feile_for_denne_enheten.
+Empty_database=Empty_database
+empty_database=tom_database
+Enable source_editing=Tillat_redigering_av_BibTeX-kildekode
+Enable_source_editing=Tillat_redigering_av_kildekode
+Endnote=Endnote
+Enter_URL=Skriv_inn_URL
+Enter_URL_to_download=Skriv_inn_URL_som_skal_lastes_ned
+entries=enheter
+Entries_cannot_be_manually_assigned_to_or_removed_from_this_group.=Enheter_kan_ikke_manuelt_legges_til_i_eller_fjernes_fra_denne_gruppen.
+Entries_exported_to_clipboard=Enheter_eksportert_til_utklippstavle
+entries_have_undefined_BibTeX_key=enheter_har_udefinert_BibTeX-n\u00f8kkel
+entries_into_new_database=enheter_i_ny_database
+entry=enhet
+Entry_editor=Enhetsskjema
+# The following lines correspond to names of key bindings:
+Entry_editor,_next_entry=Enhetsskjema,_neste_enhet
+Entry_editor,_next_panel=Enhetsskjema,_neste_panel
+Entry_editor,_previous_entry=Enhetsskjema,_forrige_enhet
+Entry_editor,_previous_panel=Enhetsskjema,_forrige_panel
+Entry_editor,_store_field=Enhetsskjema,_lagre_felt
+Entry_in_current_database=Enhet_i_eksisterende_database
+Entry_in_import=Enhet_i_import
+Entry_is_incomplete=Enheten_er_ufullstendig
+Entry_preview=Forh\u00E5ndsvisning
+Entry_table=Hovedtabell
+Entry_table_columns=Tabellkolonner
+Entry_type=Enhetstype
+Entry_type_names_are_not_allowed_to_contain_white_space_or_the_following_characters=Navn_p\u00E5_typer_kan_ikke_inneholde_opperom_eller_noen_av_de_f\u00F8lgende_tegnene
+Entry_types=Enhetstyper
+EOF_in_mid-string=EOF_in_mid-string
+Error=Feil
+##Error:_check_your_External_viewer_settings_in_Preferences=Feil:_unders\u00F8k_innstillingene_for_Eksterne_programmer_i_Innstillinger
+Error_in_field=Feil_i_felt
+Error_in_line=Error_in_line
+Error_opening_file=Feil_ved_\u00E5pning_av_fil
+Error_setting_field=Problem_med_\u00E5_sette_felt
+exists._Overwrite?=eksisterer._Skriv_over?
+exists._Overwrite_file?=eksisterer._Erstatt_filen?
+Exit=Avslutt
+Expand_subtree=\u00c5pne_forgrening
+Explicit=Explicit
+Export=Eksporter
+Export_entry_types=Eksporter_enhetstyper
+Export_name=Navn_p\u00E5_filter
+Export_preferences=Eksporter_innstillinger
+Export_preferences_to_file=Eksporter_innstillinger_til_fil
+Export_properties=Egenskaper_for_eksportfilter
+Export_selected_to_clipboard=Eksporter_valgte_enheter_til_utklippstavle
+Export_to_clipboard=Eksporter_til_utklippstavle
+Exported_database_to_file=Eksporterte_databasen_til_fil
+Exporting=Eksporterer
+External_changes=Eksterne_endringer
+External_programs=Eksterne_programmer
+External_viewer_called=Eksternt_program_kalt_opp
+Failed_to_read_groups_data_(unsupported_version:_%0)=Kunne_ikke_lese_gruppedata_(ikke_st\u00f8ttet_versjon:_%0)
+Fetch=Hent
+Fetch_Articles_Citing_your_Database=Hent_publikasjoner_som_refererer_enheter_i_din_database
+Fetch_Citations_from_CiteSeer=Hent_referanser_fra_CiteSeer
+Fetch_citations_from_CiteSeer=Hent_refererende_publikasjoner_fra_CiteSeer
+Fetch_CiteSeer=Hent_CiteSeer
+Fetch_Medline=Hent_Medline
+fetch_Medline=hent_Medline
+Fetch_Medline_by_author=Fetch_Medline_by_author
+Fetch_Medline_by_ID=Hent_Medline_ved_hjelp_av_ID
+Fetched_all_citations_from_target_database.=Hentet_alle_refererende_publikasjoner_fra_CiteSeer.
+Fetching_Citations=Henter_referanser
+Fetching_Identifiers=Henter_identifikatorer
+Fetching_Medline...=Henter_Medline...
+Fetching_Medline_by_ID...=Henter_Medline_ved_hjelp_av_ID...
+Fetching_Medline_by_id_...=Henter_Medline_ved_hjelp_av_id...
+Fetching_Medline_by_term_...=S\u00F8ker_i_Medline_...
+Field=Felt
+field=felt
+# 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=Innhold_i_felt
+Field_name=Feltnavn
+Field_names_are_not_allowed_to_contain_white_space_or_the_following_characters=Feltnavn_kan_ikke_inneholde_opperom_eller_noen_av_de_f\u00F8lgende_tegnene
+Field_sizes=
+Field_to_group_by=Grupperingsfelt
+Field_to_search=S\u00F8kefelt
+Fields=Felter
+File=Fil
+file=fil
+File_changed=Endret_fil
+File_extension=Etternavn_p\u00E5_filer
+File_has_been_updated_externally._Are_you_sure_you_want_to_save?=Filen_har_blitt_endret_eksternt._Er_du_sikker_p\u00E5_at_du_vil_lagre?
+File_not_found=Fant_ikke_filen
+File_updated_externally=Filen_har_blitt_endret_eksternt
+filename=filnavn
+Files_opened=Filer_\u00E5pnet
+Find_duplicates=S\u00F8k_etter_duplikater
+Finished_autosetting_%0_field._Entries_changed:_%1.=Fullf\ufffdrte_automatisk_setting_av_%0-felt._Enheter_endret:_%1
+Finished_synchronizing_%0_links._Entries_changed%c_%1.=Fullf\u00f8rte_synkronisering_av_%0-linker._Enheter_endret%c_%1.
+First_select_the_entries_you_want_keys_to_be_generated_for.=Velg_f\u00F8rst_hvilke_enheter_du_vil_generere_n\u00F8kler_for.
+Fit_table_horizontally_on_screen=Tilpass_tabellbredden_horisontalt
+Float=Flyt
+Font_Family=Familie
+Font_Preview=Forh\u00E5ndsvisning
+Font_Size=St\u00F8rrelse
+Font_Style=Stil
+FontSelector=Fontvelger
+for=for
+Format_of_author_and_editor_names=Formatering_av_forfatter-_og_redakt\u00F8rnavn
+Format_used=Format_brukt
+Formatter_not_found=Ukjent_formaterer
+found=funnet
+found_in_aux_file=funnet_i_aux-fil
+General=Generelt
+General_fields=Generelle_felter
+Generate=Generer
+Generate_BibTeX_key=Generere_BibTeX-n\u00F8kkel
+Generate_keys=Generer_n\u00F8kler
+Generate_now=Generer_n\u00e5
+Generated_BibTeX_key_for=Genererte_BibTeX-n\u00F8kkel_for
+Generating_BibTeX_key_for=Genererer_BibTeX-n\u00F8kkel_for
+Grab=Fang_hurtigtast
+Gray_out_entries_not_in_group_selection=Skraver_enheter_utenfor_valgte_grupper
+Gray_out_non-hits=Vis_ikke-treff_i-gr\u00E5tt
+Gray_out_non-matching_entries=Skraver_ikke-treff
+Group_definitions_have_been_converted_to_JabRef_1.7_format.=Gruppedefinisjoner_har_blitt_konvertert_til_JabRef_1.7-format.
+Group_name=Gruppenavn
+Group_properties=Gruppeegenskaper
+Groups=Gruppering
+Harvard_RTF=Harvard_RTF
+Help=Hjelp
+Help_contents=Oversikt_over_hjelpefiler
+Help_on_groups=Hjelp_om_grupper
+Help_on_key_patterns=Hjelp_om_n\u00F8kkeloppskrifter
+Hide_non-hits=Skjul_ikke-treff
+Highlight=Uthev
+Highlight_groups_matching_all_selected_entries=Uthev_grupper_som_inneholder_alle_valgte_enheter
+Highlight_groups_matching_any_selected_entry=Uthev_grupper_som_inneholder_minst_en_av_de_valgte_enhetene
+Highlight_groups_that_contain_entries_contained_in_any_currently_selected_group=Highlight_groups_that_contain_entries_contained_in_any_currently_selected_group
+Highlight_overlapping_groups=Uthev_overlappende_grupper
+Hint%c_To_search_specific_fields_only,_enter_for_example%c<p><tt>author%esmith_and_title%eelectrical</tt>=Hint%c_For_bare_\u00e5_s\u00f8ke_i_spesifikke_felt,_skriv_f._eks.%c<p><tt>author%esmith_and_title%eelectrical</tt>
+HTML=HTML
+Ignore=Ignorer
+Illegal_type_name=Ugyldig_typenavn
+Immediate_subgroups=N\u00e6rmeste_undergrupper
+Import=Importer
+Import_and_append=Importer_til_\u00E5pen_database
+Import_and_keep_old_entry=Importer_og_behold_den_gamle_enheten
+Import_and_remove_old_entry=Importer_og_fjern_den_gamle_enheten
+Import_cancelled.=Import_kansellert.
+Import_Data_from_CiteSeer=Importer_data_fra_CiteSeer
+Import_Data_from_CiteSeer_Database=Importer_data_fra_CiteSeer-database
+Import_database=Import_av_database
+Import_entries=Importer_enheter
+Import_entry_types=Importer_enhetstyper
+Import_failed=Import_mislyktes
+Import_Fields_from_CiteSeer=Importer_felter_fra_CiteSeer
+Import_fields_from_CiteSeer=Importer_felter_fra_CiteSeer
+Import_fields_from_CiteSeer_Database=Importer_felter_fra_CiteSeer-database
+Import_Fields_from_CiteSeer_Database=Importer_felter_fra_CiteSeer-database
+Import_file=Importer_fil
+Import_group_definitions=Importer_gruppedefinisjoner
+Import_plain_text=Importer_fra_ren_tekst
+Import_preferences=Importer_innstillinger
+Import_preferences_from_file=Importer_innstillinger_fra_fil
+Import_strings=Importer_strenger
+Import_to_open_tab=
+Import_word_selector_definitions=Importer_definisjoner_for_hurtigvelgere
+Imported_database=Importerte_database
+Imported_entries=Importerte_enheter
+Imported_entry_types=Importerte_enhetstyper
+Imported_file=Importerte_fil
+Imported_from_database=Importerte_fra_databasen
+Importing=Importerer
+Importing_file=Importerer_fil
+Importing_in_unknown_format=Importerer_ukjent_format
+In_JabRef,_use_pairs_of_#_characters_to_indicate_a_string.=I_JabRef_brukes_#-tegn_parvis_for_\u00E5_indikere_strenger.
+Include_subgroups=Inkluder_undergrupper
+Include_subgroups\:_When_selected,_view_entries_contained_in_this_group_or_its_subgroups=Inkluder_undergrupper:_Vis_enheter_inneholdt_i_denne_gruppen_eller_en_undergruppe
+Incremental=Inkrementell
+Incremental_search=Inkrementelt_s\u00F8k
+Incremental_search_failed._Repeat_to_search_from_top.=Incremental_search_failed._Repeat_to_search_from_top.
+Independent=Uavhengig
+Independent_group\:_When_selected,_view_only_this_group's_entries=Uavhengig_gruppe:_Vis_bare_denne_gruppens_enheter
+Initially_show_groups_tree_expanded=Vis_gruppetreet_ekspandert_i_utgangspunktet
+Input=Inndata
+Input_error=Inputfeil
+Insert=Legg_til
+Insert_rows=Legg_til_rader
+Insert_selected_citations_into_LyX/Kile=Send_valgte_enheter_til_LyX/Kile
+Insert_selected_citations_into_WinEdt=Send_valgte_enheter_til_WinEdt
+insert_string_=sett_inn_streng_
+Insert_URL=Sett_inn_URL
+INSPEC=INSPEC
+integrity=integritet
+Integrity_check=Integritetssjekk
+Intersection=Snitt
+Intersection_with_supergroups=Snitt_med_supergrupper
+Invalid_BibTeX_key=Ugyldig_BibTeX-n\u00F8kkel
+Invalid_URL=Ugyldig_URL
+Inverted=Invertert
+is_a_standard_type.=er_en_standardtype.
+ISI=ISI
+Item_list_for_field=Ordliste_for_felt
+JabRef_help=JabRef-hjelp
+JabRef_preferences=JabRef-oppsett
+JStor_file=JStor-fil
+Keep=Behold
+Keep_both=Behold_begge
+Keep_lower=Behold_nederste
+Keep_upper=Behold_\u00F8verste
+Key_bindings=Hurtigtaster
+Key_bindings_changed=Hurtigtaster_endret
+Key_generator_settings=Innstillinger_for_n\u00F8kkelgenerering
+Key_pattern=N\u00F8kkeloppskrift
+keys_in_database=n\u00F8kler_i_databasen
+Keyword=N\u00F8kkelord
+Label=Navn
+Language=Spr\u00E5k
+Latex_AUX_file=LaTeX_AUX-fil
+LaTeX_AUX_file=LaTeX_AUX-fil
+Left=Venstre
+License=
+Limit_to_fields=Begrens_til_f\u00F8lgende_felter
+Limit_to_selected_entries=Begrens_til_valgte_enheter
+Listen_for_remote_operation_on_port=
+Load_session=Gjenopprett_tilstand
+Loading_session...=Gjenoppretter_tilstand...
+Look_and_feel=Utseende
+lower=sm\u00E5
+Main_layout_file=Hoved-layoutfil
+Main_PDF_directory=Hovedkatalog_for_PDF-filer
+Main_PS_directory=Hovedkatalog_for_PS-filer
+Manage=Sett_opp
+Manage_content_selectors=Sett_opp_ordvelgere
+Manage_custom_exports=Sett_opp_eksterne_eksportfiltre
+Mark_entries=Merk_enheter
+Mark_entry=Merk_enhet
+Mark_new_entries_with_addition_date=
+Mark_new_entries_with_owner_name=Merk_nye_enheter_med_navn_p\u00E5_eier
+Marked_selected=Merket_valgte_enheter
+Medline_entries_fetched=Medline-enheter_hentet
+Medline_XML=Medline_XML
+Medline_XML_File=Medline_XML-fil
+Menu_and_label_font_size=St\u00F8rrelse_av_menyfonter
+Merged_external_changes=Inkorporerte_eksterne_endringer
+messages=beskjeder
+Messages=Meldinger
+Messages_and_Hints=Beskjeder_og_hint
+Miscellaneous=Diverse
+Modification_of_field=Endring_av_felt
+Modified_group_"%0".=Endret_gruppen_"%0".
+Modified_groups=Endrede_grupper
+Modified_groups_tree=Endret_gruppedefinisjoner
+Modified_string=Endret_streng
+Modify=Endre
+modify_group=endre_gruppe
+MODS=MODS
+Move=Flytt
+Move_down=Flytt_ned
+Move_entries_in_group_selection_to_the_top=Flytt_enheter_i_valgte_grupper_\u00F8verst
+move_group=flytt_gruppe
+Move_matching_entries_to_the_top=Flytt_treff_\u00F8verst
+Move_string_down=Flytt_streng_ned
+Move_string_up=Flytt_streng_opp
+Move_up=Flytt_opp
+Moved_Group=Flyttet_gruppe
+Moved_group_"%0".=Flyttet_gruppen_"%0".
+Name=Navn
+Ne_entries_imported.=Ingen_enheter_importert.
+nested_aux_files=n\u00F8stede_aux-filer
+New=Ny
+new=ny
+New_article=Ny_'article'
+New_BibTeX_database=Ny_BibTeX-database
+New_BibTeX_entry=Ny_BibTeX-enhet
+New_BibTeX_subdatabase=Ny_BibTeX-deldatabase
+New_book=Ny_'book'
+New_content=Nytt_innhold
+New_database=Ny_database
+New_database_created.=Opprettet_ny_database.
+New_entry=Ny_enhet
+New_entry...=Ny_enhet...
+New_entry_from_plain_text=Ny_enhet_fra_ren_tekst
+New_group=Ny_gruppe
+New_inbook=Ny_'inbook'
+New_mastersthesis=Ny_'mastersthesis'
+New_phdthesis=Ny_'phdthesis'
+New_proceedings=Ny_'proceedings'
+New_string=Ny_streng
+New_subdatabase=Ny_deldatabase
+New_subdatabase_based_on_AUX_file=Ny_deldatabase_basert_p\u00E5_AUX-fil
+New_unpublished=Ny_'unpublished'
+Next_entry=Neste_enhet
+Next_tab=Neste_tab
+No_%0_found=Fant_ingen_%0
+No_actual_changes_found.=Ingen_reelle_endringer_funnet.
+no_base-bibtex-file_specified=ingen_basis-bibtexfil_spesifisert
+no_database_generated=ingen_database_generert
+No_duplicates_found=Ingen_duplikater_funnet
+No_entries_imported.=Ingen_enheter_importert.
+No_entries_or_multiple_entries_selected.=Ingen_eller_flere_enheter_valgt.
+No_entries_selected=Ingen_enheter_valgt
+No_GUI._Only_process_command_line_options.=Ingen_GUI._Bare_behandle_kommandolinjevalg.
+No_Medline_entries_found.=Ingen_Medline-enheter_funnet
+No_pdf_or_ps_defined,_and_no_file_matching_Bibtex_key_found=Ingen_pdf_eller_ps_definert_og_fant_ingen_filer_med_navn_tilsvarende_BibTeX-n\u00f8kkelen
+No_references_found=Ingen_referanser_funnet
+No_saved_session_found.=Fant_ingen_lagret_tilstand.
+No_url_defined=Ingen_url_er_definert
+non-Mac_only=ikke_for_Mac
+not=ikke
+not_found=ikke_funnet
+Not_saved_(empty_session)=Tilstand_ikke_lagret_(ingen_filer_\u00E5pne)
+Note_that_the_entry_causing_the_problem_has_been_selected.=Legg_merke_til_at_enheten_som_skaper_problemet_har_blitt_valgt.
+Note_that_the_new_definitions_will_not_be_compatible_with_previous_JabRef_versions.=Merk_at_de_nye_definisjonene_ikke_vil_v\u00E6re_kompatible_med_tidligere_versjoner_av_JabRef.
+Note_that_you_must_specify_the_fully_qualified_class_name_for_the_look_and_feel,=Merk_at_du_m\u00E5_spesifisere_det_fullstendige_klassenavnet_for_utseendet,
+Nothing_to_redo=Ingenting_\u00E5_gjenta
+Nothing_to_undo=Ingenting_\u00E5_angre
+# The next is used like in "References found: 1  Number of references to fetch?"
+Number_of_references_to_fetch?=Antall_referanser_som_skal_hentes?
+occurences=treff
+OK=OK
+Ok=OK
+One_or_more_keys_will_be_overwritten._Continue?=En_eller_flere_n\u00f8kler_vil_bli_skrevet_over._Fortsett?
+Open=\u00C5pne
+open=open
+Open_BibTeX_database=\u00C5pne_BibTeX-database
+Open_database=\u00C5pne_database
+Open_editor_when_a_new_entry_is_created=Start_redigering_n\u00E5r_en_ny_enhet_opprettes
+Open_file=\u00C5pne_fil
+Open_last_edited_databases_at_startup=\u00C5pne_sist_viste_databaser_ved_oppstart
+Open_PDF_or_PS=\u00C5pne_PDF_eller_PS
+Open_right-click_menu_with_Ctrl+left_button=\u00C5pne_h\u00F8yreklikkmeny_med_Ctrl+venstre_knapp
+Open_URL_or_DOI=\u00C5pne_URL_eller_DOI
+Opened_database=\u00C5pnet_database
+Opening=\u00C5pner
+Opening_preferences...=\u00C5pner_innstillinger...
+Optional_fields=Valgfrie_felter
+Options=Valg
+or=eller
+out_of=ut_av
+Output_or_export_file=Lagre_eller_eksporter_fil
+Overlapping_groups=Overlappende_grupper
+Override=Skriv_over
+override_the_bibtex_key_by_the_selected_text=
+Overwrite_keys=Skriv_over_n\u00F8kler
+Ovid=Ovid
+pairs_processed=par_revidert
+Paste=Lim_inn
+paste_entries=lim_inn
+paste_entry=lim_inn
+Paste_from_clipboard=Lim_inn
+Pasted=Limte_inn
+Path_to_HTML_viewer=Sti_til_HTML-leser
+Path_to_LyX_pipe=Sti_til_LyX-pipe
+Path_to_PDF_viewer=Sti_til_PDF-leser
+Path_to_PS_viewer=Sti_til_PS-leser
+Path_to_WinEdt.exe=Sti_til_WinEdt.exe
+Paths_to_external_programs=Stier_til_eksterne_programmer
+PDF_links=PDF-koblinger
+Pick_titles=Velg_titler
+Plain_right_menu=Plain_right_menu
+Plain_text=Ren_tekst
+Plain_text_import=Import_fra_ren_tekst
+Please_check_your_network_connection_to_this_machine.=Vennligst_sjekk_maskinens_nettverksforbindelse.
+Please_define_BibTeX_key_first=Vennligst_definer_BibTeX-n\u00F8kkel_f\u00F8rst
+Please_enter_a_name_for_the_group.=Skriv_inn_et_navn_for_gruppen.
+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>=Skriv_inn_et_s\u00F8kebegrep._For_eksempel,_for_\u00E5_s\u00F8ke_i_alle_felter_etter_<b>Olsen</b>,_skriv%c<p><tt>olsen</tt><p>For_\u00E5_s\u00F8ke_i_<b>Author</b>-feltet_etter_<b>Olsen</b>_og_i_<b>Title</b>-feltet_etter_<b>electr [...]
+Please_enter_a_semicolon_or_comma_separated_list_of_Medline_IDs_(numbers).=Du_m\u00E5_oppgi_en_semikolon-_eller_kommaseparert_liste_av_Medline-IDer_(tall).
+Please_enter_the_field_to_search_(e.g._<b>keywords</b>)_and_the_keyword_to_search_it_for_(e.g._<b>electrical</b>).=Vennligst_skriv_inn_feltet_som_skal_s\u00F8kes_i_(f.eks._<b>keywords</b>)_og_n\u00f8kkelordet_\u00e5_s\u00F8ke_etter_(f._eks._<b>electrical</b>).
+Please_enter_the_string's_label=Skriv_inn_et_navn_for_strengen
+Please_refer_to_the_JabRef_help_manual_on_using_the_CiteSeer_tools.=Vennligst_se_JabRef-dokumentasjonen_for_informasjon_om_bruk_av_CiteSeer-verkt\u00F8yene.
+Please_select_exactly_one_group_to_move.=Velg_eksakt_en_gruppe_for_flytting.
+Please_wait_until_it_has_finished.=Vennligst_vent_til_den_er_fullf\u00F8rt.
+Possible_duplicate_entries=Mulige_duplikater
+Possible_duplicate_of_existing_entry._Click_to_resolve.=Mulig_duplikat_av_eksisterende_enhet._Klikk_for_\u00e5_h\u00e5ndtere.
+Preamble=Preamble
+Preamble_editor,_store_changes=Preamble-skjema,_lagre_innhold
+Preferences=Oppsett
+Preferences_recorded=Lagret_innstillinger
+Preferences_recorded.=Lagret_oppsett.
+Preserve_formatting_of_non-BibTeX_fields=Bevar_formatering_av_ikke-standard_BibTeX-felter
+Preview=Forh\u00E5ndsvisning
+Previous_entry=Forrige_enhet
+Previous_tab=Forrige_tab
+Problem_with_parsing_entry=Problem_med_\u00E5_lese_enhet
+PS_links=PS-koblinger
+Push_selection_to_LyX/Kile=Send_valgte_enheter_til_LyX/Kile
+Push_selection_to_WinEdt=Send_valgte_til_WinEdt
+Push_to_LyX=Send_til_LyX
+Push_to_WinEdt=Send_til_WinEdt
+Pushed_the_citations_for_the_following_rows_to=Sendte_referanser_til_de_f\u00F8lgende_radene_til
+Query_author(s)=S\u00f8k_etter_forfatter(e)
+Quit=Avslutt
+Quit_JabRef=Avslutt_JabRef
+Quit_synchronization=Avslutt_synkronisering
+Raw_source=Kilde
+Really_delete_the_selected=Vil_du_slette_de_valgte
+Recent_files=Siste_filer
+Redo=Gjenta
+Refer/Endnote=Refer/Endnote
+Reference_database=Referansedatabase
+# The next two lines are used like in "References found: 1  Number of references to fetch?"
+References_found=Referanser_funnet
+Refine_supergroup\:_When_selected,_view_entries_contained_in_both_this_group_and_its_supergroup=Undergruppe:_Vis_enheter_inneholdt_b�de_i_denne_gruppen_og_gruppen_over
+Refresh_view=Oppdater
+Regexp=Regexp
+Regular_Expression=Regul\u00e6ruttrykk
+Remember_these_entry_types?=Husk_disse_enhetstypene?
+Remote_operation=
+Remote_server_port=
+Remove=Fjern
+Remove_all?=Fjern_alle?
+Remove_all_subgroups=Fjern_undergrupper
+Remove_all_subgroups_of_"%0"?=Remove_all_subgroups_of_"%0"?
+Remove_duplicates=Fjern_duplikater
+Remove_entry_from_import=Fjern_enhet_fra_import
+Remove_entry_type=Slett_enhetstype
+remove_from_group=fjern_fra_gruppe
+Remove_from_group=Fjern_fra_gruppe
+Remove_group=Fjern_gruppe
+Remove_group,_keep_subgroups=Fjern_gruppe,_behold_undergrupper
+Remove_group_"%0"?=Fjern_gruppen_"%0"?
+Remove_group_"%0"_and_its_subgroups?=Fjern_gruppen_"%0"_og_dens_undergrupper?
+remove_group_(keep_subgroups)=fjern_gruppe_(behold_undergrupper)
+remove_group_and_subgroups=fjern_gruppe_og_undergrupper
+Remove_group_and_subgroups=Fjern_gruppe_og_undergrupper
+Remove_old_entry=Fjern_gammel_enhet
+Remove_selected_strings=Slett_valgte_strenger
+remove_string=slett_streng
+remove_string_=slett_streng_
+Removed_entry_type.=Slettet_enhetstype.
+Removed_group=Fjernet_gruppe
+Removed_group_"%0".=Fjernet_gruppen_"%0"
+Removed_group_"%0"_and_its_subgroups.=Fjernet_gruppen_"%0"_og_dens_undergrupper
+Removed_string=Fjernet_streng
+Renamed_string=Endret_navn_p\u00e5_streng
+Repeat_incremental_search=Gjenta_inkrementelt_s\u00F8k
+Replace=
+Replace_string=Erstatt_streng
+Replace_with=Erstatt_med
+Replaced=Erstattet
+Required_fields=N\u00F8dvendige_felter
+Reset_all=Tilbakestill_alle
+resolved=tatt_h\u00E5nd_om
+Results=Resultater
+Revert_to_original_source=Resett_til_opprinnelig_kildekode
+Review_changes=Se_over_endringer
+Right=H\u00f8yre
+RIS=RIS
+Save=Lagre
+Save_before_closing=Lagre_f\u00F8r_databasen_lukkes
+Save_database=Lagre_database
+Save_database_as_...=Lagre_database_som_...
+Save_selected_as_...=Lagre_valgte_som_...
+Save_session=Lagre_tilstand
+Saved_database=Lagret_database
+Saved_selected_to=Lagret_valgte_i
+Saved_session=Lagret_tilstand
+Saving=Lagrer
+# Integrity check is a process that checks for indications of wrongly filled out bibtex fields. "Scan" is the button that starts the check.
+Scan=S\u00F8k
+SciFinder=SciFinder
+Search=S\u00F8k
+Search_All_Fields=S\u00F8k_i_alle_felter
+Search_all_fields=S\u00F8k_i_alle_felter
+Search_error=Feil_ved_s\u00F8k
+Search_expression=S\u00F8keuttrykk
+Search_for=S\u00F8k_etter
+Search_General_Fields=S\u00f8k_i_generelle_felter
+Search_general_fields=S\u00f8k_i_generelle_felter
+Search_Optional_Fields=S\u00f8k_i_valgfrie_felter
+Search_optional_fields=S\u00f8k_i_valgfrie_felter
+Search_Required_Fields=S\u00f8k_i_n\u00f8dvendige_felter
+Search_required_fields=S\u00f8k_i_n\u00f8dvendige_felter
+Search_Specified_Field(s)=S\u00F8k_spesifiserte_felt(er)
+Search_term=S\u00F8kestreng
+Searched_database._Number_of_hits=S\u00F8kte_gjennom_basen._Antall_treff
+Searching_for_%0_file=S\u00F8ker_etter_%0-fil
+Searching_for_duplicates...=S\u00F8ker_etter_duplikater...
+Secondary_sort_criterion=Andre_sorteringskriterium
+Select=Velg
+Select_action=Select_action
+Select_all=Velg_alle
+Select_entries_in_group_selection=Velg_enheter_i_valgte_grupper
+Select_entry_type=Velg_enhetstype
+Select_format=Velg_format
+Select_matches=Velg_treff
+Select_matching_entries=Velg_treff
+Select_the_tree_nodes_to_view_and_accept_or_reject_changes=Velg_trenodene_for_\u00E5_inspisere_og_akseptere_eller_avsl\u00E5_endringer
+Selector_enabled_fields=Felter_med_ordliste
+Set_general_fields=Tilpass_generelle_felter
+Set_table_font=Velg_tabellfont
+Set_up_general_fields=Set_up_general_fields
+Settings=Innstillinger
+Setup_selectors=Sett_opp_ordlister
+Short_form=Kort_form
+Shortcut=Snarvei
+Show/edit_BibTeX_source=Vis/rediger_BibTeX-kilde
+Show_'Firstname_Lastname'=Vis_'Fornavn_Etternavn'
+Show_'Lastname,_Firstname'=Vis_'Etternavn,_Fornavn'
+Show_abstract=Vis_abstract
+Show_BibTeX_source_by_default=Vis_BibTeX-kode_som_standard
+Show_BibTeX_source_panel=Vis_BibTeX-kilde-panel
+Show_CiteSeer_column=Vis_CiteSeer-kolonne
+Show_confirmation_dialog_when_deleting_entries=Vis_dialog_for_\u00E5_bekrefte_sletting_av_enheter
+Show_dynamic_groups_in_<i>italics</i>=Vis_dynamiske_grupper_i_<i>kursiv</i>
+Show_entries_*not*_in_group_selection=Vis_enheter_*utenfor*_valgte_grupper
+Show_general_fields=Vis_generelle_felter
+Show_groups_matching_all=Uthev_grupper_som_inneholder_alle
+Show_groups_matching_any=Uthev_grupper_som_inneholder_noen
+Show_icons_for_groups=Vis_ikoner_for_grupper
+Show_names_unchanged=Vis_navn_uforandret
+Show_one_less_rows=Vis_en_rad_mindre
+Show_one_more_row=Vis_en_rad_mer
+Show_optional_fields=Vis_valgfrie_felter
+Show_overlapping_groups=Vis_overlappende_grupper
+Show_PDF/PS_column=Vis_PDF/PS-kolonne
+Show_required_fields=Vis_n\u00F8dvendige_felter
+Show_URL/DOI_column=Vis_URL/DOI-kolonne
+Show_warning_dialog_when_a_duplicate_BibTeX_key_is_entered=Vis_advarsel_n\u00E5r_en_ikke_unik_BibTeX-n\u00F8kkel_skrives_inn
+Show_warning_dialog_when_an_empty_BibTeX_key_is_entered=Vis_dialogboks_med_advarsel_n\u00E5r_en_tom_BibTeX-n\u00F8kkel_skrives_inn
+Simple_HTML=Enkel_HTML
+Sixpack=Sixpack
+Size_of_groups_interface_(rows)=
+Skip=
+Sort_alphabetically=Sorter_alfabetisk
+Sort_Automatically=Sorter_automatisk
+Sort_options=Sortering
+sort_subgroups=sorter_undergrupper
+Sorted_all_subgroups_recursively=Sorterte_alle_undergrupper_rekursivt
+Sorted_all_subgroups_recursively.=Sorterte_alle_undergrupper_rekursivt.
+Sorted_immediate_subgroups=Sorterte_n\u00e6rmeste_undergrupper
+Sorted_immediate_subgroups.=Sorterte_n\u00e6rmeste_undergrupper.
+source_edit=redigering_av_kilde
+Special_table_columns=Spesielle_kolonner
+Start=Start
+Start_incremental_search=Start_inkrementelt_s\u00F8k
+Start_search=Start_s\u00f8k
+Statically_group_entries_by_manual_assignment=Grupper_enheter_statisk_ved_manuell_tildeling
+Status=Status
+Stop=Stopp
+Store=Lagre
+Store_fields_with_double_braces,_and_remove_extra_braces_when_loading.<BR>Double_braces_signal_that_BibTeX_should_preserve_character_case.=Lagre_felter_med_doble_kr\u00F8llparenteser,_og_fjern_ekstra_kr\u00F8llparenteser_ved_innlasting.<BR>Doble_kr\u00F8llparenteser_signaliserer_at_BibTeX_ikke_skal_bytte_store_og_sm\u00E5_bokstaver.
+Store_string=Lagre_streng
+Stored_definition_for_type=Lagret_typedefinisjon
+Stored_entry=Lagret_enhet
+Stored_entry.=Lagret_enhet.
+Strings=Strenger
+Strings_for_database=Strenger_for_database
+subdatabase_from_aux=underdatabase_fra_aux
+Subdatabase_from_aux=Deldatabase_fra_aux-fil
+Suggest=Foresl\u00E5
+Switch_preview_layout=Skift_layout_p\u00E5_forh\u00E5ndsvisning
+Synchronize_%0_links=Synkroniser_%0-linker
+Synchronizing_%0_links...=Synkroniserer_%0-linker...
+Table=Tabell
+Table_appearance=Tabelloppsett
+Tabname=Tabnavn
+Tertiary_sort_criterion=Tredje_sorteringskriterium
+Test=Test
+Text_Input_Area=Inndatafelt
+The_#_character_is_not_allowed_in_BibTeX_fields=#-tegnet_er_ikke_tillatt_i_BibTeX-felter
+The_CiteSeer_fetch_operation_returned_zero_results.=Nedlastingen_fra_CiteSeer_ga_ingen_resultater.
+the_field_<b>%0</b>=feltet_<b>%0</b>
+The_file<BR>'%0'<BR>has_been_modified<BR>externally!=Filen<BR>'%0'<BR>har_blitt_endret<BR>eksternt!
+The_group_"%0"_already_contains_the_selection.=Gruppen_"%0"_inneholder_allerede_de_valgte_enhetene.
+The_group_"%0"_does_not_support_the_adding_of_entries.=Gruppen_"%0"_st\u00F8tter_ikke_tilordning_av_enheter.
+The_group_"%0"_does_not_support_the_removal_of_entries.=Gruppen_"%0"_st\u00F8tter_ikke_fjerning_av_enheter.
+The_label_of_the_string_can_not_be_a_number.=Navnet_p\u00E5_strengen_kan_ikke_v\u00E6re_et_tall.
+The_label_of_the_string_can_not_contain_spaces.=Navnet_p\u00E5_strengen_kan_ikke_inneholde_mellomrom.
+The_label_of_the_string_can_not_contain_the_'#'_character.=Navnet_p\u00E5_strengen_kan_ikke_inneholde_tegnet_'#'.
+The_output_option_depends_on_a_valid_import_option.=Lagre-operasjonen_er_avhengig_av_en_gyldig_import-operasjon.
+The_regular_expression_<b>%0</b>_is_invalid%c=Regul\u00e6ruttrykket_<b>%0</b>_er_ugyldig%c
+The_search_is_case_insensitive.=S\u00f8ket_skiller_ikke_mellom_store_og_sm\u00E5_bokstaver.
+The_search_is_case_sensitive.=S\u00F8ket_skiller_mellom_store_og_sm\u00E5_bokstaver.
+The_string_has_been_removed_locally=Strengen_har_blitt_slettet_lokalt
+The_type_name_can_not_contain_spaces.=Typenavnet_kan_ikke_inneholde_mellomrom.
+The_URL_field_appears_to_be_empty_on_entry_number_=URL-feltet_ser_ut_til_\u00E5_v\u00e6re_tomt_for_enhet_nummer_
+There_are_possible_duplicates_(marked_with_a_'D'_icon)_that_haven't_been_resolved._Continue?=Det_finnes_mulige_duplikater_(merket_med_et_'D'-ikon)_som_ikke_har_blitt_h\u00e5ndtert._Fortsette?
+There_is_no_entry_type=Ingen_enhetstype
+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?=
+this_button_will_update=denne_knappen_vil_oppdatere
+this_button_will_update_the_column_width_settings<BR>to_match_the_current_widths_in_your_table=denne_knappen_vil_oppdatere_kolonnebreddeinnstillingene<BR>til_\u00E5_samsvare_med_breddene_i_tabellen_for_\u00F8yeblikket
+This_entry_is_incomplete=Denne_enheten_er_ufullstendig
+This_entry_type_cannot_be_removed.=Denne_enhetstypen_kan_ikke_slettes.
+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.=Denne_gruppen_inneholder_enheter_basert_p\u00e5_manuell_tilordning._Enheter_kan_tilordnes_til_denne_gruppen_ved_\u00e [...]
+This_group_contains_entries_in_which=Denne_gruppen_inneholder_enheter_hvor
+This_group_contains_entries_in_which_any_field_contains_the_regular_expression_<b>%0</b>=Denne_gruppen_inneholder_enheter_som_stemmer_med_regul\u00e6ruttrykket_<b>%0</b>_i_et_hvilket_som_helst_felt
+This_group_contains_entries_in_which_any_field_contains_the_term_<b>%0</b>=Denne_gruppen_inneholder_enheter_som_har_teksten_<b>%0</b>_i_et_hvilket_som_helst_felt
+This_group_contains_entries_whose_<b>%0</b>_field_contains_the_keyword_<b>%1</b>=Denne_gruppen_inneholder_enheter_hvis_<b>%0</b>-felt_inneholder_n\u00F8kkelordet_<b>%1</b>
+This_group_contains_entries_whose_<b>%0</b>_field_contains_the_regular_expression_<b>%1</b>=Denne_gruppen_inneholder_enheter_hvis_<b>%0</b>-felt_stemmer_med_regul\u00e6ruttrykket_<b>%1</b>
+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.=Dette_er_et_enkelt_klipp-og-lim-vindu._F\u00F8rst_last_inn_eller_kopier_tekst_til_inndatafeltet._Deretter_kan_du_merke_tekst_og_tildele_den_til_et_BibTeX-felt.
+This_is_a_simple_copy_and_paste_dialog_for_import_some_fields_from_normal_text.=Dette_er_et_enkelt_klipp-og-lim-vindu._F\u00F8rst_last_inn_eller_kopier_tekst_til_inndatafeltet._Deretter_kan_du_merke_tekst_og_tildele_den_til_et_BibTeX-felt.
+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.=Dette_f\u00E5r_JabRef_til_\u00E5_unders\u00F8ke_hver_av_%0-linkene,_og_sjekke_om_filen_eksisterer._Hvis_ikke_vil_du_bli_gitt_valg<BR>for_\u00E5_l\u00F8se_problemet.
+This_operation_cannot_work_on_multiple_rows.=Denne_operasjonen_kan_ikke_brukes_p\u00E5_flere_rader_samtidig.
+Toggle_entry_preview=Vis/skjul_forh\u00E5ndsvisning
+Toggle_groups_interface=Vis/skjul_grupperingskontroll
+Toggle_search_panel=Vis/skjul_s\u00F8kepanel
+Tools=Verkt\u00F8y
+Type=Type
+Type_set_to_'other'=Type_satt_til_'other'
+unable_to_access_LyX-pipe=ingen_tilgang_til_LyX-pipe
+Unable_to_create_graphical_interface=Kunne_ikke_opprette_grafisk_grensesnitt
+Unable_to_parse_clipboard_text_as_Bibtex_entries.=Kunne_ikke_lese_tekst_p\ufffd_utklippstavlen_som_BibTeX-enheter.
+Unable_to_parse_the_following_URL=Kunne_ikke_tolke_f\u00F8lgende_URL
+unable_to_write_to=kunne_ikke_skrive_til
+Undo=Angre
+Union=Union
+unknown_bibtex_entries=ukjente_BibTeX-enheter
+Unknown_bibtex_entries=Ukjente_BibTeX-enheter
+unknown_edit=ukjent_endring
+unknown_entry_type=ukjent_enhetstype
+Unknown_export_format=Ukjent_eksportformat
+Unmark_all=Fjern_merking_fra_alle
+Unmark_entries=Fjern_merking
+Unmark_entry=Fjern_merking
+Unmarked_selected=Fjernet_merking_fra_valgte_enheter
+Unpack_EndNote_filter_set=Pakk_ut_EndNote-filtersett
+Unpacked_file=Pakket_ut_fil
+Unpacked_file.=Pakket_ut_fil.
+Unsupported_version_of_class_%0:_%1=Ikke_st\u00F8ttet_versjon_av_klassen_%0:_%1
+untitled=uten_navn
+Up=Opp
+Update_to_current_column_widths=Bruk_n\u00E5v\u00E6rende_kolonnebredder
+Updated_group_selection=Updated_group_selection
+Updating_entries...=Oppdaterer_enheter...
+UPPER=STORE
+Upper_Each_First=Store_Forbokstaver_I_Alle_Ord
+Upper_first=Stor_forbokstav_i_f\u00F8rste_ord
+usage=bruk
+Use_antialiasing_font_in_table=Bruk_glattet_font_i_tabell
+Use_inspection_window_also_when_a_single_entry_is_imported.=Bruk_inspeksjonsvindu_ogs\u00E5_n\u00E5r_bare_\u00e9n_enhet_importeres.
+Use_other_look_and_feel=Bruk_annet_utseende
+Use_regular_expressions=Bruk_"regular_expressions"
+Use_the_following_delimiter=Bruk_f\u00F8lgende_skilletegn
+Use_the_following_delimiter_character(s)=Use_the_following_delimiter_character(s)
+Uses_default_application=Bruker_standardprogram
+Value_cleared_externally=Verdien_slettet_eksternt
+Value_set_externally=Verdi_satt_eksternt
+verify_that_LyX_is_running_and_that_the_lyxpipe_is_valid=kontroller_at_LyX_kj\u00F8rer,_og_at_den_angitte_lyxpipe_stemmer
+View=Vis
+Visible_fields=Synlige_felter
+Warn_about_unresolved_duplicates_when_closing_inspection_window=Advar_om_duplikater_som_ikke_er_blitt_h\u00e5ndtert_n\u00e5r_inspeksjonsvinduet_lukkes
+Warn_before_overwriting_existing_keys=Gi_advarsel_f�r_eksisterende_n�kler_skrives_over
+Warning=Advarsel
+Warning_there_is_a_duplicate_key=
+Warnings=Advarsler
+web_link=link
+When_adding/removing_keywords,_separate_them_by=N\u00e5r_n\u00f8kkelord_legges_til_eller_fjernes_skill_dem_med
+with=med
+Word=Ord
+Wrong_file_format=Feil_filformat
+You_have_changed_the_language_setting._You_must_restart_JabRef_for_this_to_come_into_effect.=Du_har_valgt_et_nytt_spr\u00E5k._Du_m\u00E5_starte_JabRef_p\u00E5_nytt_for_at_dette_skal_tre_i_kraft.
+You_have_cleared_this_field._Original_value=Du_har_slettet_dette_feltet._Original_verdi
+You_must_enter_an_integer_value_in_the_text_field_for=Du_m\ufffd_skrive_et_heltall_i_tekstfeltet_for
+You_must_fill_in_a_name_for_the_entry_type.=Du_m\u00E5_velge_et_navn_for_enhetstypen.
+You_must_provide_a_name,_a_search_string_and_a_field_name_for_this_group.=Du_m\u00E5_oppgi_et_navn,_en_s\u00F8kestreng_og_et_feltnavn_for_denne_gruppen.
+You_must_restart_JabRef_for_the_new_key_bindings_to_work_properly.=Du_m\u00E5_starte_JabRef_p\u00E5_nytt_for_at_de_nye_hurtigtastene_skal_fungere.
+You_must_select_a_row_to_perform_this_operation.=Du_m\u00E5_velge_en_rad_for_\u00E5_kunne_bruke_denne_operasjonen.
+You_must_select_at_least_one_row_to_perform_this_operation.=Du_m\u00E5_velge_minst_\u00E9n_rad_f\u00F8r_du_kan_bruke_denne_operasjonen.
+You_must_set_both_BibTeX_key_and_%0_directory=Du_m\u00E5_sette_b\u00E5de_BibTeX-n\u00F8kkel_og_%0-katalog
+You_must_set_both_bibtex_key_and_PDF_directory=You_must_set_both_bibtex_key_and_PDF_directory
+Your_new_key_bindings_have_been_stored.=Dine_nye_hurtigtaster_har_blitt_lagret.
+Manage_custom_imports=
+Select_Classpath_of_New_Importer=Velg_classpath_for_nytt_importformat
+Select_new_ImportFormat_Subclass=Velg_klasse_for_nytt_importformat
+Could_not_instantiate_%0_%1=
+Add_a_(compiled)_custom_ImportFormat_class_from_a_class_path._\nThe_path_need_not_be_on_the_classpath_of_JabRef.=
+Please_select_an_importer=Vennligst_velg_et_importformat
+Import_name=Navn_p\u00e5_import
+Command_line_id=Kommandolinje-id
+ImportFormat_class=ImportFormat-klasse
+Contained_in=Inneholdt_i
+Show_description=Vis_beskrivelse
+Add_from_folder=Legg_til_fra_mappe
+Custom_importers=Egendefinerte_importformat
+No_custom_imports_registered_yet.=Ingen_egne_importformater_er_definert.
+Abbreviate_journal_names_of_the_selected_entries_(ISO_abbreviation)=Forkort_journalnavn_for_de_valgte_enhetene_(ISO-forkortelse)
+Abbreviate_journal_names_of_the_selected_entries_(MEDLINE_abbreviation)=Forkort_journalnavn_for_de_valgte_enhetene_(MEDLINE-forkortelse)
+Background_color_for_marked_entries=Bakgrunnsfarge_for_merkede_enheter
+Background_color_for_optional_fields=Bakgrunnsfarge_for_valgfrie_felter
+Background_color_for_required_fields=Bakgrunnsfarge_for_n\u00F8dvendige_felter
+Choose_the_URL_to_download._The_default_value_points_to_a_list_provided_by_the_JabRef_developers.=Velg_URL_for_nedlasting._Den_forh\u00e5ndsvalgte_adressen_peker_til_en_liste_gjort_tilgjengelig_av_JabRef-utviklerne.
+Color_for_marking_incomplete_entries=Farge_for_markering_av_ufullstendige_enheter
+Do_not_abbreviate_names=Ikke_forkort_navn
+Do_not_wrap_the_following_fields_when_saving=Ikke_introduser_linjeskift_i_f\u00f8lgende_felter_ved_lagring
+External_files=Eksterne_filer
+File_'%0'_not_found=Fant_ikke_filen_'%0'
+Journal_abbreviations=Journalforkortelser
+Journal_name=Journalnavn
+Manage_journal_abbreviations=Sett_opp_journalforkortelser
+Natbib_style=Natbib-stil
+New_file=Ny_fil
+Personal_journal_list=Personlig_journalliste
+Remove_double_braces_around_BibTeX_fields_when_loading.=Fjern_doble_kr\u00f8llparenteser_rundt_BibTeX-felter_ved_innlasting.
+Store_the_following_fields_with_braces_around_capital_letters=Lagre_de_f\u00f8lgende_feltene_med_kr\u00f8llparenteser_rundt_store_bokstaver
+Table_background_color=Bakgrunnsfarge_for_tabell
+Table_grid_color=Farge_p\u00e5_linjer_i_tabell
+Table_text_color=Tekstfarge_i_tabell
+Toggle_abbreviation=Forkort/ekspander
+Unabbreviate_journal_names_of_the_selected_entries=Ekspander_journalnavn_for_de_valgte_enhetene
+Use_antialiasing_font=Bruk_glattet_font
+Abbreviate_names=Forkort_navn
+Abbreviation=Forkortelse
+ISO_abbreviation=ISO-forkortelse
+Edit_journal=Rediger_journal
+Existing_file=Eksisterende_fil
+Saving_database=Lagrer_database
+Normal=Normal
+Default_sort_criteria=Standard_sorteringskriteria
+Primary_sort_criterion=Prim\u00e6rt_sorteringskriterium
+Database_properties=Databaseegenskaper
+Database_encoding=Tegnkoding_for_database
+No_journal_names_could_be_abbreviated.=Ingen_journalnavn_kunne_forkortes.
+No_journal_names_could_be_unabbreviated.=Ingen_journalnavn_kunne_ekspanderes.
+Save_failed=Lagring_mislyktes
+Pushed_citations_to_WinEdt=Sendte_referanser_til_WinEdt
+Try_different_encoding=Pr�v_en_annen_tegnkoding
+Select_encoding=Velg_koding
+The_chosen_date_format_for_new_entries_is_not_valid=Det_valgte_datoformatet_er_ugyldig
+Invalid_date_format=Ugyldig_datoformat
+Review=Kommentarer
+Journal_names=Journalnavn
+Save_failed_during_backup_creation=Lagring_mislyktes_ved_opprettelse_av_sikkerhetskopi
+Save_failed_while_committing_changes=Lagring_mislyktes_ved_sluttf�ring_av_endringer
+Add_from_jar=Legg_til_fra_jar-fil
+Please_select_an_importer.=Velg_et_importfilter.
+Switches_between_full_and_abbreviated_journal_name_if_the_journal_name_is_known.=Bytter_mellom_fullt_og_forkortet_journalnavn_dersom_navnet_er_kjent.
+To_set_up,_go_to_<B>Tools_->_Manage_journal_abbreviations</B>=For_�_sette_opp,_g�_til_<B>Verkt�y_->_Sett_opp_journalforkortelser</b>
+Full_name=Fullt_navn
+Store_journal_abbreviations=Lagre_journalforkortelser
+You_must_choose_a_file_name_to_store_journal_abbreviations=Du_m�_velge_et_filnavn_for_�_lagre_journalforkortelser
+Journal_list_preview=Forh�ndsvisning_av_journalliste
+
+Add_a_(compiled)_custom_ImportFormat_class_from_a_Zip-archive.\nThe_Zip-archive_need_not_be_on_the_classpath_of_JabRef.=Legg_til_en_kompilert_ImportFormat-klasse_fra_en_ZIP-fil._ZIP-filen_trenger_ikke_�_v�re_i_din_classpath.
+Select_a_Zip-archive=Velg_ZIP-fil
+Arguments_passed_on_to_running_JabRef_instance._Shutting_down.=Argumentene_sendt_til_allerede_aktiv_JabRef-instans._Avslutter.
+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').=Kunne_ikke_opprette_kontakt_med_en_gnuserv-prosess._Kontroller_at_Emacs_eller_XEmacs_er_i_gang<BR>og_at_serveren_har_blitt_startet_(med_kommandoen_'gnuserv-start').
+Last_modified=Sist_endret
+Push_selection_to_Emacs=Send_valgte_enheter_til_Emacs
+Pushed_citations_to_Emacs=Sendte_enheter_til_Emacs
+Select_file_from_ZIP-archive=Velg_fil_fra_ZIP-fil
+Size=St�rrelse
+
+Filter=Filter
+Hide_non-matching_entries=Gjem_ikke-treff
+Replace_(regular_expression)=Erstatt_(regul�ruttrykk)
+
+Cite_command_(for_Emacs/WinEdt)=Kommando_for_referanser_(for_Emacs/WinEdt)
+
+Could_not_instantiate_%0_%1._Have_you_chosen_the_correct_package_path?=Kunne_ikke_instansiere_%0_%1._Har_du_valgt_riktig_katalog?
+No_entries_found._Please_make_sure_you_are_using_the_correct_import_filter.=Ingen_enheter_funnet._Kontroller_at_du_bruker_riktig_importfilter.
+Could_not_run_the_'gnuclient'_program._Make_sure_you_have_the_gnuserv/gnuclient_programs_installed.=Kunne_ikke_kalle_'gnuclient'-programmet._Kontroller_at_du_har_installert_gnuserv/gnuclient-programmene.
+
+Hierarchical_context=Gruppehierarki
+Add_entry_selection_to_this_group=Legg_valgte_enheter_til_denne_gruppen
+Assign_entry_selection_exclusively_to_this_group=Legg_valgte_enheter_eksklusivt_til_denne_gruppen
+Remove_entry_selection_from_this_group=Fjern_valgte_enheter_fra_denne_gruppen
diff --git a/src/resource/Menu_de.properties b/src/resource/Menu_de.properties
new file mode 100644
index 0000000..c81a8db
--- /dev/null
+++ b/src/resource/Menu_de.properties
@@ -0,0 +1,95 @@
+#! created/edited by Popeye version 0.51 sunshine (popeye.sourceforge.net)
+
+# Menu names
+File=&Datei
+Edit=&Bearbeiten
+View=&Ansicht
+BibTeX=Bib&TeX
+Tools=&Extras
+Options=&Optionen
+Help=&Hilfe
+# File menu
+New_database=&Neue_Datei
+Open_database=Datei_\u00F6&ffnen
+Append_database=Datei_&anh\u00E4ngen
+Import_and_append=&Importieren_und_anh\u00E4ngen
+Import=I&mportieren
+Custom_importers=Externe_&Importfilter
+Save_database=Datei_&speichern
+Save_database_as_...=Datei_speichern_&unter_...
+Save_selected_as_...=Aus&wahl_speichern_unter_...
+Export=&Exportieren
+Custom_export=E&xterne_Exportfilter
+Database_properties=Ei&genschaften_der_Datei
+Recent_files=&Zuletzt_ge\u00F6ffnete_Dateien
+Load_session=Sitzung_&laden
+Save_session=Sitzung_s&peichern
+Close_database=Datei_s&chlie\u00DFen
+Quit=&Beenden
+# Export menu
+Tab-separated_file=Mit_&Tabulatoren_unterteilte_Datei
+# Edit
+Undo=&R\u00FCckg\u00E4ngig
+Redo=&Wiederholen
+Cut=Aus&schneiden
+Copy=&Kopieren
+Paste=&Einf\u00FCgen
+Delete=&L\u00F6schen
+Copy_BibTeX_key=&BibTeX_key_kopieren
+Copy_\\cite{BibTeX_key}=\\c&ite{BibTeX_key}_kopieren
+Mark_entries=Eintr\u00E4ge_&markieren
+Unmark_entries=Markierung_a&ufheben
+Unmark_all=S\u00E4mtliche_Markierungen_au&fheben
+Select_all=&Alle_ausw\u00E4hlen
+# View
+Next_tab=&N\u00E4chster_Tab
+Previous_tab=&Vorheriger_Tab
+Toggle_entry_preview=&Eintragsvorschau_ein-/ausblenden
+Switch_preview_layout=&Layout_der_Vorschau_wechseln
+Toggle_groups_interface=&Gruppenansicht_ein-/ausblenden
+Highlight_groups_matching_all_selected_entries=Gruppen_mit_&allen_ausgew\u00e4hlten_Eintr\u00e4gen_markieren
+Highlight_groups_matching_any_selected_entry=G&ruppen_mit_einem_der_ausgew\u00e4hlten_Eintr\u00e4ge_markieren
+# Bibtex
+Edit_entry=Eintrag_&bearbeiten
+# Menu BibTeX (BibTeX)
+New_entry=&Neuer_Eintrag
+New_entry...=Neuer_&Eintrag...
+New_entry_from_plain_text=Neuer_Eintrag_aus_&Klartext
+Import_Fields_from_CiteSeer=Felder_von_&CiteSeer_importieren
+Edit_preamble=&Pr\u00E4ambel_bearbeiten
+Edit_strings=&Strings_bearbeiten
+# Tools
+Search=&Suchen
+Incremental_search=&Weitersuchen
+Replace_string=&Ersetzen
+Find_duplicates=Nach_&doppelten_Eintr\u00E4gen_suchen
+Find_and_remove_exact_duplicates=E&xakte_Duplikate_Finden_und_Entfernen
+Manage_content_selectors=W&ortauswahl_verwalten
+Autogenerate_BibTeX_keys=&BibTeX_keys_automatisch_generieren
+Insert_selected_citations_into_LyX/Kile=Ausgew\u00E4hlte_Literaturangaben_in_&LyX/Kile_einf\u00FCgen
+Insert_selected_citations_into_WinEdt=&Ausgew\u00E4hlte_Literaturangaben_in_WinEdt_einf\u00FCgen
+Fetch_Medline=&Medline_abrufen
+Fetch_citations_from_CiteSeer=Literaturangaben_von_&CiteSeer_abrufen
+Open_PDF_or_PS=&PDF_oder_PS_\u00F6ffnen
+Open_URL_or_DOI=&URL_oder_DOI_\u00F6ffnen
+New_subdatabase_based_on_AUX_file=&Neue_Teildatei_aus_AUX-Datei
+Abbreviate_journal_names_(MEDLINE)=&Zeitschriftennamen_abk\u00fcrzen_(MEDLINE)
+Abbreviate_journal_names_(ISO)=Zeitschriftennamen_abk\u00fcrzen_(&ISO)
+Unabbreviate_journal_names=Ab&k\u00fcrzung_der_Zeitschriften_aufheben
+# Options
+Preferences=&Einstellungen
+Customize_entry_types=Eintragstypen_&anpassen
+Manage_custom_exports=&Verwalte_externe_Exportfilter
+Manage_custom_imports=Verwalte_externe_&Importfilter
+# Help
+JabRef_help=JabRef_&Hilfe
+Help_contents=Hilfe_-_&Inhalt
+About_JabRef=\u00DCber_&JabRef
+Export_selected_entries_to_clipboard=&Ausgw\u00E4hlte_Eintr\u00E4ge_in_die_Zwischenablage_kopieren
+Unpack_EndNote_filter_set=&EndNote_Filter-Set_entpacken
+Fetch_CiteSeer=&CiteSeer_abrufen
+Set_up_general_fields=All&gemeine_Felder_festlegen
+Integrity_check=\u00DCberpr\u00FCfung_der_Integrit\u00E4t
+Synchronize_PDF_links=PDF_Links_synchronisieren
+Synchronize_PS_links=PS_Links_synchronisieren
+Insert_selected_citations_into_Emacs=Ausgew\u00e4hlte_Literaturangaben_in_Emacs_ein&f\u00fcgen
diff --git a/src/resource/Menu_en.properties b/src/resource/Menu_en.properties
new file mode 100644
index 0000000..9d156dd
--- /dev/null
+++ b/src/resource/Menu_en.properties
@@ -0,0 +1,96 @@
+#! created/edited by Popeye version 0.51 sunshine (popeye.sourceforge.net)
+
+# Menu names
+File=&File
+Edit=&Edit
+View=&View
+BibTeX=&BibTeX
+Tools=&Tools
+Options=&Options
+Help=&Help
+# File menu
+New_database=&New_database
+Open_database=&Open_database
+Append_database=&Append_database
+Import_and_append=I&mport_and_append
+Import=&Import
+Custom_importers=Custom_importers
+Save_database=&Save_database
+Save_database_as_...=S&ave_database_as_...
+Save_selected_as_...=Save_se&lected_as_...
+Export=&Export
+Custom_export=Custom_e&xport
+Database_properties=Database_&properties
+Recent_files=&Recent_files
+Load_session=Loa&d_session
+Save_session=Save_session
+Close_database=&Close_database
+Quit=&Quit
+# Export menu
+Tab-separated_file=&Tab-separated_file
+# Edit
+Undo=&Undo
+Redo=&Redo
+Cut=&Cut
+Copy=C&opy
+Paste=&Paste
+Delete=&Delete
+Copy_BibTeX_key=Copy_&BibTeX_key
+Copy_\\cite{BibTeX_key}=Copy_\\c&ite{BibTeX_key}
+Mark_entries=&Mark_entries
+Unmark_entries=U&nmark_entries
+Unmark_all=Unmark_a&ll
+Select_all=Select_&all
+# View
+Next_tab=&Next_tab
+Previous_tab=&Previous_tab
+Toggle_entry_preview=&Toggle_entry_preview
+Switch_preview_layout=&Switch_preview_layout
+Toggle_groups_interface=Toggle_&groups_interface
+Highlight_groups_matching_all_selected_entries=Highlight_groups_matching_all_selected_entries
+Highlight_groups_matching_any_selected_entry=Highlight_groups_matching_any_selected_entry
+# Bibtex
+Edit_entry=&Edit_entry
+# Menu BibTeX (BibTeX)
+New_entry=N&ew_entry
+New_entry...=&New_entry_...
+New_entry_from_plain_text=Ne&w_entry_from_plain_text
+Import_Fields_from_CiteSeer=Import_fields_from_&CiteSeer
+Edit_preamble=Edit_&preamble
+Edit_strings=Edit_&strings
+# Tools
+Search=&Search
+Incremental_search=&Incremental_search
+Replace_string=&Replace_string
+Find_duplicates=&Find_duplicates
+Find_and_remove_exact_duplicates=Find_and_remove_exact_&duplicates
+Manage_content_selectors=Manage_&content_selectors
+Autogenerate_BibTeX_keys=&Autogenerate_BibTeX_keys
+Insert_selected_citations_into_LyX/Kile=Insert_selected_citations_into_&LyX/Kile
+Insert_selected_citations_into_WinEdt=Insert_selected_citations_into_&WinEdt
+Fetch_Medline=Fetch_&Medline
+Fetch_citations_from_CiteSeer=Fetch_citations_from_&CiteSeer
+Open_PDF_or_PS=Open_&PDF_or_PS
+Open_URL_or_DOI=Open_&URL_or_DOI
+New_subdatabase_based_on_AUX_file=New_subdatabase_based_on_AU&X_file
+Abbreviate_journal_names_(MEDLINE)=Abbreviate_journal_names_(MEDLINE)
+Abbreviate_journal_names_(ISO)=Abbreviate_journal_names_(ISO)
+Unabbreviate_journal_names=Unabbreviate_journal_names
+# Options
+Preferences=&Preferences
+Customize_entry_types=&Customize_entry_types
+Manage_custom_exports=&Manage_custom_exports
+Manage_custom_imports=Manage_custom_&imports
+# Help
+JabRef_help=JabRef_&help
+Help_contents=Help_&contents
+About_JabRef=&About_JabRef
+Export_selected_entries_to_clipboard=&Export selected entries to clipboard
+Unpack_EndNote_filter_set=Unpack_&EndNote_filter_set
+Fetch_CiteSeer=Fetch_CiteSeer
+Set_up_general_fields=Set_up_&general_fields
+Integrity_check=Integrity_check
+Synchronize_PDF_links=Synchronize_PDF_links
+Synchronize_PS_links=Synchronize_PS_links
+
+Insert_selected_citations_into_Emacs=Insert selected_citations_into_&Emacs
diff --git a/src/resource/Menu_fr.properties b/src/resource/Menu_fr.properties
new file mode 100644
index 0000000..2f51e8f
--- /dev/null
+++ b/src/resource/Menu_fr.properties
@@ -0,0 +1,95 @@
+#! created/edited by Popeye version 0.51 sunshine (popeye.sourceforge.net)
+
+# Menu names
+File=&Fichier
+Edit=&Edition
+View=&Affichage
+BibTeX=&BibTeX
+Tools=&Outils
+Options=Opt&ions
+Help=Ai&de
+# File menu
+New_database=&Nouvelle_base
+Open_database=&Ouvrir_base
+Append_database=&Joindre_\u00E0_la_base
+Import_and_append=I&mporter_et_joindre
+Import=&Importer
+Custom_importers=Custom_importers
+Save_database=&Sauvegarder_la_base
+Save_database_as_...=S&auvegarder_la_base_sous_...
+Save_selected_as_...=Sauvegarder_la_s\u00E9&lection_sous_...
+Export=&Exporter
+Custom_export=E&xportation personnalis\u00E9e
+Database_properties=&Propri\u00E9t\u00E9s_de la base de donn\u00e9es
+Recent_files=Fichiers_&r\u00E9cents
+Load_session=&Charger_session
+Save_session=Sau&ver_session
+Close_database=&Fermer_la_base
+Quit=&Quitter
+# Export menu
+Tab-separated_file=Fichier_-_s\u00E9paration_par_&tabulation
+# Edit
+Undo=&Annuler
+Redo=&R\u00E9p\u00E9ter
+Cut=&Couper
+Copy=Co&pier
+Paste=C&oller
+Delete=&Supprimer
+Copy_BibTeX_key=Copier_la_cl\u00E9_&BibTeX
+Copy_\\cite{BibTeX_key}=Copier_\\c&ite{cl\u00E9_BibTeX}
+Mark_entries=Etiqueter_des_&entr\u00E9es
+Unmark_entries=&D\u00E9s\u00E9tiqueter_des_entr\u00E9es
+Unmark_all=To&ut_d\u00E9s\u00E9tiqueter
+Select_all=&Tout_s\u00E9lectionner
+# View
+Next_tab=Onglet_&suivant
+Previous_tab=Onglet_&pr\u00E9c\u00E9dent
+Toggle_groups_interface=Afficher/masquer_l'interface_des_&groupes
+Toggle_entry_preview=&Afficher/masquer_l'aper\u00E7u
+Switch_preview_layout=Pr\u00E9&visualiser_la_mise_en_page
+Highlight_groups_matching_any_selected_entry=Surligner_les_groupes_correspondant_\u00e0_au_moins_&une_des_entr\u00e9es_s\u00e9lectionn\u00e9es
+Highlight_groups_matching_all_selected_entries=Surligner_les_groupes_correspondant_\u00e0_&toutes_les_entr\u00e9es_s\u00e9lectionn\u00e9es
+# Bibtex
+New_entry=N&ouvelle_entr\u00E9e
+New_entry...=&Nouvelle_entr\u00E9e...
+New_entry_from_plain_text=Nouvelle_entr\u00E9e_depuis_&texte brut
+Edit_entry=&Editer_l'entr\u00E9e
+Import_Fields_from_CiteSeer=Importer_les_champs_depuis_&CiteSeer
+Edit_preamble=Editer_le_&pr\u00E9ambule
+Edit_strings=Editer_les_c&ha\u00EEnes
+# Tools
+Search=&Recherche
+Incremental_search=Recherche_&incr\u00E9mentale
+Replace_string=Remplacer_la_c&ha\u00EEne
+Find_duplicates=Chercher_les_&doublons
+Find_and_remove_exact_duplicates=Chercher_et_&supprimer_les_doublons_identiques
+Manage_content_selectors=&G\u00E9rer_les_s\u00E9lecteurs_de_contenu
+Autogenerate_BibTeX_keys=Cr\u00E9ation_&automatique_des_cl\u00E9s_BibTeX
+Insert_selected_citations_into_Emacs=Envoyer_les_citations_s\u00E9lectionn\u00E9es_dans_&Emacs
+Insert_selected_citations_into_LyX/Kile=Envoyer_les_citations_s\u00E9lectionn\u00E9es_dans_&LyX/Kile
+Insert_selected_citations_into_WinEdt=Envoyer_les_citations_s\u00E9lectionn\u00E9es_dans_&WinEdt
+Fetch_Medline=Recherche_&Medline
+Fetch_CiteSeer=Recherche_Ci&teSeer
+Fetch_citations_from_CiteSeer=Recherche_de_citations_dans_&CiteSeer
+Open_PDF_or_PS=Ouvrir_&PDF_ou_PS
+Open_URL_or_DOI=Ouvrir_&URL_ou_DOI
+New_subdatabase_based_on_AUX_file=Nouveau_Fichier_BibTeX_depuis_fichier_AU&X
+Integrity_check=&V\u00E9rification_d'int\u00E9grit\u00E9
+Synchronize_PDF_links=Synchroniser_les_liens_PD&F
+Synchronize_PS_links=S&ynchroniser_les_liens_PS
+Abbreviate_journal_names_(ISO)=Abr\u00e9ger_les_noms_de_journaux_(IS&O)
+Abbreviate_journal_names_(MEDLINE)=Abr\u00e9ger_les_noms_de_journaux_(MEDLI&NE)
+Unabbreviate_journal_names=D\u00e9&velopper_les_noms_de_journaux
+# Options
+Preferences=&Pr\u00E9f\u00E9rences
+Customize_entry_types=Personnaliser_les_&types_d'entr\u00E9es
+Set_up_general_fields=Configurer_les_champs_&g\u00E9n\u00E9raux
+Manage_custom_exports=&G\u00E9rer_les_exportations_personnalis\u00E9es
+Manage_custom_imports=G\u00E9rer_les_&importations_personnalis\u00E9es
+# Help
+JabRef_help=&Aide_de_JabRef
+Help_contents=&Contenu_de_l'aide
+About_JabRef=A_&propos_de_JabRef
+
+Export_selected_entries_to_clipboard=Exporter_les_entr\u00E9es_s\u00E9lectionn\u00E9es_vers_le_presse-papiers
+Unpack_EndNote_filter_set=D\u00E9compacter_la_s\u00E9rie_de filtres_&EndNote
diff --git a/src/resource/Menu_no.properties b/src/resource/Menu_no.properties
new file mode 100644
index 0000000..1b67566
--- /dev/null
+++ b/src/resource/Menu_no.properties
@@ -0,0 +1,95 @@
+#! created/edited by Popeye version 0.51 sunshine (popeye.sourceforge.net)
+
+# Menu names
+File=&Fil
+Edit=&Rediger
+View=&Vis
+BibTeX=&BibTeX
+Tools=V&erkt\u00F8y
+Options=V&alg
+Help=&Hjelp
+# File menu
+New_database=&Ny_database
+Open_database=&\u00C5pne_database
+Append_database=Legg_til_inn&hold_fra_database
+Import_and_append=I&mporter_til_\u00E5pen_database
+Import=&Importer
+Custom_importers=Custom_importers
+Save_database=&Lagre_database
+Save_database_as_...=L&agre_database_som_...
+Save_selected_as_...=Lagre_&valgte_enheter_som_...
+Export=&Eksporter
+Custom_export=E&ksterne_eksportfiltre
+Database_properties=
+Recent_files=&Siste_filer
+Load_session=&Gjenopprett_tilstand
+Save_session=Lag&re_tilstand
+Close_database=L&ukk_database
+Quit=&Avslutt
+# Export menu
+Tab-separated_file=&Tab_separert_fil
+# Edit
+Undo=&Angre
+Redo=&Gjenta
+Cut=&Klipp_up
+Copy=K&opier
+Paste=&Lim_inn
+Delete=&Slett
+Copy_BibTeX_key=Kopier_&BibTeX-n\u00F8kkel
+Copy_\\cite{BibTeX_key}=Kopier_\\c&ite{BibTeX-n\u00F8kkel}
+Mark_entries=&Merk_enheter
+Unmark_entries=&Fjern_merking
+Unmark_all=F&jern_merking_fra_alle
+Select_all=&Velg_alle
+# View
+Next_tab=&Neste_tab
+Previous_tab=&Forrige_tab
+Toggle_entry_preview=&Vis/skjul_forh\u00E5ndsvisning
+Switch_preview_layout=&Skift_layout_p\u00E5_forh\u00E5ndsvisning
+Toggle_groups_interface=Vis/skjul_&grupperingskontroll
+Highlight_groups_matching_all_selected_entries=Uthev_grupper_som_inneholder_alle_valgte_enheter
+Highlight_groups_matching_any_selected_entry=Uthev_grupper_som_inneholder_minst_en_av_de_valgte_enhetene
+# Bibtex
+Edit_entry=&Rediger_enhet
+# Menu BibTeX (BibTeX)
+New_entry=N&y_enhet
+New_entry...=&Ny_enhet_...
+New_entry_from_plain_text=Ny_&enhet_fra_ren_tekst
+Import_Fields_from_CiteSeer=Importer_felter_fra_&CiteSeer
+Edit_preamble=Rediger_'&preamble'
+Edit_strings=Rediger_&strenger
+# Tools
+Search=&S\u00F8k
+Incremental_search=&Inkrementelt_s\u00F8k
+Replace_string=&Erstatt_streng
+Find_duplicates=S\u00F8k_etter_&duplikater
+Find_and_remove_exact_duplicates=&Finn_og_fjern_eksakte_duplikater
+Manage_content_selectors=Sett_opp_&ordvelgere
+Autogenerate_BibTeX_keys=&Autogenerer_BibTeX-n\u00F8kler
+Insert_selected_citations_into_LyX/Kile=Send_valgte_enheter_til_&LyX/Kile
+Insert_selected_citations_into_WinEdt=Send_valgte_enheter_til_&WinEdt
+Fetch_Medline=Hent_&Medline
+Fetch_citations_from_CiteSeer=Hent_refererende_publikasjoner_fra_&CiteSeer
+Open_PDF_or_PS=\u00C5pne_&PDF_eller_PS
+Open_URL_or_DOI=\u00C5pne_&URL_eller_DOI
+New_subdatabase_based_on_AUX_file=Ny_deldatabase_basert_p\u00E5_AU&X-fil
+Abbreviate_journal_names_(MEDLINE)=Forkort_journalnavn_(MEDLINE)
+Abbreviate_journal_names_(ISO)=Forkort_journalnavn_(ISO)
+Unabbreviate_journal_names=Ekspander_journalnavn
+# Options
+Preferences=&Oppsett
+Customize_entry_types=&Tilpass_enhetstyper
+Manage_custom_exports=&Sett_opp_eksterne_eksportfiltre
+Manage_custom_imports=Sett_opp_eksterne_importfiltre
+# Help
+JabRef_help=JabRef-&hjelp
+Help_contents=&Oversikt_over_hjelpefiler
+About_JabRef=Om_&JabRef
+Export_selected_entries_to_clipboard=Eksporter_valgte_enheter_til_utklippstavlen
+Unpack_EndNote_filter_set=Pakk_ut_&EndNote-filtersett
+Fetch_CiteSeer=Hent_CiteSeer
+Set_up_general_fields=Sett_opp_&generelle_felter
+Integrity_check=Sjekk_integritet
+Synchronize_PDF_links=Synkroniser_PDF-lenker
+Synchronize_PS_links=Synkroniser_PS-lenker
+Insert_selected_citations_into_Emacs=Send_valgte_enheter_til_Emacs
diff --git a/src/resource/build.properties b/src/resource/build.properties
new file mode 100644
index 0000000..026db04
--- /dev/null
+++ b/src/resource/build.properties
@@ -0,0 +1,3 @@
+builddate=February 2 2006
+build=185
+version=2.0.1
\ 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/bibtexml.begin.layout b/src/resource/layout/bibtexml.begin.layout
new file mode 100644
index 0000000..296d1b0
--- /dev/null
+++ b/src/resource/layout/bibtexml.begin.layout
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<bibtex:file xmlns:bibtex="http://bibtexml.sf.net/">
+<!-- This file was exported from JabRef -->
+
diff --git a/src/resource/layout/bibtexml.end.layout b/src/resource/layout/bibtexml.end.layout
new file mode 100644
index 0000000..0447a2f
--- /dev/null
+++ b/src/resource/layout/bibtexml.end.layout
@@ -0,0 +1 @@
+</bibtex:file>
diff --git a/src/resource/layout/bibtexml.layout b/src/resource/layout/bibtexml.layout
new file mode 100755
index 0000000..a59bd97
--- /dev/null
+++ b/src/resource/layout/bibtexml.layout
@@ -0,0 +1,35 @@
+<bibtex:entry id="\bibtexkey">
+  <bibtex:\format[ToLowerCase]{\bibtextype}>
+\begin{author}    <bibtex:author>\format[XMLChars,AuthorFirstFirst]{\author}</bibtex:author>\end{author}
+\begin{editor}    <bibtex:editor>\format[XMLChars,AuthorFirstFirst]{\editor}</bibtex:editor>\end{editor}
+\begin{title}    <bibtex:title>\format[XMLChars]{\title}</bibtex:title>\end{title}
+\begin{booktitle}    <bibtex:booktitle>\format[XMLChars]{\booktitle}</bibtex:booktitle>\end{booktitle}
+\begin{journal}    <bibtex:journal>\format[XMLChars]{\journal}</bibtex:journal>\end{journal}
+\begin{publisher}    <bibtex:publisher>\format[XMLChars]{\publisher}</bibtex:publisher>\end{publisher}
+\begin{year}    <bibtex:year>\year</bibtex:year>\end{year}
+\begin{volume}    <bibtex:volume>\format[XMLChars]{\volume}</bibtex:volume>\end{volume}
+\begin{month}    <bibtex:month>\format[XMLChars]{\month}</bibtex:month>\end{month}
+\begin{chapter}    <bibtex:chapter>\format[XMLChars]{\chapter}</bibtex:chapter>\end{chapter}
+\begin{pages}    <bibtex:pages>\format[FormatPagesForXML]{\pages}</bibtex:pages>\end{pages}
+\begin{number}    <bibtex:number>\format[XMLChars]{\number}</bibtex:number>\end{number}
+\begin{edition}    <bibtex:edition>\format[XMLChars]{\edition}</bibtex:edition>\end{edition}
+\begin{series}    <bibtex:series>\format[XMLChars]{\series}</bibtex:series>\end{series}
+\begin{institution}    <bibtex:institution>\format[XMLChars]{\institution}</bibtex:institution>\end{institution}
+\begin{organization}    <bibtex:organization>\format[XMLChars]{\organization}</bibtex:organization>\end{organization}
+\begin{school}    <bibtex:school>\format[XMLChars]{\school}</bibtex:school>\end{school}
+\begin{address}    <bibtex:address>\format[XMLChars]{\address}</bibtex:address>\end{address}
+\begin{howpublished}    <bibtex:howpublished>\format[XMLChars]{\howpublished}</bibtex:howpublished>\end{howpublished}
+\begin{abstract}    <bibtex:abstract>\format[XMLChars]{\abstract}</bibtex:abstract>\end{abstract}
+\begin{url}    <bibtex:url>\url</bibtex:url>\end{url}
+\begin{doi}    <bibtex:doi>\doi</bibtex:doi>\end{doi}
+\begin{eid}    <bibtex:eid>\format[XMLChars]{\eid}</bibtex:eid>\end{eid}
+\begin{pdf}    <bibtex:pdf>\format[ResolvePDF,XMLChars]{\pdf}</bibtex:pdf>\end{pdf}
+\begin{type}    <bibtex:type>\format[XMLChars]{\type}</bibtex:type>\end{type}
+\begin{crossref}    <bibtex:crossref>\format[XMLChars]{\crossref}</bibtex:crossref>\end{crossref}
+\begin{annote}    <bibtex:annote>\format[XMLChars]{\annote}</bibtex:annote>\end{annote}
+\begin{keywords}    <bibtex:keywords>\format[XMLChars]{\keywords}</bibtex:keywords>\end{keywords}
+\begin{comment}    <bibtex:comment>\format[XMLChars]{\comment}</bibtex:comment>\end{comment}
+\begin{note}    <bibtex:note>\format[XMLChars]{\note}</bibtex:note>\end{note}
+\begin{key}    <bibtex:key>\format[XMLChars]{\key}</bibtex:key>\end{key}
+  </bibtex:\format[ToLowerCase]{\bibtextype}>
+</bibtex:entry>
diff --git a/src/resource/layout/docbook.begin.layout b/src/resource/layout/docbook.begin.layout
new file mode 100644
index 0000000..7a747c5
--- /dev/null
+++ b/src/resource/layout/docbook.begin.layout
@@ -0,0 +1,5 @@
+<?xml version="1.0" ?>
+<!-- This file was exported from JabRef -->
+
+<bibliography>
+
diff --git a/src/resource/layout/docbook.end.layout b/src/resource/layout/docbook.end.layout
new file mode 100644
index 0000000..0dd396c
--- /dev/null
+++ b/src/resource/layout/docbook.end.layout
@@ -0,0 +1 @@
+</bibliography>
diff --git a/src/resource/layout/docbook.layout b/src/resource/layout/docbook.layout
new file mode 100755
index 0000000..dfe23f8
--- /dev/null
+++ b/src/resource/layout/docbook.layout
@@ -0,0 +1,18 @@
+<biblioentry xreflabel="\bibtexkey" id="\bibtexkey">
+   <authorgroup>
+\begin{author}       \format[XMLChars,CreateDocBookAuthors]{\author} \end{author}
+   </authorgroup>
+<citetitle pubwork="article">\format[XMLChars,RemoveLatexCommands]{\title}</citetitle>
+\begin{journal}   <citetitle pubwork="journal">\format[XMLChars]{\journal}</citetitle>\end{journal}
+\begin{publisher}   <publisher>
+      <publishername>\format[XMLChars]{\publisher}</publishername>
+   </publisher>\end{publisher}
+\begin{volume}   <volumenum>\volume</volumenum> \end{volume}
+\begin{edition}   <edition>\format[XMLChars,RemoveLatexCommands]{\edition}</edition> \end{edition}
+\begin{pages}   <artpagenums>\format[FormatPagesForXML]{\pages}</artpagenums> \end{pages}
+\begin{year}   <pubdate>\year</pubdate>  \end{year}
+\begin{abstract}   <abstract>
+      <para>\format[XMLChars,RemoveLatexCommands]{\abstract}
+      </para>
+   </abstract>\end{abstract}
+</biblioentry>
diff --git a/src/resource/layout/endnote/EndNote.article.layout b/src/resource/layout/endnote/EndNote.article.layout
new file mode 100755
index 0000000..7868de7
--- /dev/null
+++ b/src/resource/layout/endnote/EndNote.article.layout
@@ -0,0 +1,42 @@
+%0 \endnotereftype
+%0 Journal Article
+%A \format[AuthorLastFirst,RemoveBracketsAddComma,AuthorAndsReplacer]{\author}
+%D \year
+%T \format[RemoveLatexCommands]{\title}
+%E 
+%B \journal
+%C 
+%I \publisher
+%V \volume
+%6
+%N \number
+%P \pages
+%& 
+%Y 
+%S 
+%7
+%8 \month
+%9
+%? 
+%! \shorttitle
+%Z 
+%@ \issn
+%(
+%)
+%*
+%L
+%M
+%1 \pdf
+%2 \comment
+%3 article
+%4 \crossref
+%# \owner
+%$ \key
+%F \bibtexkey
+%K \keywords
+%X \abstract
+%Z \note
+%U \url
+%+
+%^
+
diff --git a/src/resource/layout/endnote/EndNote.book.layout b/src/resource/layout/endnote/EndNote.book.layout
new file mode 100755
index 0000000..0d0e490
--- /dev/null
+++ b/src/resource/layout/endnote/EndNote.book.layout
@@ -0,0 +1,42 @@
+%0 \endnotereftype
+%0 Book
+%A \format[AuthorLastFirst,RemoveBracketsAddComma,AuthorAndsReplacer]{\author}
+%D \year
+%T \format[RemoveLatexCommands]{\title}
+%E \format[AuthorLastFirst,RemoveBracketsAddComma,AuthorAndsReplacer]{\editor}
+%B \series
+%C \address
+%I \publisher
+%V \volume
+%6
+%N \number
+%P
+%& 
+%Y 
+%S 
+%7 \edition
+%8 \month
+%9
+%? 
+%! \shorttitle
+%Z 
+%@ \isbn
+%(
+%)
+%*
+%L
+%M
+%1 \pdf
+%2 \comment
+%3 book
+%4 \crossref
+%# \owner
+%$ \key
+%F \bibtexkey
+%K \keywords
+%X \abstract
+%Z \note
+%U \url
+%+
+%^
+
diff --git a/src/resource/layout/endnote/EndNote.booklet.layout b/src/resource/layout/endnote/EndNote.booklet.layout
new file mode 100755
index 0000000..7a4455c
--- /dev/null
+++ b/src/resource/layout/endnote/EndNote.booklet.layout
@@ -0,0 +1,42 @@
+%0 \endnotereftype
+%0 Personal Communication
+%A \format[AuthorLastFirst,RemoveBracketsAddComma,AuthorAndsReplacer]{\author}
+%D \year
+%T \format[RemoveLatexCommands]{\title}
+%E
+%B
+%C \address
+%I \howpublished
+%V
+%6
+%N \lastchecked
+%P
+%& 
+%Y 
+%S 
+%7
+%8 \month
+%9
+%? 
+%! \shorttitle
+%Z 
+%@ 
+%(
+%)
+%*
+%L
+%M
+%1 \pdf
+%2 \comment
+%3 booklet
+%4 \crossref
+%# \owner
+%$ \key
+%F \bibtexkey
+%K \keywords
+%X \abstract
+%Z \note
+%U \url
+%+
+%^
+
diff --git a/src/resource/layout/endnote/EndNote.inbook.layout b/src/resource/layout/endnote/EndNote.inbook.layout
new file mode 100755
index 0000000..d0296c6
--- /dev/null
+++ b/src/resource/layout/endnote/EndNote.inbook.layout
@@ -0,0 +1,42 @@
+%0 \endnotereftype
+%0 Book Section
+%A \format[AuthorLastFirst,RemoveBracketsAddComma,AuthorAndsReplacer]{\author}
+%D \year
+%T \format[RemoveLatexCommands]{\title}
+%E \format[AuthorLastFirst,RemoveBracketsAddComma,AuthorAndsReplacer]{\editor}
+%B \booktitle
+%C \address
+%I \publisher
+%V \volume
+%6
+%N 
+%P \pages
+%& \chapter
+%Y 
+%S \series
+%7 \edition
+%8 \month
+%9 \type
+%? 
+%! \shorttitle
+%Z 
+%@ \isbn
+%(
+%)
+%*
+%L
+%M
+%1 \pdf
+%2 \comment
+%3 inbook
+%4 \crossref
+%# \owner
+%$ \key
+%F \bibtexkey
+%K \keywords
+%X \abstract
+%Z \note
+%U \url
+%+
+%^
+
diff --git a/src/resource/layout/endnote/EndNote.incollection.layout b/src/resource/layout/endnote/EndNote.incollection.layout
new file mode 100755
index 0000000..7d1c068
--- /dev/null
+++ b/src/resource/layout/endnote/EndNote.incollection.layout
@@ -0,0 +1,42 @@
+%0 \endnotereftype
+%0 Book Section
+%A \format[AuthorLastFirst,RemoveBracketsAddComma,AuthorAndsReplacer]{\author}
+%D \year
+%T \format[RemoveLatexCommands]{\title}
+%E \format[AuthorLastFirst,RemoveBracketsAddComma,AuthorAndsReplacer]{\editor}
+%B \booktitle
+%C \address
+%I \publisher
+%V \volume
+%6
+%N 
+%P \pages
+%& \chapter
+%Y 
+%S \series
+%7 \edition
+%8 \month
+%9 \type
+%? 
+%! \shorttitle
+%Z 
+%@ \isbn
+%(
+%)
+%*
+%L
+%M
+%1 \pdf
+%2 \comment
+%3 incollection
+%4 \crossref
+%# \owner
+%$ \key
+%F \bibtexkey
+%K \keywords
+%X \abstract
+%Z \note
+%U \url
+%+
+%^
+
diff --git a/src/resource/layout/endnote/EndNote.inproceedings.layout b/src/resource/layout/endnote/EndNote.inproceedings.layout
new file mode 100755
index 0000000..52dba9d
--- /dev/null
+++ b/src/resource/layout/endnote/EndNote.inproceedings.layout
@@ -0,0 +1,42 @@
+%0 \endnotereftype
+%0 Conference Proceedings
+%A \format[AuthorLastFirst,RemoveBracketsAddComma,AuthorAndsReplacer]{\author}
+%D \year
+%T \format[RemoveLatexCommands]{\title}
+%E \format[AuthorLastFirst,RemoveBracketsAddComma,AuthorAndsReplacer]{\editor}
+%B \booktitle
+%C \address
+%I \publisher
+%V \volume
+%6
+%N 
+%P \pages
+%& 
+%Y \organization
+%S \series
+%7
+%8 \month
+%9
+%? 
+%! \shorttitle
+%Z 
+%@ \isbn
+%(
+%)
+%*
+%L
+%M
+%1 \pdf
+%2 \comment
+%3 inproceedings
+%4 \crossref
+%# \owner
+%$ \key
+%F \bibtexkey
+%K \keywords
+%X \abstract
+%Z \note
+%U \url
+%+
+%^
+
diff --git a/src/resource/layout/endnote/EndNote.layout b/src/resource/layout/endnote/EndNote.layout
new file mode 100755
index 0000000..3cf6bf1
--- /dev/null
+++ b/src/resource/layout/endnote/EndNote.layout
@@ -0,0 +1,42 @@
+%0 \endnotereftype
+%0 Generic
+%A \format[AuthorLastFirst,RemoveBracketsAddComma,AuthorAndsReplacer]{\author}
+%D \year
+%T \format[RemoveLatexCommands]{\title}
+%E
+%B 
+%C
+%I \howpublished
+%V 
+%6
+%N 
+%P 
+%& 
+%Y 
+%S 
+%7
+%8 \month
+%9
+%? 
+%! \shorttitle
+%Z 
+%@ 
+%(
+%)
+%*
+%L
+%M
+%1 \pdf
+%2 \comment
+%3 \entrytype
+%4 \crossref
+%# \owner
+%$ \key
+%F \bibtexkey
+%K \keywords
+%X \abstract
+%Z \note
+%U \url
+%+
+%^
+
diff --git a/src/resource/layout/endnote/EndNote.manual.layout b/src/resource/layout/endnote/EndNote.manual.layout
new file mode 100755
index 0000000..37cac25
--- /dev/null
+++ b/src/resource/layout/endnote/EndNote.manual.layout
@@ -0,0 +1,42 @@
+%0 \endnotereftype
+%0 Computer Program
+%A \format[AuthorLastFirst,RemoveBracketsAddComma,AuthorAndsReplacer]{\author}
+%D \year
+%T \format[RemoveLatexCommands]{\title}
+%E
+%B 
+%C \address
+%I \organization
+%V 
+%6
+%N 
+%P 
+%& 
+%Y 
+%S 
+%7 \edition
+%8 \month
+%9
+%? 
+%! \shorttitle
+%Z 
+%@ \isbn
+%(
+%)
+%*
+%L
+%M
+%1 \pdf
+%2 \comment
+%3 manual
+%4 \crossref
+%# \owner
+%$ \key
+%F \bibtexkey
+%K \keywords
+%X \abstract
+%Z \note
+%U \url
+%+
+%^
+
diff --git a/src/resource/layout/endnote/EndNote.mastersthesis.layout b/src/resource/layout/endnote/EndNote.mastersthesis.layout
new file mode 100755
index 0000000..085ff35
--- /dev/null
+++ b/src/resource/layout/endnote/EndNote.mastersthesis.layout
@@ -0,0 +1,42 @@
+%0 \endnotereftype
+%0 Thesis
+%A \format[AuthorLastFirst,RemoveBracketsAddComma,AuthorAndsReplacer]{\author}
+%D \year
+%T \format[RemoveLatexCommands]{\title}
+%E 
+%B 
+%C \address
+%I \school
+%V 
+%6
+%N 
+%P 
+%& 
+%Y 
+%S 
+%7
+%8 \month
+%9 \type
+%? 
+%! \shorttitle
+%Z 
+%@ 
+%(
+%)
+%*
+%L
+%M
+%1 \pdf
+%2 \comment
+%3 mastersthesis
+%4 \crossref
+%# \owner
+%$ \key
+%F \bibtexkey
+%K \keywords
+%X \abstract
+%Z \note
+%U \url
+%+
+%^
+
diff --git a/src/resource/layout/endnote/EndNote.misc.layout b/src/resource/layout/endnote/EndNote.misc.layout
new file mode 100755
index 0000000..f50b2c7
--- /dev/null
+++ b/src/resource/layout/endnote/EndNote.misc.layout
@@ -0,0 +1,42 @@
+%0 \endnotereftype
+%0 Generic
+%A \format[AuthorLastFirst,RemoveBracketsAddComma,AuthorAndsReplacer]{\author}
+%D \year
+%T \format[RemoveLatexCommands]{\title}
+%E
+%B 
+%C
+%I \howpublished
+%V 
+%6
+%N 
+%P 
+%& 
+%Y 
+%S 
+%7
+%8 \month
+%9
+%? 
+%! \shorttitle
+%Z 
+%@ 
+%(
+%)
+%*
+%L
+%M
+%1 \pdf
+%2 \comment
+%3 misc
+%4 \crossref
+%# \owner
+%$ \key
+%F \bibtexkey
+%K \keywords
+%X \abstract
+%Z \note
+%U \url
+%+
+%^
+
diff --git a/src/resource/layout/endnote/EndNote.other.layout b/src/resource/layout/endnote/EndNote.other.layout
new file mode 100755
index 0000000..0bed803
--- /dev/null
+++ b/src/resource/layout/endnote/EndNote.other.layout
@@ -0,0 +1,42 @@
+%0 \endnotereftype
+%0 Generic
+%A \format[AuthorLastFirst,RemoveBracketsAddComma,AuthorAndsReplacer]{\author}
+%D \year
+%T \format[RemoveLatexCommands]{\title}
+%E
+%B 
+%C
+%I \howpublished
+%V 
+%6
+%N 
+%P 
+%& 
+%Y 
+%S 
+%7
+%8 \month
+%9
+%? 
+%! \shorttitle
+%Z 
+%@ 
+%(
+%)
+%*
+%L
+%M
+%1 \pdf
+%2 \comment
+%3 other
+%4 \crossref
+%# \owner
+%$ \key
+%F \bibtexkey
+%K \keywords
+%X \abstract
+%Z \note
+%U \url
+%+
+%^
+
diff --git a/src/resource/layout/endnote/EndNote.phdthesis.layout b/src/resource/layout/endnote/EndNote.phdthesis.layout
new file mode 100755
index 0000000..534525d
--- /dev/null
+++ b/src/resource/layout/endnote/EndNote.phdthesis.layout
@@ -0,0 +1,42 @@
+%0 \endnotereftype
+%0 Thesis
+%A \format[AuthorLastFirst,RemoveBracketsAddComma,AuthorAndsReplacer]{\author}
+%D \year
+%T \format[RemoveLatexCommands]{\title}
+%E 
+%B 
+%C \address
+%I \school
+%V 
+%6
+%N 
+%P 
+%& 
+%Y 
+%S 
+%7
+%8 \month
+%9 \type
+%? 
+%! \shorttitle
+%Z 
+%@ 
+%(
+%)
+%*
+%L
+%M
+%1 \pdf
+%2 \comment
+%3 phdthesis
+%4 \crossref
+%# \owner
+%$ \key
+%F \bibtexkey
+%K \keywords
+%X \abstract
+%Z \note
+%U \url
+%+
+%^
+
diff --git a/src/resource/layout/endnote/EndNote.proceedings.layout b/src/resource/layout/endnote/EndNote.proceedings.layout
new file mode 100755
index 0000000..e520c9c
--- /dev/null
+++ b/src/resource/layout/endnote/EndNote.proceedings.layout
@@ -0,0 +1,42 @@
+%0 \endnotereftype
+%0 Conference Proceedings
+%A \format[AuthorLastFirst,RemoveBracketsAddComma,AuthorAndsReplacer]{\author}
+%D \year
+%T \format[RemoveLatexCommands]{\title}
+%E \format[AuthorLastFirst,RemoveBracketsAddComma,AuthorAndsReplacer]{\editor}
+%B \booktitle
+%C \address
+%I \publisher
+%V \volume
+%6
+%N 
+%P \pages
+%& 
+%Y \organization
+%S \series
+%7
+%8 \month
+%9
+%? 
+%! \shorttitle
+%Z 
+%@ \isbn
+%(
+%)
+%*
+%L
+%M
+%1 \pdf
+%2 \comment
+%3 proceedings
+%4 \crossref
+%# \owner
+%$ \key
+%F \bibtexkey
+%K \keywords
+%X \abstract
+%Z \note
+%U \url
+%+
+%^
+
diff --git a/src/resource/layout/endnote/EndNote.techreport.layout b/src/resource/layout/endnote/EndNote.techreport.layout
new file mode 100755
index 0000000..aa7e40c
--- /dev/null
+++ b/src/resource/layout/endnote/EndNote.techreport.layout
@@ -0,0 +1,42 @@
+%0 \endnotereftype
+%0 Report
+%A \format[AuthorLastFirst,RemoveBracketsAddComma,AuthorAndsReplacer]{\author}
+%D \year
+%T \format[RemoveLatexCommands]{\title}
+%E 
+%B 
+%C \address
+%I \institution
+%V 
+%6
+%N 
+%P 
+%& 
+%Y 
+%S 
+%7
+%8 \month
+%9 \type
+%? 
+%! \shorttitle
+%Z 
+%@ \number
+%(
+%)
+%*
+%L
+%M
+%1 \pdf
+%2 \comment
+%3 techreport
+%4 \crossref
+%# \owner
+%$ \key
+%F \bibtexkey
+%K \keywords
+%X \abstract
+%Z \note
+%U \url
+%+
+%^
+
diff --git a/src/resource/layout/endnote/EndNote.unpublished.layout b/src/resource/layout/endnote/EndNote.unpublished.layout
new file mode 100755
index 0000000..66f9507
--- /dev/null
+++ b/src/resource/layout/endnote/EndNote.unpublished.layout
@@ -0,0 +1,42 @@
+%0 \endnotereftype
+%0 Manuscript
+%A \format[AuthorLastFirst,RemoveBracketsAddComma,AuthorAndsReplacer]{\author}
+%D \year
+%T \format[RemoveLatexCommands]{\title}
+%E
+%B 
+%C
+%I
+%V 
+%6
+%N 
+%P 
+%& 
+%Y 
+%S 
+%7
+%8 \month
+%9
+%? 
+%! \shorttitle
+%Z 
+%@ 
+%(
+%)
+%*
+%L
+%M
+%1 \pdf
+%2 \comment
+%3 unpublished
+%4 \crossref
+%# \owner
+%$ \key
+%F \bibtexkey
+%K \keywords
+%X \abstract
+%Z \note
+%U \url
+%+
+%^
+
diff --git a/src/resource/layout/endnote/Readme.txt b/src/resource/layout/endnote/Readme.txt
new file mode 100755
index 0000000..471830b
--- /dev/null
+++ b/src/resource/layout/endnote/Readme.txt
@@ -0,0 +1,70 @@
+EndNote Export Filter for JabRef
+version 1.0
+2004-12-02
+
+Written by Alex Montgomery (ahm at stanford.edu)
+
+*********************************************************************************
+Overview:
+*********************************************************************************
+
+The EndNote Export Filter for JabRef (when combined with the "EndNote Import from JabRef.enf" filter for EndNote, derived from the "EndNote Import" filter) allows for most of the default JabRef fields to be imported into the appropriate EndNote fields. Two export styles from EndNote ("BibTeX Export to JabRef") are also included that support the same fields. Note that the default EndNote Reference Types must be modified by the user to support the import of certain fields.
+
+*********************************************************************************
+Installation:
+*********************************************************************************
+EndNote Import from JabRef.eni
+This file must be placed in your EndNote Filters directory. On a Mac OS X system, the default directory is /Applications/EndNote 7/Filters. On a Windows XP system, the default directory is C:\Program Files\EndNote\Filters. The default EndNote Import filter will be able to import the files from JabRef, but supports fewer fields. You should then open up the Filter Manager (Edit->Import Filters->Open Filter Manager) and add it to your Favorites.
+
+EndNote Preferences
+The filter provided will only work if certain fields are added to EndNote's default Reference Types. Open up Preferences and click on Reference Types, then Modify Reference Types. The following table lists the field names that must be added to certain reference types for EndNote to support these fields. For example, the Publisher field for Journal Article is blank by default; Type in Publisher in this field. 
+
+Tag	Generic Name 	New Field Name	Ref Types
+%I	Publisher	Publisher	(Journal Article)
+%& 	Section		Section 	(Book Section)
+%9 	Type of Work	Type of Work 	(Book Section)
+%8 	Date		Date 		(Book, Book Section, Thesis)
+%1 	Custom 1	pdf		(All)
+%2 	Custom 2	comment		(All)
+%3 	Custom 3	entrytype	(All)
+%4 	Custom 4	crossref	(All)
+%# 	Custom 5	owner		(All)
+%$ 	Custom 6	key		(All)
+(All = Journal Article, Book, Book Section, Conference Proceedings, Report, Thesis)
+
+EndNote.*.layout:
+These files must be kept together in a single directory.
+Start JabRef. In the "Options" menu you will find the button "Manage custom exports". The "Manage custom exports" interface will appear. Click the "Add new" button. You can choose a name for the export filter (e.g. "EndNote"). Specify the location of the main layout file (which is the file "EndNote.layout") by typing the full path or by using the "Browse" button. The file extension should be set to ".txt" Click "OK". Now you will find the new custom export filter in the "File" menu under [...]
+
+EndNote.tab:
+This is the tab-delimited spreadsheet containing a list of all the Refer codes, how they map to the Generic EndNote fields, and how the JabRef fields for the default BibTeX types are mapped to the Generic EndNote fields.
+
+BibTeX Export to JabRef, BibTeX Export to JabRef*
+These file are optional for if you wish to re-export these entries to JabRef. They must be placed in your EndNote Styles directory. On a Mac OS X system, the default directory is /Applications/EndNote 7/Styles. On a Windows XP system, the default directory is C:\Program Files\EndNote\Styles. You may then want to open up the Filter Manager (Edit->Output Styles->Open Style Manager) and add it to your Favorites.
+
+*********************************************************************************
+Usage
+*********************************************************************************
+To export the entries of your database select File->Custom Export->EndNote and type in the output filename.
+
+To import the entries into Endnote, open up a (or create a new) database. Select File->Import, then select "EndNote Import from JabRef." Click on Choose File, then select the output file you created in the previous step.
+
+To re-export to JabRef, two EndNote Styles are provided. Select a style (see "Notes" for the problems with each), then select File->Export. The exported text file is a BibTeX file ready to be read by JabRef.
+
+*********************************************************************************
+Notes:
+*********************************************************************************
+The export format implemented is the EndNote Import format, an extension of the Refer format.
+
+Only two JabRef fields are unsupported due to a lack of Custom fields in EndNote: doi and citeseerurl. Enterprising users should be able to modify the enclosed files in order to swap out two other fields (e.g. pdf and owner) instead. Note that EndNote 8 has additional fields that could be ideal for doi and citeseerurl (part of the reason why these are excluded here). In particular, Electronic Resource Number (DOI) and Link to PDF. The latter is actually a URL field, not a relative field  [...]
+
+This has been tested on Mac OS X 10.3.6 using JabRef 1.6 and EndNote 7. It should work on Windows XP using EndNote 7, or EndNote 8 on either platform.
+
+BibTeX Export to JabRef munges together some BibTeX types (e.g. misc/unpublished/other/manual -> misc). Use BibTeX Export to JabRef* instead if you need better mapping - but only if you are using field Custom 3 (entrytype) to store the BibTeX entrytypes. Note that this export filter ONLY currently covers the reference types that the EndNote Export Filter uses (i.e. Journal Article, Book, Book Section, Conference Proceedings, Report, Thesis).
+
+BibTeX Export to JabRef* is ONLY for use if you are re-exporting a file that was imported from JabRef. This is because it uses Custom 3 (entrytype) to store and output the entrytype rather than guessing from the EndNote reference type. If this field isn't filled in, it will export bad BibTeX code. You have been warned.
+
+Booklet, when exported back to JabRef using either BibTeX Export to JabRef,
+has \publisher filled instead of \howpublished; \lastchecked is not re-exported. This is due to the fact that EndNote doesn't have export filters sophisticated enough to fix this properly; however, the Book EndNote reference type is the only one appropriate for the "booklet" BibTeX type.
+
+Corporate Authors (e.g. {Central Intelligence Agency} should be mapped to "Central Intelligence Agency," in EndNote, but aren't (this would require a new formatter in JabRef).
\ No newline at end of file
diff --git a/src/resource/layout/harvard/harvard.article.layout b/src/resource/layout/harvard/harvard.article.layout
new file mode 100644
index 0000000..1f35b9e
--- /dev/null
+++ b/src/resource/layout/harvard/harvard.article.layout
@@ -0,0 +1,13 @@
+\format[RTFChars,AuthorLastFirst,AuthorAbbreviator,AuthorAndsReplacer]{\author} (\year)
+, '\format[RTFChars]{\title}', }{\\i \format[RTFChars]{\journal}}{
+\begin{volume}
+ }{\\b \volume}{
+\end{volume}
+\begin{number}
+(\number)
+\end{number}
+\begin{pages}
+, \pages
+\end{pages}.
+\\par
+\\par
diff --git a/src/resource/layout/harvard/harvard.begin.layout b/src/resource/layout/harvard/harvard.begin.layout
new file mode 100644
index 0000000..610023a
--- /dev/null
+++ b/src/resource/layout/harvard/harvard.begin.layout
@@ -0,0 +1,3 @@
+{\\rtf1\\ansi\\ansicpg1252\\uc1 \\deff0\\deflang1031\\deflangfe1031{\\fonttbl{\\f0\\froman\\fcharset0\\fprq2{\\*\\panose 02020603050405020304}Times New Roman;}{\\f28\\froman\\fcharset238\\fprq2 Times New Roman CE;}{\\f29\\froman\\fcharset204\\fprq2 Times New Roman Cyr;}
+{\\f31\\froman\\fcharset161\\fprq2 Times New Roman Greek;}{\\f32\\froman\\fcharset162\\fprq2 Times New Roman Tur;}{\\f33\\froman\\fcharset177\\fprq2 Times New Roman (Hebrew);}{\\f34\\froman\\fcharset178\\fprq2 Times New Roman (Arabic);}
+{\\f35\\froman\\fcharset186\\fprq2 Times New Roman Baltic;}}{
diff --git a/src/resource/layout/harvard/harvard.book.layout b/src/resource/layout/harvard/harvard.book.layout
new file mode 100644
index 0000000..9f74a7d
--- /dev/null
+++ b/src/resource/layout/harvard/harvard.book.layout
@@ -0,0 +1,19 @@
+\begin{author}
+\format[RTFChars,AuthorLastFirst,AuthorAbbreviator,AuthorAndsReplacer]{\author}
+\end{author}
+\begin{editor}
+\format[RTFChars,AuthorLastFirst,AuthorAbbreviator,AuthorAndsReplacer]{\editor}, ed.
+\end{editor}
+ (\year), 
+}{\\i \format[RTFChars]{\title}}{
+\begin{volume}
+, Vol. \volume
+\end{volume}
+\begin{publisher}
+, \format[RTFChars]{\publisher}
+\end{publisher}
+\begin{address}
+, \format[RTFChars]{\address}
+\end{address}.
+\\par
+\\par
diff --git a/src/resource/layout/harvard/harvard.end.layout b/src/resource/layout/harvard/harvard.end.layout
new file mode 100644
index 0000000..a2950a1
--- /dev/null
+++ b/src/resource/layout/harvard/harvard.end.layout
@@ -0,0 +1 @@
+}}
\ No newline at end of file
diff --git a/src/resource/layout/harvard/harvard.inbook.layout b/src/resource/layout/harvard/harvard.inbook.layout
new file mode 100644
index 0000000..743176b
--- /dev/null
+++ b/src/resource/layout/harvard/harvard.inbook.layout
@@ -0,0 +1,19 @@
+\begin{author}
+\format[RTFChars,AuthorLastFirst,AuthorAbbreviator,AuthorAndsReplacer]{\author}
+\end{author}
+ (\year), 
+}{\\i \format[RTFChars]{\title}}{
+\begin{publisher}
+, \format[RTFChars]{\publisher}
+\end{publisher}
+\begin{address}
+, \format[RTFChars]{\address}
+\end{address}
+\begin{chapter}
+, chapter \chapter
+\end{chapter}
+\begin{pages}
+, pp. \pages
+\end{pages}.
+\\par
+\\par
diff --git a/src/resource/layout/harvard/harvard.incollection.layout b/src/resource/layout/harvard/harvard.incollection.layout
new file mode 100644
index 0000000..f393742
--- /dev/null
+++ b/src/resource/layout/harvard/harvard.incollection.layout
@@ -0,0 +1,16 @@
+\format[RTFChars,AuthorLastFirst,AuthorAbbreviator,AuthorAndsReplacer]{\author} (\year),
+}{\format[RTFChars]{\title}}{
+\begin{editor}
+, }{\\i in }{\format[RTFChars,AuthorFirstFirst,AuthorAndsReplacer]{\editor}, ed.,
+\end{editor}
+\begin{booktitle}
+'\format[RTFChars]{\booktitle}'
+\end{booktitle}
+\begin{publisher}
+, \format[RTFChars]{\publisher}, \format[RTFChars]{\address}
+\end{publisher}
+\begin{pages}
+, pp. \pages
+\end{pages}.
+\\par
+\\par
diff --git a/src/resource/layout/harvard/harvard.inproceedings.layout b/src/resource/layout/harvard/harvard.inproceedings.layout
new file mode 100644
index 0000000..dbcf492
--- /dev/null
+++ b/src/resource/layout/harvard/harvard.inproceedings.layout
@@ -0,0 +1,17 @@
+\format[RTFChars,AuthorLastFirst,AuthorAbbreviator,AuthorAndsReplacer]{\author} (\year),
+\format[RTFChars]{\title}
+, }{\\i in }{
+\begin{editor}
+\format[RTFChars,AuthorFirstFirst,AuthorAndsReplacer]{\editor}, ed.,
+\end{editor}
+\begin{booktitle}
+'\format[RTFChars]{\booktitle}'
+\end{booktitle}
+\begin{publisher}
+, \format[RTFChars]{\publisher}, \format[RTFChars]{\address}
+\end{publisher}
+\begin{pages}
+, pp. \pages
+\end{pages}.
+\\par
+\\par
diff --git a/src/resource/layout/harvard/harvard.layout b/src/resource/layout/harvard/harvard.layout
new file mode 100644
index 0000000..5bc0278
--- /dev/null
+++ b/src/resource/layout/harvard/harvard.layout
@@ -0,0 +1,37 @@
+\format[AuthorLastFirst,AuthorAbbreviator,AuthorAndsReplacer,RTFChars]{\author} (\year),
+'\format[RTFChars]{\title}'
+\begin{journal}
+, }{\\i \format[RTFChars]{\journal}} {\\b \volume}{
+\end{journal}
+\begin{number}
+(\number)
+\end{number}
+\begin{editor}
+, }{\\i in }{\format[AuthorFirstFirst,AuthorAndsReplacer,RTFChars]{\editor}, ed.,
+\end{editor}
+\begin{booktitle}
+'\format[RTFChars]{\booktitle}'
+\end{booktitle}
+\begin{organization}
+, \organization
+\end{organization}
+\begin{institution}
+, Technical report, \institution
+\end{institution}
+\begin{publisher}
+, \format[RTFChars]{\publisher}
+\end{publisher}
+\begin{howpublished}
+, \howpublished
+\end{howpublished}
+\begin{address}
+, \format[RTFChars]{\address}
+\end{address}
+\begin{note}
+, \note
+\end{note}
+\begin{pages}
+, \pages
+\end{pages}.
+\\par
+\\par
diff --git a/src/resource/layout/harvard/harvard.mastersthesis.layout b/src/resource/layout/harvard/harvard.mastersthesis.layout
new file mode 100644
index 0000000..ad44617
--- /dev/null
+++ b/src/resource/layout/harvard/harvard.mastersthesis.layout
@@ -0,0 +1,7 @@
+\format[RTFChars,AuthorLastFirst,AuthorAbbreviator,AuthorAndsReplacer]{\author} (\year),
+'\format[RTFChars]{\title}'
+\begin{school}
+, Master's thesis, \school
+\end{school}.
+\\par
+\\par
diff --git a/src/resource/layout/harvard/harvard.phdthesis.layout b/src/resource/layout/harvard/harvard.phdthesis.layout
new file mode 100644
index 0000000..0cc528d
--- /dev/null
+++ b/src/resource/layout/harvard/harvard.phdthesis.layout
@@ -0,0 +1,7 @@
+\format[RTFChars,AuthorLastFirst,AuthorAbbreviator,AuthorAndsReplacer]{\author} (\year),
+'\format[RTFChars]{\title}'
+\begin{school}
+, PhD thesis, \school
+\end{school}.
+\\par
+\\par
diff --git a/src/resource/layout/harvard/harvard.proceedings.layout b/src/resource/layout/harvard/harvard.proceedings.layout
new file mode 100644
index 0000000..41633c0
--- /dev/null
+++ b/src/resource/layout/harvard/harvard.proceedings.layout
@@ -0,0 +1,19 @@
+\begin{author}
+\format[RTFChars,uthorLastFirst,AuthorAbbreviator,AuthorAndsReplacer]{\author}
+\end{author}
+\begin{editor}
+\format[RTFChars,AuthorLastFirst,AuthorAbbreviator,AuthorAndsReplacer]{\editor}, ed.
+\end{editor}
+ (\year), 
+}{\\i \format[RTFChars]{\title}}{
+\begin{volume}
+, Vol. \volume
+\end{volume}
+\begin{publisher}
+, \format[RTFChars]{\publisher}
+\end{publisher}
+\begin{address}
+, \format[RTFChars]{\address}
+\end{address}.
+\\par
+\\par
diff --git a/src/resource/layout/harvard/harvard.readme b/src/resource/layout/harvard/harvard.readme
new file mode 100644
index 0000000..1b4ea74
--- /dev/null
+++ b/src/resource/layout/harvard/harvard.readme
@@ -0,0 +1,55 @@
+************************************************
+
+*******                                 ********
+*******  Readme: Harvard Export Filter  ********
+*******                                 ******** 
+*******           for JabRef            ********
+*******                                 ********
+*******           version 1.0           ********
+*******            04/12/01             ********
+*******                                 ******** 
+************************************************
+
+
+written by gottfried (vosgerau at uni-tuebingen.de)
+
+
+
+The harvard export filter allows you to export your biliography entries into an Rich Text Format file (*.rtf) according to the Harvard citation standards often used in arts and humanities. The Rich Text Format file can be opened with word processing programms like Word, Open Office, Star Writer, etc. on all systems and then be copied directly into the other files.
+
+
+Installation
+************
+
+The following 11 files are needed for the harvard export filter:
+	harvard.article.layout
+	harvard.begin.layout
+	harvard.book.layout
+	harvard.end.layout
+	harvard.inbook.layout
+	harvard.incollection.layout
+	harvard.inproceedings.layout
+	harvard.layout
+	harvard.mastersthesis.layout
+	harvard.phdthesis.layout
+	harvard.proceedings.layout
+
+Put all of these 11 files in one directory. Note that all have to be in the same directory.
+
+Start JabRef. In the "Options" menu you will find the button "Manage costum exports". The "Manage costum exports" interface will appear. Click the "Add new" button. You can choose a name for the export filter (e.g. "Harvard"). Specify the location of the main layout file (which is the file "harvard.layout") by typing the full path or by using the "Browse" button. The file extension should be set to ".rtf". Click "OK".
+
+Now you will find the new costum export filter in the "File" menu under the pop-up menu "Custom export". To export the entries of your database just click on the name of the new filter and specify the output file.
+
+
+Important Notes
+***************
+
+Although we tried to make the filter as good as possible, please note that formatting command like \emph or \textbf are ignored. 
+
+The use of special characters such as \"a or \`a may lead to strange results. Therefore, if you use special characters check the output and use the find and replace command to correct the output.
+
+The ordering of the entries may not match the usual alphabetic order in some cases. Please check your file before usage.
+
+
+**************************
+end of file harvard.readme
diff --git a/src/resource/layout/html.begin.layout b/src/resource/layout/html.begin.layout
new file mode 100644
index 0000000..0288b2c
--- /dev/null
+++ b/src/resource/layout/html.begin.layout
@@ -0,0 +1,62 @@
+<html>
+<header>
+	<title>JabRef Output</title>
+	<style type="text/css">
+body {
+    font-family:Georgia, Garamond, Serif;
+    background-color:#ddd;
+}
+
+.bibtex_entry {
+    border:2px solid black;
+    margin:1em;
+}
+
+.bibtex_header {
+    border-bottom:solid gray 2px;
+}
+.bibtex_key {
+    font-size:small;
+    color:#555;
+    display:inline;
+	font-weight:bold;
+}
+
+.bibtex_content {
+    padding-bottom:1em;
+}
+
+.bibtex_author {
+    font-weight:bold;
+    padding-bottom:1em;
+}
+
+.bibtex_title {
+    font-weight:bold;
+    padding-bottom:1em;
+}
+
+.bibtex_url, .bibtex_pdf, .bibtex_doi, .bibtex_citeseer {
+    display:inline;
+	font-size:small;
+	float:right;
+	padding-left:1em;
+	padding-right:1em;
+}
+
+.bibtex_url a, .bibtex_pdf a, .bibtex_doi a, .bibtex_citeseer a , .bibtex_url a:visited, .bibtex_pdf a:visited, .bibtex_doi a:visited, .bibtex_citeseer a:visited {
+	text-decoration:none;
+	font-weight:bold;
+	color:darkblue;
+
+}
+
+.bibtex_journal, .bibtex_year, .bibtex_volume, .bibtex_pages, .bibtex_publisher {
+    display:inline;
+}
+	</style>
+</header>
+<body>
+
+
+<hr>
\ No newline at end of file
diff --git a/src/resource/layout/html.book.layout b/src/resource/layout/html.book.layout
new file mode 100755
index 0000000..086bcbe
--- /dev/null
+++ b/src/resource/layout/html.book.layout
@@ -0,0 +1,51 @@
+<div class="bibtex_entry">
+
+	<div class="bibtex_header">
+		<div class="bibtex_key">
+			<a name="\bibtexkey">\bibtexkey</a>
+		</div>
+
+		\begin{pdf}
+		<div class="bibtex_pdf">
+			<a href="\format[ResolvePDF]{\pdf}">pdf</a>
+		</div>
+		\end{pdf}
+
+		\begin{url}
+		<div class="bibtex_url">
+			<a href="\url">url</a>
+		</div>
+		\end{url}
+	</div>
+
+	<div class="bibtex_content">
+
+		\begin{title}
+		<div class="bibtex_title">
+			\format[HTMLChars,RemoveLatexCommands]{\title}
+		</div>
+ 		\end{title}
+
+		\begin{author}
+		<div class="bibtex_author">
+			\format[AuthorLastFirst,AuthorAbbreviator,AuthorAndsReplacer,HTMLChars]{\author}
+		</div>
+		\end{author}
+
+		\begin{publisher}
+		<div class="bibtex_publisher">
+			\format[HTMLChars]{\publisher}
+		</div>,
+		\end{publisher}
+
+		\begin{pages}
+		<div class="bibtex_pages">
+			pp. \format[FormatPagesForHTML]{\pages}
+		</div>,
+		\end{pages}
+
+		<div class="bibtex_year">
+			\year
+		</div>
+	</div>
+</div>
diff --git a/src/resource/layout/html.end.layout b/src/resource/layout/html.end.layout
new file mode 100644
index 0000000..42828b5
--- /dev/null
+++ b/src/resource/layout/html.end.layout
@@ -0,0 +1,6 @@
+
+<hr>
+<p style="font-size: smaller;">Generated on \format[CurrentDate]{}</p>
+
+</body>
+</html>
diff --git a/src/resource/layout/html.inbook.layout b/src/resource/layout/html.inbook.layout
new file mode 100644
index 0000000..3c84bdc
--- /dev/null
+++ b/src/resource/layout/html.inbook.layout
@@ -0,0 +1,63 @@
+<div class="bibtex_entry">
+
+	<div class="bibtex_header">
+		<div class="bibtex_key">
+			<a name="\bibtexkey">\bibtexkey</a>
+		</div>
+
+		\begin{doi}
+		<div class="bibtex_doi">
+			<a href="http://dx.doi.org/\doi">doi</a>
+		</div>
+		\end{doi}
+
+		\begin{pdf}
+		<div class="bibtex_pdf">
+			<a href="\format[ResolvePDF]{\pdf}">pdf</a>
+		</div>
+		\end{pdf}
+
+		\begin{url}
+		<div class="bibtex_url">
+			<a href="\url">url</a>
+		</div>
+		\end{url}
+	</div>
+
+	<div class="bibtex_content">
+
+		\begin{title}
+		<div class="bibtex_title">
+			In: \format[HTMLChars,RemoveLatexCommands]{\title}
+		</div>
+		\end{title}
+
+		\begin{author}
+		<div class="bibtex_author">
+			\format[AuthorLastFirst,AuthorAbbreviator,AuthorAndsReplacer,HTMLChars]{\author}
+		</div>
+		\end{author}
+
+		\begin{publisher}
+		<div class="bibtex_journal">
+			\format[HTMLChars]{\publisher}
+		</div>,
+		\end{publisher}
+
+		\begin{volume}
+		<div class="bibtex_volume">
+			Vol. \volume
+		</div>,
+		\end{volume}
+
+		\begin{pages}
+		<div class="bibtex_pages">
+			pp. \format[FormatPagesForHTML]{\pages}
+		</div>,
+		\end{pages}
+
+		<div class="bibtex_year">
+			\year
+		</div>
+	</div>
+</div>
diff --git a/src/resource/layout/html.inproceedings.layout b/src/resource/layout/html.inproceedings.layout
new file mode 100644
index 0000000..449ba12
--- /dev/null
+++ b/src/resource/layout/html.inproceedings.layout
@@ -0,0 +1,63 @@
+<div class="bibtex_entry">
+
+	<div class="bibtex_header">
+		<div class="bibtex_key">
+			<a name="\bibtexkey">\bibtexkey</a>
+		</div>
+
+		\begin{doi}
+		<div class="bibtex_doi">
+			<a href="http://dx.doi.org/\doi">doi</a>
+		</div>
+		\end{doi}
+
+		\begin{pdf}
+		<div class="bibtex_pdf">
+			<a href="\format[ResolvePDF]{\pdf}">pdf</a>
+		</div>
+		\end{pdf}
+
+		\begin{url}
+		<div class="bibtex_url">
+			<a href="\url">url</a>
+		</div>
+		\end{url}
+	</div>
+
+	<div class="bibtex_content">
+
+		\begin{title}
+		<div class="bibtex_title">
+			\format[HTMLChars,RemoveLatexCommands]{\title}
+		</div>
+		\end{title}
+
+		\begin{author}
+		<div class="bibtex_author">
+			\format[AuthorLastFirst,AuthorAbbreviator,AuthorAndsReplacer,HTMLChars]{\author}
+		</div>
+		\end{author}
+
+		\begin{booktitle}
+		<div class="bibtex_journal">
+			\format[HTMLChars]{\booktitle}
+		</div>,
+		\end{booktitle}
+
+		\begin{volume}
+		<div class="bibtex_volume">
+			Vol. \volume
+		</div>,
+		\end{volume}
+
+		\begin{pages}
+		<div class="bibtex_pages">
+			pp. \format[FormatPagesForHTML]{\pages}
+		</div>,
+		\end{pages}
+
+		<div class="bibtex_year">
+			\year
+		</div>
+	</div>
+</div>
diff --git a/src/resource/layout/html.layout b/src/resource/layout/html.layout
new file mode 100755
index 0000000..170d7b5
--- /dev/null
+++ b/src/resource/layout/html.layout
@@ -0,0 +1,69 @@
+<div class="bibtex_entry" title="Generated on \format[CurrentDate]{mm|dd|yyyy}">
+
+	<div class="bibtex_header">
+		<div class="bibtex_key">
+			<a name="\bibtexkey">\bibtexkey</a>
+		</div>
+
+		\begin{doi}
+		<div class="bibtex_doi">
+			<a href="http://dx.doi.org/\doi">doi</a>
+		</div>
+		\end{doi}
+
+		\begin{citeseerurl}
+		<div class="bibtex_citeseer">
+			<a href="http://citeseer.ist.psu.edu/\citeseerurl">cs</a>
+		</div>
+		\end{citeseerurl}
+
+		\begin{pdf}
+		<div class="bibtex_pdf">
+			<a href="\format[ResolvePDF]{\pdf}">pdf</a>
+		</div>
+		\end{pdf}
+
+		\begin{url}
+		<div class="bibtex_url">
+			<a href="\url">url</a>
+		</div>
+		\end{url}
+	</div>
+
+	<div class="bibtex_content">
+
+		\begin{title}
+		<div class="bibtex_title">
+			\format[HTMLChars,RemoveLatexCommands]{\title}
+		</div>
+		\end{title}
+
+		\begin{author}
+		<div class="bibtex_author">
+			\format[AuthorLastFirst,AuthorAbbreviator,AuthorAndsReplacer,HTMLChars]{\author}
+		</div>
+		\end{author}
+
+		\begin{journal}
+		<div class="bibtex_journal">
+			\format[HTMLChars]{\journal}
+		</div>,
+		\end{journal}
+
+		\begin{volume}
+		<div class="bibtex_volume">
+			Vol. \volume
+		</div>,
+		\end{volume}
+
+		\begin{pages}
+		<div class="bibtex_pages">
+			pp. \format[FormatPagesForHTML]{\pages}
+		</div>,
+		\end{pages}
+
+		<div class="bibtex_year">
+			\year
+		</div>
+	</div>
+</div>
diff --git a/src/resource/layout/html.mastersthesis.layout b/src/resource/layout/html.mastersthesis.layout
new file mode 100644
index 0000000..c6b7b0d
--- /dev/null
+++ b/src/resource/layout/html.mastersthesis.layout
@@ -0,0 +1,45 @@
+<div class="bibtex_entry">
+
+	<div class="bibtex_header">
+		<div class="bibtex_key">
+			<a name="\bibtexkey">\bibtexkey</a>
+		</div>
+
+		\begin{pdf}
+		<div class="bibtex_pdf">
+			<a href="\format[ResolvePDF]{\pdf}">pdf</a>
+		</div>
+		\end{pdf}
+
+		\begin{url}
+		<div class="bibtex_url">
+			<a href="\url">url</a>
+		</div>
+		\end{url}
+	</div>
+
+	<div class="bibtex_content">
+
+		\begin{title}
+		<div class="bibtex_title">
+			\format[HTMLChars,RemoveLatexCommands]{\title}
+		</div>
+		\end{title}
+
+		\begin{author}
+		<div class="bibtex_author">
+			\format[AuthorLastFirst,AuthorAbbreviator,AuthorAndsReplacer,HTMLChars]{\author}
+		</div>
+		\end{author}
+
+		\begin{school}
+		<div class="bibtex_journal">
+			\format[HTMLChars]{\school}
+		</div>,
+		\end{school}
+
+		<div class="bibtex_year">
+			\year
+		</div>
+	</div>
+</div>
diff --git a/src/resource/layout/html.phdthesis.layout b/src/resource/layout/html.phdthesis.layout
new file mode 100644
index 0000000..c6b7b0d
--- /dev/null
+++ b/src/resource/layout/html.phdthesis.layout
@@ -0,0 +1,45 @@
+<div class="bibtex_entry">
+
+	<div class="bibtex_header">
+		<div class="bibtex_key">
+			<a name="\bibtexkey">\bibtexkey</a>
+		</div>
+
+		\begin{pdf}
+		<div class="bibtex_pdf">
+			<a href="\format[ResolvePDF]{\pdf}">pdf</a>
+		</div>
+		\end{pdf}
+
+		\begin{url}
+		<div class="bibtex_url">
+			<a href="\url">url</a>
+		</div>
+		\end{url}
+	</div>
+
+	<div class="bibtex_content">
+
+		\begin{title}
+		<div class="bibtex_title">
+			\format[HTMLChars,RemoveLatexCommands]{\title}
+		</div>
+		\end{title}
+
+		\begin{author}
+		<div class="bibtex_author">
+			\format[AuthorLastFirst,AuthorAbbreviator,AuthorAndsReplacer,HTMLChars]{\author}
+		</div>
+		\end{author}
+
+		\begin{school}
+		<div class="bibtex_journal">
+			\format[HTMLChars]{\school}
+		</div>,
+		\end{school}
+
+		<div class="bibtex_year">
+			\year
+		</div>
+	</div>
+</div>
diff --git a/src/resource/layout/openoffice/README b/src/resource/layout/openoffice/README
new file mode 100644
index 0000000..1396661
--- /dev/null
+++ b/src/resource/layout/openoffice/README
@@ -0,0 +1,15 @@
+A very simple export filter that outputs a comma-separated file that can be used by Openoffice (OO) as a bibliography database.
+
+Uses two new custom formaters: 
+
+  - GetOpenofficeType: 
+      converts the default bibtextype entries into the numeric codes that
+	  OO uses to identify the kind of publication.
+  - RemoveWhitespace: 
+      removes all whitespace chars (newlines, tabs, form-feeds, etc) except
+	  for the "space character".
+
+Enjoy.
+
+Juan M. Peralta
+peralta_jm at earthlink.net
diff --git a/src/resource/layout/openoffice/openoffice-csv.begin.layout b/src/resource/layout/openoffice/openoffice-csv.begin.layout
new file mode 100644
index 0000000..0b19bc9
--- /dev/null
+++ b/src/resource/layout/openoffice/openoffice-csv.begin.layout
@@ -0,0 +1 @@
+BibliographyType,ISBN,Identifier,Author,Title,Journal,Volume,Number,Month,Pages,Year,Address,Note,URL,Booktitle,Chapter,Edition,Series,Editor,Publisher,ReportType,Howpublished,Institution,Organizations,School,Annote,Custom1,Custom2,Custom3,Custom4,Custom5
diff --git a/src/resource/layout/openoffice/openoffice-csv.layout b/src/resource/layout/openoffice/openoffice-csv.layout
new file mode 100644
index 0000000..f454957
--- /dev/null
+++ b/src/resource/layout/openoffice/openoffice-csv.layout
@@ -0,0 +1 @@
+\format[GetOpenOfficeType]{\bibtextype},"\begin{isbn}\isbn\end{isbn}","\bibtexkey","\format[AuthorLastFirst,AuthorAndsReplacer]{\author}","\format[RemoveBrackets,RemoveWhitespace]{\title}","\journal",\volume,\number,"\month","\pages",\year,"\address","\note","\url","\booktitle","\chapter","\edition","\series","\format[AuthorLastFirst,AuthorAndsReplacer]{\editor}","\publisher","\begin{reporttype}\reporttype\end{reporttype}","\howpublished","\institution","\organization","\school","\annote [...]
diff --git a/src/resource/layout/simplehtml.layout b/src/resource/layout/simplehtml.layout
new file mode 100755
index 0000000..8535f63
--- /dev/null
+++ b/src/resource/layout/simplehtml.layout
@@ -0,0 +1,15 @@
+<font face="arial">
+<b><i>\bibtextype</i><a name="\bibtexkey">\begin{bibtexkey} (\bibtexkey)</a>\end{bibtexkey}</b>
+<br>
+\begin{author} \format[AuthorLastFirst,AuthorAbbreviator,AuthorAndsReplacer,HTMLChars]{\author}<BR>\end{author}
+\begin{editor} \format[AuthorLastFirst,AuthorAbbreviator,AuthorAndsReplacer,HTMLChars]{\editor} <i>(ed.)</i><BR>\end{editor}
+\begin{title} \format[HTMLChars]{\title} \end{title}<BR>
+\begin{chapter} \format[HTMLChars]{\chapter}<BR>\end{chapter}
+\begin{journal} <em>\format[HTMLChars]{\journal}, </em>\end{journal}
+\begin{school} <em>\format[HTMLChars]{\school}, </em>\end{school}
+\begin{institution} <em>\format[HTMLChars]{\institution}, </em>\end{institution}
+\begin{publisher} <em>\format[HTMLChars]{\publisher}, </em>\end{publisher}
+\begin{year}<b>\year</b>\end{year}\begin{volume}<i>, \volume</i>\end{volume}\begin{pages}, \format[FormatPagesForHTML]{\pages} \end{pages}
+</dd>
+<p></p>
+</font>
diff --git a/src/resource/layout/text.layout b/src/resource/layout/text.layout
new file mode 100755
index 0000000..f3637cd
--- /dev/null
+++ b/src/resource/layout/text.layout
@@ -0,0 +1,10 @@
+@\bibtextype{\bibtexkey,
+\begin{author}  author = {\author},\end{author}
+\begin{title}  title  = {\format[RemoveBrackets]{\title}},\end{title}
+\begin{journal}  journal = {\journal},\end{journal}
+  year   = {\year},
+  number = {\number},
+  url    = {\url},
+\begin{doi}  doi = {\doi},\end{doi}
+  const  = {\\ text}
+}
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/resource/ods/manifest.xml b/src/resource/ods/manifest.xml
new file mode 100644
index 0000000..745c622
--- /dev/null
+++ b/src/resource/ods/manifest.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE manifest:manifest PUBLIC "-//OpenOffice.org//DTD Manifest 1.0//EN" "Manifest.dtd">
+<manifest:manifest xmlns:manifest="urn:oasis:names:tc:opendocument:xmlns:manifest:1.0">
+ <manifest:file-entry manifest:media-type="application/vnd.oasis.opendocument.spreadsheet" manifest:full-path="/"/>
+ <manifest:file-entry manifest:media-type="text/xml" manifest:full-path="content.xml"/>
+ <manifest:file-entry manifest:media-type="text/xml" manifest:full-path="meta.xml"/>
+ <manifest:file-entry manifest:media-type="text/xml" manifest:full-path="settings.xml"/>
+</manifest:manifest>
\ No newline at end of file
diff --git a/src/resource/ods/meta.xml b/src/resource/ods/meta.xml
new file mode 100644
index 0000000..043813a
--- /dev/null
+++ b/src/resource/ods/meta.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<office:document-meta xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" office:version="1.0">
+ <office:meta>
+  <meta:generator>JabRef version @version@
+  </meta:generator>
+<!--  <meta:creation-date>2005-11-01T22:55:38</meta:creation-date>  <dc:date>2005-11-01T22:59:26</dc:date>  <dc:language>en-US</dc:language>  <meta:editing-cycles>3</meta:editing-cycles>  <meta:editing-duration>PT3M50S</meta:editing-duration>-->
+  <meta:user-defined meta:name="Info 1"/>
+  <meta:user-defined meta:name="Info 2"/>
+  <meta:user-defined meta:name="Info 3"/>
+  <meta:user-defined meta:name="Info 4"/>
+<!--  <meta:document-statistic meta:table-count="3" meta:cell-count="4"/>-->
+ </office:meta>
+</office:document-meta>
\ No newline at end of file
diff --git a/src/resource/ods/settings.xml b/src/resource/ods/settings.xml
new file mode 100644
index 0000000..711c200
--- /dev/null
+++ b/src/resource/ods/settings.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<office:document-settings xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" office:version="1.0">
+
+
+</office:document-settings>
\ No newline at end of file
diff --git a/src/resource/openoffice/manifest.xml b/src/resource/openoffice/manifest.xml
new file mode 100644
index 0000000..4bd2223
--- /dev/null
+++ b/src/resource/openoffice/manifest.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE manifest:manifest PUBLIC "-//OpenOffice.org//DTD Manifest 1.0//EN" "Manifest.dtd">
+<manifest:manifest xmlns:manifest="http://openoffice.org/2001/manifest">
+ <manifest:file-entry manifest:media-type="application/vnd.sun.xml.calc" manifest:full-path="/"/>
+ <manifest:file-entry manifest:media-type="text/xml" manifest:full-path="content.xml"/>
+ <manifest:file-entry manifest:media-type="text/xml" manifest:full-path="meta.xml"/>
+</manifest:manifest>
\ No newline at end of file
diff --git a/src/resource/openoffice/meta.xml b/src/resource/openoffice/meta.xml
new file mode 100644
index 0000000..556c08f
--- /dev/null
+++ b/src/resource/openoffice/meta.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE office:document-meta PUBLIC "-//OpenOffice.org//DTD OfficeDocument 1.0//EN" "office.dtd">
+<office:document-meta xmlns:office="http://openoffice.org/2000/office" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="http://openoffice.org/2000/meta" office:version="1.0">
+ <office:meta>
+  <meta:generator>JabRef @version@</meta:generator>
+ </office:meta>
+</office:document-meta>
\ No newline at end of file
diff --git a/src/resource/openoffice/mimetype b/src/resource/openoffice/mimetype
new file mode 100644
index 0000000..5b5832e
--- /dev/null
+++ b/src/resource/openoffice/mimetype
@@ -0,0 +1 @@
+application/vnd.sun.xml.calc
\ No newline at end of file
diff --git a/src/txt/INSTALL b/src/txt/INSTALL
new file mode 100644
index 0000000..bc4938d
--- /dev/null
+++ b/src/txt/INSTALL
@@ -0,0 +1,31 @@
+Quick instructions, compiling JabRef from source
+------------------------------------------------
+
+To compile JabRef from source, you need:
+
+* A Java compiler, supporting Java 1.4 or higher.
+* Jakarta Ant (http://ant.apache.org). Don't know what version is
+  needed; the latest stable version should work fine.
+
+To compile, use the command "ant compile unjarlib jars".
+After the build is finished, you can find the executable jar file
+named "jabref.jar" in the "build/lib" directory. Enjoy!
+
+You can also build and run JabRef directly with the command "ant run".
+Note that this will not run the "unjarlib" target that bundles 3rd party
+libraries inside the jar file.
+
+On Mac OS X you should include the targets osx and osxjar,
+making the correct command "ant compile unjarlib osx jars osxjar".
+AFter the build is finished, you will find the OS X application
+"JabRef.app" in the "build/lib" directory along with the executable
+jar.
+
+If you have the required libraries (found as jar files in the "lib"
+directory in your classpath, you can remove the "unjarlib" target to
+avoid these libraries being bundled inside the JabRef jar.
+
+
+
+Morten Alver
+Revised June 11, 2005.
diff --git a/src/txt/README b/src/txt/README
new file mode 100644
index 0000000..38febc8
--- /dev/null
+++ b/src/txt/README
@@ -0,0 +1,441 @@
+
+JabRef 2.0.1
+------------
+
+
+Introduction:
+
+JabRef is a graphical Java application for editing bibtex (.bib)
+databases. JabRef lets you organize your entries into overlapping
+logical groups, and with a single click limit your view to a single
+group or an intersection or union of several groups. You can customize
+the entry information shown in the main window, and sort by any of the
+standard Bibtex fields. JabRef can autogenerate bibtex keys for your
+entries. JabRef also lets you easily link to PDF or web sources for your
+reference entries.
+
+JabRef can import from and export to several formats, and you can
+customize export filters. JabRef can be run as a command line application
+to convert from any import format to any export format.
+
+
+License:
+JabRef is free open source software, distributed under the GNU General
+Public Licence. See the enclosed text file 'gpl.txt', or the About
+dialog, for details about the GPL.
+
+JabRef also uses libraries distributed by other porties; see the About
+box for details.
+
+
+Requirements:
+JabRef runs on any system equipped with the Java Virtual Machine
+(1.4.2 or newer), which can be downloaded at no cost from
+http://java.sun.com. If you do not plan to compile JabRef, the Java
+Runtime Environment may be a better choice than the Java Development
+Kit.
+
+
+Installing and running, Windows:
+JabRef is available in Windows Installer (.msi) format. To install,
+double-click the .msi file. A shortcut to JabRef will be added to your
+start menu.
+
+The Windows installation was made by Dale Visser, using the following open-source tools:
+JSmooth (.exe wrapper for Java apps), available at http://jsmooth.sf.net/
+Wix (tool for compiling MSI files from an XML specification), available at http://wix.sf.net/
+
+
+Installing and running, general:
+JabRef can be downloaded as an executable .jar file. Run the
+program as follows:
+If you are using the Java Development Kit:
+     java -jar <path to jar>
+or, if you are using the Java Runtime Environment:
+     jre -new -jar <path to jar> or
+     jrew -new -jar <path to jar>
+
+We recommend running JabRef under the Java 5.0 JRE. If you do, you should add
+the option "-Dswing.aatext=true" before the "-jar" option, to activate
+antialiased text throughout the application.
+
+
+The jar file containing JabRef can be unpacked with the command:
+    jar xf <path to jar>
+or  jar xf <path to jar> <list of files to extract>
+Unpacking the jar file is not necessary to run the program.
+
+
+
+Building JabRef from source:
+Please see the INSTALL file for instructions for building from source.
+
+Documentation:
+JabRef comes with an online help function, accessed by pressing F1 or
+clicking on a question mark icon. The help files are probably not
+exhaustive enough to satisfy everyone yet, but they should help sort
+out the most important issues about using the program. The help files
+can also be viewed outside the program with a standard HTML browser.
+If you choose languages other than English, some or all help pages may
+appear in your chosen languages.
+
+Change log:
+2.0.1:	- Fixed bug that made a hidden entry editor under some circumstances store a
+	  field value to the wrong entry.
+	- Fixed synchronization bug that made the opening of a new database sometimes fail.
+	- Fixed bug in setting external journal lists when no personal list is set.
+2.0:    - Changed sorting selection interface for main table for more intuitive
+          operation.
+        - Made import operation update "working directory".
+        - Removed hard-coded author/editor name rearrangement in OpenOffice and
+          OpenDocument exports.
+        - Fixed hangup when parsing RIS files from Nature.
+        - Fixed NullPointerException when generating database from AUX file on Mac OS X.
+        - Fixed bug in routine for adding braces around capital letters.
+        - Fixed bug in switching preview layouts.
+        - Fixed bug in link handling in entry preview.
+2.0b2:  - Changed field order in OpenDocument export to comply with bibliography requirement.
+        - Added support for inserting citations into Emacs using gnuserv/gnuclient.
+        - Added option to set a regular expression replace operation on generated bibtex keys.
+        - Added support for custom importers inside a jar file.
+        - Fixed bug in opening URLs containing '&' on Windows.
+2.0b:   - Added a system for registering custom import formats in the form of Java classes.
+        - Added export option for OpenDocument spreadsheet.
+        - Added new options for name formatting in main table.
+        - Added REPEC-NEP import filter.
+        - Added option for non-field parameters for export formatters. If the parameters does not start with the
+          backslash character, it will be passed unchanged to the formatter in place of any field value.
+        - Added export formatter CurrentDate, which returns the current date, and takes a format string as
+          parameter.                   
+        - Added customization of table colors, accessible from Tools -> Preferences -> Entry table.
+        - Added new Appearance tab to preferences dialog to gather appearance related options.
+        - Added toggling of abbreviated and full journal names. The list of journals is realized as
+           an external file, but editable from a Manage Journal Abbreviations panel. Secondary lists can also
+           be linked, but not edited. There is a download option to quickly get a list available on the internet,
+           and we will provide one or more lists for download from the SourceForge web server.
+        - Added functionality for new JabRef instances to detect a running instance, and send
+          command line parameters to the running instance for processing.
+        - Added handling of HTML links in preview panel.
+        - Added confirmation dialog when database is saved and the chosen encoding doesn't support all characters.
+          Gives options to save, cancel or try a different encoding.
+        - The encoding used when opening a database is now remembered, and used when database is stored.
+        - Added review field for research comments, paper reviews, etc.
+        - Added option to disable wrapping for certain fields. Wrapping of pdf, ps, doi and url is disabled by
+          default.
+        - Antialiasing option now affects entry editor text fields as well as table text.
+        - Changed to monospaced font in source editor field.
+        - Removed option to put double braces around BibTeX fields, but retained option to remove double braces
+          when loading. Added option to put braces around capital letters of a chosen set of fields.
+        - Improved Ovid import.
+        - Fixed problem with ordering of BibTeX strings that are referred to by other strings.
+        - Fixed problem with loading 16-bit encoded bib files with 8-bit encoding as default, and vice versa.
+        - Fixed multiplying authors bug when author/editor field appears both in Required and Optional tabs.
+        - Fixed startup freeze when trying to load certain malformed bib files.
+        - Fixed bug related to multi-line fields in RIS import.
+        - Fixed bug related to looking up a fully qualified DOI
+        - Included review field to preview panel 1, which shows the abstract
+        - Fixed bug where booktitle field was not displayed in preview
+          for conference proceedings, similar to journal field
+        - By default preserve capitalization on the following fields: title;journal;booktitle;review;abstract
+1.8.1:  - Added automatic timestamp with configurable format for entries.
+        - Added new key generator modifier ":abbr" to abbreviate field contents.
+        - Added Help button in Preferences -> Entry preview
+        - Added Big5, Big5_HKSCS and GBK encodings for Chinese.
+        - Improved marking feature. Username is now used for marking, so different users can mark
+          entries separately without interference.
+        - Improved handling of names such as "Firstname de la Lastname jr.", with different handling
+          for presentation and sorting purposes. Key generation now should always use the genuine last
+          name, and not produce keys like "de2001".
+        - Removed duplicate warning from inspection dialog for non-selected entries.
+        - Fixed setting of sheet name in OpenOffice.org Calc export.
+        - Fixed bug that prevented PDF/PS opening by F4 from automatically finding files in
+          subdirectories below the main PDF/PS dir.
+        - Fixed BibTeX parser bug that made it choke on short comment strings.
+        - Fixed bug that made regexp search fail for fields containing newline characters.
+        - Fixed platform-dependent handling of newline characters.
+        - Fixed bug that prevented command line import with explicit format.
+        - Fixed bug that made it impossible to disable table antialiasing.
+        - Fixed AuthorAndsCommaReplacer.
+1.8:    - Search panel now starts visible if it was visible at last shutdown.
+        - Added option to disable import inspection window when only one entry is being imported.
+        - Fixed parser bug that caused problems for bib files containing extra characters after the
+          last entry.
+        - Fixed missing month in JStor import.
+	    - Fixed some bugs in "new from plain-text" wizard
+1.8b2:  - Changed handling of external updates so the notification is suppressed when there are
+          no actual changes.
+        - Changed autodetecting import so BibTeX files are handled more similarly to other formats.
+        - Enabled sorting by icon columns.
+        - Added option to remove BibTeX source panel from entry editor.
+        - Added command line option to not load any files at startup. Will override any autoloading
+          or other command line options that normally load or import files.
+        - Added handling of duplicates to import inspection window.
+        - Made entry preview be updated whenever the selection is expanded by one row, to make
+          it more useful while selecting a set of entries.
+        - Changed BibTeX field parsing to avoid inserting line breaks at wrong places.
+        - Improved handling of page numbers in Medline import.
+        - Fixed import of file links when importing SixPack files.
+        - Fixed bug that prevented closing of search interface when no databases are open.
+        - Fixed OpenOffice Calc export to be compatible with OpenOffice.org 2.0 beta.
+        - Fixed bugs in Refer/Endnote import filter. 
+        - Fixed bug that caused changes to be lost in some cases when the same field is present
+          in multiple entry editor tabs.
+        - Fixed bug that prevented command line autodetecting import from working with BibTeX files.
+        - Fixed minor bug in routine for removing double braces.
+1.8b:   - Added option to store bib file with double braces.
+        - Follow @input tags in aux files to indicate nested aux files for
+          generating subdatabases.
+        - Improved wrapping and formatting of bib files, to preserve paragraph separator (empty line).
+        - Added test buttons for customization of preview layouts.
+        - Added inspection dialog for previewing and generating keys for imported entries,
+          and deciding which ones to keep and discard. The dialog allows inspection during long import
+          processes such as Medline search.
+        - Restructured layout to use a common side pane with all tabs.
+        - Added import filter for Cambridge Scientific Abstracts (CSA) format.
+        - Added PS directory with similar options as PDF.
+	    - Added [authshort] and [edtrshort] key field markers. Patch submitted by
+	      Kolja Brix.
+        - Made the program remember preview enable setting.
+        - Improved handling of illegal regular expressions in search.
+        - Removed options to search only Required, Optional and/or General fields,
+          in order to simplify search interface.
+        - Changed keys for Next and Previous tab to CTRL-PGDN and CTRL-PGUP to match shortcuts in a
+          certain popular web browser.
+        - Minor change to Preferences -> Table columns to enable insertion of column in position 2.
+        - Fixed parser bug that caused problems for files with >10000 entries.
+        - Fixed bug in entry editor that caused the source edit panel to remove marking from entries.
+        - Fixed export bug that made "\begin" tags fail if encountered immediately after an "\end" tag. 
+        - Fixed export bug that made whitespace disappear after empty field values.
+        - Fixed ISI import bug that handled SO fields with line breaks wrong.
+        - Fixed bug occuring when choosing not to import duplicate imported entry.
+        - Fixed problem with detecting popup trigger on Mac OSX with one button mouse.
+        - Fixed erroneous relative paths for PDF files when PDF directory is not set.
+        - Fixed entry preview to resolve string references.
+1.7.1   - Removed unnecessary stack traces when opening external viewer.
+        - Fixed bug that made Ctrl-E destroy current edit in entry editor.
+        - Fixed problem when copying modified BibTeX key gave old value.
+        - Fixed missing 'booktitle' import in CONF entries in RIS import.
+        - Fixed bug that made group tree disappear for certain keyword expressions.
+        - Fixed bug that made standard BibTeX fields be saved without line wrapping.
+1.7     - When fetching from Medline or CiteSeer, fetched entry is now opened in editor.
+        - Added French translations of help files.
+        - Added color highlighting of focused text field in entry editor.
+        - Added option in context menu of entry editor for changing capitalization
+              of field contents.
+            - Added name conversion "Smith, RA" -> "Smith, R. A." to Medline import.
+            - Fixed bug that left some search settings items disabled when they shouldn't be.
+        - Fixed bug that caused requirement for restart to register change in default
+          key pattern.
+        - Fixed bug that caused crash some times after adding/removing field content selectors.
+        - Fixed bug in recognizing custom entry types when reading bib files.
+        - Fixed bug that allowed a deleted entry to stay visible in the entry editor.
+1.7b2:  - Made side pane resizable.
+        - Replaced entry customization dialog with improved interface.
+        - Added standard entry type "conference", similar to "inproceedings".
+        - Added default key pattern to avoid the need to set similar patterns manually.
+        - Added line wrapping to metadata in saved .bib file to avoid long lines.
+        - Added "bibtexkey" as implicit fourth sort criterion, to minimize problem with almost
+          similar entries swapping places.
+        - Added OpenOffice.org Calc export filter that exports spreadsheet compatible with the
+          OpenOffice.org bibliography feature.
+        - Added a couple of previously unsupported publication types in SciFinder.
+        - Added extra shortcuts CTRL-+ and CTRL-- for switching tabs in entry editor, since
+          original shortcuts CTRL[-SHIFT]-TAB is used by some window managers.
+        - Updated Endnote export filter.
+        - Fixed focus and key binding problems for switching tabs/entries in entry editor
+        - Fixed bug that prevented required fields tab from appearing for entries with only bibtex key
+          as required field.
+        - Fixed bug that prevented the user from changing the default encoding.
+        - Fixed bugs in RIS import.
+        - Fixed bug 1112050; freeze when reading certain author fields with mismatched braces.
+1.7b:	- Changed routine for rearranging author names (Lastname, Firstname) so bracketed
+            expressions are treated as units.
+        - Grouping controls now allow group hierarchies, and now allow explicit and search
+          expression groups as well as keyword groups.
+        - Added full customization of general fields tabs
+        - Added option to preserve formatting for non-BibTeX fields.
+        - Added integrity check for database.
+        - Added export filters EndNote and Harvard RTF.
+        - Added automatic import format chooser for import (same as wildcard import below).
+        - Added wildcard (*) option for command-line import, to try to automatically
+          determine the correct format.
+        - Improved layout of Preferences dialog.
+        - Improved several import filters.
+        - Added authIniN/edtrIniN key formatters.
+        - Marked entries now float to the top when no searching or grouping reordering is active.
+        - Fixed problem with opening file dialog on Win NT - AWT dialog is now opened if
+          Swing dialog fails.
+1.6:    - Improved handling of entry selection in various ways. E.g. selected entry is now scrolled
+          into view when opening entry editor and entry is kept selected when importing CiteSeer
+          fields.
+        - Fixed update bug between autogenerated bibtex key and source panel.
+        - Fixed missing . at the end of last author name in RIS import.
+        - Fixed NullPointerException on certain special characters when exporting to BibTeXML.
+        - Fixed bug that sometimes prevented the unmarking of entries.
+        - Fixed problem with formatting one-name authors.
+1.6b:	- Added mnemonic keys to menus and menu items.
+        - Added MODS and tab-separated file export
+        - Added facility for detecting and handling external changes to open bib files.
+        - Added scan option for exact duplicates with automatic removal.
+        - Bibtex strings are now sorted automatically.
+        - Bibtex strings are now resolved when exporting database.
+        - Fixed problem with field content selector getting too wide. Limited width.
+        - Fixed PDF/PS view routine to remove problems with filenames
+          containing spaces.
+        - Fixed bug that interfered with Fetch Medline by ID, and fixed
+          parsing problem with certain Medline entries.
+        - Fixed bug that interfered with Push to WinEdt.
+        - Fixed HTML output so \c{c} is handled correctly.
+        - command line option for generating a sub-database from LaTex aux file
+          entries
+        - simple copy/paste menu in entry editor
+        - experimental: text-input-area with underlying infotext in plaintext import dialog
+1.55:	- Made method for opening PDF files robust with regard to file separators (/ and \),
+          so bib files can easier be used across platforms.
+        - Improved Medline fetcher. Can now fetch entries based on a search expression.
+        - Added features for fetching fields and referring publications from the CiteSeer
+          database.
+        - Added option to always save database ordered by author/editor/year, and made this
+          the default setting.
+        - When a single entry is selected, right-click menu now shows a checkbox menu for group
+          memberships instead of the regular "Add to" and "Remove from" menus.
+        - Improved [shorttitle] and [veryshorttitle] special key pattern fields.
+        - Added dialog box for conveniently setting the fields of an entry from a
+          plain text description.
+        - Added formatter "ResolvePDF" to create correct PDF/PS links in HTML export when
+          relative file names are used.
+        - Added Abstract panel in entry editor.
+        - Added alternate preview with abstract, and made both previews configurable.
+        - Added the option to create a subset of a database based on an .aux file.
+        - Added 'Cancel' button to duplicate resolver dialog, so the process can be stopped.
+        - Added check for spaces in custom entry type names.
+        - Added several new key pattern markers.
+        - Added toolbar buttons for Mark/Unmark to improve discoverability.
+        - Fixed bug that made export filters ignore the chosen character encoding.
+        - Fixed bug that interfered with author name formatting.
+        - Fixed various bugs in import filters.
+        - Fixed bug that prevented confirmation dialog when deleting entry from the entry editor.
+        - Fixed bug that made the next entry be opened instead of the current, when pressing
+          Enter in table.
+        - Fixed bug that made it possible to leave a source edit when the source didn't validate
+          properly. Also made it impossible to change table selection until source validates.
+1.5:	- Enabled selection of default encoding, and started storing encoding information in
+          saved .bib files, which is used when reopening.
+        - Added Highlight and select options to the group interface, and made it possible
+            to change the number of visible lines in the list.
+              - Added option to allow or disallow direct table editing.
+        - Added optional confirmation dialog for deleting entries.
+              - Added optional warning dialog for duplicate BibTeX keys.
+        - Added warnings to bibtex parser, and prevented failure to load files with
+          duplicate string definitions.
+              - Added JStor import filter.
+        - Changed the look and feel to JGoodies Forms on non-Macintosh platforms.
+        - Optimized performance in several areas.
+        - Numerous usability improvements.
+        - Fixed RIS import bug caused by short lines.
+              - Fixed bug in SciFinder import.
+              - Fixed bug that made entire field get cleared when removing from group.
+1.4:	- Added advanced search feature.
+        - Added facility for using custom export formats.
+        - Added command line options for importing/exporting files, importing/exporting
+          user preferences, loading session and for suppressing the GUI (using RitOpt for
+          parsing options).
+        - Added automatic stripping of \url{} when opening url.
+        - Improved export filters.
+        - Fixed focus bug which sometimes interfered with cut/copy/paste.
+1.3.1:	- Bugfix.
+1.3:	- Added entry preview.
+        - Added detection of duplicate entries.
+              - Added possibility to mark entries persistently.
+        - Added import filter for Sixpack and Biblioscape Tag files.
+              - Added option to use a standard directory for PDFs. PDFs placed in or below this directory
+          and named after an entry's BibTeX key can be automatically found.
+            - Added optional columns showing clickable icons for pdf/ps and url/doi links.
+        - Added menu and toolbar actions for open pdf/ps and url/doi.
+        - Added web lookup of DOI.
+        - Added several new special field markers to the key autogenerator.
+              - Added BibTeXML and simple HTML export.
+              - Changed browsing of entries. Entry editor now shows the selected entry.
+              - Improved HTML export for several entry types.
+              - Improved compatibility with Mac OS X.
+        - Made it possible to set custom secondary and tertiary sort fields.
+        - Made the entry number column width customizable.
+              - Fixed bug that caused database to always be marked as changed after viewing source.
+               - Fixed bug in selector word removal.
+               - Fixed	bug that made the file chooser unable to interpret Mac OS X aliases.
+1.2:	- Replaced the icon set.
+        - Added support for French language.
+        - Added customization of key generation.
+        - Improved HTML export.
+        - Added Replace string feature.
+            - Made a couple of adaptations for Mac OS X users.
+        - Added option in Table Preferences to set current column widths as default.
+            - Added import filter for BibTeXML.
+        - Fixed bug that allowed non-lowercase grouping field, leading to problems.
+        - Fixed bug that made selector words added in the dialog to be lowercased.
+        - Fixed bug relating to translated help files.
+1.19:	- Entry editor is now opened for an entry that causes an error when saving.
+        - Added options to display names in harmonised format in the main table.
+        - Added Docbook and (experimental) HTML export.
+        - Enabled 'doi' and 'pii' fields for Medline import.
+        - Enabled antialiasing fonts.
+        - Added the Kunststoff look&feel to give a more pleasant user interface.
+        - Added font selector for the main table.
+        - Improved table column customization.
+        - Added word selector feature for selected fields (keywords, journal).
+        - Added support for German and Norwegian language.
+        - Generalized copy cite key features for multiple entries.
+        - Added quick load/save session feature.
+        - Fixed issue/number bug in ISI import.
+        - Added "Open pdf/ps" item in right-click menu.
+        - Fixed bug causing external viewer to only work in General fields.
+        - Added functionality for using Browse buttons for file-related fields
+          (ps, pdf, etc.).
+        - Added Browse buttons to External programs tab in Preferences.
+        - Fixed bug related to Save database and Source field which caused changes
+          to disappear.
+1.1:	- Added bibtex key uniqueness checking, and prevented autogeneration
+          from generating non-unique keys.
+        - Added command line option to load file on startup.
+        - Fixed problem with autogeneration creating invalid keys.
+        - Improved Refer/Endnote import.
+        - Added feature for importing entries and/or strings and/or group
+          definitions from another BibTeX database.
+        - Added menu choices to import into open database.
+              - Added toolbar button for closing current database.
+              - Fixed shortcut key for "Store field" in entry editor, and fixed
+                problem that made shortcut for "Save database" unavailable from
+          entry editor.
+        - Added option to fetch Medline entries automatically by
+          ID, based on a patch submitted by Mike Smoot.
+        - Fixed bug in RIS import.
+        - Added options to copy key and copy "\cite{key}" to right-click menu.
+        - Fixed bug that caused some General fields not to get displayed.
+        - Enabled customization of General fields.
+        - Enabled customization of existing entry types, and definition of
+          new types.
+1.0:	First release.
+
+
+Bug reports, suggestions, other feedback:
+We are thankful for any bug reports or other feedback. If there are
+features you want included in JabRef, tell us!
+
+
+JabRef homepage:
+http://jabref.sourceforge.net
+
+You can always get the very latest version of the program from our CVS
+repository; instructions for downloading are found on the
+homepage. Note that the CVS version may contain untested features, or
+have other stability issues. Unless you're feeling extremely lucky, go
+for the version in the HEAD branch of the module 'jabref'.
+
+
+Bug submission and Open Discussions and Help forums are found at:
+http://sourceforge.net/projects/jabref
+
+
+Corresponding authors:
+mortenalver _ users.sourceforge.net
+nbatada _ users.sourceforge.net
diff --git a/src/txt/apache-license.txt b/src/txt/apache-license.txt
new file mode 100644
index 0000000..06b8fa5
--- /dev/null
+++ b/src/txt/apache-license.txt
@@ -0,0 +1,62 @@
+/*
+ * $Header: /cvsroot/jabref/jabref/src/txt/apache-license.txt,v 1.1 2004/12/11 23:18:30 mortenalver Exp $
+ * $Revision: 1.1 $
+ * $Date: 2004/12/11 23:18:30 $
+ *
+ * ====================================================================
+ *
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 1999-2003 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ *    any, must include the following acknowlegement:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowlegement may appear in the software itself,
+ *    if and wherever such third-party acknowlegements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ *    Foundation" must not be used to endorse or promote products derived
+ *    from this software without prior written permission. For written
+ *    permission, please contact apache at apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ *    nor may "Apache" appear in their names without prior written
+ *    permission of the Apache Group.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ * [Additional notices, if required by prior licensing conditions]
+ *
+ */
diff --git a/src/txt/cpl-v10.html b/src/txt/cpl-v10.html
new file mode 100644
index 0000000..36aa208
--- /dev/null
+++ b/src/txt/cpl-v10.html
@@ -0,0 +1,125 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
+<HTML>
+<HEAD>
+<TITLE>Common Public License - v 1.0</TITLE>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+</HEAD>
+
+<BODY BGCOLOR="#FFFFFF" VLINK="#800000">
+
+
+<P ALIGN="CENTER"><B>Common Public License - v 1.0</B>
+<P><B></B><FONT SIZE="3"></FONT>
+<P><FONT SIZE="3"></FONT><FONT SIZE="2">THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT").  ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.</FONT>
+<P><FONT SIZE="2"></FONT>
+<P><FONT SIZE="2"><B>1.  DEFINITIONS</B></FONT>
+<P><FONT SIZE="2">"Contribution" means:</FONT>
+
+<UL><FONT SIZE="2">a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and<BR CLEAR="LEFT">
+b) in the case of each subsequent Contributor:</FONT></UL>
+
+
+<UL><FONT SIZE="2">i)	 	changes to the Program, and</FONT></UL>
+
+
+<UL><FONT SIZE="2">ii)		additions to the Program;</FONT></UL>
+
+
+<UL><FONT SIZE="2">where such changes and/or additions to the Program originate from and are distributed by that particular Contributor.  </FONT><FONT SIZE="2">A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf.  </FONT><FONT SIZE="2">Contributions do not include additions to the Program which:  (i) are separate modules of software distributed in conjunction with the Program under their ow [...]
+
+<P><FONT SIZE="2"></FONT>
+<P><FONT SIZE="2">"Contributor" means any person or entity that distributes the Program.</FONT>
+<P><FONT SIZE="2"></FONT><FONT SIZE="2"></FONT>
+<P><FONT SIZE="2">"Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program.  </FONT>
+<P><FONT SIZE="2"></FONT><FONT SIZE="2"></FONT>
+<P><FONT SIZE="2"></FONT><FONT SIZE="2">"Program" means the Contributions distributed in accordance with this Agreement.</FONT>
+<P><FONT SIZE="2"></FONT>
+<P><FONT SIZE="2">"Recipient" means anyone who receives the Program under this Agreement, including all Contributors.</FONT>
+<P><FONT SIZE="2"><B></B></FONT>
+<P><FONT SIZE="2"><B>2.  GRANT OF RIGHTS</B></FONT>
+
+<UL><FONT SIZE="2"></FONT><FONT SIZE="2">a)	</FONT><FONT SIZE="2">Subject to the terms of this Agreement, each Contributor hereby grants</FONT><FONT SIZE="2"> Recipient a non-exclusive, worldwide, royalty-free copyright license to</FONT><FONT SIZE="2" COLOR="#FF0000"> </FONT><FONT SIZE="2">reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object  [...]
+
+
+<UL><FONT SIZE="2"></FONT></UL>
+
+
+<UL><FONT SIZE="2"></FONT><FONT SIZE="2">b) 	Subject to the terms of this Agreement, each Contributor hereby grants </FONT><FONT SIZE="2">Recipient a non-exclusive, worldwide,</FONT><FONT SIZE="2" COLOR="#008000"> </FONT><FONT SIZE="2">royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form.  This patent license shall apply to the combination of th [...]
+
+
+<UL><FONT SIZE="2"></FONT></UL>
+
+
+<UL><FONT SIZE="2">c)	Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity.  Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise.  As a condition to exercising the rights and  [...]
+
+
+<UL><FONT SIZE="2"></FONT></UL>
+
+
+<UL><FONT SIZE="2">d)	Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. </FONT></UL>
+
+
+<UL><FONT SIZE="2"></FONT></UL>
+
+<P><FONT SIZE="2"><B>3.  REQUIREMENTS</B></FONT>
+<P><FONT SIZE="2"><B></B>A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that:</FONT>
+
+<UL><FONT SIZE="2">a)	it complies with the terms and conditions of this Agreement; and</FONT></UL>
+
+
+<UL><FONT SIZE="2">b)	its license agreement:</FONT></UL>
+
+
+<UL><FONT SIZE="2">i)	effectively disclaims</FONT><FONT SIZE="2"> on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; </FONT></UL>
+
+
+<UL><FONT SIZE="2">ii) 	effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; </FONT></UL>
+
+
+<UL><FONT SIZE="2">iii)</FONT><FONT SIZE="2">	states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and</FONT></UL>
+
+
+<UL><FONT SIZE="2">iv)	states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange.</FONT><FONT SIZE="2" COLOR="#0000FF"> </FONT><FONT SIZE="2" COLOR="#FF0000"></FONT></UL>
+
+
+<UL><FONT SIZE="2" COLOR="#FF0000"></FONT><FONT SIZE="2"></FONT></UL>
+
+<P><FONT SIZE="2">When the Program is made available in source code form:</FONT>
+
+<UL><FONT SIZE="2">a)	it must be made available under this Agreement; and </FONT></UL>
+
+
+<UL><FONT SIZE="2">b)	a copy of this Agreement must be included with each copy of the Program.  </FONT></UL>
+
+<P><FONT SIZE="2"></FONT><FONT SIZE="2" COLOR="#0000FF"><STRIKE></STRIKE></FONT>
+<P><FONT SIZE="2" COLOR="#0000FF"><STRIKE></STRIKE></FONT><FONT SIZE="2">Contributors may not remove or alter any copyright notices contained within the Program.  </FONT>
+<P><FONT SIZE="2"></FONT>
+<P><FONT SIZE="2">Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution.  </FONT>
+<P><FONT SIZE="2"></FONT>
+<P><FONT SIZE="2"><B>4.  COMMERCIAL DISTRIBUTION</B></FONT>
+<P><FONT SIZE="2">Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like.  While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors.   Therefore, if a Contributor includes the Program in a commercial product offering, such Contrib [...]
+<P><FONT SIZE="2"></FONT>
+<P><FONT SIZE="2">For example, a Contributor might include the Program in a commercial product offering, Product X.  That Contributor is then a Commercial Contributor.  If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone.  Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to thos [...]
+<P><FONT SIZE="2"></FONT><FONT SIZE="2" COLOR="#0000FF"></FONT>
+<P><FONT SIZE="2" COLOR="#0000FF"></FONT><FONT SIZE="2"><B>5.  NO WARRANTY</B></FONT>
+<P><FONT SIZE="2">EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is</FONT><FONT SIZE="2"> solely responsible for determining the appropriateness of using and distributing </FONT><FONT SIZE="2">the Program</FONT><FONT  [...]
+<P><FONT SIZE="2"></FONT>
+<P><FONT SIZE="2"></FONT><FONT SIZE="2"><B>6.  DISCLAIMER OF LIABILITY</B></FONT>
+<P><FONT SIZE="2"></FONT><FONT SIZE="2">EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES </FONT><FONT SIZE="2">(INCLUDING WITHOUT LIMITATION LOST PROFITS),</FONT><FONT SIZE="2"> HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR  [...]
+<P><FONT SIZE="2"></FONT><FONT SIZE="2"></FONT>
+<P><FONT SIZE="2"><B>7.  GENERAL</B></FONT>
+<P><FONT SIZE="2"></FONT><FONT SIZE="2">If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable.</FONT>
+<P><FONT SIZE="2"></FONT>
+<P><FONT SIZE="2">If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed.  In addition, if Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program i [...]
+<P><FONT SIZE="2"></FONT>
+<P><FONT SIZE="2">All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance.  If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable.  However, Recipient's obligations under this Agreement and any lice [...]
+<P><FONT SIZE="2"></FONT>
+<P><FONT SIZE="2"></FONT><FONT SIZE="2">Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted  and may only be modified in the following manner. The Agreement Steward reserves the right to </FONT><FONT SIZE="2">publish new versions (including revisions) of this Agreement from time to </FONT><FONT SIZE="2">time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initia [...]
+<P><FONT SIZE="2"></FONT>
+<P><FONT SIZE="2">This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose.  Each party waives its rights to a jury trial in any resulting litigation.</FONT>
+<P><FONT SIZE="2"></FONT><FONT SIZE="2"></FONT>
+<P><FONT SIZE="2"></FONT>
+
+</BODY>
+
+</HTML>
\ No newline at end of file
diff --git a/src/txt/gpl.txt b/src/txt/gpl.txt
new file mode 100755
index 0000000..5b6e7c6
--- /dev/null
+++ b/src/txt/gpl.txt
@@ -0,0 +1,340 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                       59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+

+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+

+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+

+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+

+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+

+	    How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    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
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/src/txt/lesser.txt b/src/txt/lesser.txt
new file mode 100644
index 0000000..b1e3f5a
--- /dev/null
+++ b/src/txt/lesser.txt
@@ -0,0 +1,504 @@
+		  GNU LESSER GENERAL PUBLIC LICENSE
+		       Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL.  It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+  This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it.  You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+  When we speak of free software, we are referring to freedom of use,
+not price.  Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+  To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights.  These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+  For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you.  You must make sure that they, too, receive or can get the source
+code.  If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it.  And you must show them these terms so they know their rights.
+
+  We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+  To protect each distributor, we want to make it very clear that
+there is no warranty for the free library.  Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+

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

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

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

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

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

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

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

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

+           How to Apply These Terms to Your New Libraries
+
+  If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change.  You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+  To apply these terms, attach the following notices to the library.  It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the library's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the
+  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+  <signature of Ty Coon>, 1 April 1990
+  Ty Coon, President of Vice
+
+That's all there is to it!
+
+
diff --git a/src/windows/JabRef-Logo.gif b/src/windows/JabRef-Logo.gif
new file mode 100644
index 0000000..89fefc4
Binary files /dev/null and b/src/windows/JabRef-Logo.gif differ
diff --git a/src/windows/jabref.jsmooth b/src/windows/jabref.jsmooth
new file mode 100644
index 0000000..0d81dad
--- /dev/null
+++ b/src/windows/jabref.jsmooth
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<jsmoothproject>
+<JVMSearchPath>registry</JVMSearchPath>
+<JVMSearchPath>javahome</JVMSearchPath>
+<JVMSearchPath>jrepath</JVMSearchPath>
+<JVMSearchPath>jdkpath</JVMSearchPath>
+<JVMSearchPath>exepath</JVMSearchPath>
+<JVMSearchPath>jview</JVMSearchPath>
+<classPath>jabref.jar</classPath>
+<currentDirectory>.</currentDirectory>
+<embeddedJar>false</embeddedJar>
+<executableName>jabref.exe</executableName>
+<iconLocation>JabRef-Logo.gif</iconLocation>
+<initialMemoryHeap>-1</initialMemoryHeap>
+<mainClassName>net.sf.jabref.JabRef</mainClassName>
+<maximumMemoryHeap>-1</maximumMemoryHeap>
+<maximumVersion></maximumVersion>
+<minimumVersion>1.4.0</minimumVersion>
+<skeletonName>Windowed Wrapper</skeletonName>
+<skeletonProperties>
+<key>Message</key>
+<value>Java has not been found on your computer. Do you want to download it?</value>
+</skeletonProperties>
+<skeletonProperties>
+<key>URL</key>
+<value>http://www.java.com</value>
+</skeletonProperties>
+<skeletonProperties>
+<key>SingleProcess</key>
+<value>0</value>
+</skeletonProperties>
+<skeletonProperties>
+<key>Debug</key>
+<value>0</value>
+</skeletonProperties>
+</jsmoothproject>
diff --git a/src/windows/jabref.wxs b/src/windows/jabref.wxs
new file mode 100644
index 0000000..ba4ea14
--- /dev/null
+++ b/src/windows/jabref.wxs
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Wix xmlns="http://schemas.microsoft.com/wix/2003/01/wi">
+    <Product Name="JabRef 1.8.1" Id="118b0801-c924-4071-a0ab-6ec9844cc55a"
+            Version="1.8.1" Manufacturer="http://jabref.sf.net/"
+            Language="1033">
+        <Package Id="????????-????-????-????-????????????"
+                Comments="This MSI file installs JabRef."
+                Manufacturer="http://jabref.sf.net/" InstallerVersion="200"
+                Languages="1033" Compressed="yes"/>
+        <Media Id="1" EmbedCab="yes" Cabinet="JabRef.cab"/>
+        <Directory Id="TARGETDIR" Name="SourceDir">
+            <Directory Id="ProgramFilesFolder" Name="PFiles">
+                <Directory Id="JabRefDir" Name="JabRef" LongName="JabRef 1.8.1">
+                        <Component Id="Libraries"
+                                Guid="6922b877-d0ea-4c52-a2b4-1e1339c398f5">
+                            <File Id="jabrefjar" Name="JabRef.jar" LongName="jabref.jar" DiskId="1" src="jabref.jar" />
+                        </Component>
+                        <Component Id="Executables"
+                                Guid="bed93d86-d9c3-4c02-8cca-dfc7977b31a7">
+                            <File Id="jabref.exe" Name="JabRef.exe" DiskId="1"
+                                    src="jabref.exe">
+                                <Shortcut Id="shortcut"
+                                        Directory="ProgramMenuFolder" Name="JabRef"
+                                        LongName="JabRef 1.8.1"
+                                        Show="normal"
+                                        WorkingDirectory="TARGETDIR"/>
+                            </File>
+                        </Component>
+                </Directory>
+            </Directory>
+            <Directory Id="ProgramMenuFolder" Name="PMFolder"></Directory>
+        </Directory>
+        <Feature Id="DefaultFeature" Level="1">
+            <ComponentRef Id="Libraries"/>
+            <ComponentRef Id="Executables"/>
+        </Feature>
+    </Product>
+</Wix>
\ No newline at end of file

-- 
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