Index: trunk/src/org/openstreetmap/josm/Main.java
===================================================================
--- trunk/src/org/openstreetmap/josm/Main.java	(revision 8014)
+++ trunk/src/org/openstreetmap/josm/Main.java	(revision 8015)
@@ -387,4 +387,14 @@
 
     /**
+     * Prints a formatted trace message if logging is on. Calls {@link MessageFormat#format}
+     * function to format text.
+     * @param msg The formatted message to print.
+     * @param objects The objects to insert into format string.
+     */
+    public static void trace(String msg, Object... objects) {
+        trace(MessageFormat.format(msg, objects));
+    }
+
+    /**
      * Prints an error message for the given Throwable.
      * @param t The throwable object causing the error
Index: trunk/src/org/openstreetmap/josm/gui/MainApplication.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/MainApplication.java	(revision 8014)
+++ trunk/src/org/openstreetmap/josm/gui/MainApplication.java	(revision 8015)
@@ -367,4 +367,6 @@
         processOffline(args);
 
+        Main.platform.afterPrefStartupHook();
+
         FontsManager.initialize();
 
Index: trunk/src/org/openstreetmap/josm/tools/PlatformHook.java
===================================================================
--- trunk/src/org/openstreetmap/josm/tools/PlatformHook.java	(revision 8014)
+++ trunk/src/org/openstreetmap/josm/tools/PlatformHook.java	(revision 8015)
@@ -24,4 +24,12 @@
       */
     public void preStartupHook();
+    
+    /**
+      * The afterPrefStartupHook will be called early, but after
+      * the preferences have been loaded and basic processing of
+      * command line arguments is finished. 
+      * It is guaranteed to be called before the GUI setup has started.
+      */
+    public void afterPrefStartupHook();
 
     /**
Index: trunk/src/org/openstreetmap/josm/tools/PlatformHookUnixoid.java
===================================================================
--- trunk/src/org/openstreetmap/josm/tools/PlatformHookUnixoid.java	(revision 8014)
+++ trunk/src/org/openstreetmap/josm/tools/PlatformHookUnixoid.java	(revision 8015)
@@ -9,10 +9,16 @@
 import java.awt.event.KeyEvent;
 import java.io.BufferedReader;
+import java.io.BufferedWriter;
 import java.io.File;
+import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
 import java.net.URI;
 import java.net.URISyntaxException;
 import java.nio.charset.StandardCharsets;
+import java.nio.file.FileSystems;
 import java.nio.file.Files;
 import java.nio.file.Path;
@@ -22,5 +28,9 @@
 import java.security.NoSuchAlgorithmException;
 import java.security.cert.CertificateException;
+import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.Properties;
 
 import javax.swing.JOptionPane;
@@ -29,4 +39,6 @@
 import org.openstreetmap.josm.gui.ExtendedDialog;
 import org.openstreetmap.josm.gui.util.GuiHelper;
+import org.openstreetmap.josm.data.Preferences.pref;
+import org.openstreetmap.josm.data.Preferences.writeExplicitly;
 
 /**
@@ -38,8 +50,45 @@
 public class PlatformHookUnixoid implements PlatformHook {
 
+    /**
+     * Simple data class to hold information about a font.
+     *
+     * Used for fontconfig.properties files.
+     */
+    public static class FontEntry {
+        /**
+         * The character subset. Basically a free identifier, but should
+         * be unique.
+         */
+        @pref
+        public String charset;
+        /**
+         * Platform font name.
+         */
+        @pref @writeExplicitly
+        public String name = "";
+        /**
+         * File name.
+         */
+        @pref @writeExplicitly
+        public String file = "";
+
+        public FontEntry() {
+        }
+
+        public FontEntry(String charset, String name, String file) {
+            this.charset = charset;
+            this.name = name;
+            this.file = file;
+        }
+    }
+
     private String osDescription;
 
     @Override
     public void preStartupHook() {
+    }
+
+    @Override
+    public void afterPrefStartupHook() {
     }
 
@@ -386,3 +435,135 @@
         return Main.pref.getPreferencesDirectory();
     }
