Index: trunk/src/org/openstreetmap/josm/gui/mappaint/MapImage.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/mappaint/MapImage.java	(revision 6147)
+++ trunk/src/org/openstreetmap/josm/gui/mappaint/MapImage.java	(revision 6148)
@@ -58,4 +58,5 @@
                 .setId("mappaint."+source.getPrefName())
                 .setArchive(source.zipIcons)
+                .setInArchiveDir(source.getZipEntryDirName())
                 .setWidth(width)
                 .setHeight(height)
Index: trunk/src/org/openstreetmap/josm/gui/mappaint/MapPaintStyles.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/mappaint/MapPaintStyles.java	(revision 6147)
+++ trunk/src/org/openstreetmap/josm/gui/mappaint/MapPaintStyles.java	(revision 6148)
@@ -6,5 +6,4 @@
 import java.io.File;
 import java.io.IOException;
-import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.util.ArrayList;
@@ -97,4 +96,5 @@
                 .setId("mappaint."+namespace)
                 .setArchive(ref.source.zipIcons)
+                .setInArchiveDir(ref.source.getZipEntryDirName())
                 .setWidth(width)
                 .setHeight(height)
@@ -121,4 +121,5 @@
                 .setId("mappaint."+source.getPrefName())
                 .setArchive(source.zipIcons)
+                .setInArchiveDir(source.getZipEntryDirName())
                 .setOptional(true).get();
     }
