Change %xd to allow for a number to be used to specify the subimage. i.e %xd(Ac) can now we written as %xd(A, 3). subimage count start at 1 so a=1, b=2 etc.
Also adds the possibility to specify a set of params which a tag can have (i.e a tag or a integer)


git-svn-id: svn://svn.rockbox.org/rockbox/trunk@27812 a1c6a512-1295-4272-9138-f99709370657
diff --git a/apps/gui/skin_engine/skin_parser.c b/apps/gui/skin_engine/skin_parser.c
index 39eefc6..90c5938 100644
--- a/apps/gui/skin_engine/skin_parser.c
+++ b/apps/gui/skin_engine/skin_parser.c
@@ -243,6 +243,7 @@
     }
     id->label = label;
     id->offset = 0;
+    id->token = NULL;
     img->using_preloaded_icons = false;
     if (!strcmp(img->bm.data, "__list_icons__"))
     {
@@ -253,19 +254,21 @@
     
     if (element->params_count > 1)
     {
-        id->token = element->params[1].data.code->data;
+        if (element->params[1].type == CODE)
+            id->token = element->params[1].data.code->data;
+        /* specify a number. 1 being the first subimage (i.e top) NOT 0 */
+        else if (element->params[1].type == INTEGER)
+            id->subimage = element->params[1].data.number - 1;
         if (element->params_count > 2)
             id->offset = element->params[2].data.number;
     }
     else
     {
-        id->token = NULL;
         if ((subimage = get_image_id(sublabel)) != -1)
         {
             if (subimage >= img->num_subimages)
                 return WPS_ERROR_INVALID_PARAM;
             id->subimage = subimage;
-            token->value.i = label | (subimage << 8);
         } else {
             id->subimage = 0;
         }
diff --git a/lib/skin_parser/skin_parser.c b/lib/skin_parser/skin_parser.c
index fba074f..66deaab 100644
--- a/lib/skin_parser/skin_parser.c
+++ b/lib/skin_parser/skin_parser.c
@@ -579,6 +579,7 @@
     /* Now we have to actually parse each argument */
     for(i = 0; i < num_args; i++)
     {
+        char type_code;
         /* Making sure we haven't run out of arguments */
         if(*tag_args == '\0')
         {
@@ -600,14 +601,71 @@
         /* Checking for comments */
         if(*cursor == COMMENTSYM)
             skip_comment(&cursor);
-
+            
+        if (*tag_args == '[')
+        {
+            /* we need to guess which type of param it is. 
+             * guess using this priority:
+             * default > decimal/integer > single tag/code > string
+             */
+            int j=0;
+            bool canbedefault = false;
+            bool haspercent = false, number = true, hasdecimal = false;
+            char temp_params[8];
+            tag_args++;
+            while (*tag_args != ']')
+            {
+                if (*tag_args >= 'a' && *tag_args <= 'z')
+                    canbedefault = true;
+                temp_params[j++] = tolower(*tag_args++);
+            }
+            temp_params[j] = '\0';
+            j = 0;
+            while (cursor[j] != ',' && cursor[j] != ')')
+            {
+                haspercent = haspercent || (cursor[j] == '%');
+                hasdecimal = hasdecimal || (cursor[j] == '.');
+                number = number && (isdigit(cursor[j]) || (cursor[j] == '.'));
+                j++;
+            }
+            type_code = '*';
+            if (canbedefault && *cursor == DEFAULTSYM && !isdigit(cursor[1]))
+            {
+                type_code = 'i';
+            }
+            else if (number && hasdecimal && strchr(temp_params, 'd'))
+            {
+                type_code = 'd';
+            }
+            else if (number && 
+                     (strchr(temp_params, 'i') || strchr(temp_params, 'd')))
+            {
+                type_code = strchr(temp_params, 'i') ? 'i' : 'd';
+            }
+            else if (haspercent && 
+                    (strchr(temp_params, 't') || strchr(temp_params, 'c')))
+            {
+                type_code = strchr(temp_params, 't') ? 't' : 'c';
+            }
+            else if (strchr(temp_params, 's'))
+            {
+                type_code = 's';
+            }
+            if (type_code == '*')
+            {
+                skin_error(INSUFFICIENT_ARGS, cursor);
+                return 0;
+            }   
+        }
+        else
+            type_code = *tag_args;
         /* Storing the type code */
-        element->params[i].type_code = *tag_args;
+        element->params[i].type_code = type_code;
 
         /* Checking a nullable argument for null. */
         if(*cursor == DEFAULTSYM && !isdigit(cursor[1]))
         {
-            if(islower(*tag_args))
+            if(islower(type_code))
             {
                 element->params[i].type = DEFAULT;
                 cursor++;
@@ -618,7 +676,7 @@
                 return 0;
             }
         }
-        else if(tolower(*tag_args) == 'i')
+        else if(tolower(type_code) == 'i')
         {
             /* Scanning an int argument */
             if(!isdigit(*cursor) && *cursor != '-')
@@ -630,7 +688,7 @@
             element->params[i].type = INTEGER;
             element->params[i].data.number = scan_int(&cursor);
         }
-        else if(tolower(*tag_args) == 'd')
+        else if(tolower(type_code) == 'd')
         {
             int val = 0;
             bool have_point = false;
@@ -657,15 +715,15 @@
             element->params[i].type = DECIMAL;
             element->params[i].data.number = val;
         }
-        else if(tolower(*tag_args) == 'n' ||
-                tolower(*tag_args) == 's' || tolower(*tag_args) == 'f')
+        else if(tolower(type_code) == 'n' ||
+                tolower(type_code) == 's' || tolower(type_code) == 'f')
         {
             /* Scanning a string argument */
             element->params[i].type = STRING;
             element->params[i].data.text = scan_string(&cursor);
 
         }
-        else if(tolower(*tag_args) == 'c')
+        else if(tolower(type_code) == 'c')
         {
             /* Recursively parsing a code argument */
             element->params[i].type = CODE;
@@ -673,7 +731,7 @@
             if(!element->params[i].data.code)
                 return 0;
         }
-        else if (tolower(*tag_args) == 't')
+        else if (tolower(type_code) == 't')
         {
             struct skin_element* child = skin_alloc_element();
             child->type = TAG;
diff --git a/lib/skin_parser/tag_table.c b/lib/skin_parser/tag_table.c
index dccb9f8..4f201ec 100644
--- a/lib/skin_parser/tag_table.c
+++ b/lib/skin_parser/tag_table.c
@@ -167,7 +167,7 @@
     { SKIN_TOKEN_DRAW_INBUILTBAR,       "wi", "", SKIN_REFRESH_STATIC|NOBREAK },
     
     { SKIN_TOKEN_IMAGE_PRELOAD,         "xl", "SFII|I", 0|NOBREAK },
-    { SKIN_TOKEN_IMAGE_PRELOAD_DISPLAY, "xd", "S|TI", 0 },
+    { SKIN_TOKEN_IMAGE_PRELOAD_DISPLAY, "xd", "S|[IT]I", 0 },
     { SKIN_TOKEN_IMAGE_DISPLAY,         "x", "SFII", 0|NOBREAK },
     
     { SKIN_TOKEN_LOAD_FONT,             "Fl" , "IF", 0|NOBREAK },
diff --git a/lib/skin_parser/tag_table.h b/lib/skin_parser/tag_table.h
index c96fecc..4b7efaa 100644
--- a/lib/skin_parser/tag_table.h
+++ b/lib/skin_parser/tag_table.h
@@ -291,6 +291,10 @@
  *             2s
  *          will specify two strings.  An asterisk (*) at the beginning of the
  *          string will specify that you may choose to omit all arguments
+ * 
+ *          You may also group param types in [] which will tell the parser to 
+ *          accept any *one* of those types for that param. i.e [IT] will
+ *          accept either an integer or tag type. [ITs] will also accept a string or -
  *
  */
 struct tag_info