Index: trunk/src/org/openstreetmap/josm/gui/mappaint/AreaElemStyle.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/mappaint/AreaElemStyle.java	(revision 3966)
+++ trunk/src/org/openstreetmap/josm/gui/mappaint/AreaElemStyle.java	(revision 3967)
@@ -78,6 +78,6 @@
 
         TextElement text = null;
-        String textPos = c.get("text-position", null, String.class);
-        if (textPos == null || Utils.equal(textPos, "center")) {
+        Keyword textPos = c.get("text-position", null, Keyword.class);
+        if (textPos == null || Utils.equal(textPos.val, "center")) {
             text = TextElement.create(c, PaintColors.AREA_TEXT.get());
         }
Index: trunk/src/org/openstreetmap/josm/gui/mappaint/Cascade.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/mappaint/Cascade.java	(revision 3966)
+++ trunk/src/org/openstreetmap/josm/gui/mappaint/Cascade.java	(revision 3967)
@@ -1,4 +1,6 @@
 // License: GPL. For details, see LICENSE file.
 package org.openstreetmap.josm.gui.mappaint;
+
+import static org.openstreetmap.josm.tools.Utils.equal;
 
 import java.awt.Color;
@@ -54,4 +56,20 @@
     }
 
+    public void put(String key, Object val) {
+        prop.put(key, val);
+    }
+
+    public void putOrClear(String key, Object val) {
+        if (val != null) {
+            prop.put(key, val);
+        } else {
+            prop.remove(key);
+        }
+    }
+
+    public void remove(String key) {
+        prop.remove(key);
+    }
+
     @SuppressWarnings("unchecked")
     public static <T> T convertTo(Object o, Class<T> klass) {
@@ -81,6 +99,10 @@
             return (T) toColor(o);
 
-        if (klass == String.class)
+        if (klass == String.class) {
+            if (o instanceof Keyword)
+                return (T) ((Keyword) o).val;
+
             return (T) o.toString();
+        }
 
         return null;
@@ -107,9 +129,9 @@
         if (o instanceof Boolean)
             return (Boolean) o;
-        if (o instanceof String) {
-            String s = (String) o;
-            if ("true".equals(o) || "yes".equals(o))
+        if (o instanceof Keyword) {
+            String s = ((Keyword) o).val;
+            if (equal(s, "true") || equal(s, "yes"))
                 return true;
-            if ("false".equals(o) || "no".equals(o))
+            if (equal(s, "false") || equal(s, "no"))
                 return false;
         }
@@ -138,26 +160,10 @@
     }
 
-     public static Color toColor(Object o) {
+    private static Color toColor(Object o) {
         if (o instanceof Color)
             return (Color) o;
-        if (o instanceof String)
-            return CSSColors.get((String) o);
-        return null;
-    }
-
-    public void put(String key, Object val) {
-        prop.put(key, val);
-    }
-
-    public void putOrClear(String key, Object val) {
-        if (val != null) {
-            prop.put(key, val);
-        } else {
-            prop.remove(key);
-        }
-    }
-
-    public void remove(String key) {
-        prop.remove(key);
+        if (o instanceof Keyword)
+            return CSSColors.get(((Keyword) o).val);
+        return null;
     }
 
Index: trunk/src/org/openstreetmap/josm/gui/mappaint/ElemStyle.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/mappaint/ElemStyle.java	(revision 3966)
+++ trunk/src/org/openstreetmap/josm/gui/mappaint/ElemStyle.java	(revision 3967)
@@ -33,4 +33,11 @@
     public abstract void paintPrimitive(OsmPrimitive primitive, MapPaintSettings paintSettings, MapPainter painter, boolean selected, boolean member);
 
+    /**
+     * Get a property value of type Width
+     * @param c the cascade
+     * @param key property key for the width value
+     * @param relativeTo reference width. Only needed, when relative width syntax
+     *              is used, e.g. "+4".
+     */
     protected static Float getWidth(Cascade c, String key, Float relativeTo) {
         Float width = c.get(key, null, Float.class, true);
@@ -39,10 +46,10 @@
                 return width;
         } else {
-            String width_key = c.get(key, null, String.class, true);
-            if (equal(width_key, "thinnest"))
+            Keyword widthKW = c.get(key, null, Keyword.class, true);
+            if (equal(widthKW, Keyword.THINNEST))
                 return 0f;
-            else if(equal(width_key, "default"))
+            if (equal(widthKW, Keyword.DEFAULT))
                 return (float) MapPaintSettings.INSTANCE.getDefaultSegmentWidth();
-            else if (relativeTo != null) {
+            if (relativeTo != null) {
                 RelativeFloat width_rel = c.get(key, null, RelativeFloat.class, true);
                 if (width_rel != null)
@@ -57,11 +64,11 @@
         float size = c.get("font-size", (float) Main.pref.getInteger("mappaint.fontsize", 8), Float.class);
         int weight = Font.PLAIN;
-        String weightStr = c.get("font-wheight", null, String.class);
-        if (equal(weightStr, "bold")) {
+        Keyword weightKW = c.get("font-wheight", null, Keyword.class);
+        if (weightKW != null && equal(weightKW, "bold")) {
             weight = Font.BOLD;
         }
         int style = Font.PLAIN;
-        String styleStr = c.get("font-style", null, String.class);
-        if (equal(styleStr, "italic")) {
+        Keyword styleKW = c.get("font-style", null, Keyword.class);
+        if (styleKW != null && equal(styleKW.val, "italic")) {
             style = Font.ITALIC;
         }
Index: trunk/src/org/openstreetmap/josm/gui/mappaint/Keyword.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/mappaint/Keyword.java	(revision 3967)
+++ trunk/src/org/openstreetmap/josm/gui/mappaint/Keyword.java	(revision 3967)
@@ -0,0 +1,36 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.gui.mappaint;
+
+import org.openstreetmap.josm.tools.Utils;
+
+public class Keyword {
+    public final String val;
+
+    public Keyword(String val) {
+        this.val = val.toLowerCase();
+    }
+
+    @Override
+    public String toString() {
+        return "Keyword{" + val + '}';
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj == null || getClass() != obj.getClass())
+            return false;
+        return Utils.equal(val, ((Keyword) obj).val);
+    }
+
+    @Override
+    public int hashCode() {
+        return val.hashCode();
+    }
+
+    public final static Keyword AUTO = new Keyword("auto");
+    public final static Keyword BOTTOM = new Keyword("bottom");
+    public final static Keyword CENTER = new Keyword("center");
+    public final static Keyword DEFAULT = new Keyword("default");
+    public final static Keyword RIGHT = new Keyword("right");
+    public final static Keyword THINNEST = new Keyword("thinnest");
+}
Index: trunk/src/org/openstreetmap/josm/gui/mappaint/LineElemStyle.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/mappaint/LineElemStyle.java	(revision 3966)
+++ trunk/src/org/openstreetmap/josm/gui/mappaint/LineElemStyle.java	(revision 3967)
@@ -21,5 +21,5 @@
         MultiCascade mc = new MultiCascade();
         Cascade c = mc.getOrCreateCascade("default");
-        c.put("width", "default");
+        c.put("width", Keyword.DEFAULT);
         c.put("color", color != null ? color : PaintColors.UNTAGGED.get());
         return createLine(new Environment(null, mc, "default", null));
@@ -103,5 +103,5 @@
 
         int alpha = 255;
-        Integer pAlpha = Utils.color_float2int(c.get("opacity", null, float.class));
+        Integer pAlpha = Utils.color_float2int(c.get("opacity", null, Float.class));
         if (pAlpha != null) {
             alpha = pAlpha;
@@ -136,25 +136,31 @@
         }
 
-        int cap;
-        String capStr = c.get(prefix + "linecap", null, String.class);
-        if (equal(capStr, "none")) {
-            cap = BasicStroke.CAP_BUTT;
-        } else if (equal(capStr, "round")) {
-            cap = BasicStroke.CAP_ROUND;
-        } else if (equal(capStr, "square")) {
-            cap = BasicStroke.CAP_SQUARE;
-        } else {
+        Integer cap = null;
+        Keyword capKW = c.get(prefix + "linecap", null, Keyword.class);
+        if (capKW != null) {
+            if (equal(capKW.val, "none")) {
+                cap = BasicStroke.CAP_BUTT;
+            } else if (equal(capKW.val, "round")) {
+                cap = BasicStroke.CAP_ROUND;
+            } else if (equal(capKW.val, "square")) {
+                cap = BasicStroke.CAP_SQUARE;
+            }
+        }
+        if (cap == null) {
             cap = dashes != null ? BasicStroke.CAP_BUTT : BasicStroke.CAP_ROUND;
         }
 
-        int join;
-        String joinStr = c.get(prefix + "linejoin", null, String.class);
-        if (equal(joinStr, "round")) {
-            join = BasicStroke.JOIN_ROUND;
-        } else if (equal(joinStr, "miter")) {
-            join = BasicStroke.JOIN_MITER;
-        } else if (equal(joinStr, "bevel")) {
-            join = BasicStroke.JOIN_BEVEL;
-        } else {
+        Integer join = null;
+        Keyword joinKW = c.get(prefix + "linejoin", null, Keyword.class);
+        if (joinKW != null) {
+            if (equal(joinKW.val, "round")) {
+                join = BasicStroke.JOIN_ROUND;
+            } else if (equal(joinKW.val, "miter")) {
+                join = BasicStroke.JOIN_MITER;
+            } else if (equal(joinKW.val, "bevel")) {
+                join = BasicStroke.JOIN_BEVEL;
+            }
+        }
+        if (join == null) {
             join = BasicStroke.JOIN_ROUND;
         }
@@ -177,6 +183,6 @@
         TextElement text = null;
         if (!casing) {
-            String textPos = c.get("text-position", null, String.class);
-            if (textPos == null || equal(textPos, "line")) {
+            Keyword textPos = c.get("text-position", null, Keyword.class);
+            if (textPos == null || equal(textPos.val, "line")) {
                 text = TextElement.create(c, PaintColors.TEXT.get());
             }
Index: trunk/src/org/openstreetmap/josm/gui/mappaint/MapPaintStyles.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/mappaint/MapPaintStyles.java	(revision 3966)
+++ trunk/src/org/openstreetmap/josm/gui/mappaint/MapPaintStyles.java	(revision 3967)
@@ -55,5 +55,5 @@
         @Override
         public String toString() {
-            return "IconReference{" + "iconName=" + iconName + " source=" + source.getDisplayString() + '}';
+            return "IconReference{" + "iconName='" + iconName + "' source='" + source.getDisplayString() + "'}";
         }
     }
Index: trunk/src/org/openstreetmap/josm/gui/mappaint/NodeElemStyle.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/mappaint/NodeElemStyle.java	(revision 3966)
+++ trunk/src/org/openstreetmap/josm/gui/mappaint/NodeElemStyle.java	(revision 3967)
@@ -121,5 +121,5 @@
 
     }
-    
+
     public static final NodeElemStyle SIMPLE_NODE_ELEMSTYLE;
     static {
@@ -171,14 +171,14 @@
         if (te != null) {
             HorizontalTextAlignment hAlign = HorizontalTextAlignment.RIGHT;
-            String hAlignStr = c.get("text-anchor-horizontal", null, String.class);
-            if (equal(hAlignStr, "left")) {
+            Keyword hAlignKW = c.get("text-anchor-horizontal", Keyword.RIGHT, Keyword.class);
+            if (equal(hAlignKW.val, "left")) {
                 hAlign = HorizontalTextAlignment.LEFT;
-            } else if (equal(hAlignStr, "center")) {
+            } else if (equal(hAlignKW.val, "center")) {
                 hAlign = HorizontalTextAlignment.CENTER;
-            } else if (equal(hAlignStr, "right")) {
+            } else if (equal(hAlignKW.val, "right")) {
                 hAlign = HorizontalTextAlignment.RIGHT;
             }
             VerticalTextAlignment vAlign = VerticalTextAlignment.BOTTOM;
-            String vAlignStr = c.get("text-anchor-vertical", null, String.class);
+            String vAlignStr = c.get("text-anchor-vertical", Keyword.BOTTOM, Keyword.class).val;
             if (equal(vAlignStr, "above")) {
                 vAlign = VerticalTextAlignment.ABOVE;
@@ -203,8 +203,10 @@
 
         SymbolShape shape;
-        String shapeStr = c.get("symbol-shape", null, String.class);
-        if (equal(shapeStr, "square")) {
+        Keyword shapeKW = c.get("symbol-shape", null, Keyword.class);
+        if (shapeKW == null)
+            return null;
+        if (equal(shapeKW, "square")) {
             shape = SymbolShape.SQUARE;
-        } else if (equal(shapeStr, "circle")) {
+        } else if (equal(shapeKW, "circle")) {
             shape = SymbolShape.CIRCLE;
         } else
Index: trunk/src/org/openstreetmap/josm/gui/mappaint/TextElement.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/mappaint/TextElement.java	(revision 3966)
+++ trunk/src/org/openstreetmap/josm/gui/mappaint/TextElement.java	(revision 3967)
@@ -12,4 +12,6 @@
 
 public class TextElement {
+    // textKey == null means automatic generation of text string, otherwise
+    // the corresponding tag value is used
     public String textKey;
     public Font font;
@@ -29,12 +31,13 @@
 
     public static TextElement create(Cascade c, Color defTextColor) {
-        String textStr = c.get("text", null, String.class);
-        if (textStr == null)
-            return null;
 
         String textKey = null;
-        if (!"auto".equalsIgnoreCase(textStr)) {
-            textKey = textStr;
-        }
+        Keyword textKW = c.get("text", null, Keyword.class, true);
+        if (textKW == null) {
+            textKey = c.get("text", null, String.class);
+            if (textKey == null)
+                return null;
+        } else if (!textKW.val.equals("auto"))
+            return null;
 
         Font font = ElemStyle.getFont(c);
Index: trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/parser/MapCSSParser.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/parser/MapCSSParser.java	(revision 3966)
+++ trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/parser/MapCSSParser.java	(revision 3967)
@@ -6,4 +6,5 @@
 import java.util.List;
 
+import org.openstreetmap.josm.gui.mappaint.Keyword;
 import org.openstreetmap.josm.gui.mappaint.mapcss.Condition;
 import org.openstreetmap.josm.gui.mappaint.mapcss.Expression;
@@ -1039,12 +1040,15 @@
 
   final public Object literal() throws ParseException {
-    Object val;
+    String val;
     Token t;
     float f;
     switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
     case IDENT:
+      t = jj_consume_token(IDENT);
+                    {if (true) return new Keyword(t.image);}
+      break;
     case STRING:
-      val = string_or_ident();
-                                {if (true) return val;}
+      val = string();
+                       {if (true) return val;}
       break;
     case PLUS:
@@ -1167,10 +1171,4 @@
   }
 
-  private boolean jj_3R_41() {
-    if (jj_scan_token(DOLLAR)) return true;
-    if (jj_scan_token(EQUAL)) return true;
-    return false;
-  }
-
   private boolean jj_3R_40() {
     if (jj_scan_token(CARET)) return true;
@@ -1273,4 +1271,9 @@
   }
 
+  private boolean jj_3R_85() {
+    if (jj_scan_token(HEXCOLOR)) return true;
+    return false;
+  }
+
   private boolean jj_3R_27() {
     if (jj_3R_50()) return true;
@@ -1279,9 +1282,10 @@
 
   private boolean jj_3R_84() {
-    if (jj_scan_token(HEXCOLOR)) return true;
+    if (jj_3R_28()) return true;
     return false;
   }
 
   private boolean jj_3R_83() {
+    if (jj_scan_token(PLUS)) return true;
     if (jj_3R_28()) return true;
     return false;
@@ -1304,11 +1308,10 @@
 
   private boolean jj_3R_82() {
-    if (jj_scan_token(PLUS)) return true;
-    if (jj_3R_28()) return true;
+    if (jj_3R_54()) return true;
     return false;
   }
 
   private boolean jj_3R_81() {
-    if (jj_3R_56()) return true;
+    if (jj_scan_token(IDENT)) return true;
     return false;
   }
@@ -1323,5 +1326,8 @@
     if (jj_3R_83()) {
     jj_scanpos = xsp;
-    if (jj_3R_84()) return true;
+    if (jj_3R_84()) {
+    jj_scanpos = xsp;
+    if (jj_3R_85()) return true;
+    }
     }
     }
@@ -1361,5 +1367,5 @@
   }
 
-  private boolean jj_3R_85() {
+  private boolean jj_3R_86() {
     if (jj_scan_token(COMMA)) return true;
     if (jj_3R_18()) return true;
@@ -1383,5 +1389,5 @@
     while (true) {
       xsp = jj_scanpos;
-      if (jj_3R_85()) { jj_scanpos = xsp; break; }
+      if (jj_3R_86()) { jj_scanpos = xsp; break; }
     }
     return false;
@@ -1850,4 +1856,10 @@
   private boolean jj_3R_42() {
     if (jj_scan_token(STAR)) return true;
+    if (jj_scan_token(EQUAL)) return true;
+    return false;
+  }
+
+  private boolean jj_3R_41() {
+    if (jj_scan_token(DOLLAR)) return true;
     if (jj_scan_token(EQUAL)) return true;
     return false;
Index: trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/parser/MapCSSParser.jj
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/parser/MapCSSParser.jj	(revision 3966)
+++ trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/parser/MapCSSParser.jj	(revision 3967)
@@ -11,4 +11,5 @@
 import java.util.List;
 
+import org.openstreetmap.josm.gui.mappaint.Keyword;
 import org.openstreetmap.josm.gui.mappaint.mapcss.Condition;
 import org.openstreetmap.josm.gui.mappaint.mapcss.Expression;
@@ -523,10 +524,12 @@
 Object literal() :
 {
-    Object val;
+    String val;
     Token t;
     float f;
 }
 {
-        val=string_or_ident() { return val; }
+        t=<IDENT> { return new Keyword(t.image); }
+    |
+        val=string() { return val; }
     |
         <PLUS> f=ufloat() { return new Instruction.RelativeFloat(f); }
Index: trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/parser/MapCSSParserTokenManager.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/parser/MapCSSParserTokenManager.java	(revision 3966)
+++ trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/parser/MapCSSParserTokenManager.java	(revision 3967)
@@ -4,4 +4,5 @@
 import java.util.ArrayList;
 import java.util.List;
+import org.openstreetmap.josm.gui.mappaint.Keyword;
 import org.openstreetmap.josm.gui.mappaint.mapcss.Condition;
 import org.openstreetmap.josm.gui.mappaint.mapcss.Expression;
Index: trunk/src/org/openstreetmap/josm/gui/mappaint/xml/XmlStyleSource.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/mappaint/xml/XmlStyleSource.java	(revision 3966)
+++ trunk/src/org/openstreetmap/josm/gui/mappaint/xml/XmlStyleSource.java	(revision 3967)
@@ -20,4 +20,5 @@
 import org.openstreetmap.josm.data.osm.Way;
 import org.openstreetmap.josm.gui.mappaint.Cascade;
+import org.openstreetmap.josm.gui.mappaint.Keyword;
 import org.openstreetmap.josm.gui.mappaint.MultiCascade;
 import org.openstreetmap.josm.gui.mappaint.Range;
@@ -288,5 +289,5 @@
                     if (icon.annotate != null) {
                         if (icon.annotate) {
-                            def.put("text", "auto");
+                            def.put("text", Keyword.AUTO);
                         } else {
                             def.remove("text");
@@ -352,6 +353,6 @@
             if (p.area != null) {
                 def.putOrClear("fill-color", p.area.color);
-                def.putOrClear("text-position", "center");
-                def.putOrClear("text", "auto");
+                def.putOrClear("text-position", Keyword.CENTER);
+                def.putOrClear("text", Keyword.AUTO);
                 def.remove("fill-image");
             }
