diff --git a/apps/gui/skin_engine/skin_parser.c b/apps/gui/skin_engine/skin_parser.c index befc843891..0be88f4e69 100644 --- a/apps/gui/skin_engine/skin_parser.c +++ b/apps/gui/skin_engine/skin_parser.c @@ -739,6 +739,16 @@ static int parse_setting_and_lang(struct skin_element *element, token->value.i = i; return 0; } + +static int parse_logical_andor(struct skin_element *element, + struct wps_token *token, + struct wps_data *wps_data) +{ + (void)wps_data; + token->value.data = PTRTOSKINOFFSET(skin_buffer, element); + return 0; +} + static int parse_logical_if(struct skin_element *element, struct wps_token *token, struct wps_data *wps_data) @@ -1946,6 +1956,10 @@ static int skin_element_callback(struct skin_element* element, void* data) case SKIN_TOKEN_LOGICAL_IF: function = parse_logical_if; break; + case SKIN_TOKEN_LOGICAL_AND: + case SKIN_TOKEN_LOGICAL_OR: + function = parse_logical_andor; + break; case SKIN_TOKEN_SUBSTRING: function = parse_substring_tag; break; diff --git a/apps/gui/skin_engine/skin_tokens.c b/apps/gui/skin_engine/skin_tokens.c index bae8ae8f8e..82d96f6993 100644 --- a/apps/gui/skin_engine/skin_tokens.c +++ b/apps/gui/skin_engine/skin_tokens.c @@ -887,6 +887,32 @@ const char *get_token_value(struct gui_wps *gwps, return get_lif_token_value(gwps, lif, offset, buf, buf_size); } break; + case SKIN_TOKEN_LOGICAL_AND: + case SKIN_TOKEN_LOGICAL_OR: + { + int i = 0, truecount = 0; + char *skinbuffer = get_skin_buffer(data); + struct skin_element *element = + SKINOFFSETTOPTR(skinbuffer, token->value.data); + struct skin_tag_parameter* params = + SKINOFFSETTOPTR(skinbuffer, element->params); + struct skin_tag_parameter* thistag; + for (i=0; iparams_count; i++) + { + thistag = ¶ms[i]; + struct skin_element *tokenelement = + SKINOFFSETTOPTR(skinbuffer, thistag->data.code); + out_text = get_token_value(gwps, + SKINOFFSETTOPTR(skinbuffer, tokenelement->data), + offset, buf, buf_size, intval); + if (out_text && *out_text) + truecount++; + else if (token->type == SKIN_TOKEN_LOGICAL_AND) + return NULL; + } + return truecount ? "true" : NULL; + } + break; case SKIN_TOKEN_SUBSTRING: { struct substring *ss = SKINOFFSETTOPTR(get_skin_buffer(data), token->value.data); 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 diff --git a/manual/appendix/wps_tags.tex b/manual/appendix/wps_tags.tex index d882baadea..0096075695 100644 --- a/manual/appendix/wps_tags.tex +++ b/manual/appendix/wps_tags.tex @@ -565,6 +565,10 @@ Example: \config{\%ax\%V(\dots)} \config{operand}: either a second tag, a number, or text.\newline \config{[option count]}: optional parameter used to select which parameter of a tag to use when the tag has multiple options, e.g. \%?pv\\ +\config{\%and(tag1, tag2, ..., tagN)}\newline + & Logical ``and'' operator. Will be evaluate to true if all the tag parameters are true.\\ +\config{\%or(tag1, tag2, ..., tagN)}\newline + & Logical ``or'' operator. Will be evaluate to true if any of the tag parameters are true.\\ \end{tagmap} Examples of the \%if tag:\\