diff options
author | Jonathan Gordon <rockbox@jdgordon.info> | 2012-02-02 22:26:16 +1100 |
---|---|---|
committer | Jonathan Gordon <rockbox@jdgordon.info> | 2012-02-07 21:41:18 +1100 |
commit | 40ecdf6811d9a717ef67ff1833a67dbb521f91be (patch) | |
tree | ddde16bbb941fb70515a6127339b0a2f176e224f | |
parent | f1eedb80a2efbf60cfc25182b72e3da07e0f1250 (diff) | |
download | rockbox-40ecdf6811d9a717ef67ff1833a67dbb521f91be.tar.gz rockbox-40ecdf6811d9a717ef67ff1833a67dbb521f91be.zip |
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<something>>
NEW: %?and(%C, %Ia)<something>
Change-Id: Ia3bbe4611cf808e87dcd1b1147181461fa08294a
-rw-r--r-- | apps/gui/skin_engine/skin_parser.c | 14 | ||||
-rw-r--r-- | apps/gui/skin_engine/skin_tokens.c | 26 | ||||
-rw-r--r-- | lib/skin_parser/skin_parser.c | 51 | ||||
-rw-r--r-- | lib/skin_parser/tag_table.c | 8 | ||||
-rw-r--r-- | lib/skin_parser/tag_table.h | 7 | ||||
-rw-r--r-- | manual/appendix/wps_tags.tex | 4 |
6 files changed, 83 insertions, 27 deletions
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, | |||
739 | token->value.i = i; | 739 | token->value.i = i; |
740 | return 0; | 740 | return 0; |
741 | } | 741 | } |
742 | |||
743 | static int parse_logical_andor(struct skin_element *element, | ||
744 | struct wps_token *token, | ||
745 | struct wps_data *wps_data) | ||
746 | { | ||
747 | (void)wps_data; | ||
748 | token->value.data = PTRTOSKINOFFSET(skin_buffer, element); | ||
749 | return 0; | ||
750 | } | ||
751 | |||
742 | static int parse_logical_if(struct skin_element *element, | 752 | static int parse_logical_if(struct skin_element *element, |
743 | struct wps_token *token, | 753 | struct wps_token *token, |
744 | struct wps_data *wps_data) | 754 | struct wps_data *wps_data) |
@@ -1946,6 +1956,10 @@ static int skin_element_callback(struct skin_element* element, void* data) | |||
1946 | case SKIN_TOKEN_LOGICAL_IF: | 1956 | case SKIN_TOKEN_LOGICAL_IF: |
1947 | function = parse_logical_if; | 1957 | function = parse_logical_if; |
1948 | break; | 1958 | break; |
1959 | case SKIN_TOKEN_LOGICAL_AND: | ||
1960 | case SKIN_TOKEN_LOGICAL_OR: | ||
1961 | function = parse_logical_andor; | ||
1962 | break; | ||
1949 | case SKIN_TOKEN_SUBSTRING: | 1963 | case SKIN_TOKEN_SUBSTRING: |
1950 | function = parse_substring_tag; | 1964 | function = parse_substring_tag; |
1951 | break; | 1965 | 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, | |||
887 | return get_lif_token_value(gwps, lif, offset, buf, buf_size); | 887 | return get_lif_token_value(gwps, lif, offset, buf, buf_size); |
888 | } | 888 | } |
889 | break; | 889 | break; |
890 | case SKIN_TOKEN_LOGICAL_AND: | ||
891 | case SKIN_TOKEN_LOGICAL_OR: | ||
892 | { | ||
893 | int i = 0, truecount = 0; | ||
894 | char *skinbuffer = get_skin_buffer(data); | ||
895 | struct skin_element *element = | ||
896 | SKINOFFSETTOPTR(skinbuffer, token->value.data); | ||
897 | struct skin_tag_parameter* params = | ||
898 | SKINOFFSETTOPTR(skinbuffer, element->params); | ||
899 | struct skin_tag_parameter* thistag; | ||
900 | for (i=0; i<element->params_count; i++) | ||
901 | { | ||
902 | thistag = ¶ms[i]; | ||
903 | struct skin_element *tokenelement = | ||
904 | SKINOFFSETTOPTR(skinbuffer, thistag->data.code); | ||
905 | out_text = get_token_value(gwps, | ||
906 | SKINOFFSETTOPTR(skinbuffer, tokenelement->data), | ||
907 | offset, buf, buf_size, intval); | ||
908 | if (out_text && *out_text) | ||
909 | truecount++; | ||
910 | else if (token->type == SKIN_TOKEN_LOGICAL_AND) | ||
911 | return NULL; | ||
912 | } | ||
913 | return truecount ? "true" : NULL; | ||
914 | } | ||
915 | break; | ||
890 | case SKIN_TOKEN_SUBSTRING: | 916 | case SKIN_TOKEN_SUBSTRING: |
891 | { | 917 | { |
892 | struct substring *ss = SKINOFFSETTOPTR(get_skin_buffer(data), token->value.data); | 918 | 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) | |||
513 | { | 513 | { |
514 | const char* cursor = *document + 1; | 514 | const char* cursor = *document + 1; |
515 | const char* bookmark; | 515 | const char* bookmark; |
516 | char *open_square_bracket = NULL; | ||
516 | 517 | ||
517 | char tag_name[3]; | 518 | char tag_name[MAX_TAG_LENGTH]; |
518 | char* tag_args; | 519 | char* tag_args; |
519 | const struct tag_info *tag; | 520 | const struct tag_info *tag; |
520 | struct skin_tag_parameter* params = NULL; | 521 | struct skin_tag_parameter* params = NULL; |
521 | 522 | ||
522 | int num_args = 1; | 523 | int num_args = 1; |
523 | int i; | 524 | int i; |
524 | int star = 0; /* Flag for the all-or-none option */ | 525 | int qmark = 0; /* Flag for the all-or-none option */ |
525 | 526 | ||
526 | int optional = 0; | 527 | int optional = 0; |
527 | 528 | ||
528 | /* Checking the tag name */ | 529 | /* Checking the tag name */ |
529 | tag_name[0] = cursor[0]; | 530 | for (i=0; cursor[i] && i<MAX_TAG_LENGTH; i++) |
530 | tag_name[1] = cursor[1]; | 531 | tag_name[i] = cursor[i]; |
531 | tag_name[2] = '\0'; | ||
532 | 532 | ||
533 | /* First we check the two characters after the '%', then a single char */ | 533 | /* First we check the two characters after the '%', then a single char */ |
534 | tag = find_tag(tag_name); | 534 | tag = NULL; |
535 | 535 | i = MAX_TAG_LENGTH; | |
536 | if(!tag) | 536 | while (!tag && i > 1) |
537 | { | 537 | { |
538 | tag_name[1] = '\0'; | 538 | tag_name[i-1] = '\0'; |
539 | tag = find_tag(tag_name); | 539 | tag = find_tag(tag_name); |
540 | cursor++; | 540 | i--; |
541 | } | ||
542 | else | ||
543 | { | ||
544 | cursor += 2; | ||
545 | } | 541 | } |
546 | 542 | ||
547 | if(!tag) | 543 | if(!tag) |
@@ -549,6 +545,7 @@ static int skin_parse_tag(struct skin_element* element, const char** document) | |||
549 | skin_error(ILLEGAL_TAG, cursor); | 545 | skin_error(ILLEGAL_TAG, cursor); |
550 | return 0; | 546 | return 0; |
551 | } | 547 | } |
548 | cursor += i; | ||
552 | 549 | ||
553 | /* Copying basic tag info */ | 550 | /* Copying basic tag info */ |
554 | if(element->type != CONDITIONAL && element->type != VIEWPORT) | 551 | if(element->type != CONDITIONAL && element->type != VIEWPORT) |
@@ -558,16 +555,16 @@ static int skin_parse_tag(struct skin_element* element, const char** document) | |||
558 | element->line = skin_line; | 555 | element->line = skin_line; |
559 | 556 | ||
560 | /* Checking for the * flag */ | 557 | /* Checking for the * flag */ |
561 | if(tag_args[0] == '*') | 558 | if(tag_args[0] == '?') |
562 | { | 559 | { |
563 | star = 1; | 560 | qmark = 1; |
564 | tag_args++; | 561 | tag_args++; |
565 | } | 562 | } |
566 | 563 | ||
567 | /* If this tag has no arguments, we can bail out now */ | 564 | /* If this tag has no arguments, we can bail out now */ |
568 | if(strlen(tag_args) == 0 | 565 | if(strlen(tag_args) == 0 |
569 | || (tag_args[0] == '|' && *cursor != ARGLISTOPENSYM) | 566 | || (tag_args[0] == '|' && *cursor != ARGLISTOPENSYM) |
570 | || (star && *cursor != ARGLISTOPENSYM)) | 567 | || (qmark && *cursor != ARGLISTOPENSYM)) |
571 | { | 568 | { |
572 | 569 | ||
573 | #ifdef ROCKBOX | 570 | #ifdef ROCKBOX |
@@ -663,6 +660,7 @@ static int skin_parse_tag(struct skin_element* element, const char** document) | |||
663 | bool canbedefault = false; | 660 | bool canbedefault = false; |
664 | bool haspercent = false, number = true, hasdecimal = false; | 661 | bool haspercent = false, number = true, hasdecimal = false; |
665 | char temp_params[8]; | 662 | char temp_params[8]; |
663 | open_square_bracket = tag_args; | ||
666 | tag_args++; | 664 | tag_args++; |
667 | while (*tag_args != ']') | 665 | while (*tag_args != ']') |
668 | { | 666 | { |
@@ -681,7 +679,7 @@ static int skin_parse_tag(struct skin_element* element, const char** document) | |||
681 | (cursor[j] == '-')); | 679 | (cursor[j] == '-')); |
682 | j++; | 680 | j++; |
683 | } | 681 | } |
684 | type_code = '*'; | 682 | type_code = '?'; |
685 | if (canbedefault && *cursor == DEFAULTSYM && !isdigit(cursor[1])) | 683 | if (canbedefault && *cursor == DEFAULTSYM && !isdigit(cursor[1])) |
686 | { | 684 | { |
687 | type_code = 'i'; | 685 | type_code = 'i'; |
@@ -704,7 +702,7 @@ static int skin_parse_tag(struct skin_element* element, const char** document) | |||
704 | { | 702 | { |
705 | type_code = 's'; | 703 | type_code = 's'; |
706 | } | 704 | } |
707 | if (type_code == '*') | 705 | if (type_code == '?') |
708 | { | 706 | { |
709 | skin_error(INSUFFICIENT_ARGS, cursor); | 707 | skin_error(INSUFFICIENT_ARGS, cursor); |
710 | return 0; | 708 | return 0; |
@@ -768,8 +766,7 @@ static int skin_parse_tag(struct skin_element* element, const char** document) | |||
768 | params[i].type = DECIMAL; | 766 | params[i].type = DECIMAL; |
769 | params[i].data.number = val; | 767 | params[i].data.number = val; |
770 | } | 768 | } |
771 | else if(tolower(type_code) == 'n' || | 769 | else if(tolower(type_code) == 's' || tolower(type_code) == 'f') |
772 | tolower(type_code) == 's' || tolower(type_code) == 'f') | ||
773 | { | 770 | { |
774 | /* Scanning a string argument */ | 771 | /* Scanning a string argument */ |
775 | params[i].type = STRING; | 772 | params[i].type = STRING; |
@@ -813,7 +810,17 @@ static int skin_parse_tag(struct skin_element* element, const char** document) | |||
813 | cursor++; | 810 | cursor++; |
814 | } | 811 | } |
815 | 812 | ||
816 | if (*tag_args != 'N') | 813 | if (*(tag_args + 1) == '*') |
814 | { | ||
815 | if (i+1 == num_args) | ||
816 | tag_args += 2; | ||
817 | else if (open_square_bracket) | ||
818 | { | ||
819 | tag_args = open_square_bracket; | ||
820 | open_square_bracket = NULL; | ||
821 | } | ||
822 | } | ||
823 | else | ||
817 | tag_args++; | 824 | tag_args++; |
818 | 825 | ||
819 | /* Checking for the optional bar */ | 826 | /* 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 @@ | |||
22 | #include "tag_table.h" | 22 | #include "tag_table.h" |
23 | 23 | ||
24 | #include <string.h> | 24 | #include <string.h> |
25 | #define BAR_PARAMS "*iiii|sN" | 25 | #define BAR_PARAMS "?iiii|s^" |
26 | /* The tag definition table */ | 26 | /* The tag definition table */ |
27 | static const struct tag_info legal_tags[] = | 27 | static const struct tag_info legal_tags[] = |
28 | { | 28 | { |
@@ -34,6 +34,8 @@ static const struct tag_info legal_tags[] = | |||
34 | { SKIN_TOKEN_ALIGN_LANGDIRECTION, "ax", "", 0 }, | 34 | { SKIN_TOKEN_ALIGN_LANGDIRECTION, "ax", "", 0 }, |
35 | 35 | ||
36 | { SKIN_TOKEN_LOGICAL_IF, "if", "TS[ITS]|D", SKIN_REFRESH_DYNAMIC }, | 36 | { SKIN_TOKEN_LOGICAL_IF, "if", "TS[ITS]|D", SKIN_REFRESH_DYNAMIC }, |
37 | { SKIN_TOKEN_LOGICAL_AND, "and", "T*", SKIN_REFRESH_DYNAMIC }, | ||
38 | { SKIN_TOKEN_LOGICAL_OR, "or", "T*", SKIN_REFRESH_DYNAMIC }, | ||
37 | 39 | ||
38 | { SKIN_TOKEN_BATTERY_PERCENT, "bl" , BAR_PARAMS, SKIN_REFRESH_DYNAMIC }, | 40 | { SKIN_TOKEN_BATTERY_PERCENT, "bl" , BAR_PARAMS, SKIN_REFRESH_DYNAMIC }, |
39 | { SKIN_TOKEN_BATTERY_VOLTS, "bv", "", SKIN_REFRESH_DYNAMIC }, | 41 | { SKIN_TOKEN_BATTERY_VOLTS, "bv", "", SKIN_REFRESH_DYNAMIC }, |
@@ -214,10 +216,10 @@ static const struct tag_info legal_tags[] = | |||
214 | /* HACK Alert (jdgordon): The next two tags have hacks so we could | 216 | /* HACK Alert (jdgordon): The next two tags have hacks so we could |
215 | * add a S param at the front without breaking old skins. | 217 | * add a S param at the front without breaking old skins. |
216 | * [SD]D <- handled by the callback, allows SD or S or D params | 218 | * [SD]D <- handled by the callback, allows SD or S or D params |
217 | * [SI]III[SI]|SN -< SIIIIS|S or IIIIS|S | 219 | * [SI]III[SI]|SN <- SIIIIS|S or IIIIS|S |
218 | * keep in sync with parse_touchregion() and parse_lasttouch() */ | 220 | * keep in sync with parse_touchregion() and parse_lasttouch() */ |
219 | { SKIN_TOKEN_LASTTOUCH, "Tl" , "|[SD]D", SKIN_REFRESH_DYNAMIC }, | 221 | { SKIN_TOKEN_LASTTOUCH, "Tl" , "|[SD]D", SKIN_REFRESH_DYNAMIC }, |
220 | { SKIN_TOKEN_TOUCHREGION, "T" , "[SI]III[SI]|SN", 0|NOBREAK }, | 222 | { SKIN_TOKEN_TOUCHREGION, "T" , "[SI]III[SI]|S*", 0|NOBREAK }, |
221 | 223 | ||
222 | { SKIN_TOKEN_HAVE_TOUCH, "Tp", "", FEATURE_TAG }, | 224 | { SKIN_TOKEN_HAVE_TOUCH, "Tp", "", FEATURE_TAG }, |
223 | 225 | ||
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" | |||
27 | { | 27 | { |
28 | #endif | 28 | #endif |
29 | 29 | ||
30 | #define MAX_TAG_LENGTH 4 /* includes the \0 */ | ||
30 | #define MAX_TAG_PARAMS 12 | 31 | #define MAX_TAG_PARAMS 12 |
31 | 32 | ||
32 | #define NOBREAK 0x1 /* Flag to tell the renderer not to insert a line break */ | 33 | #define NOBREAK 0x1 /* Flag to tell the renderer not to insert a line break */ |
@@ -73,6 +74,8 @@ enum skin_token_type { | |||
73 | 74 | ||
74 | /* Conditional */ | 75 | /* Conditional */ |
75 | SKIN_TOKEN_LOGICAL_IF, | 76 | SKIN_TOKEN_LOGICAL_IF, |
77 | SKIN_TOKEN_LOGICAL_AND, | ||
78 | SKIN_TOKEN_LOGICAL_OR, | ||
76 | SKIN_TOKEN_CONDITIONAL, | 79 | SKIN_TOKEN_CONDITIONAL, |
77 | SKIN_TOKEN_CONDITIONAL_START, | 80 | SKIN_TOKEN_CONDITIONAL_START, |
78 | SKIN_TOKEN_CONDITIONAL_OPTION, | 81 | SKIN_TOKEN_CONDITIONAL_OPTION, |
@@ -301,7 +304,7 @@ enum skin_token_type { | |||
301 | * f - Nullable file name | 304 | * f - Nullable file name |
302 | * C - Required skin code | 305 | * C - Required skin code |
303 | * T - Required single skin tag | 306 | * T - Required single skin tag |
304 | * N - any amount of strings.. must be the last param in the list | 307 | * * - Any amonut of the previous tag (or group if after a [] |
305 | * \n - causes the parser to eat everything up to and including the \n | 308 | * \n - causes the parser to eat everything up to and including the \n |
306 | * MUST be the last character of the prams string | 309 | * MUST be the last character of the prams string |
307 | * Any nullable parameter may be replaced in the WPS file | 310 | * Any nullable parameter may be replaced in the WPS file |
@@ -315,7 +318,7 @@ enum skin_token_type { | |||
315 | * To specify multiple instances of the same type, put a | 318 | * To specify multiple instances of the same type, put a |
316 | * number before the character. For instance, the string... | 319 | * number before the character. For instance, the string... |
317 | * 2s | 320 | * 2s |
318 | * will specify two strings. An asterisk (*) at the beginning of the | 321 | * will specify two strings. A ? at the beginning of the |
319 | * string will specify that you may choose to omit all arguments | 322 | * string will specify that you may choose to omit all arguments |
320 | * | 323 | * |
321 | * You may also group param types in [] which will tell the parser to | 324 | * 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)} | |||
565 | \config{operand}: either a second tag, a number, or text.\newline | 565 | \config{operand}: either a second tag, a number, or text.\newline |
566 | \config{[option count]}: optional parameter used to select which parameter | 566 | \config{[option count]}: optional parameter used to select which parameter |
567 | of a tag to use when the tag has multiple options, e.g. \%?pv<a|b|c|d>\\ | 567 | of a tag to use when the tag has multiple options, e.g. \%?pv<a|b|c|d>\\ |
568 | \config{\%and(tag1, tag2, ..., tagN)}\newline | ||
569 | & Logical ``and'' operator. Will be evaluate to true if all the tag parameters are true.\\ | ||
570 | \config{\%or(tag1, tag2, ..., tagN)}\newline | ||
571 | & Logical ``or'' operator. Will be evaluate to true if any of the tag parameters are true.\\ | ||
568 | \end{tagmap} | 572 | \end{tagmap} |
569 | 573 | ||
570 | Examples of the \%if tag:\\ | 574 | Examples of the \%if tag:\\ |