summaryrefslogtreecommitdiffstats
path: root/apps/gui/skin_engine/skin_parser.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/gui/skin_engine/skin_parser.c')
-rw-r--r--apps/gui/skin_engine/skin_parser.c458
1 files changed, 263 insertions, 195 deletions
diff --git a/apps/gui/skin_engine/skin_parser.c b/apps/gui/skin_engine/skin_parser.c
index b3840f689f..4d1526fcbc 100644
--- a/apps/gui/skin_engine/skin_parser.c
+++ b/apps/gui/skin_engine/skin_parser.c
@@ -343,11 +343,12 @@ static int parse_image_display(struct skin_element *element,
if (element->params_count > 1)
{
- if (get_param(element, 1)->type == CODE)
+ struct skin_tag_parameter *param1 = get_param(element, 1);
+ if (param1->type == CODE)
id->token = get_param_code(element, 1)->data;
/* specify a number. 1 being the first subimage (i.e top) NOT 0 */
- else if (get_param(element, 1)->type == INTEGER)
- id->subimage = get_param(element, 1)->data.number - 1;
+ else if (param1->type == INTEGER)
+ id->subimage = param1->data.number - 1;
if (element->params_count > 2)
id->offset = get_param(element, 2)->data.number;
}
@@ -391,14 +392,16 @@ static int parse_image_load(struct skin_element *element,
subimages = get_param(element, 2)->data.number;
else if (element->params_count > 3)
{
- if (get_param(element, 2)->type == PERCENT)
- x = get_param(element, 2)->data.number * curr_vp->vp.width / 1000;
+ struct skin_tag_parameter *param2 = get_param(element, 2);
+ struct skin_tag_parameter *param3 = get_param(element, 3);
+ if (param2->type == PERCENT)
+ x = param2->data.number * curr_vp->vp.width / 1000;
else
- x = get_param(element, 2)->data.number;
- if (get_param(element, 3)->type == PERCENT)
- y = get_param(element, 3)->data.number * curr_vp->vp.height / 1000;
+ x = param2->data.number;
+ if (param3->type == PERCENT)
+ y = param3->data.number * curr_vp->vp.height / 1000;
else
- y = get_param(element, 3)->data.number;
+ y = param3->data.number;
if (element->params_count == 5)
subimages = get_param(element, 4)->data.number;
@@ -423,12 +426,16 @@ static int parse_image_load(struct skin_element *element,
img->buflib_handle = -1;
img->is_9_segment = false;
img->loaded = false;
-
- /* save current viewport */
- img->vp = PTRTOSKINOFFSET(skin_buffer, &curr_vp->vp);
+ img->dither = false;
if (token->type == SKIN_TOKEN_IMAGE_DISPLAY)
+ {
token->value.data = PTRTOSKINOFFSET(skin_buffer, img);
+#ifdef HAVE_BACKDROP_IMAGE
+ if (curr_vp)
+ img->dither = curr_vp->output_to_backdrop_buffer;
+#endif
+ }
if (!strcmp(img->bm.data, "__list_icons__"))
{
@@ -494,7 +501,6 @@ static int parse_playlistview(struct skin_element *element,
struct playlistviewer *viewer = skin_buffer_alloc(sizeof(*viewer));
if (!viewer)
return WPS_ERROR_INVALID_PARAM;
- viewer->vp = PTRTOSKINOFFSET(skin_buffer, &curr_vp->vp);
viewer->show_icons = true;
viewer->start_offset = get_param(element, 0)->data.number;
viewer->line = PTRTOSKINOFFSET(skin_buffer, get_param_code(element, 1));
@@ -561,6 +567,7 @@ static int parse_listitemviewport(struct skin_element *element,
struct wps_data *wps_data)
{
#ifndef __PCTOOL__
+ struct skin_tag_parameter *param;
struct listitem_viewport_cfg *cfg = skin_buffer_alloc(sizeof(*cfg));
if (!cfg)
return -1;
@@ -569,10 +576,15 @@ static int parse_listitemviewport(struct skin_element *element,
cfg->label = PTRTOSKINOFFSET(skin_buffer, get_param_text(element, 0));
cfg->width = -1;
cfg->height = -1;
- if (!isdefault(get_param(element, 1)))
- cfg->width = get_param(element, 1)->data.number;
- if (!isdefault(get_param(element, 2)))
- cfg->height = get_param(element, 2)->data.number;
+
+ param = get_param(element, 1);
+ if (!isdefault(param))
+ cfg->width = param->data.number;
+
+ param = get_param(element, 2);
+ if (!isdefault(param))
+ cfg->height = param->data.number;
+
if (element->params_count > 3 &&
!strcmp(get_param_text(element, 3), "tile"))
cfg->tile = true;
@@ -592,20 +604,26 @@ static int parse_viewporttextstyle(struct skin_element *element,
*line = (struct line_desc)LINE_DESC_DEFINIT;
unsigned colour;
- if (!strcmp(mode, "invert"))
+ static const char * const vp_options[] = { "invert", "color", "colour",
+ "clear", "gradient", NULL};
+
+ int vp_op = string_option(mode, vp_options, false);
+
+ if (vp_op == 0) /*invert*/
{
line->style = STYLE_INVERT;
}
- else if (!strcmp(mode, "colour") || !strcmp(mode, "color"))
+ else if (vp_op == 1 || vp_op == 2) /*color/colour*/
{
if (element->params_count < 2 ||
!parse_color(curr_screen, get_param_text(element, 1), &colour))
return 1;
- line->style = STYLE_COLORED;
+ /* STYLE_COLORED is only a modifier and can't be used on its own */
+ line->style = STYLE_COLORED | STYLE_DEFAULT;
line->text_color = colour;
}
#ifdef HAVE_LCD_COLOR
- else if (!strcmp(mode, "gradient"))
+ else if (vp_op == 4) /*gradient*/
{
int num_lines;
if (element->params_count < 2)
@@ -618,7 +636,7 @@ static int parse_viewporttextstyle(struct skin_element *element,
line->nlines = num_lines;
}
#endif
- else if (!strcmp(mode, "clear"))
+ else if (vp_op == 3) /*clear*/
{
line->style = STYLE_DEFAULT;
}
@@ -634,34 +652,39 @@ static int parse_drawrectangle( struct skin_element *element,
struct wps_data *wps_data)
{
(void)wps_data;
+ struct skin_tag_parameter *param;
struct draw_rectangle *rect = skin_buffer_alloc(sizeof(*rect));
if (!rect)
return -1;
- if (get_param(element, 0)->type == PERCENT)
- rect->x = get_param(element, 0)->data.number * curr_vp->vp.width / 1000;
+ param = get_param(element, 0);
+ if (param->type == PERCENT)
+ rect->x = param->data.number * curr_vp->vp.width / 1000;
else
- rect->x = get_param(element, 0)->data.number;
+ rect->x = param->data.number;
- if (get_param(element, 1)->type == PERCENT)
- rect->y = get_param(element, 1)->data.number * curr_vp->vp.height / 1000;
+ param = get_param(element, 1);
+ if (param->type == PERCENT)
+ rect->y = param->data.number * curr_vp->vp.height / 1000;
else
- rect->y = get_param(element, 1)->data.number;
+ rect->y = param->data.number;
- if (isdefault(get_param(element, 2)))
+ param = get_param(element, 2);
+ if (isdefault(param))
rect->width = curr_vp->vp.width - rect->x;
- else if (get_param(element, 2)->type == PERCENT)
- rect->width = get_param(element, 2)->data.number * curr_vp->vp.width / 1000;
+ else if (param->type == PERCENT)
+ rect->width = param->data.number * curr_vp->vp.width / 1000;
else
- rect->width = get_param(element, 2)->data.number;
+ rect->width = param->data.number;
- if (isdefault(get_param(element, 3)))
+ param = get_param(element, 3);
+ if (isdefault(param))
rect->height = curr_vp->vp.height - rect->y;
- else if (get_param(element, 3)->type == PERCENT)
- rect->height = get_param(element, 3)->data.number * curr_vp->vp.height / 1000;
+ else if (param->type == PERCENT)
+ rect->height = param->data.number * curr_vp->vp.height / 1000;
else
- rect->height = get_param(element, 3)->data.number;
+ rect->height = param->data.number;
rect->start_colour = curr_vp->vp.fg_pattern;
rect->end_colour = curr_vp->vp.fg_pattern;
@@ -695,8 +718,35 @@ static int parse_viewportcolour(struct skin_element *element,
return -1;
if (isdefault(param))
{
- colour->colour = get_viewport_default_colour(curr_screen,
- token->type == SKIN_TOKEN_VIEWPORT_FGCOLOUR);
+ unsigned int fg_color;
+ unsigned int bg_color;
+
+ switch (curr_screen)
+ {
+#if defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1
+ case SCREEN_REMOTE:
+ fg_color = LCD_REMOTE_DEFAULT_FG;
+ bg_color = LCD_REMOTE_DEFAULT_BG;
+ break;
+#endif
+ default:
+#if defined(HAVE_LCD_COLOR)
+ fg_color = global_settings.fg_color;
+ bg_color = global_settings.bg_color;
+#elif LCD_DEPTH > 1
+ fg_color = LCD_DEFAULT_FG;
+ bg_color = LCD_DEFAULT_BG;
+#else
+ fg_color = 0;
+ bg_color = 0;
+#endif
+ break;
+ }
+
+ if (token->type == SKIN_TOKEN_VIEWPORT_FGCOLOUR)
+ colour->colour = fg_color;
+ else
+ colour->colour = bg_color;
}
else
{
@@ -704,7 +754,6 @@ static int parse_viewportcolour(struct skin_element *element,
&colour->colour))
return -1;
}
- colour->vp = PTRTOSKINOFFSET(skin_buffer, &curr_vp->vp);
token->value.data = PTRTOSKINOFFSET(skin_buffer, colour);
if (element->line == curr_viewport_element->line)
{
@@ -761,14 +810,14 @@ static int parse_setting_and_lang(struct skin_element *element,
*/
(void)wps_data;
char *temp = get_param_text(element, 0);
- int i;
if (token->type == SKIN_TOKEN_TRANSLATEDSTRING)
{
#ifndef __PCTOOL__
- i = lang_english_to_id(temp);
+ int i = lang_english_to_id(temp);
if (i < 0)
i = LANG_LAST_INDEX_IN_ARRAY;
+ token->value.i = i;
#endif
}
else if (element->params_count > 1)
@@ -781,12 +830,13 @@ static int parse_setting_and_lang(struct skin_element *element,
else
{
#ifndef __PCTOOL__
- if (find_setting_by_cfgname(temp, &i) == NULL)
+ const struct settings_list *setting = find_setting_by_cfgname(temp);
+ if (!setting)
return WPS_ERROR_INVALID_PARAM;
+
+ token->value.xdata = (void *)setting;
#endif
}
- /* Store the setting number */
- token->value.i = i;
return 0;
}
@@ -811,19 +861,38 @@ static int parse_logical_if(struct skin_element *element,
token->value.data = PTRTOSKINOFFSET(skin_buffer, lif);
lif->token = get_param_code(element, 0)->data;
- if (!strncmp(op, "=", 1))
- lif->op = IF_EQUALS;
- else if (!strncmp(op, "!=", 2))
- lif->op = IF_NOTEQUALS;
- else if (!strncmp(op, ">=", 2))
- lif->op = IF_GREATERTHAN_EQ;
- else if (!strncmp(op, "<=", 2))
- lif->op = IF_LESSTHAN_EQ;
- else if (!strncmp(op, ">", 2))
- lif->op = IF_GREATERTHAN;
- else if (!strncmp(op, "<", 1))
- lif->op = IF_LESSTHAN;
-
+ /* one or two operator conditionals */
+ #define OPS2VAL(op1, op2) ((int)op1 << 8 | (int)op2)
+ #define CLAUSE(op1, op2, symbol) {OPS2VAL(op1, op2), symbol }
+
+ struct clause_symbol {int value;int symbol;};
+ static const struct clause_symbol get_clause_match[] =
+ {
+ CLAUSE('=', '=', IF_EQUALS),
+ CLAUSE('!', '=', IF_NOTEQUALS),
+ CLAUSE('>', '=', IF_GREATERTHAN_EQ),
+ CLAUSE('<', '=', IF_LESSTHAN_EQ),
+ /*All Single value items @ end */
+ CLAUSE('>', 0, IF_GREATERTHAN),
+ CLAUSE('<', 0, IF_LESSTHAN),
+ CLAUSE('=', 0, IF_EQUALS),
+ };
+
+ int val1 = OPS2VAL(op[0], 0);
+ int val2;
+ if (val1 != 0) /* Empty string ?*/
+ {
+ val2 = OPS2VAL(op[0], op[1]);
+ for (unsigned int i = 0; i < ARRAYLEN(get_clause_match); i++)
+ {
+ const struct clause_symbol *sym = &get_clause_match[i];
+ if(sym->value == val1 || sym->value == val2)
+ {
+ lif->op = sym->symbol;
+ break;
+ }
+ }
+ }
memcpy(&lif->operand, get_param(element, 2), sizeof(lif->operand));
if (element->params_count > 3)
lif->num_options = get_param(element, 3)->data.number;
@@ -904,7 +973,6 @@ static int parse_progressbar_tag(struct skin_element* element,
if (!pb)
return WPS_ERROR_INVALID_PARAM;
- pb->vp = PTRTOSKINOFFSET(skin_buffer, vp);
pb->follow_lang_direction = follow_lang_direction > 0;
pb->nofill = false;
pb->noborder = false;
@@ -912,7 +980,7 @@ static int parse_progressbar_tag(struct skin_element* element,
pb->image = PTRTOSKINOFFSET(skin_buffer, NULL);
pb->slider = PTRTOSKINOFFSET(skin_buffer, NULL);
pb->backdrop = PTRTOSKINOFFSET(skin_buffer, NULL);
- pb->setting_id = -1;
+ pb->setting = NULL;
pb->invert_fill_direction = false;
pb->horizontal = true;
@@ -1009,20 +1077,37 @@ static int parse_progressbar_tag(struct skin_element* element,
}
pb->horizontal = pb->width > pb->height;
+
+ enum
+ {
+ eINVERT = 0, eNOFILL, eNOBORDER, eNOBAR, eSLIDER, eIMAGE,
+ eBACKDROP, eVERTICAL, eHORIZONTAL, eNOTOUCH, eSETTING,
+ e_PB_TAG_COUNT
+ };
+
+ static const char *pb_options[e_PB_TAG_COUNT + 1] = {[eINVERT] = "invert",
+ [eNOFILL] = "nofill", [eNOBORDER] = "noborder", [eNOBAR] = "nobar",
+ [eSLIDER] = "slider", [eIMAGE] = "image", [eBACKDROP] = "backdrop",
+ [eVERTICAL] = "vertical", [eHORIZONTAL] = "horizontal",
+ [eNOTOUCH] = "notouch", [eSETTING] = "setting", [e_PB_TAG_COUNT] = NULL};
+ int pb_op;
+
while (curr_param < element->params_count)
{
char* text;
param++;
text = SKINOFFSETTOPTR(skin_buffer, param->data.text);
- if (!strcmp(text, "invert"))
+
+ pb_op = string_option(text, pb_options, false);
+ if (pb_op == eINVERT)
pb->invert_fill_direction = true;
- else if (!strcmp(text, "nofill"))
+ else if (pb_op == eNOFILL)
pb->nofill = true;
- else if (!strcmp(text, "noborder"))
+ else if (pb_op == eNOBORDER)
pb->noborder = true;
- else if (!strcmp(text, "nobar"))
+ else if (pb_op == eNOBAR)
pb->nobar = true;
- else if (!strcmp(text, "slider"))
+ else if (pb_op == eSLIDER)
{
if (curr_param+1 < element->params_count)
{
@@ -1035,7 +1120,7 @@ static int parse_progressbar_tag(struct skin_element* element,
else /* option needs the next param */
return -1;
}
- else if (!strcmp(text, "image"))
+ else if (pb_op == eIMAGE)
{
if (curr_param+1 < element->params_count)
{
@@ -1046,7 +1131,7 @@ static int parse_progressbar_tag(struct skin_element* element,
else /* option needs the next param */
return -1;
}
- else if (!strcmp(text, "backdrop"))
+ else if (pb_op == eBACKDROP)
{
if (curr_param+1 < element->params_count)
{
@@ -1060,31 +1145,32 @@ static int parse_progressbar_tag(struct skin_element* element,
else /* option needs the next param */
return -1;
}
- else if (!strcmp(text, "vertical"))
+ else if (pb_op == eVERTICAL)
{
pb->horizontal = false;
if (isdefault(get_param(element, 3)))
pb->height = vp->height - pb->y;
}
- else if (!strcmp(text, "horizontal"))
+ else if (pb_op == eHORIZONTAL)
pb->horizontal = true;
#ifdef HAVE_TOUCHSCREEN
- else if (!strcmp(text, "notouch"))
+ else if (pb_op == eNOTOUCH)
suppress_touchregion = true;
#endif
- else if (token->type == SKIN_TOKEN_SETTING && !strcmp(text, "setting"))
- {
+ else if (token->type == SKIN_TOKEN_SETTING && pb_op == eSETTING)
+ {
if (curr_param+1 < element->params_count)
{
curr_param++;
param++;
text = SKINOFFSETTOPTR(skin_buffer, param->data.text);
#ifndef __PCTOOL__
- if (find_setting_by_cfgname(text, &pb->setting_id) == NULL)
- return WPS_ERROR_INVALID_PARAM;
+ pb->setting = find_setting_by_cfgname(text);
+ if (!pb->setting)
+ return WPS_ERROR_INVALID_PARAM;
#endif
- }
- }
+ }
+ }
else if (curr_param == 4)
image_filename = text;
@@ -1114,7 +1200,6 @@ static int parse_progressbar_tag(struct skin_element* element,
img->display = -1;
img->using_preloaded_icons = false;
img->buflib_handle = -1;
- img->vp = PTRTOSKINOFFSET(skin_buffer, &curr_vp->vp);
img->loaded = false;
struct skin_token_list *item = new_skin_token_list_item(NULL, img);
if (!item)
@@ -1219,24 +1304,28 @@ static int parse_albumart_load(struct skin_element* element,
aa->xalign = WPS_ALBUMART_ALIGN_CENTER; /* default */
aa->yalign = WPS_ALBUMART_ALIGN_CENTER; /* default */
- aa->x = get_param(element, 0)->data.number;
- aa->y = get_param(element, 1)->data.number;
- aa->width = get_param(element, 2)->data.number;
- aa->height = get_param(element, 3)->data.number;
+ struct skin_tag_parameter *param0 = get_param(element, 0);
+ struct skin_tag_parameter *param1 = get_param(element, 1);
+ struct skin_tag_parameter *param2 = get_param(element, 2);
+ struct skin_tag_parameter *param3 = get_param(element, 3);
- if (!isdefault(get_param(element, 0)) && get_param(element, 0)->type == PERCENT)
- aa->x = get_param(element, 0)->data.number * curr_vp->vp.width / 1000;
+ aa->x = param0->data.number;
+ aa->y = param1->data.number;
+ aa->width = param2->data.number;
+ aa->height = param3->data.number;
- if (!isdefault(get_param(element, 1)) && get_param(element, 1)->type == PERCENT)
- aa->y = get_param(element, 1)->data.number * curr_vp->vp.height / 1000;
+ if (!isdefault(param0) && param0->type == PERCENT)
+ aa->x = param0->data.number * curr_vp->vp.width / 1000;
- if (!isdefault(get_param(element, 2)) && get_param(element, 2)->type == PERCENT)
- aa->width = get_param(element, 2)->data.number * curr_vp->vp.width / 1000;
+ if (!isdefault(param1) && param1->type == PERCENT)
+ aa->y = param1->data.number * curr_vp->vp.height / 1000;
- if (!isdefault(get_param(element, 3)) && get_param(element, 3)->type == PERCENT)
- aa->height = get_param(element, 3)->data.number * curr_vp->vp.height / 1000;
+ if (!isdefault(param2) && param2->type == PERCENT)
+ aa->width = param2->data.number * curr_vp->vp.width / 1000;
+
+ if (!isdefault(param3) && param3->type == PERCENT)
+ aa->height = param3->data.number * curr_vp->vp.height / 1000;
- aa->vp = PTRTOSKINOFFSET(skin_buffer, &curr_vp->vp);
aa->draw_handle = -1;
/* if we got here, we parsed everything ok .. ! */
@@ -1341,27 +1430,32 @@ static int parse_skinvar( struct skin_element *element,
return 0;
case SKIN_TOKEN_VAR_SET:
{
+ static const char * const sv_options[] = {"touch", "set", "inc", "dec", NULL};
+
struct skin_var_changer *data = skin_buffer_alloc(sizeof(*data));
if (!data)
return WPS_ERROR_INVALID_PARAM;
data->var = PTRTOSKINOFFSET(skin_buffer, var);
+ char *text_param1 = get_param_text(element, 1);
+ int sv_op = string_option(text_param1, sv_options, false);
+
if (!isdefault(get_param(element, 2)))
data->newval = get_param(element, 2)->data.number;
- else if (strcmp(get_param_text(element, 1), "touch"))
+ else if (sv_op != 0) /*!touch*/
return WPS_ERROR_INVALID_PARAM;
data->max = 0;
- if (!strcmp(get_param_text(element, 1), "set"))
+ if (sv_op == 1) /*set*/
data->direct = true;
- else if (!strcmp(get_param_text(element, 1), "inc"))
+ else if (sv_op == 2) /*inc*/
{
data->direct = false;
}
- else if (!strcmp(get_param_text(element, 1), "dec"))
+ else if (sv_op == 3) /*dec*/
{
data->direct = false;
data->newval *= -1;
}
- else if (!strcmp(get_param_text(element, 1), "touch"))
+ else if (sv_op == 0) /*touch*/
{
data->direct = false;
data->newval = 0;
@@ -1403,12 +1497,12 @@ static int parse_lasttouch(struct skin_element *element,
for (i=0; i<element->params_count; i++)
{
- if (get_param(element, i)->type == STRING)
+ struct skin_tag_parameter *param = get_param(element, i);
+ if (param->type == STRING)
region = skin_find_item(get_param_text(element, i),
SKIN_FIND_TOUCHREGION, wps_data);
- else if (get_param(element, i)->type == INTEGER ||
- get_param(element, i)->type == DECIMAL)
- data->timeout = get_param(element, i)->data.number;
+ else if (param->type == INTEGER || param->type == DECIMAL)
+ data->timeout = param->data.number;
}
data->region = PTRTOSKINOFFSET(skin_buffer, region);
@@ -1461,48 +1555,48 @@ static int touchregion_setup_setting(struct skin_element *element, int param_no,
#ifndef __PCTOOL__
int p = param_no;
char *name = get_param_text(element, p++);
- int j;
-
- region->setting_data.setting = find_setting_by_cfgname(name, &j);
- if (region->setting_data.setting == NULL)
+ const struct settings_list *setting = find_setting_by_cfgname(name);
+ if (!setting)
return WPS_ERROR_INVALID_PARAM;
+ region->setting_data.setting = setting;
+
if (region->action == ACTION_SETTINGS_SET)
{
char* text;
int temp;
- struct touchsetting *setting =
+ struct touchsetting *touchsetting =
&region->setting_data;
if (element->params_count < p+1)
return -1;
text = get_param_text(element, p++);
- switch (settings[j].flags&F_T_MASK)
+ switch (setting->flags & F_T_MASK)
{
case F_T_CUSTOM:
- setting->value.text = PTRTOSKINOFFSET(skin_buffer, text);
+ touchsetting->value.text = PTRTOSKINOFFSET(skin_buffer, text);
break;
case F_T_INT:
case F_T_UINT:
- if (settings[j].cfg_vals == NULL)
+ if (setting->cfg_vals == NULL)
{
- setting->value.number = atoi(text);
+ touchsetting->value.number = atoi(text);
}
- else if (cfg_string_to_int(j, &temp, text))
+ else if (cfg_string_to_int(setting, &temp, text))
{
- if (settings[j].flags&F_TABLE_SETTING)
- setting->value.number =
- settings[j].table_setting->values[temp];
+ if (setting->flags & F_TABLE_SETTING)
+ touchsetting->value.number =
+ setting->table_setting->values[temp];
else
- setting->value.number = temp;
+ touchsetting->value.number = temp;
}
else
return -1;
break;
case F_T_BOOL:
- if (cfg_string_to_int(j, &temp, text))
+ if (cfg_string_to_int(setting, &temp, text))
{
- setting->value.number = temp;
+ touchsetting->value.number = temp;
}
else
return -1;
@@ -1640,16 +1734,21 @@ static int parse_touchregion(struct skin_element *element,
if (region->action == ACTION_NONE)
return WPS_ERROR_INVALID_PARAM;
}
+ static const char * const pm_options[] = {"allow_while_locked", "reverse_bar",
+ "repeat_press", "long_press", NULL};
+ int pm_op;
+
while (p < element->params_count)
{
char* param = get_param_text(element, p++);
- if (!strcmp(param, "allow_while_locked"))
+ pm_op = string_option(param, pm_options, false);
+ if (pm_op == 0)
region->allow_while_locked = true;
- else if (!strcmp(param, "reverse_bar"))
+ else if (pm_op == 1)
region->reverse_bar = true;
- else if (!strcmp(param, "repeat_press"))
+ else if (pm_op == 2)
region->press_length = REPEAT;
- else if (!strcmp(param, "long_press"))
+ else if (pm_op == 3)
region->press_length = LONG_PRESS;
}
struct skin_token_list *item = new_skin_token_list_item(NULL, region);
@@ -1758,9 +1857,7 @@ void skin_data_free_buflib_allocs(struct wps_data *wps_data)
abort:
wps_data->font_ids = PTRTOSKINOFFSET(skin_buffer, NULL); /* Safe if skin_buffer is NULL */
wps_data->images = PTRTOSKINOFFSET(skin_buffer, NULL);
- if (wps_data->buflib_handle > 0)
- core_free(wps_data->buflib_handle);
- wps_data->buflib_handle = -1;
+ wps_data->buflib_handle = core_free(wps_data->buflib_handle);
#endif
}
@@ -1801,13 +1898,11 @@ static void skin_data_reset(struct wps_data *wps_data)
}
#ifndef __PCTOOL__
-static int currently_loading_handle = -1;
static int buflib_move_callback(int handle, void* current, void* new)
{
+ (void)handle;
(void)current;
(void)new;
- if (handle == currently_loading_handle)
- return BUFLIB_CB_CANNOT_MOVE;
/* Any active skins may be scrolling - which means using viewports which
* will be moved after this callback returns. This is a hammer to make that
* safe. TODO: use a screwdriver instead.
@@ -1820,85 +1915,63 @@ static int buflib_move_callback(int handle, void* current, void* new)
return BUFLIB_CB_OK;
}
-static struct buflib_callbacks buflib_ops = {buflib_move_callback, NULL, NULL};
-static void lock_handle(int handle)
-{
- currently_loading_handle = handle;
-}
-static void unlock_handle(void)
-{
- currently_loading_handle = -1;
-}
#endif
-static int load_skin_bmp(struct wps_data *wps_data, struct bitmap *bitmap, char* bmpdir)
+static int load_skin_bmp(struct wps_data *wps_data, struct gui_img *img, char* bmpdir)
{
+
(void)wps_data; /* only needed for remote targets */
char img_path[MAX_PATH];
- int fd;
- int handle;
+ struct bitmap *bitmap = &img->bm;
+
get_image_filename(bitmap->data, bmpdir,
img_path, sizeof(img_path));
- /* load the image */
- int format;
-#ifdef HAVE_REMOTE_LCD
- if (curr_screen == SCREEN_REMOTE)
- format = FORMAT_ANY|FORMAT_REMOTE;
- else
-#endif
- format = FORMAT_ANY|FORMAT_TRANSPARENT;
-
- fd = open(img_path, O_RDONLY);
+#ifdef __PCTOOL__ /* just check if image exists */
+ int fd = open(img_path, O_RDONLY);
if (fd < 0)
{
DEBUGF("Couldn't open %s\n", img_path);
return fd;
}
-#ifndef __PCTOOL__
- int buf_size = read_bmp_fd(fd, bitmap, 0,
- format|FORMAT_RETURN_SIZE, NULL);
- if(buf_size < 0)
- {
- close(fd);
- return buf_size;
- }
+ close(fd);
+ return 1;
+#else /* load the image */
+ static struct buflib_callbacks buflib_ops = {buflib_move_callback, NULL, NULL};
+ int handle;
+ int bmpformat;
+ ssize_t buf_reqd;
+#ifdef HAVE_REMOTE_LCD
+ if (curr_screen == SCREEN_REMOTE)
+ bmpformat = FORMAT_ANY|FORMAT_REMOTE;
+ else
+#endif
+ bmpformat = img->dither ? FORMAT_ANY|FORMAT_DITHER|FORMAT_TRANSPARENT :
+ FORMAT_ANY|FORMAT_TRANSPARENT;
- handle = core_alloc_ex(bitmap->data, buf_size, &buflib_ops);
- if (handle <= 0)
+ handle = core_load_bmp(img_path, bitmap, bmpformat, &buf_reqd, &buflib_ops);
+ if (handle != CLB_ALOC_ERR)
{
- DEBUGF("Not enough skin buffer: need %zd more.\n",
- buf_size - skin_buffer_freespace());
- close(fd);
+ /* NOTE!: bitmap->data == NULL to force a crash later if the
+ caller doesnt call core_get_data() */
+ _stats->buflib_handles++;
+ _stats->images_size += buf_reqd;
return handle;
}
- _stats->buflib_handles++;
- _stats->images_size += buf_size;
- lseek(fd, 0, SEEK_SET);
- lock_handle(handle);
- bitmap->data = core_get_data(handle);
- int ret = read_bmp_fd(fd, bitmap, buf_size, format, NULL);
- bitmap->data = NULL; /* do this to force a crash later if the
- caller doesnt call core_get_data() */
- unlock_handle();
- close(fd);
- if (ret > 0)
+
+ if (buf_reqd == CLB_READ_ERR)
{
- /* free unused alpha channel, if any */
- core_shrink(handle, core_get_data(handle), ret);
- return handle;
+ /* Abort if we can't load an image */
+ DEBUGF("Couldn't load '%s' (%zu)\n", img_path, buf_reqd);
}
else
{
- /* Abort if we can't load an image */
- DEBUGF("Couldn't load '%s'\n", img_path);
- core_free(handle);
- return -1;
+ DEBUGF("Not enough skin buffer: need %zd more.\n",
+ buf_reqd - skin_buffer_freespace());
}
-#else /* !__PCTOOL__ */
- close(fd);
- return 1;
-#endif
+
+ return -1;
+#endif/* !__PCTOOL__ */
}
static bool load_skin_bitmaps(struct wps_data *wps_data, char *bmpdir)
@@ -1926,14 +1999,15 @@ static bool load_skin_bitmaps(struct wps_data *wps_data, char *bmpdir)
char path[MAX_PATH];
int handle;
strcpy(path, img->bm.data);
- handle = load_skin_bmp(wps_data, &img->bm, bmpdir);
+ handle = load_skin_bmp(wps_data, img, bmpdir);
img->buflib_handle = handle;
- img->loaded = img->buflib_handle >= 0;
+ img->loaded = img->buflib_handle > 0;
if (img->loaded)
{
struct skin_token_list *imglist = SKINOFFSETTOPTR(skin_buffer, list->next);
img->subimage_height = img->bm.height / img->num_subimages;
+ struct bitmap* loaded_bm = &img->bm;
while (imglist)
{
token = SKINOFFSETTOPTR(skin_buffer, imglist->token);
@@ -1943,6 +2017,7 @@ static bool load_skin_bitmaps(struct wps_data *wps_data, char *bmpdir)
{
img->loaded = true;
img->buflib_handle = handle;
+ img->bm = *loaded_bm;
img->subimage_height = img->bm.height / img->num_subimages;
}
}
@@ -2326,13 +2401,6 @@ static int skin_element_callback(struct skin_element* element, void* data)
break;
#endif
#ifdef HAVE_ALBUMART
- case SKIN_TOKEN_ALBUMART_DISPLAY:
- if (SKINOFFSETTOPTR(skin_buffer, wps_data->albumart))
- {
- struct skin_albumart *aa = SKINOFFSETTOPTR(skin_buffer, wps_data->albumart);
- aa->vp = PTRTOSKINOFFSET(skin_buffer, &curr_vp->vp);
- }
- break;
case SKIN_TOKEN_ALBUMART_LOAD:
function = parse_albumart_load;
break;
@@ -2468,8 +2536,9 @@ bool skin_data_load(enum screen_type screen, struct wps_data *wps_data,
skin_buffer = wps_buffer;
wps_buffer = (char*)buf;
}
- skin_buffer = ALIGN_UP(skin_buffer, 4); /* align on 4-byte boundary */
- buffersize -= 3;
+
+ /* align to long */
+ ALIGN_BUFFER(skin_buffer, buffersize, sizeof(long));
#ifdef HAVE_BACKDROP_IMAGE
backdrop_filename = "-";
wps_data->backdrop_id = -1;
@@ -2492,7 +2561,7 @@ bool skin_data_load(enum screen_type screen, struct wps_data *wps_data,
{
/* get the bitmap dir */
char *dot = strrchr(buf, '.');
- strlcpy(bmpdir, buf, dot - buf + 1);
+ strmemccpy(bmpdir, buf, dot - buf + 1);
}
else
{
@@ -2516,8 +2585,7 @@ bool skin_data_load(enum screen_type screen, struct wps_data *wps_data,
}
#endif
#ifndef __PCTOOL__
- wps_data->buflib_handle = core_alloc(isfile ? buf : "failsafe skin",
- skin_buffer_usage());
+ wps_data->buflib_handle = core_alloc(skin_buffer_usage());
if (wps_data->buflib_handle > 0)
{
wps_data->wps_loaded = true;