diff options
Diffstat (limited to 'apps/gui/skin_engine/skin_parser.c')
-rw-r--r-- | apps/gui/skin_engine/skin_parser.c | 487 |
1 files changed, 282 insertions, 205 deletions
diff --git a/apps/gui/skin_engine/skin_parser.c b/apps/gui/skin_engine/skin_parser.c index 7f3f4d62e1..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) - return WPS_ERROR_INVALID_PARAM; + 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) @@ -1148,7 +1233,6 @@ static int parse_progressbar_tag(struct skin_element* element, { struct touchregion *region = skin_buffer_alloc(sizeof(*region)); struct skin_token_list *item; - int wpad, hpad; if (!region) return 0; @@ -1163,24 +1247,24 @@ static int parse_progressbar_tag(struct skin_element* element, /* try to add some extra space on either end to make pressing the * full bar easier. ~5% on either side */ - wpad = pb->width * 5 / 100; - if (wpad > 10) - wpad = 10; - hpad = pb->height * 5 / 100; - if (hpad > 10) - hpad = 10; - - region->x = pb->x - wpad; + region->wpad = pb->width * 5 / 100; + if (region->wpad > 10) + region->wpad = 10; + region->hpad = pb->height * 5 / 100; + if (region->hpad > 10) + region->hpad = 10; + + region->x = pb->x; if (region->x < 0) region->x = 0; - region->width = pb->width + 2 * wpad; + region->width = pb->width; if (region->x + region->width > curr_vp->vp.x + curr_vp->vp.width) region->width = curr_vp->vp.x + curr_vp->vp.width - region->x; - region->y = pb->y - hpad; + region->y = pb->y; if (region->y < 0) region->y = 0; - region->height = pb->height + 2 * hpad; + region->height = pb->height; if (region->y + region->height > curr_vp->vp.y + curr_vp->vp.height) region->height = curr_vp->vp.y + curr_vp->vp.height - region->y; @@ -1188,7 +1272,7 @@ static int parse_progressbar_tag(struct skin_element* element, region->reverse_bar = false; region->allow_while_locked = false; region->press_length = PRESS; - region->last_press = 0xffff; + region->last_press = -1; region->armed = false; region->bar = PTRTOSKINOFFSET(skin_buffer, pb); @@ -1220,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); + + 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, 0)) && get_param(element, 0)->type == PERCENT) - aa->x = get_param(element, 0)->data.number * curr_vp->vp.width / 1000; + if (!isdefault(param0) && param0->type == PERCENT) + aa->x = param0->data.number * curr_vp->vp.width / 1000; - 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(param1) && param1->type == PERCENT) + aa->y = param1->data.number * curr_vp->vp.height / 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(param2) && param2->type == PERCENT) + aa->width = param2->data.number * curr_vp->vp.width / 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(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 .. ! */ @@ -1342,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; @@ -1404,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); @@ -1462,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 = ®ion->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; @@ -1541,6 +1634,10 @@ static int parse_touchregion(struct skin_element *element, /* should probably do some bounds checking here with the viewport... but later */ region->action = ACTION_NONE; + /* padding is only for bars, user defined regions have no need of it */ + region->wpad = 0; + region->hpad = 0; + if (get_param(element, 0)->type == STRING) { region->label = PTRTOSKINOFFSET(skin_buffer, get_param_text(element, 0)); @@ -1599,7 +1696,7 @@ static int parse_touchregion(struct skin_element *element, region->armed = false; region->reverse_bar = false; region->value = 0; - region->last_press = 0xffff; + region->last_press = -1; region->press_length = PRESS; region->allow_while_locked = false; region->bar = PTRTOSKINOFFSET(skin_buffer, NULL); @@ -1637,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); @@ -1755,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 } @@ -1798,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. @@ -1817,79 +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__ - size_t buf_size = read_bmp_fd(fd, bitmap, 0, - format|FORMAT_RETURN_SIZE, NULL); - handle = core_alloc_ex(bitmap->data, buf_size, &buflib_ops); - if (handle <= 0) + 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_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) @@ -1917,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); @@ -1934,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; } } @@ -2317,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; @@ -2459,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; @@ -2483,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 { @@ -2507,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; |