+
+    /**
+     * Add more fallback fonts to the Java runtime, in order to get
+     * support for more scripts.
+     *
+     * The font configuration in Java doesn't include some Indic scripts,
+     * even though MS Windows ships with fonts that cover these unicode
+     * ranges.
+     *
+     * To fix this, the fontconfig.properties template is copied to the JOSM
+     * cache folder. Then, the additional entries are added to the font
+     * configuration. Finally the system property "sun.awt.fontconfig" is set
+     * to the customized fontconfig.properties file.
+     * 
+     * This is a crude hack, but better than no font display at all for these
+     * languages.
+     * There is no guarantee, that the template file
+     * ($JAVA_HOME/lib/fontconfig.properties.src) matches the default
+     * configuration (which is in a binary format).
+     * Furthermore, the system property "sun.awt.fontconfig" is undocumented and
+     * may no longer work in future versions of Java.
+     *
+     * @param templateFileName file name of the fontconfig.properties template file
+     */
+    protected void extendFontconfig(String templateFileName) {
+        String customFontconfigFile = Main.pref.get("fontconfig.properties", null);
+        if (customFontconfigFile != null) {
+            Utils.updateSystemProperty("sun.awt.fontconfig", customFontconfigFile);
+            return;
+        }
+        if (!Main.pref.getBoolean("font.extended-unicode", true))
+            return;
+
+        String javaLibPath = System.getProperty("java.home") + File.separator + "lib";
+        Path templateFile = FileSystems.getDefault().getPath(javaLibPath, templateFileName);
+        if (!Files.isReadable(templateFile)) {
+            Main.warn("extended font config - unable to find font config template file "+templateFile.toString());
+            return;
+        }
+        try {
+            Properties props = new Properties();
+            props.load(new FileInputStream(templateFile.toFile()));
+            byte[] content = Files.readAllBytes(templateFile);
+            File cachePath = Main.pref.getCacheDirectory();
+            Path fontconfigFile = cachePath.toPath().resolve("fontconfig.properties");
+            OutputStream os = Files.newOutputStream(fontconfigFile);
+            os.write(content);
+            try (Writer w = new BufferedWriter(new OutputStreamWriter(os))) {
+                Collection<FontEntry> extrasPref = Main.pref.getListOfStructs(
+                        "font.extended-unicode.extra-items", getAdditionalFonts(), FontEntry.class);
+                Collection<FontEntry> extras = new ArrayList<>();
+                w.append("\n\n# Added by JOSM to extend unicode coverage of Java font support:\n\n");
+                List<String> allCharSubsets = new ArrayList<>();
+                for (FontEntry entry: extrasPref) {
+                    Collection<String> fontsAvail = getInstalledFonts();
+                    if (fontsAvail != null && fontsAvail.contains(entry.file.toUpperCase())) {
+                        if (!allCharSubsets.contains(entry.charset)) {
+                            allCharSubsets.add(entry.charset);
+                            extras.add(entry);
+                        } else {
+                            Main.trace("extended font config - already registered font for charset ''{0}'' - skipping ''{1}''",
+                                    entry.charset, entry.name);
+                        }
+                    } else {
+                        Main.trace("extended font config - Font ''{0}'' not found on system - skipping", entry.name);
+                    }
+                }
+                for (FontEntry entry: extras) {
+                    allCharSubsets.add(entry.charset);
+                    if ("".equals(entry.name)) {
+                        continue;
+                    }
+                    String key = "allfonts." + entry.charset;
+                    String value = entry.name;
+                    String prevValue = props.getProperty(key);
+                    if (prevValue != null && !prevValue.equals(value)) {
+                        Main.warn("extended font config - overriding ''{0}={1}'' with ''{2}''", key, prevValue, value);
+                    }
+                    w.append(key + "=" + value + "\n");
+                }
+                w.append("\n");
+                for (FontEntry entry: extras) {
+                    if ("".equals(entry.name) || "".equals(entry.file)) {
+                        continue;
+                    }
+                    String key = "filename." + entry.name.replace(" ", "_");
+                    String value = entry.file;
+                    String prevValue = props.getProperty(key);
+                    if (prevValue != null && !prevValue.equals(value)) {
+                        Main.warn("extended font config - overriding ''{0}={1}'' with ''{2}''", key, prevValue, value);
+                    }
+                    w.append(key + "=" + value + "\n");
+                }
+                w.append("\n");
+                String fallback = props.getProperty("sequence.fallback");
+                if (fallback != null) {
+                    w.append("sequence.fallback=" + fallback + "," + Utils.join(",", allCharSubsets) + "\n");
+                } else {
+                    w.append("sequence.fallback=" + Utils.join(",", allCharSubsets) + "\n");
+                }
+            }
+            Utils.updateSystemProperty("sun.awt.fontconfig", fontconfigFile.toString());
+        } catch (IOException ex) {
+            Main.error(ex);
+        }
+    }
+
+    /**
+     * Get a list of fonts that are installed on the system.
+     *
+     * Must be done without triggering the Java Font initialization.
+     * (See {@link #extendFontconfig(java.lang.String)}, have to set system
+     * property first, which is then read by sun.awt.FontConfiguration upon
+     * initialization.)
+     *
+     * @return list of file names
+     */
+    public Collection<String> getInstalledFonts() {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Get default list of additional fonts to add to the configuration.
+     *
+     * Java will choose thee first font in the list that can render a certain
+     * character.
+     *
+     * @return list of FontEntry objects
+     */
+    public Collection<FontEntry> getAdditionalFonts() {
+        throw new UnsupportedOperationException();
+    }
 }