@@ -211,9 +212,12 @@
         try {
             in = new MirroredInputStream(entry.url);
-            InputStream zip = in.getZipEntry("mapcss", "style");
-            if (zip != null)
+            String zipEntryPath = in.findZipEntryPath("mapcss", "style");
+            if (zipEntryPath != null) {
+                entry.isZip = true;
+                entry.zipEntryPath = zipEntryPath;
                 return new MapCSSStyleSource(entry);
-            zip = in.getZipEntry("xml", "style");
-            if (zip != null)
+            }
+            zipEntryPath = in.findZipEntryPath("xml", "style");
+            if (zipEntryPath != null)
                 return new XmlStyleSource(entry);
             if (entry.url.toLowerCase().endsWith(".mapcss"))
Index: trunk/src/org/openstreetmap/josm/gui/mappaint/StyleSource.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/mappaint/StyleSource.java	(revision 6147)
+++ trunk/src/org/openstreetmap/josm/gui/mappaint/StyleSource.java	(revision 6148)
@@ -40,5 +40,5 @@
 
     public StyleSource(SourceEntry entry) {
-        super(entry.url, entry.name, entry.title, entry.active);
+        super(entry);
     }
 
Index: trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSStyleSource.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSStyleSource.java	(revision 6147)
+++ trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSStyleSource.java	(revision 6148)
@@ -6,4 +6,5 @@
 import java.awt.Color;
 import java.io.ByteArrayInputStream;
+import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
@@ -11,4 +12,6 @@
 import java.util.List;
 import java.util.Map.Entry;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
 
 import org.openstreetmap.josm.data.osm.Node;
@@ -88,8 +91,11 @@
 
         MirroredInputStream in = new MirroredInputStream(url);
-        InputStream zip = in.getZipEntry("mapcss", "style");
-        if (zip != null) {
-            zipIcons = in.getFile();
-            return zip;
+        if (isZip) {
+            File file = in.getFile();
+            Utils.close(in);
+            ZipFile zipFile = new ZipFile(file);
+            zipIcons = file;
+            ZipEntry zipEntry = zipFile.getEntry(zipEntryPath);
+            return zipFile.getInputStream(zipEntry);
         } else {
             zipIcons = null;
Index: trunk/src/org/openstreetmap/josm/gui/mappaint/xml/XmlStyleSource.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/mappaint/xml/XmlStyleSource.java	(revision 6147)
+++ trunk/src/org/openstreetmap/josm/gui/mappaint/xml/XmlStyleSource.java	(revision 6148)
@@ -94,5 +94,5 @@
     public InputStream getSourceInputStream() throws IOException {
         MirroredInputStream in = new MirroredInputStream(url);
-        InputStream zip = in.getZipEntry("xml", "style");
+        InputStream zip = in.findZipEntryInputStream("xml", "style");
         if (zip != null) {
             zipIcons = in.getFile();
Index: trunk/src/org/openstreetmap/josm/gui/preferences/SourceEntry.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/preferences/SourceEntry.java	(revision 6147)
+++ trunk/src/org/openstreetmap/josm/gui/preferences/SourceEntry.java	(revision 6148)
@@ -1,10 +1,10 @@
 // License: GPL. For details, see LICENSE file.
 package org.openstreetmap.josm.gui.preferences;
+
+import static org.openstreetmap.josm.tools.Utils.equal;
 
 import java.io.File;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
-
-import static org.openstreetmap.josm.tools.Utils.equal;
 
 /**
@@ -19,4 +19,15 @@
      */
     public String url;
+
+    /**
+     * Indicates, that {@link #url} is a zip file and the resource is
+     * inside the zip file.
+     */
+    public boolean isZip;
+
+    /**
+     * If {@link #isZip} is true, denotes the path inside the zip file.
+     */
+    public String zipEntryPath;
 
     /**
@@ -42,6 +53,8 @@
     public boolean active;
 
-    public SourceEntry(String url, String name, String title, Boolean active) {
+    public SourceEntry(String url, boolean isZip, String zipEntryPath, String name, String title, boolean active) {
         this.url = url;
+        this.isZip = isZip;
+        this.zipEntryPath = equal(zipEntryPath, "") ? null : zipEntryPath;
         this.name = equal(name, "") ? null : name;
         this.title = equal(title, "") ? null : title;
@@ -49,6 +62,12 @@
     }
 
+    public SourceEntry(String url, String name, String title, Boolean active) {
+        this(url, false, null, name, title, active);
+    }
+
     public SourceEntry(SourceEntry e) {
         this.url = e.url;
+        this.isZip = e.isZip;
+        this.zipEntryPath = e.zipEntryPath;
         this.name = e.name;
         this.title = e.title;
@@ -62,4 +81,6 @@
         final SourceEntry other = (SourceEntry) obj;
         return equal(other.url, url) &&
+                other.isZip == isZip &&
+                equal(other.zipEntryPath, zipEntryPath) &&
                 equal(other.name, name) &&
                 equal(other.title, title) &&
@@ -71,4 +92,6 @@
         int hash = 5;
         hash = 89 * hash + (this.url != null ? this.url.hashCode() : 0);
+        hash = 89 * hash + (this.isZip ? 1 : 0);
+        hash = 89 * hash + (this.zipEntryPath != null ? this.zipEntryPath.hashCode() : 0);
         hash = 89 * hash + (this.name != null ? this.name.hashCode() : 0);
         hash = 89 * hash + (this.title != null ? this.title.hashCode() : 0);
@@ -133,3 +156,13 @@
         return dir.getPath();
     }
+
+    /**
+     * Returns the parent directory of the resource inside the zip file.
+     * @return null, if zipEntryPath is null, otherwise the parent directory of
+     * the resource inside the zip file
+     */
+    public String getZipEntryDirName() {
+        if (zipEntryPath == null) return null;
+        return new File(zipEntryPath).getParent().toString();
+    }
 }
Index: trunk/src/org/openstreetmap/josm/gui/preferences/map/MapPaintPreference.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/preferences/map/MapPaintPreference.java	(revision 6147)
+++ trunk/src/org/openstreetmap/josm/gui/preferences/map/MapPaintPreference.java	(revision 6148)
@@ -41,5 +41,5 @@
     private static final List<SourceProvider> styleSourceProviders = new ArrayList<SourceProvider>();
 
-    public static final boolean registerSourceProvider(SourceProvider provider) {
+    public static boolean registerSourceProvider(SourceProvider provider) {
         if (provider != null)
             return styleSourceProviders.add(provider);
Index: trunk/src/org/openstreetmap/josm/gui/tagging/TaggingPresetReader.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/tagging/TaggingPresetReader.java	(revision 6147)
+++ trunk/src/org/openstreetmap/josm/gui/tagging/TaggingPresetReader.java	(revision 6148)
@@ -159,5 +159,5 @@
         MirroredInputStream s = new MirroredInputStream(source);
         try {
-            InputStream zip = s.getZipEntry("xml","preset");
+            InputStream zip = s.findZipEntryInputStream("xml","preset");
             if(zip != null) {
                 zipIcons = s.getFile();
Index: trunk/src/org/openstreetmap/josm/io/MirroredInputStream.java
===================================================================
--- trunk/src/org/openstreetmap/josm/io/MirroredInputStream.java	(revision 6147)
+++ trunk/src/org/openstreetmap/josm/io/MirroredInputStream.java	(revision 6148)
@@ -22,4 +22,5 @@
 
 import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.tools.Pair;
 import org.openstreetmap.josm.tools.Utils;
 
@@ -91,18 +92,41 @@
 
     /**
-     * Replies an input stream for a file in a ZIP-file. Replies a file in the top
-     * level directory of the ZIP file which has an extension <code>extension</code>. If more
-     * than one files have this extension, the last file whose name includes <code>namepart</code>
+     * Looks for a certain entry inside a zip file and returns the entry path.
+     *
+     * Replies a file in the top level directory of the ZIP file which has an
+     * extension <code>extension</code>. If more than one files have this
+     * extension, the last file whose name includes <code>namepart</code>
      * is opened.
      *
      * @param extension  the extension of the file we're looking for
      * @param namepart the name part
-     * @return an input stream. Null if this mirrored input stream doesn't represent a zip file or if
-     * there was no matching file in the ZIP file
-     */
+     * @return The zip entry path of the matching file. Null if this mirrored
+     * input stream doesn't represent a zip file or if there was no matching
+     * file in the ZIP file.
+     */
+    public String findZipEntryPath(String extension, String namepart) {
+        Pair<String, InputStream> ze = findZipEntryImpl(extension, namepart);
+        if (ze == null) return null;
+        return ze.a;
+    }
+
+    /**
+     * Like {@link #findZipEntryPath}, but returns the corresponding InputStream.
+     */
+    public InputStream findZipEntryInputStream(String extension, String namepart) {
+        Pair<String, InputStream> ze = findZipEntryImpl(extension, namepart);
+        if (ze == null) return null;
+        return ze.b;
+    }
+
+    @Deprecated // use findZipEntryInputStream
     public InputStream getZipEntry(String extension, String namepart) {
+        return findZipEntryInputStream(extension, namepart);
+    }
+
+    private Pair<String, InputStream> findZipEntryImpl(String extension, String namepart) {
         if (file == null)
             return null;
-        InputStream res = null;
+        Pair<String, InputStream> res = null;
         try {
             ZipFile zipFile = new ZipFile(file);
@@ -120,5 +144,6 @@
             }
             if (resentry != null) {
-                res = zipFile.getInputStream(resentry);
+                InputStream is = zipFile.getInputStream(resentry);
+                res = Pair.create(resentry.getName(), is);
             } else {
                 Utils.close(zipFile);
Index: trunk/src/org/openstreetmap/josm/tools/ImageProvider.java
===================================================================
--- trunk/src/org/openstreetmap/josm/tools/ImageProvider.java	(revision 6147)
+++ trunk/src/org/openstreetmap/josm/tools/ImageProvider.java	(revision 6148)
@@ -93,4 +93,5 @@
     protected String name;
     protected File archive;
+    protected String inArchiveDir;
     protected int width = -1;
     protected int height = -1;
@@ -153,4 +154,16 @@
     public ImageProvider setArchive(File archive) {
         this.archive = archive;
+        return this;
+    }
+
+    /**
+     * Specify a base path inside the zip file.
+     *
+     * The subdir and name will be relative to this path.
+     *
+     * (optional)
+     */
+    public ImageProvider setInArchiveDir(String inArchiveDir) {
+        this.inArchiveDir = inArchiveDir;
         return this;
     }
@@ -438,5 +451,5 @@
                     case ARCHIVE:
                         if (archive != null) {
-                            ir = getIfAvailableZip(full_name, archive, type);
+                            ir = getIfAvailableZip(full_name, archive, inArchiveDir, type);
                             if (ir != null) {
                                 cache.put(cache_name, ir);
@@ -521,10 +534,17 @@
     }
 
-    private static ImageResource getIfAvailableZip(String full_name, File archive, ImageType type) {
+    private static ImageResource getIfAvailableZip(String full_name, File archive, String inArchiveDir, ImageType type) {
         ZipFile zipFile = null;
         try
         {
             zipFile = new ZipFile(archive);
-            ZipEntry entry = zipFile.getEntry(full_name);
+            String entry_name;
+            if (inArchiveDir != null) {
+                File dir = new File(inArchiveDir);
+                entry_name = new File(dir, full_name).getPath();
+            } else {
+                entry_name = full_name;
+            }
+            ZipEntry entry = zipFile.getEntry(entry_name);
             if(entry != null)
             {
@@ -537,5 +557,5 @@
                     switch (type) {
                     case SVG:
-                        URI uri = getSvgUniverse().loadSVG(is, full_name);
+                        URI uri = getSvgUniverse().loadSVG(is, entry_name);
                         SVGDiagram svg = getSvgUniverse().getDiagram(uri);
                         return svg == null ? null : new ImageResource(svg);
