compiler Support for expression of non-breaking-space and zero-width-space in CSS
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/driver/js/royale/JSCSSCompilationSession.java b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/driver/js/royale/JSCSSCompilationSession.java
index 88a5d49..2b9d067 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/driver/js/royale/JSCSSCompilationSession.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/driver/js/royale/JSCSSCompilationSession.java
@@ -347,10 +347,22 @@
     
     private String escapeDoubleQuotes(String s)
     {
+        s = replaceUnicodeEncoded(s);
     	if (s.contains("\""))
     		s = s.replace("\"", "\\\"");
     	return s;
     }
+
+    private String replaceUnicodeEncoded(String s)
+    {
+        //almost all escape sequences are converted to actual character sequences, except for some that don't have
+        //a good result for Character.toChars (e.g. zero width space or non-breaking-space)
+        //convert hex char values to unicode
+        if (s.matches("\\\\[0-9a-fA-F]{1,4}")) {
+            s = s.replaceAll("\\\\([0-9a-fA-F]{1,4})\\s?","\\\\u$1");
+        }
+        return s;
+    }
     
     private String encodeRule(ICSSRule rule)
     {
@@ -378,7 +390,6 @@
 
         ImmutableList<ICSSSelector> slist = rule.getSelectorGroup();
         result.append(slist.size());
-
         for (ICSSSelector sel : slist)
         {
             result.append(",\n");
@@ -525,7 +536,7 @@
             }
             else if (value instanceof CSSStringPropertyValue)
             {
-                line.append("\"" + ((CSSStringPropertyValue)value).getValue() + "\"");
+                line.append("\"" + replaceUnicodeEncoded(((CSSStringPropertyValue)value).getValue()) + "\"");
             }
             else if (value instanceof CSSColorPropertyValue)
             {
diff --git a/compiler/src/main/antlr3/org/apache/royale/compiler/internal/css/CSS.g b/compiler/src/main/antlr3/org/apache/royale/compiler/internal/css/CSS.g
index e14dc99..37b631a 100644
--- a/compiler/src/main/antlr3/org/apache/royale/compiler/internal/css/CSS.g
+++ b/compiler/src/main/antlr3/org/apache/royale/compiler/internal/css/CSS.g
@@ -140,28 +140,32 @@
 
     // Check if there's white space between the previous token and the next token.
     final CommonToken lastToken = (CommonToken) getTokenStream().LT(-1);
-    final int lastType = lastToken.getType();
-    if (lastType == CHILD) 
-    { 
-        return 1;
-    }
-    if (lastType == PRECEDED)
+    if (lastToken != null)
     {
-        return 2;
-    }
-    if (lastType == TILDE)
-    {
-        return 3;
-    }
-    if (lastToken != null && nextToken != null)
-    {
-        final int lastStop = lastToken.getStopIndex();
-        final int nextStart = nextToken.getStartIndex();
-        if (lastStop + 1 < nextStart)
+        final int lastType = lastToken.getType();
+        if (lastType == CHILD)
         {
-            return 0;
+            return 1;
+        }
+        if (lastType == PRECEDED)
+        {
+            return 2;
+        }
+        if (lastType == TILDE)
+        {
+            return 3;
+        }
+        if (nextToken != null)
+        {
+            final int lastStop = lastToken.getStopIndex();
+            final int nextStart = nextToken.getStartIndex();
+            if (lastStop + 1 < nextStart)
+            {
+                return 0;
+            }
         }
     }
+
     
     // If the next token is "{" or ",", it's also end of a selector.
     if (nextType == BLOCK_OPEN || nextType == COMMA)
diff --git a/compiler/src/main/java/org/apache/royale/compiler/internal/css/CSSStringPropertyValue.java b/compiler/src/main/java/org/apache/royale/compiler/internal/css/CSSStringPropertyValue.java
index 22dd35b..c5c5a57 100644
--- a/compiler/src/main/java/org/apache/royale/compiler/internal/css/CSSStringPropertyValue.java
+++ b/compiler/src/main/java/org/apache/royale/compiler/internal/css/CSSStringPropertyValue.java
@@ -81,7 +81,8 @@
     {
         int idx = 0;
         int c = value.indexOf('\\');
-        while (c != -1)
+
+        while (c != -1 && c + 1 < value.length())
         {
             char cnext = value.charAt(c + 1);
             if (cnext != '\\' && cnext != 'n' && cnext != 't' && cnext != 'r')
@@ -94,15 +95,28 @@
                 for (; i < n; i++)
                 {
                     char cc = value.charAt(c + i + 1);
-                    if (cc != ' ')
+                    if (cc != ' ') {
                         sub.append(cc);
+                        idx++; //this represents each 'digit' char
+                    }
                     else
                         break;
                 }
+                idx++; //this represents the first escape char
                 int ccode = Integer.parseInt(sub.toString(), 16);
-                sub = new StringBuilder();
-                sub.append(Character.toChars(ccode));
-                value = value.substring(0, c) + sub.toString() + value.substring(c + i + 1);
+                String insert;
+
+                if (ccode == /* nbsp */ 0xA0) {
+                    insert = "\\a0"; //restore nbsp as the encoded form
+                } else if (ccode == /* ZERO WIDTH SPACE */ 0x200B) {
+                    insert = "\\200b"; //restore zero-width space as the encoded form
+                } else {
+                    sub = new StringBuilder();
+                    sub.append(Character.toChars(ccode));
+                    insert = sub.toString();
+                }
+
+                value = value.substring(0, c) + insert + value.substring(c + i + 1);
             }
             else
                 idx += 2;