Index: trunk/src/org/openstreetmap/josm/tools/PlatformHookWindows.java
===================================================================
--- trunk/src/org/openstreetmap/josm/tools/PlatformHookWindows.java	(revision 8014)
+++ trunk/src/org/openstreetmap/josm/tools/PlatformHookWindows.java	(revision 8015)
@@ -29,11 +29,7 @@
 
 import java.awt.GraphicsEnvironment;
-import java.io.BufferedWriter;
 import java.io.File;
-import java.io.FileInputStream;
 import java.io.IOException;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.io.Writer;
+import java.nio.file.DirectoryStream;
 import java.nio.file.FileSystems;
 import java.nio.file.Files;
@@ -51,11 +47,10 @@
 import java.security.spec.X509EncodedKeySpec;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collection;
 import java.util.Enumeration;
 import java.util.List;
-import java.util.Properties;
 
 import javax.swing.JOptionPane;
+
 import org.openstreetmap.josm.Main;
 
@@ -96,115 +91,8 @@
 
     @Override
-    public void preStartupHook() {
-        extendFontconfig();
-    }
-    
-    /**
-     * Add more fallback fonts to the Java runtime, in order to get wider 
-     * unicode support.
-     * 
-     * The font configuration in Java doesn't include some Indic scripts,
-     * even though MS Windows ships with fonts that cover these unicode
-     * ranges.
-     * 
-     * To fix this, the fontconfig.properties template is copied to the JOSM
-     * cache folder. Then, the additional entries are added to the font
-     * configuration. Finally the system property "sun.awt.fontconfig" is set
-     * to the customized fontconfig.properties file.
-     * 
-     * This is a crude hack, but better than no font display at all for these
-     * languages.
-     * There is no guarantee, that the template file
-     * ($JAVA_HOME/lib/fontconfig.properties.src) matches the default
-     * configuration (which is in a binary format).
-     * Furthermore, the system property "sun.awt.fontconfig" is undocumented and
-     * may no longer work in future versions of Java.
-     */
-    protected void extendFontconfig() {
-        String customFontconfigFile = Main.pref.get("fontconfig.properties", null);
-        if (customFontconfigFile != null) {
-            Utils.updateSystemProperty("sun.awt.fontconfig", customFontconfigFile);
-            return;
-        }
-        if (!Main.pref.getBoolean("font.extended-unicode", true))
-            return;
-        String javaLibPath = System.getProperty("java.home") + File.separator + "lib";
-        Path templateFile = FileSystems.getDefault().getPath(javaLibPath, "fontconfig.properties.src");
-        if (!Files.isReadable(templateFile)) {
-            Main.warn("extended unicode - unable to find font config template file "+templateFile.toString());
-            return;
-        }
-        try {
-            Properties props = new Properties();
-            props.load(new FileInputStream(templateFile.toFile()));
-            byte[] content = Files.readAllBytes(templateFile);
-            File cachePath = Main.pref.getCacheDirectory();
-            Path fontconfigFile = cachePath.toPath().resolve("fontconfig.properties");
-            OutputStream os = Files.newOutputStream(fontconfigFile);
-            os.write(content);
-            try (Writer w = new BufferedWriter(new OutputStreamWriter(os))) {
-                Collection<Collection<String>> def = new ArrayList<>();
-                def.add(Arrays.asList("devanagari", "", "")); // just include in fallback list
-                                                              // no font definition needed
-                // all of the following fonts are available in Win XP and later
-                def.add(Arrays.asList("gujarati", "Shruti", "SHRUTI.TTF"));
-                def.add(Arrays.asList("kannada", "Tunga", "TUNGA.TTF"));
-                def.add(Arrays.asList("gurmuhi", "Raavi", "RAAVI.TTF"));
-                def.add(Arrays.asList("tamil", "Latha", "LATHA.TTF"));
-                def.add(Arrays.asList("telugu", "Gautami", "GAUTAMI.TTF"));
-                def.add(Arrays.asList("bengali", "Vrinda", "VRINDA.TTF"));
-                def.add(Arrays.asList("syriac", "Estrangelo Edessa", "ESTRE.TTF")); // ISO 639: arc
-                def.add(Arrays.asList("thaana", "MV Boli", "MVBOLI.TTF"));          // ISO 639: dv
-                def.add(Arrays.asList("malayalam", "Kartika", "KARTIKA.TTF"));      // ISO 639: ml; since XP SP2
-                Collection<Collection<String>> additions = 
-                        Main.pref.getArray("font.extended-unicode.added-items", def);
-                w.append("\n\n# Added by JOSM to extend unicode coverage of Java font support:\n\n");
-                List<String> allCharSubsets = new ArrayList<>();
-                for (Collection<String> entry: additions) {
-                    List<String> lentry = new ArrayList<>(entry);
-                    String charSubset = lentry.get(0);
-                    allCharSubsets.add(charSubset);
-                    String platformFontName = lentry.get(1);
-                    if ("".equals(platformFontName)) {
-                        continue;
-                    }
-                    String key = "allfonts." + charSubset;
-                    String value = platformFontName;
-                    String prevValue = props.getProperty(key);
-                    if (prevValue != null && !prevValue.equals(value)) {
-                        Main.warn("extended unicode - overriding " + key + "=" + prevValue + " with " + value);
-                    }
-                    w.append(key + "=" + value + "\n");
-                }
-                w.append("\n");
-                for (Collection<String> entry: additions) {
-                    List<String> lentry = new ArrayList<>(entry);
-                    String platformFontName = lentry.get(1);
-                    String fontFile = lentry.get(2);
-                    if ("".equals(platformFontName) || "".equals(fontFile)) {
-                        continue;
-                    }
-                    String key = "filename." + platformFontName;
-                    String value = fontFile;
-                    String prevValue = props.getProperty(key);
-                    if (prevValue != null && !prevValue.equals(value)) {
-                        Main.warn("extended unicode - overriding " + key + "=" + prevValue + " with " + value);
-                    }
-                    w.append(key + "=" + value + "\n");
-                }
-                w.append("\n");
-                String fallback = props.getProperty("sequence.fallback");
-                if (fallback != null) {
-                    w.append("sequence.fallback=" + fallback + "," + Utils.join(",", allCharSubsets) + "\n");
-                } else {
-                    w.append("sequence.fallback=" + Utils.join(",", allCharSubsets) + "\n");
-                }
-            }
-            Utils.updateSystemProperty("sun.awt.fontconfig", fontconfigFile.toString());
-        } catch (IOException ex) {
-            Main.error(ex);
-        }
-    }
-    
+    public void afterPrefStartupHook() {
+        extendFontconfig("fontconfig.properties.src");
+    }
+
     @Override
     public void openUrl(String url) throws IOException {
@@ -420,3 +308,65 @@
         return new File(System.getenv("APPDATA"), "JOSM");
     }
