From 40ecdf6811d9a717ef67ff1833a67dbb521f91be Mon Sep 17 00:00:00 2001 From: Jonathan Gordon Date: Thu, 2 Feb 2012 22:26:16 +1100 Subject: skin engine: New logical 'and' and 'or' tags to evaluate multiple tags in a single conditional. Use these tags to stop having multiple conditionals.. e.g: OLD: %?C<%?Ia> NEW: %?and(%C, %Ia) Change-Id: Ia3bbe4611cf808e87dcd1b1147181461fa08294a --- lib/skin_parser/skin_parser.c | 51 ++++++++++++++++++++++++------------------- lib/skin_parser/tag_table.c | 8 ++++--- lib/skin_parser/tag_table.h | 7 ++++-- 3 files changed, 39 insertions(+), 27 deletions(-) (limited to 'lib/skin_parser') diff --git a/lib/skin_parser/skin_parser.c b/lib/skin_parser/skin_parser.c index 24f64fd788..a81bcded34 100644 --- a/lib/skin_parser/skin_parser.c +++ b/lib/skin_parser/skin_parser.c @@ -513,35 +513,31 @@ static int skin_parse_tag(struct skin_element* element, const char** document) { const char* cursor = *document + 1; const char* bookmark; + char *open_square_bracket = NULL; - char tag_name[3]; + char tag_name[MAX_TAG_LENGTH]; char* tag_args; const struct tag_info *tag; struct skin_tag_parameter* params = NULL; int num_args = 1; int i; - int star = 0; /* Flag for the all-or-none option */ + int qmark = 0; /* Flag for the all-or-none option */ int optional = 0; /* Checking the tag name */ - tag_name[0] = cursor[0]; - tag_name[1] = cursor[1]; - tag_name[2] = '\0'; + for (i=0; cursor[i] && i 1) { - tag_name[1] = '\0'; + tag_name[i-1] = '\0'; tag = find_tag(tag_name); - cursor++; - } - else - { - cursor += 2; + i--; } if(!tag) @@ -549,6 +545,7 @@ static int skin_parse_tag(struct skin_element* element, const char** document) skin_error(ILLEGAL_TAG, cursor); return 0; } + cursor += i; /* Copying basic tag info */ if(element->type != CONDITIONAL && element->type != VIEWPORT) @@ -558,16 +555,16 @@ static int skin_parse_tag(struct skin_element* element, const char** document) element->line = skin_line; /* Checking for the * flag */ - if(tag_args[0] == '*') + if(tag_args[0] == '?') { - star = 1; + qmark = 1; tag_args++; } /* If this tag has no arguments, we can bail out now */ if(strlen(tag_args) == 0 || (tag_args[0] == '|' && *cursor != ARGLISTOPENSYM) - || (star && *cursor != ARGLISTOPENSYM)) + || (qmark && *cursor != ARGLISTOPENSYM)) { #ifdef ROCKBOX @@ -663,6 +660,7 @@ static int skin_parse_tag(struct skin_element* element, const char** document) bool canbedefault = false; bool haspercent = false, number = true, hasdecimal = false; char temp_params[8]; + open_square_bracket = tag_args; tag_args++; while (*tag_args != ']') { @@ -681,7 +679,7 @@ static int skin_parse_tag(struct skin_element* element, const char** document) (cursor[j] == '-')); j++; } - type_code = '*'; + type_code = '?'; if (canbedefault && *cursor == DEFAULTSYM && !isdigit(cursor[1])) { type_code = 'i'; @@ -704,7 +702,7 @@ static int skin_parse_tag(struct skin_element* element, const char** document) { type_code = 's'; } - if (type_code == '*') + if (type_code == '?') { skin_error(INSUFFICIENT_ARGS, cursor); return 0; @@ -768,8 +766,7 @@ static int skin_parse_tag(struct skin_element* element, const char** document) params[i].type = DECIMAL; params[i].data.number = val; } - else if(tolower(type_code) == 'n' || - tolower(type_code) == 's' || tolower(type_code) == 'f') + else if(tolower(type_code) == 's' || tolower(type_code) == 'f') { /* Scanning a string argument */ params[i].type = STRING; @@ -813,7 +810,17 @@ static int skin_parse_tag(struct skin_element* element, const char** document) cursor++; } - if (*tag_args != 'N') + if (*(tag_args + 1) == '*') + { + if (i+1 == num_args) + tag_args += 2; + else if (open_square_bracket) + { + tag_args = open_square_bracket; + open_square_bracket = NULL; + } + } + else tag_args++; /* Checking for the optional bar */ diff --git a/lib/skin_parser/tag_table.c b/lib/skin_parser/tag_table.c index dda5074d9a..f8fbb99c18 100644 --- a/lib/skin_parser/tag_table.c +++ b/lib/skin_parser/tag_table.c @@ -22,7 +22,7 @@ #include "tag_table.h" #include -#define BAR_PARAMS "*iiii|sN" +#define BAR_PARAMS "?iiii|s^" /* The tag definition table */ static const struct tag_info legal_tags[] = { @@ -34,6 +34,8 @@ static const struct tag_info legal_tags[] = { SKIN_TOKEN_ALIGN_LANGDIRECTION, "ax", "", 0 }, { SKIN_TOKEN_LOGICAL_IF, "if", "TS[ITS]|D", SKIN_REFRESH_DYNAMIC }, + { SKIN_TOKEN_LOGICAL_AND, "and", "T*", SKIN_REFRESH_DYNAMIC }, + { SKIN_TOKEN_LOGICAL_OR, "or", "T*", SKIN_REFRESH_DYNAMIC }, { SKIN_TOKEN_BATTERY_PERCENT, "bl" , BAR_PARAMS, SKIN_REFRESH_DYNAMIC }, { SKIN_TOKEN_BATTERY_VOLTS, "bv", "", SKIN_REFRESH_DYNAMIC }, @@ -214,10 +216,10 @@ static const struct tag_info legal_tags[] = /* HACK Alert (jdgordon): The next two tags have hacks so we could * add a S param at the front without breaking old skins. * [SD]D <- handled by the callback, allows SD or S or D params - * [SI]III[SI]|SN -< SIIIIS|S or IIIIS|S + * [SI]III[SI]|SN <- SIIIIS|S or IIIIS|S * keep in sync with parse_touchregion() and parse_lasttouch() */ { SKIN_TOKEN_LASTTOUCH, "Tl" , "|[SD]D", SKIN_REFRESH_DYNAMIC }, - { SKIN_TOKEN_TOUCHREGION, "T" , "[SI]III[SI]|SN", 0|NOBREAK }, + { SKIN_TOKEN_TOUCHREGION, "T" , "[SI]III[SI]|S*", 0|NOBREAK }, { SKIN_TOKEN_HAVE_TOUCH, "Tp", "", FEATURE_TAG }, diff --git a/lib/skin_parser/tag_table.h b/lib/skin_parser/tag_table.h index 58c3869ea6..35316b749e 100644 --- a/lib/skin_parser/tag_table.h +++ b/lib/skin_parser/tag_table.h @@ -27,6 +27,7 @@ extern "C" { #endif +#define MAX_TAG_LENGTH 4 /* includes the \0 */ #define MAX_TAG_PARAMS 12 #define NOBREAK 0x1 /* Flag to tell the renderer not to insert a line break */ @@ -73,6 +74,8 @@ enum skin_token_type { /* Conditional */ SKIN_TOKEN_LOGICAL_IF, + SKIN_TOKEN_LOGICAL_AND, + SKIN_TOKEN_LOGICAL_OR, SKIN_TOKEN_CONDITIONAL, SKIN_TOKEN_CONDITIONAL_START, SKIN_TOKEN_CONDITIONAL_OPTION, @@ -301,7 +304,7 @@ enum skin_token_type { * f - Nullable file name * C - Required skin code * T - Required single skin tag - * N - any amount of strings.. must be the last param in the list + * * - Any amonut of the previous tag (or group if after a [] * \n - causes the parser to eat everything up to and including the \n * MUST be the last character of the prams string * Any nullable parameter may be replaced in the WPS file @@ -315,7 +318,7 @@ enum skin_token_type { * To specify multiple instances of the same type, put a * number before the character. For instance, the string... * 2s - * will specify two strings. An asterisk (*) at the beginning of the + * will specify two strings. A ? 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 -- cgit v1.2.3