1
0
Fork 0
forked from len0rd/rockbox

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
This commit is contained in:
Jonathan Gordon 2012-02-02 22:26:16 +11:00
parent f1eedb80a2
commit 40ecdf6811
6 changed files with 83 additions and 27 deletions

View file

@ -739,6 +739,16 @@ static int parse_setting_and_lang(struct skin_element *element,
token->value.i = i; token->value.i = i;
return 0; 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, static int parse_logical_if(struct skin_element *element,
struct wps_token *token, struct wps_token *token,
struct wps_data *wps_data) 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: case SKIN_TOKEN_LOGICAL_IF:
function = parse_logical_if; function = parse_logical_if;
break; break;
case SKIN_TOKEN_LOGICAL_AND:
case SKIN_TOKEN_LOGICAL_OR:
function = parse_logical_andor;
break;
case SKIN_TOKEN_SUBSTRING: case SKIN_TOKEN_SUBSTRING:
function = parse_substring_tag; function = parse_substring_tag;
break; break;

View file

@ -887,6 +887,32 @@ const char *get_token_value(struct gui_wps *gwps,
return get_lif_token_value(gwps, lif, offset, buf, buf_size); return get_lif_token_value(gwps, lif, offset, buf, buf_size);
} }
break; 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; i<element->params_count; i++)
{
thistag = &params[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: case SKIN_TOKEN_SUBSTRING:
{ {
struct substring *ss = SKINOFFSETTOPTR(get_skin_buffer(data), token->value.data); struct substring *ss = SKINOFFSETTOPTR(get_skin_buffer(data), token->value.data);

View file

@ -513,35 +513,31 @@ static int skin_parse_tag(struct skin_element* element, const char** document)
{ {
const char* cursor = *document + 1; const char* cursor = *document + 1;
const char* bookmark; const char* bookmark;
char *open_square_bracket = NULL;
char tag_name[3]; char tag_name[MAX_TAG_LENGTH];
char* tag_args; char* tag_args;
const struct tag_info *tag; const struct tag_info *tag;
struct skin_tag_parameter* params = NULL; struct skin_tag_parameter* params = NULL;
int num_args = 1; int num_args = 1;
int i; 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; int optional = 0;
/* Checking the tag name */ /* Checking the tag name */
tag_name[0] = cursor[0]; for (i=0; cursor[i] && i<MAX_TAG_LENGTH; i++)
tag_name[1] = cursor[1]; tag_name[i] = cursor[i];
tag_name[2] = '\0';
/* First we check the two characters after the '%', then a single char */ /* First we check the two characters after the '%', then a single char */
tag = find_tag(tag_name); tag = NULL;
i = MAX_TAG_LENGTH;
if(!tag) while (!tag && i > 1)
{ {
tag_name[1] = '\0'; tag_name[i-1] = '\0';
tag = find_tag(tag_name); tag = find_tag(tag_name);
cursor++; i--;
}
else
{
cursor += 2;
} }
if(!tag) if(!tag)
@ -549,6 +545,7 @@ static int skin_parse_tag(struct skin_element* element, const char** document)
skin_error(ILLEGAL_TAG, cursor); skin_error(ILLEGAL_TAG, cursor);
return 0; return 0;
} }
cursor += i;
/* Copying basic tag info */ /* Copying basic tag info */
if(element->type != CONDITIONAL && element->type != VIEWPORT) 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; element->line = skin_line;
/* Checking for the * flag */ /* Checking for the * flag */
if(tag_args[0] == '*') if(tag_args[0] == '?')
{ {
star = 1; qmark = 1;
tag_args++; tag_args++;
} }
/* If this tag has no arguments, we can bail out now */ /* If this tag has no arguments, we can bail out now */
if(strlen(tag_args) == 0 if(strlen(tag_args) == 0
|| (tag_args[0] == '|' && *cursor != ARGLISTOPENSYM) || (tag_args[0] == '|' && *cursor != ARGLISTOPENSYM)
|| (star && *cursor != ARGLISTOPENSYM)) || (qmark && *cursor != ARGLISTOPENSYM))
{ {
#ifdef ROCKBOX #ifdef ROCKBOX
@ -663,6 +660,7 @@ static int skin_parse_tag(struct skin_element* element, const char** document)
bool canbedefault = false; bool canbedefault = false;
bool haspercent = false, number = true, hasdecimal = false; bool haspercent = false, number = true, hasdecimal = false;
char temp_params[8]; char temp_params[8];
open_square_bracket = tag_args;
tag_args++; tag_args++;
while (*tag_args != ']') while (*tag_args != ']')
{ {
@ -681,7 +679,7 @@ static int skin_parse_tag(struct skin_element* element, const char** document)
(cursor[j] == '-')); (cursor[j] == '-'));
j++; j++;
} }
type_code = '*'; type_code = '?';
if (canbedefault && *cursor == DEFAULTSYM && !isdigit(cursor[1])) if (canbedefault && *cursor == DEFAULTSYM && !isdigit(cursor[1]))
{ {
type_code = 'i'; type_code = 'i';
@ -704,7 +702,7 @@ static int skin_parse_tag(struct skin_element* element, const char** document)
{ {
type_code = 's'; type_code = 's';
} }
if (type_code == '*') if (type_code == '?')
{ {
skin_error(INSUFFICIENT_ARGS, cursor); skin_error(INSUFFICIENT_ARGS, cursor);
return 0; return 0;
@ -768,8 +766,7 @@ static int skin_parse_tag(struct skin_element* element, const char** document)
params[i].type = DECIMAL; params[i].type = DECIMAL;
params[i].data.number = val; params[i].data.number = val;
} }
else if(tolower(type_code) == 'n' || else if(tolower(type_code) == 's' || tolower(type_code) == 'f')
tolower(type_code) == 's' || tolower(type_code) == 'f')
{ {
/* Scanning a string argument */ /* Scanning a string argument */
params[i].type = STRING; params[i].type = STRING;
@ -813,7 +810,17 @@ static int skin_parse_tag(struct skin_element* element, const char** document)
cursor++; 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++; tag_args++;
/* Checking for the optional bar */ /* Checking for the optional bar */

View file

@ -22,7 +22,7 @@
#include "tag_table.h" #include "tag_table.h"
#include <string.h> #include <string.h>
#define BAR_PARAMS "*iiii|sN" #define BAR_PARAMS "?iiii|s^"
/* The tag definition table */ /* The tag definition table */
static const struct tag_info legal_tags[] = 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_ALIGN_LANGDIRECTION, "ax", "", 0 },
{ SKIN_TOKEN_LOGICAL_IF, "if", "TS[ITS]|D", SKIN_REFRESH_DYNAMIC }, { 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_PERCENT, "bl" , BAR_PARAMS, SKIN_REFRESH_DYNAMIC },
{ SKIN_TOKEN_BATTERY_VOLTS, "bv", "", 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 /* HACK Alert (jdgordon): The next two tags have hacks so we could
* add a S param at the front without breaking old skins. * add a S param at the front without breaking old skins.
* [SD]D <- handled by the callback, allows SD or S or D params * [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() */ * keep in sync with parse_touchregion() and parse_lasttouch() */
{ SKIN_TOKEN_LASTTOUCH, "Tl" , "|[SD]D", SKIN_REFRESH_DYNAMIC }, { 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 }, { SKIN_TOKEN_HAVE_TOUCH, "Tp", "", FEATURE_TAG },

View file

@ -27,6 +27,7 @@ extern "C"
{ {
#endif #endif
#define MAX_TAG_LENGTH 4 /* includes the \0 */
#define MAX_TAG_PARAMS 12 #define MAX_TAG_PARAMS 12
#define NOBREAK 0x1 /* Flag to tell the renderer not to insert a line break */ #define NOBREAK 0x1 /* Flag to tell the renderer not to insert a line break */
@ -73,6 +74,8 @@ enum skin_token_type {
/* Conditional */ /* Conditional */
SKIN_TOKEN_LOGICAL_IF, SKIN_TOKEN_LOGICAL_IF,
SKIN_TOKEN_LOGICAL_AND,
SKIN_TOKEN_LOGICAL_OR,
SKIN_TOKEN_CONDITIONAL, SKIN_TOKEN_CONDITIONAL,
SKIN_TOKEN_CONDITIONAL_START, SKIN_TOKEN_CONDITIONAL_START,
SKIN_TOKEN_CONDITIONAL_OPTION, SKIN_TOKEN_CONDITIONAL_OPTION,
@ -301,7 +304,7 @@ enum skin_token_type {
* f - Nullable file name * f - Nullable file name
* C - Required skin code * C - Required skin code
* T - Required single skin tag * 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 * \n - causes the parser to eat everything up to and including the \n
* MUST be the last character of the prams string * MUST be the last character of the prams string
* Any nullable parameter may be replaced in the WPS file * 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 * To specify multiple instances of the same type, put a
* number before the character. For instance, the string... * number before the character. For instance, the string...
* 2s * 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 * string will specify that you may choose to omit all arguments
* *
* You may also group param types in [] which will tell the parser to * You may also group param types in [] which will tell the parser to

View file

@ -565,6 +565,10 @@ Example: \config{\%ax\%V(\dots)}
\config{operand}: either a second tag, a number, or text.\newline \config{operand}: either a second tag, a number, or text.\newline
\config{[option count]}: optional parameter used to select which parameter \config{[option count]}: optional parameter used to select which parameter
of a tag to use when the tag has multiple options, e.g. \%?pv<a|b|c|d>\\ of a tag to use when the tag has multiple options, e.g. \%?pv<a|b|c|d>\\
\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} \end{tagmap}
Examples of the \%if tag:\\ Examples of the \%if tag:\\