de40261ddd5dc4352fb61a36dfd7bf97574104a7
[debian/jabref.git] / src / java / net / sf / jabref / JabRef.java
1 /*
2  * Copyright (C) 2003 Morten O. Alver, Nizar N. Batada
3  * 
4  * All programs in this directory and subdirectories are published under the GNU
5  * General Public License as described below.
6  *
7  * This program is free software; you can redistribute it and/or modify it under
8  * the terms of the GNU General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option) any later
10  * version.
11  *
12  * This program is distributed in the hope that it will be useful, but WITHOUT
13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
15  * details.
16  *
17  * You should have received a copy of the GNU General Public License along with
18  * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
19  * Place, Suite 330, Boston, MA 02111-1307 USA
20  *
21  * Further information about the GNU GPL is available at:
22  * http://www.gnu.org/copyleft/gpl.ja.html
23  *
24  */
25 package net.sf.jabref;
26
27 import gnu.dtools.ritopt.BooleanOption;
28 import gnu.dtools.ritopt.Options;
29 import gnu.dtools.ritopt.StringOption;
30
31 import java.awt.Dimension;
32 import java.awt.Font;
33 import java.awt.Frame;
34 import java.awt.event.KeyEvent;
35 import java.io.File;
36 import java.io.FileNotFoundException;
37 import java.io.IOException;
38 import java.util.Collection;
39 import java.util.List;
40 import java.util.Vector;
41
42 import javax.swing.InputMap;
43 import javax.swing.JOptionPane;
44 import javax.swing.KeyStroke;
45 import javax.swing.LookAndFeel;
46 import javax.swing.UIDefaults;
47 import javax.swing.UIManager;
48 import javax.swing.plaf.metal.MetalLookAndFeel;
49
50 import net.sf.jabref.export.ExportFormats;
51 import net.sf.jabref.export.FileActions;
52 import net.sf.jabref.export.IExportFormat;
53 import net.sf.jabref.export.SaveException;
54 import net.sf.jabref.export.SaveSession;
55 import net.sf.jabref.imports.EntryFetcher;
56 import net.sf.jabref.imports.ImportInspectionCommandLine;
57 import net.sf.jabref.imports.OpenDatabaseAction;
58 import net.sf.jabref.imports.ParserResult;
59 import net.sf.jabref.plugin.PluginCore;
60 import net.sf.jabref.plugin.SidePanePlugin;
61 import net.sf.jabref.plugin.core.JabRefPlugin;
62 import net.sf.jabref.plugin.core.generated._JabRefPlugin;
63 import net.sf.jabref.plugin.core.generated._JabRefPlugin.EntryFetcherExtension;
64 import net.sf.jabref.remote.RemoteListener;
65 import net.sf.jabref.util.Pair;
66 import net.sf.jabref.wizard.auximport.AuxCommandLine;
67
68 import com.jgoodies.looks.FontPolicies;
69 import com.jgoodies.looks.FontPolicy;
70 import com.jgoodies.looks.FontSet;
71 import com.jgoodies.looks.FontSets;
72 import com.jgoodies.looks.plastic.Plastic3DLookAndFeel;
73 import com.jgoodies.looks.windows.WindowsLookAndFeel;
74
75 /**
76  * JabRef Main Class - The application gets started here.
77  *
78  */
79 public class JabRef {
80     
81         public static JabRef singleton;
82     public static RemoteListener remoteListener = null;
83     public JabRefFrame jrf;
84     public Options options;
85     public Frame splashScreen = null;
86
87     boolean graphicFailure = false;
88
89     StringOption importFile, exportFile, exportPrefs, importPrefs, auxImExport, importToOpenBase, fetcherEngine;
90     BooleanOption helpO, disableGui, blank, loadSess, showVersion, disableSplash;
91     
92     public static void main(String[] args) {
93         new JabRef(args);
94     }
95
96     protected JabRef(String[] args) {
97
98                 singleton = this;
99
100                 // The following two lines signal that the system proxy settings should
101                 // be used:
102                 System.setProperty("java.net.useSystemProxies", "true");
103                 System.getProperties().put("proxySet", "true");
104
105                 JabRefPreferences prefs = JabRefPreferences.getInstance();
106                 Globals.prefs = prefs;
107                 Globals.setLanguage(prefs.get("language"), "");
108
109                 /*
110                  * The Plug-in System is started automatically on the first call to
111                  * PluginCore.getManager().
112                  * 
113                  * Plug-ins are activated on the first call to their getInstance method.
114                  */
115                 
116                 /* Build list of Import and Export formats */
117                 Globals.importFormatReader.resetImportFormats();
118                 BibtexEntryType.loadCustomEntryTypes(prefs);
119                 ExportFormats.initAllExports();
120                 
121                 // Read list(s) of journal names and abbreviations:
122                 Globals.initializeJournalNames();
123
124                 // Check for running JabRef
125                 if (Globals.prefs.getBoolean("useRemoteServer")) {
126                         remoteListener = RemoteListener.openRemoteListener(this);
127
128                         if (remoteListener == null) {
129                                 // Unless we are alone, try to contact already running JabRef:
130                                 if (RemoteListener.sendToActiveJabRefInstance(args)) {
131
132                                         /*
133                                          * We have successfully sent our command line options
134                                          * through the socket to another JabRef instance. So we
135                                          * assume it's all taken care of, and quit.
136                                          */
137                                         System.out
138                                                         .println(Globals
139                                                                         .lang("Arguments passed on to running JabRef instance. Shutting down."));
140                                         System.exit(0);
141                                 }
142                         } else {
143                                 // No listener found, thus we are the first instance to be
144                                 // started.
145                                 remoteListener.start();
146                         }
147                 }
148
149                 /*
150                  * See if the user has a personal journal list set up. If so, add these
151                  * journal names and abbreviations to the list:
152                  */
153                 String personalJournalList = prefs.get("personalJournalList");
154                 if (personalJournalList != null) {
155                         try {
156                                 Globals.journalAbbrev.readJournalList(new File(
157                                                 personalJournalList));
158                         } catch (FileNotFoundException e) {
159                                 e.printStackTrace();
160                         }
161                 }
162
163                 /*
164                  * Make sure of a proper cleanup when quitting (e.g. deleting temporary
165                  * files).
166                  * 
167                  * CO 2007-07-12: Since this is deprecated, commented out:
168                  * 
169                  * System.runFinalizersOnExit(true);
170                  * 
171                  */
172                 
173                 openWindow(processArguments(args, true));
174         }
175
176     private void setupOptions() {
177
178         importFile = new StringOption("");
179         exportFile = new StringOption("");
180         helpO = new BooleanOption();
181         disableGui = new BooleanOption();
182         disableSplash = new BooleanOption();
183         blank = new BooleanOption();
184         loadSess = new BooleanOption();
185         showVersion = new BooleanOption();
186         exportPrefs = new StringOption("jabref_prefs.xml");
187         importPrefs = new StringOption("jabref_prefs.xml");
188         auxImExport = new StringOption("");
189         importToOpenBase = new StringOption("");
190         fetcherEngine = new StringOption("");
191
192         options = new Options("JabRef "); // Create an options repository.
193         options.setVersion(GUIGlobals.version);
194
195         importFile.setDescription("imopoepuoeu"); //Globals.lang);
196         options.register("version", 'v',
197                 Globals.lang("Display version"), showVersion);
198         options.register("nogui", 'n',
199             Globals.lang("No GUI. Only process command line options."), disableGui);
200         options.register("nosplash", 's',
201                 Globals.lang("Do not show splash window at startup"), disableSplash);
202         options.register("import", 'i',
203             Globals.lang("Import file") + ": " + Globals.lang("filename")
204             + "[,import format]", importFile);
205         options.register("output", 'o',
206             Globals.lang("Output or export file") + ": " + Globals.lang("filename")
207             + "[,export format]", exportFile);
208         options.register("help", 'h',
209             Globals.lang("Display help on command line options"), helpO);
210         options.register("loads", 'l', Globals.lang("Load session"), loadSess);
211         options.register("prexp", 'x', Globals.lang("Export preferences to file"),
212             exportPrefs);
213         options.register("primp", 'p', Globals.lang("Import preferences from file"),
214             importPrefs);
215         options.register("aux", 'a',
216             Globals.lang("Subdatabase from aux") + ": " + Globals.lang("file")+"[.aux]" + ","+Globals.lang("new")+"[.bib]",
217             auxImExport);
218         options.register("blank", 'b', Globals.lang("Do not open any files at startup"), blank);
219
220         options.register("importToOpen", '\0', Globals.lang("Import to open tab"), importToOpenBase);
221
222         options.register("fetch", 'f', Globals.lang("Run Fetcher, e.g. \"--fetch=Medline:cancer\""), fetcherEngine);
223
224         options.setUseMenu(false);
225     }
226
227     public Vector<ParserResult> processArguments(String[] args, boolean initialStartup) {
228
229         setupOptions();
230         String[] leftOver = options.process(args);
231
232         if (initialStartup && showVersion.isInvoked()) {
233             options.displayVersion();
234             disableGui.setInvoked(true);
235         }
236
237         if (initialStartup && helpO.isInvoked()) {
238             System.out.println("jabref [options] [bibtex-file]\n");
239             System.out.println(options.getHelp());
240
241             String importFormats = Globals.importFormatReader.getImportFormatList();
242             System.out.println(Globals.lang("Available import formats") + ":\n"
243                 + importFormats);
244
245             String outFormats = ExportFormats.getConsoleExportList(70, 20, "\t");
246             System.out.println(Globals.lang("Available export formats") + ": " + outFormats
247                 + ".");
248             System.exit(0);
249         }
250         
251         boolean commandmode = disableGui.isInvoked() || fetcherEngine.isInvoked();
252         
253         // First we quickly scan the command line parameters for any that signal
254         // that the GUI
255         // should not be opened. This is used to decide whether we should show the
256         // splash screen or not.
257         if (initialStartup && !commandmode && !disableSplash.isInvoked()) {
258             try {
259                 splashScreen = SplashScreen.splash();
260             } catch (Throwable ex) {
261                 graphicFailure = true;
262                 System.err.println(Globals.lang("Unable to create graphical interface")
263                     + ".");
264             }
265         }
266
267         // Vector to put imported/loaded database(s) in.
268         Vector<ParserResult> loaded = new Vector<ParserResult>();
269         Vector<String> toImport = new Vector<String>();
270         if (!blank.isInvoked() && (leftOver.length > 0))  {
271             for (int i = 0; i < leftOver.length; i++) {
272                 // Leftover arguments that have a "bib" extension are interpreted as
273                 // bib files to open. Other files, and files that could not be opened
274                 // as bib, we try to import instead.
275                 boolean bibExtension = leftOver[i].toLowerCase().endsWith("bib");
276                 ParserResult pr = null;
277                 if (bibExtension)
278                     pr = openBibFile(leftOver[i]);
279
280                 if ((pr == null) || (pr == ParserResult.INVALID_FORMAT)) {
281                     // We will try to import this file. Normally we
282                     // will import it into a new tab, but if this import has
283                     // been initiated by another instance through the remote
284                     // listener, we will instead import it into the current database.
285                     // This will enable easy integration with web browers that can
286                     // open a reference file in JabRef.
287                     if (initialStartup) {
288                         toImport.add(leftOver[i]);
289                     } else {
290                         ParserResult res = importToOpenBase(leftOver[i]);
291                         if (res != null)
292                             loaded.add(res);
293                     }
294                 }
295                 else
296                     loaded.add(pr);
297
298             }
299         }
300
301         if (!blank.isInvoked() && importFile.isInvoked()) {
302             toImport.add(importFile.getStringValue());
303         }
304
305         for (String filenameString : toImport) {
306                         ParserResult pr = importFile(filenameString);
307                         if (pr != null)
308                                 loaded.add(pr);
309                 }
310
311         if (!blank.isInvoked() && importToOpenBase.isInvoked()) {
312             ParserResult res = importToOpenBase(importToOpenBase.getStringValue());
313             if (res != null)
314                 loaded.add(res);
315         }
316
317         if (!blank.isInvoked() && fetcherEngine.isInvoked()) {
318             ParserResult res = fetch(fetcherEngine.getStringValue());
319             if (res != null)
320                 loaded.add(res);
321         }
322
323         if (exportFile.isInvoked()) {
324             if (loaded.size() > 0) {
325                 String[] data = exportFile.getStringValue().split(",");
326
327                 if (data.length == 1) {
328                     // This signals that the latest import should be stored in BibTeX
329                     // format to the given file.
330                     if (loaded.size() > 0) {
331                         ParserResult pr =
332                             loaded.elementAt(loaded.size() - 1);
333
334                         try {
335                             System.out.println(Globals.lang("Saving") + ": " + data[0]);
336                             SaveSession session = FileActions.saveDatabase(pr.getDatabase(),
337                                 new MetaData(pr.getMetaData(),pr.getDatabase()), new File(data[0]), Globals.prefs,
338                                 false, false, Globals.prefs.get("defaultEncoding"));
339                             // Show just a warning message if encoding didn't work for all characters:
340                             if (!session.getWriter().couldEncodeAll())
341                                 System.err.println(Globals.lang("Warning")+": "+
342                                     Globals.lang("The chosen encoding '%0' could not encode the following characters: ",
343                                     session.getEncoding())+session.getWriter().getProblemCharacters());
344                             session.commit();
345                         } catch (SaveException ex) {
346                             System.err.println(Globals.lang("Could not save file") + " '"
347                                 + data[0] + "': " + ex.getMessage());
348                         }
349                     } else
350                         System.err.println(Globals.lang(
351                                 "The output option depends on a valid import option."));
352                 } else if (data.length == 2) {
353                     // This signals that the latest import should be stored in the given
354                     // format to the given file.
355                     ParserResult pr = loaded.elementAt(loaded.size() - 1);
356
357                     // Set the global variable for this database's file directory before exporting,
358                     // so formatters can resolve linked files correctly.
359                     // (This is an ugly hack!)
360                     MetaData metaData = new MetaData(pr.getMetaData(), pr.getDatabase());
361                     metaData.setFile(pr.getFile());
362                     Globals.prefs.fileDirForDatabase = metaData.getFileDirectory(GUIGlobals.FILE_FIELD);
363                     System.out.println(Globals.lang("Exporting") + ": " + data[0]);
364                     IExportFormat format = ExportFormats.getExportFormat(data[1]);
365                     if (format != null) {
366                         // We have an ExportFormat instance:
367                         try {
368                             format.performExport(pr.getDatabase(), 
369                                     new MetaData(pr.getMetaData(), pr.getDatabase()),
370                                     data[0], pr.getEncoding(), null);
371                         } catch (Exception ex) {
372                             System.err.println(Globals.lang("Could not export file")
373                                 + " '" + data[0] + "': " + ex.getMessage());
374                         }
375                     }
376                     else
377                         System.err.println(Globals.lang("Unknown export format")
378                                 + ": " + data[1]);
379
380                 }
381             } else
382                 System.err.println(Globals.lang(
383                         "The output option depends on a valid import option."));
384         }
385
386         //Util.pr(": Finished export");
387
388         if (exportPrefs.isInvoked()) {
389             try {
390                 Globals.prefs.exportPreferences(exportPrefs.getStringValue());
391             } catch (IOException ex) {
392                 Util.pr(ex.getMessage());
393             }
394         }
395
396
397         if (importPrefs.isInvoked()) {
398             try {
399                 Globals.prefs.importPreferences(importPrefs.getStringValue());
400                 BibtexEntryType.loadCustomEntryTypes(Globals.prefs);
401             }
402             catch (IOException ex) {
403                 Util.pr(ex.getMessage());
404             }
405         }
406
407         if (!blank.isInvoked() && auxImExport.isInvoked()) {
408             boolean usageMsg = false;
409
410             if (loaded.size() > 0) // bibtex file loaded
411              {
412                 String[] data = auxImExport.getStringValue().split(",");
413
414                 if (data.length == 2) {
415                     ParserResult pr = loaded.firstElement();
416                     AuxCommandLine acl = new AuxCommandLine(data[0], pr.getDatabase());
417                     BibtexDatabase newBase = acl.perform();
418
419                     boolean notSavedMsg = false;
420
421                     // write an output, if something could be resolved
422                     if (newBase != null) {
423                         if (newBase.getEntryCount() > 0) {
424                             String subName = Util.getCorrectFileName(data[1], "bib");
425
426                             try {
427                                 System.out.println(Globals.lang("Saving") + ": "
428                                     + subName);
429                                 SaveSession session = FileActions.saveDatabase(newBase, new MetaData(), // no Metadata
430                                     new File(subName), Globals.prefs, false, false,
431                                     Globals.prefs.get("defaultEncoding"));
432                                 // Show just a warning message if encoding didn't work for all characters:
433                                 if (!session.getWriter().couldEncodeAll())
434                                     System.err.println(Globals.lang("Warning")+": "+
435                                         Globals.lang("The chosen encoding '%0' could not encode the following characters: ",
436                                         session.getEncoding())+session.getWriter().getProblemCharacters());
437                                 session.commit();
438                             } catch (SaveException ex) {
439                                 System.err.println(Globals.lang("Could not save file")
440                                     + " '" + subName + "': " + ex.getMessage());
441                             }
442
443                             notSavedMsg = true;
444                         }
445                     }
446
447                     if (!notSavedMsg)
448                         System.out.println(Globals.lang("no database generated"));
449                 } else
450                     usageMsg = true;
451             } else
452                 usageMsg = true;
453
454             if (usageMsg) {
455                 System.out.println(Globals.lang("no base-bibtex-file specified"));
456                 System.out.println(Globals.lang("usage") + " :");
457                 System.out.println(
458                     "jabref --aux infile[.aux],outfile[.bib] base-bibtex-file");
459             }
460         }
461
462         return loaded;
463     }
464
465     /**
466      * Run an entry fetcher from the command line.
467      * 
468      * Note that this only works headlessly if the EntryFetcher does not show
469      * any GUI.
470      * 
471      * @param fetchCommand
472      *            A string containing both the fetcher to use (id of
473      *            EntryFetcherExtension minus Fetcher) and the search query,
474      *            separated by a :
475      * @return A parser result containing the entries fetched or null if an
476      *         error occurred.
477      */
478     protected ParserResult fetch(String fetchCommand) {
479
480         if (fetchCommand == null || !fetchCommand.contains(":") ||
481             fetchCommand.split(":").length != 2) {
482             System.out.println(Globals.lang("Expected syntax for --fetch='<name of fetcher>:<query>'"));
483             System.out.println(Globals.lang("The following fetchers are available:"));
484             for (EntryFetcherExtension e : JabRefPlugin.getInstance(PluginCore.getManager())
485                 .getEntryFetcherExtensions()) {
486                 System.out.println("  " + e.getId().replaceAll("Fetcher", "").toLowerCase());
487             }
488             return null;
489         }
490
491         String engine = fetchCommand.split(":")[0];
492         String query = fetchCommand.split(":")[1];
493
494         EntryFetcher fetcher = null;
495         for (EntryFetcherExtension e : JabRefPlugin.getInstance(PluginCore.getManager())
496             .getEntryFetcherExtensions()) {
497             if (engine.toLowerCase().equals(e.getId().replaceAll("Fetcher", "").toLowerCase()))
498                 fetcher = e.getEntryFetcher();
499         }
500
501         if (fetcher == null) {
502             System.out.println(Globals.lang("Could not find fetcher '%0'", engine));
503             System.out.println(Globals.lang("The following fetchers are available:"));
504             for (EntryFetcherExtension e : JabRefPlugin.getInstance(PluginCore.getManager())
505                 .getEntryFetcherExtensions()) {
506                 System.out.println("  " + e.getId().replaceAll("Fetcher", "").toLowerCase());
507             }
508             return null;
509         }
510
511         System.out.println(Globals.lang("Running Query '%0' with fetcher '%1'.", query, engine) +
512             " " + Globals.lang("Please wait!"));
513         Collection<BibtexEntry> result = new ImportInspectionCommandLine().query(query, fetcher);
514
515         if (result == null || result.size() == 0) {
516             System.out.println(Globals.lang(
517                 "Query '%0' with fetcher '%1' did not return any results.", query, engine));
518             return null;
519         }
520
521         return new ParserResult(result);
522     }
523
524         public void openWindow(Vector<ParserResult> loaded) {
525         if (!graphicFailure && !disableGui.isInvoked()) {
526             // Call the method performCompatibilityUpdate(), which does any
527             // necessary changes for users with a preference set from an older
528             // Jabref version.
529             Util.performCompatibilityUpdate();
530
531
532             // Set up custom or default icon theme:
533             GUIGlobals.setUpIconTheme();
534
535             // TODO: remove temporary registering of external file types?
536             Globals.prefs.updateExternalFileTypes();
537
538            // This property is set to make the Mac OSX Java VM move the menu bar to
539             // the top
540             // of the screen, where Mac users expect it to be.
541             System.setProperty("apple.laf.useScreenMenuBar", "true");
542
543             // Set antialiasing on everywhere. This only works in JRE >= 1.5.
544             // Or... it doesn't work, period.
545             //System.setProperty("swing.aatext", "true");
546             // If we are not on Mac, deal with font sizes and LookAndFeels:
547             if (!Globals.ON_MAC) {
548                 int fontSizes = Globals.prefs.getInt("menuFontSize");
549                 boolean overrideDefaultFonts = Globals.prefs.getBoolean("overrideDefaultFonts");
550                 String defaultLookAndFeel;
551
552                 if (Globals.ON_WIN)
553                     defaultLookAndFeel = GUIGlobals.windowsDefaultLookAndFeel;
554                 else
555                     defaultLookAndFeel = GUIGlobals.linuxDefaultLookAndFeel;
556
557                 String lookAndFeel = null;
558
559                 if (!Globals.prefs.getBoolean("useDefaultLookAndFeel"))
560                     lookAndFeel = Globals.prefs.get("lookAndFeel");
561                 else
562                     lookAndFeel = defaultLookAndFeel;
563
564                 LookAndFeel lnf = null;
565                 Object objLnf = null;
566
567
568                 try {
569                     if (lookAndFeel != null)
570                         objLnf = Class.forName(lookAndFeel).newInstance();
571                     else
572                         objLnf = Class.forName(defaultLookAndFeel).newInstance();
573                 } catch (Exception ex) {
574                     ex.printStackTrace();
575
576                     try {
577                         objLnf = Class.forName(defaultLookAndFeel).newInstance();
578                     } catch (Exception ex2) {
579                     }
580                 }
581
582                 if (objLnf != null)
583                     lnf = (LookAndFeel) objLnf;
584
585                 // Set font sizes if we are using a JGoodies look and feel.
586                 if ((lnf != null) && (lnf instanceof Plastic3DLookAndFeel)) {
587
588                     //UIManager.put("jgoodies.popupDropShadowEnabled", Boolean.TRUE);
589                     MetalLookAndFeel.setCurrentTheme(new
590                      com.jgoodies.looks.plastic.theme.SkyBluer());
591
592                     // Set a "model" icon size, so menu items are evenly spaced even though
593                     // only some items have icons. We load an arbitrary icon and look at
594                     // its size to determine what size to use:
595                     int defaultIconSize = GUIGlobals.getImage("open").getIconWidth();
596                     com.jgoodies.looks.Options.setDefaultIconSize
597                             (new Dimension(defaultIconSize, defaultIconSize));
598
599
600                     if (overrideDefaultFonts) {
601                         FontSet fontSet = FontSets.createDefaultFontSet(
602                             new Font("Tahoma", Font.PLAIN, fontSizes),    // control font
603                             new Font("Tahoma", Font.PLAIN, fontSizes),    // menu font
604                             new Font("Tahoma", Font.BOLD, fontSizes)     // title font
605                             );
606                         FontPolicy fixedPolicy = FontPolicies.createFixedPolicy(fontSet);
607                         Plastic3DLookAndFeel.setFontPolicy(fixedPolicy);
608                     }
609
610                     //Plastic3DLookAndFeel plLnf = (Plastic3DLookAndFeel) lnf;
611                 }
612                 else if ((lnf != null) && (lnf instanceof WindowsLookAndFeel)) {
613
614                     // Set a "model" icon size, so menu items are evenly spaced even though
615                     // only some items have icons. We load an arbitrary icon and look at
616                     // its size to determine what size to use:
617                     int defaultIconSize = GUIGlobals.getImage("open").getIconWidth();
618                     com.jgoodies.looks.Options.setDefaultIconSize
619                         (new Dimension(defaultIconSize, defaultIconSize));
620
621                     if (overrideDefaultFonts) {
622                         FontSet fontSet = FontSets.createDefaultFontSet(
623                             new Font("Tahoma", Font.PLAIN, fontSizes),    // control font
624                             new Font("Tahoma", Font.PLAIN, fontSizes),    // menu font
625                             new Font("Tahoma", Font.BOLD, fontSizes)     // title font
626                             );
627                         FontPolicy fixedPolicy = FontPolicies.createFixedPolicy(fontSet);
628                         WindowsLookAndFeel.setFontPolicy(fixedPolicy);
629                     }
630
631                     //WindowsLookAndFeel plLnf = (WindowsLookAndFeel) lnf;
632                 }
633
634                 if (lnf != null) {
635                     try {
636
637                         UIManager.setLookAndFeel(lnf);
638
639                         if (!Globals.ON_WIN) {
640                             UIManager.put("SimpleInternalFrame.activeTitleBackground", GUIGlobals.gradientBlue);
641                         }
642
643                         if (!Globals.ON_WIN && !Globals.ON_MAC) {
644                             // For Linux, add Enter as button click key:
645                             UIDefaults def = UIManager.getDefaults();
646                             InputMap im = (InputMap)def.get("Button.focusInputMap");
647                             im.put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0, false), "pressed");
648                             im.put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0, true), "released");
649                         }
650                     } catch (Throwable ex) {
651                         ex.printStackTrace();
652                         System.err.println("Trying to set system default Look&Feel...");
653
654                         // if desired lnf could not be set, try system default
655                         try {
656                             UIManager.setLookAndFeel(UIManager
657                                 .getSystemLookAndFeelClassName());
658                         } catch (Throwable e) {
659                             e.printStackTrace();
660                         }
661                     }
662
663                     //LookAndFeel lnf = new com.sun.java.swing.plaf.gtk.GTKLookAndFeel();
664                     //Look1AndFeel lnf = new
665                     // com.incors.plaf.kunststoff.KunststoffLookAndFeel();
666                     //com.incors.plaf.kunststoff.KunststoffLookAndFeel.setCurrentTheme(new
667                     // com.incors.plaf.kunststoff.themes.KunststoffDesktopTheme());
668                 }
669
670             }
671
672
673             // If the option is enabled, open the last edited databases, if any.
674             if (!blank.isInvoked() && Globals.prefs.getBoolean("openLastEdited") && (Globals.prefs.get("lastEdited") != null)) {
675                 // How to handle errors in the databases to open?
676                 String[] names = Globals.prefs.getStringArray("lastEdited");
677 lastEdLoop: 
678                 for (int i = 0; i < names.length; i++) {
679                     File fileToOpen = new File(names[i]);
680
681                     for (int j = 0; j < loaded.size(); j++) {
682                         ParserResult pr = loaded.elementAt(j);
683
684                         if ((pr.getFile() != null) &&pr.getFile().equals(fileToOpen))
685                             continue lastEdLoop;
686                     }
687
688                     if (fileToOpen.exists()) {
689                         ParserResult pr = openBibFile(names[i]);
690
691                         if (pr != null) {
692
693                             if (pr == ParserResult.INVALID_FORMAT) {
694                                 System.out.println(Globals.lang("Error opening file")+" '"+fileToOpen.getPath()+"'");
695                             }
696                             else
697                                 loaded.add(pr);
698
699                         }
700                     }
701                 }
702             }
703
704             GUIGlobals.init();
705             GUIGlobals.CURRENTFONT =
706                 new Font(Globals.prefs.get("fontFamily"), Globals.prefs.getInt("fontStyle"),
707                     Globals.prefs.getInt("fontSize"));
708
709             //Util.pr(": Initializing frame");
710             jrf = new JabRefFrame();
711
712             // Add all loaded databases to the frame:
713             boolean first = true;
714             if (loaded.size() > 0) {
715                 for (ParserResult pr : loaded){
716                             jrf.addTab(pr.getDatabase(), pr.getFile(),
717                             pr.getMetaData(), pr.getEncoding(), first);
718                     first = false;
719                 }
720             }
721
722             if (loadSess.isInvoked())
723                 jrf.loadSessionAction.actionPerformed(new java.awt.event.ActionEvent(
724                         jrf, 0, ""));
725
726             if (splashScreen != null) {// do this only if splashscreen was actually created
727                 splashScreen.dispose();
728                 splashScreen = null;
729             }
730
731             /*JOptionPane.showMessageDialog(null, Globals.lang("Please note that this "
732                 +"is an early beta version. Do not use it without backing up your files!"),
733                     Globals.lang("Beta version"), JOptionPane.WARNING_MESSAGE);*/
734
735             //Util.pr(": Showing frame");
736             jrf.setVisible(true);
737
738             // TEST TEST TEST TEST TEST TEST
739             startSidePanePlugins(jrf);
740
741             for (int i = 0; i < loaded.size(); i++) {
742                 ParserResult pr = loaded.elementAt(i);
743                 if (Globals.prefs.getBoolean("displayKeyWarningDialogAtStartup") && pr.hasWarnings()) {
744                     String[] wrns = pr.warnings();
745                     StringBuffer wrn = new StringBuffer();
746                     for (int j = 0; j<wrns.length; j++)
747                         wrn.append(j + 1).append(". ").append(wrns[j]).append("\n");
748                     if (wrn.length() > 0)
749                         wrn.deleteCharAt(wrn.length() - 1);
750                     jrf.showBaseAt(i);
751                     JOptionPane.showMessageDialog(jrf, wrn.toString(),
752                         Globals.lang("Warnings"),
753                         JOptionPane.WARNING_MESSAGE);
754                 }
755             }
756
757             // After adding the databases, go through each and see if
758             // any post open actions need to be done. For instance, checking
759             // if we found new entry types that can be imported, or checking
760             // if the database contents should be modified due to new features
761             // in this version of JabRef:
762             for (int i = 0; i < loaded.size(); i++) {
763                 ParserResult pr = loaded.elementAt(i);
764                 BasePanel panel = jrf.baseAt(i);
765                 OpenDatabaseAction.performPostOpenActions(panel, pr, true);
766             }
767
768             //Util.pr(": Finished adding panels");
769
770             if (loaded.size() > 0) {
771                 jrf.tabbedPane.setSelectedIndex(0);
772                 new FocusRequester(((BasePanel) jrf.tabbedPane.getComponentAt(0)).mainTable);
773             }
774         } else
775             System.exit(0);
776     }
777
778     /**
779      * Go through all registered instances of SidePanePlugin, and register them
780      * in the SidePaneManager.
781      *
782      * @param jrf The JabRefFrame.
783      */
784     private void startSidePanePlugins(JabRefFrame jrf) {
785
786         JabRefPlugin jabrefPlugin = JabRefPlugin.getInstance(PluginCore.getManager());
787         List<_JabRefPlugin.SidePanePluginExtension> plugins = jabrefPlugin.getSidePanePluginExtensions();
788         for (_JabRefPlugin.SidePanePluginExtension extension : plugins) {
789             SidePanePlugin plugin = extension.getSidePanePlugin();
790             plugin.init(jrf, jrf.sidePaneManager);
791             SidePaneComponent comp = plugin.getSidePaneComponent();
792             jrf.sidePaneManager.register(comp.getName(), comp);
793             jrf.addPluginMenuItem(plugin.getMenuItem());
794         }
795     }
796
797     public static ParserResult openBibFile(String name) {
798         System.out.println(Globals.lang("Opening") + ": " + name);
799
800         try {
801             File file = new File(name);
802             String encoding = Globals.prefs.get("defaultEncoding");
803             ParserResult pr = OpenDatabaseAction.loadDatabase(file, encoding);
804             if (pr == null)
805                 return ParserResult.INVALID_FORMAT;
806             pr.setFile(file);
807             if (pr.hasWarnings()) {
808                 String[] warn = pr.warnings();
809                 for (int i=0; i<warn.length; i++)
810                     System.out.println(Globals.lang("Warning")+": "+warn[i]);
811
812             }
813             return pr;
814         } catch (Throwable ex) {
815             //System.err.println(Globals.lang("Error opening file")+" '"+ name+"':
816             // "+ex.getMessage());
817             System.err.println(Globals.lang("Error opening file") + ": "
818                 + ex.getMessage());
819         }
820
821         return null;
822     }
823
824     public static ParserResult importFile(String argument){
825         String[] data = argument.split(",");
826         try {
827             if ((data.length > 1) && !"*".equals(data[1])) {
828                 System.out.println(Globals.lang("Importing") + ": " + data[0]);
829                 List<BibtexEntry> entries =
830                         Globals.importFormatReader.importFromFile(data[1],
831                                 data[0].replaceAll("~", System.getProperty("user.home")));
832                 return new ParserResult(entries);
833             } else {
834                 // * means "guess the format":
835                 System.out.println(Globals.lang("Importing in unknown format")
836                         + ": " + data[0]);
837                 
838                 Pair<String, ParserResult> importResult = 
839                     Globals.importFormatReader.importUnknownFormat(data[0]
840                             .replaceAll("~", System.getProperty("user.home")));
841                 
842                 if (importResult != null){
843                         System.out.println(Globals.lang("Format used") + ": "
844                         + importResult.p);
845                         
846                         return importResult.v;
847                 } else {
848                         System.out.println(Globals.lang(
849                                 "Could not find a suitable import format."));
850                 }
851             }
852         } catch (IOException ex) {
853             System.err.println(Globals.lang("Error opening file") + " '"
854                     + data[0] + "': " + ex.getLocalizedMessage());
855         }
856         return null;
857     }
858
859     /**
860      * Will open a file (like importFile), but will also request JabRef to focus on this database 
861      * @param argument See importFile.
862      * @return ParserResult with setToOpenTab(true)
863      */
864     public static ParserResult importToOpenBase(String argument) {
865         ParserResult result = importFile(argument);
866         
867         if (result != null)
868                 result.setToOpenTab(true);
869         
870         return result;
871     }
872 }