+
+    @Override
+    public Collection<String> getInstalledFonts() {
+        // Cannot use GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames()
+        // because we have to set the system property before Java initializes its fonts.
+        // Use more low-level method to find the installed fonts.
+        List<String> fontsAvail = new ArrayList<>();
+        Path fontPath = FileSystems.getDefault().getPath(System.getenv("SYSTEMROOT"), "Fonts");
+        try (DirectoryStream<Path> ds = Files.newDirectoryStream(fontPath)) {
+            for (Path p : ds) {
+                fontsAvail.add(p.getFileName().toString().toUpperCase());
+            }
+        } catch (IOException ex) {
+            Main.warn("extended font config - failed to load available Fonts");
+            fontsAvail = null;
+        }
+        fontsAvail.add(""); // for devanagari
+        return fontsAvail;
+    }
+
+    @Override
+    public Collection<FontEntry> getAdditionalFonts() {
+        Collection<FontEntry> def = new ArrayList<>();
+        def.add(new FontEntry("devanagari", "", "")); // just include in fallback list
+                                                      // font already defined in template
+        // Win 8 (and later)
+        def.add(new FontEntry("myanmar", "Myanmar Text", "MMRTEXT.TTF"));           // ISO 639: my
+
+        // Win 7 and later
+        def.add(new FontEntry("nko_tifinagh_vai_osmanya", "Ebrima", "EBRIMA.TTF")); // ISO 639: ber
+        def.add(new FontEntry("khmer1", "Khmer UI", "KHMERUI.TTF"));                // ISO 639: km
+        def.add(new FontEntry("lao1", "Lao UI", "LAOUI.TTF"));                      // ISO 639: lo
+
+        // Win Vista and later:
+        def.add(new FontEntry("ethiopic", "Nyala", "NYALA.TTF"));                   // ISO 639: am,gez,ti
+        def.add(new FontEntry("tibetan", "Microsoft Himalaya", "HIMALAYA.TTF"));    // ISO 639: bo,dz
+        def.add(new FontEntry("cherokee", "Plantagenet Cherokee", "PLANTC.TTF"));   // ISO 639: chr
+        def.add(new FontEntry("unified_canadian", "Euphemia", "EUPHEMIA.TTF"));     // ISO 639: cr,in
+        def.add(new FontEntry("khmer2", "DaunPenh", "DAUNPENH.TTF"));               // ISO 639: km
+        def.add(new FontEntry("khmer3", "MoolBoran", "MOOLBOR.TTF"));               // ISO 639: km
+        def.add(new FontEntry("lao_thai", "DokChampa", "DOKCHAMP.TTF"));            // ISO 639: lo
+        def.add(new FontEntry("mongolian", "Mongolian Baiti", "MONBAITI.TTF"));     // ISO 639: mn
+        def.add(new FontEntry("oriya", "Kalinga", "KALINGA.TTF"));                  // ISO 639: or
+        def.add(new FontEntry("sinhala", "Iskoola Pota", "ISKPOTA.TTF"));           // ISO 639: si
+
+        // Win XP and later
+        def.add(new FontEntry("gujarati", "Shruti", "SHRUTI.TTF"));
+        def.add(new FontEntry("kannada", "Tunga", "TUNGA.TTF"));
+        def.add(new FontEntry("gurmuhi", "Raavi", "RAAVI.TTF"));
+        def.add(new FontEntry("tamil", "Latha", "LATHA.TTF"));
+        def.add(new FontEntry("telugu", "Gautami", "GAUTAMI.TTF"));
+        def.add(new FontEntry("bengali", "Vrinda", "VRINDA.TTF"));
+        def.add(new FontEntry("syriac", "Estrangelo Edessa", "ESTRE.TTF"));         // ISO 639: arc
+        def.add(new FontEntry("thaana", "MV Boli", "MVBOLI.TTF"));                  // ISO 639: dv
+        def.add(new FontEntry("malayalam", "Kartika", "KARTIKA.TTF"));              // ISO 639: ml; since XP SP2
+
+        // Comes with MS Office & Outlook 2000. Good unicode coverage, so add if available.
+        def.add(new FontEntry("arialuni", "Arial Unicode MS", "ARIALUNI.TTF"));
+
+        return def;
+    }
+
 }
