(hopefully) Fix FS#12639 and other skin related buflib corruption issues.

Kudos to funman for figuring out the problem - skin_find_item() rather
stupidly uses the global skin_buffer variable in skin_parser.c which is
fine in the parser EXCEPT it gets changed in skin_render when the sbs
is being redrawn while another skin is loading, so fix this by makeing
skin_find_item() use a local data pointer so a skin_render() during
parsing won't break anything.

Change-Id: I80e1c0efe569c18225e5772159c18ebb21e07332

Conflicts:

	apps/gui/skin_engine/skin_parser.c
This commit is contained in:
Jonathan Gordon 2012-05-16 22:28:59 +10:00
parent 8b9e5c906f
commit f9dce96b6a
2 changed files with 18 additions and 31 deletions

View file

@ -80,11 +80,6 @@
#define WPS_ERROR_INVALID_PARAM -1 #define WPS_ERROR_INVALID_PARAM -1
static char* skin_buffer = NULL; static char* skin_buffer = NULL;
void skinparser_set_buffer(char* pointer)
{
skin_buffer = pointer;
}
#if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1)) #if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1))
static char *backdrop_filename; static char *backdrop_filename;
#endif #endif
@ -158,7 +153,6 @@ void *skin_find_item(const char *label, enum skin_find_what what,
struct wps_data *data) struct wps_data *data)
{ {
const char *itemlabel = NULL; const char *itemlabel = NULL;
char *old_skin_buffer = skin_buffer;
char *databuf = get_skin_buffer(data); char *databuf = get_skin_buffer(data);
union { union {
struct skin_token_list *linkedlist; struct skin_token_list *linkedlist;
@ -166,28 +160,28 @@ void *skin_find_item(const char *label, enum skin_find_what what,
} list = {NULL}; } list = {NULL};
bool isvplist = false; bool isvplist = false;
void *ret = NULL; void *ret = NULL;
if (databuf && databuf != skin_buffer) if (!databuf)
skin_buffer = get_skin_buffer(data); databuf = skin_buffer;
switch (what) switch (what)
{ {
case SKIN_FIND_UIVP: case SKIN_FIND_UIVP:
case SKIN_FIND_VP: case SKIN_FIND_VP:
list.vplist = SKINOFFSETTOPTR(skin_buffer, data->tree); list.vplist = SKINOFFSETTOPTR(databuf, data->tree);
isvplist = true; isvplist = true;
break; break;
#ifdef HAVE_LCD_BITMAP #ifdef HAVE_LCD_BITMAP
case SKIN_FIND_IMAGE: case SKIN_FIND_IMAGE:
list.linkedlist = SKINOFFSETTOPTR(skin_buffer, data->images); list.linkedlist = SKINOFFSETTOPTR(databuf, data->images);
break; break;
#endif #endif
#ifdef HAVE_TOUCHSCREEN #ifdef HAVE_TOUCHSCREEN
case SKIN_FIND_TOUCHREGION: case SKIN_FIND_TOUCHREGION:
list.linkedlist = SKINOFFSETTOPTR(skin_buffer, data->touchregions); list.linkedlist = SKINOFFSETTOPTR(databuf, data->touchregions);
break; break;
#endif #endif
#ifdef HAVE_SKIN_VARIABLES #ifdef HAVE_SKIN_VARIABLES
case SKIN_VARIABLE: case SKIN_VARIABLE:
list.linkedlist = SKINOFFSETTOPTR(skin_buffer, data->skinvars); list.linkedlist = SKINOFFSETTOPTR(databuf, data->skinvars);
break; break;
#endif #endif
} }
@ -198,54 +192,50 @@ void *skin_find_item(const char *label, enum skin_find_what what,
#ifdef HAVE_LCD_BITMAP #ifdef HAVE_LCD_BITMAP
struct wps_token *token = NULL; struct wps_token *token = NULL;
if (!isvplist) if (!isvplist)
token = SKINOFFSETTOPTR(skin_buffer, list.linkedlist->token); token = SKINOFFSETTOPTR(databuf, list.linkedlist->token);
#endif #endif
switch (what) switch (what)
{ {
case SKIN_FIND_UIVP: case SKIN_FIND_UIVP:
case SKIN_FIND_VP: case SKIN_FIND_VP:
ret = SKINOFFSETTOPTR(skin_buffer, list.vplist->data); ret = SKINOFFSETTOPTR(databuf, list.vplist->data);
if (((struct skin_viewport *)ret)->label == VP_DEFAULT_LABEL) if (((struct skin_viewport *)ret)->label == VP_DEFAULT_LABEL)
itemlabel = VP_DEFAULT_LABEL_STRING; itemlabel = VP_DEFAULT_LABEL_STRING;
else else
itemlabel = SKINOFFSETTOPTR(skin_buffer, ((struct skin_viewport *)ret)->label); itemlabel = SKINOFFSETTOPTR(databuf, ((struct skin_viewport *)ret)->label);
skip = !(((struct skin_viewport *)ret)->is_infovp == skip = !(((struct skin_viewport *)ret)->is_infovp ==
(what==SKIN_FIND_UIVP)); (what==SKIN_FIND_UIVP));
break; break;
#ifdef HAVE_LCD_BITMAP #ifdef HAVE_LCD_BITMAP
case SKIN_FIND_IMAGE: case SKIN_FIND_IMAGE:
ret = SKINOFFSETTOPTR(skin_buffer, token->value.data); ret = SKINOFFSETTOPTR(databuf, token->value.data);
itemlabel = SKINOFFSETTOPTR(skin_buffer, ((struct gui_img *)ret)->label); itemlabel = SKINOFFSETTOPTR(databuf, ((struct gui_img *)ret)->label);
break; break;
#endif #endif
#ifdef HAVE_TOUCHSCREEN #ifdef HAVE_TOUCHSCREEN
case SKIN_FIND_TOUCHREGION: case SKIN_FIND_TOUCHREGION:
ret = SKINOFFSETTOPTR(skin_buffer, token->value.data); ret = SKINOFFSETTOPTR(databuf, token->value.data);
itemlabel = SKINOFFSETTOPTR(skin_buffer, ((struct touchregion *)ret)->label); itemlabel = SKINOFFSETTOPTR(databuf, ((struct touchregion *)ret)->label);
break; break;
#endif #endif
#ifdef HAVE_SKIN_VARIABLES #ifdef HAVE_SKIN_VARIABLES
case SKIN_VARIABLE: case SKIN_VARIABLE:
ret = SKINOFFSETTOPTR(skin_buffer, token->value.data); ret = SKINOFFSETTOPTR(databuf, token->value.data);
itemlabel = SKINOFFSETTOPTR(skin_buffer, ((struct skin_var *)ret)->label); itemlabel = SKINOFFSETTOPTR(databuf, ((struct skin_var *)ret)->label);
break; break;
#endif #endif
} }
if (!skip && itemlabel && !strcmp(itemlabel, label)) if (!skip && itemlabel && !strcmp(itemlabel, label))
{ {
if (old_skin_buffer != skin_buffer)
skin_buffer = old_skin_buffer;
return ret; return ret;
} }
if (isvplist) if (isvplist)
list.vplist = SKINOFFSETTOPTR(skin_buffer, list.vplist->next); list.vplist = SKINOFFSETTOPTR(databuf, list.vplist->next);
else else
list.linkedlist = SKINOFFSETTOPTR(skin_buffer, list.linkedlist->next); list.linkedlist = SKINOFFSETTOPTR(databuf, list.linkedlist->next);
} }
if (old_skin_buffer != skin_buffer)
skin_buffer = old_skin_buffer;
return NULL; return NULL;
} }
@ -2301,5 +2291,6 @@ bool skin_data_load(enum screen_type screen, struct wps_data *wps_data,
#else #else
wps_data->wps_loaded = wps_data->tree >= 0; wps_data->wps_loaded = wps_data->tree >= 0;
#endif #endif
skin_buffer = NULL;
return true; return true;
} }

View file

@ -83,8 +83,6 @@ static void skin_render_playlistviewer(struct playlistviewer* viewer,
#endif #endif
static char* skin_buffer; static char* skin_buffer;
/* hack alert: fix skin_parser.c's skin_buffer pointer */
void skinparser_set_buffer(char* pointer);
static inline struct skin_element* static inline struct skin_element*
get_child(OFFSETTYPE(struct skin_element**) children, int child) get_child(OFFSETTYPE(struct skin_element**) children, int child)
@ -694,7 +692,6 @@ void skin_render_viewport(struct skin_element* viewport, struct gui_wps *gwps,
struct align_pos * align = &info.align; struct align_pos * align = &info.align;
bool needs_update; bool needs_update;
skin_buffer = get_skin_buffer(gwps->data); skin_buffer = get_skin_buffer(gwps->data);
skinparser_set_buffer(skin_buffer);
#ifdef HAVE_LCD_BITMAP #ifdef HAVE_LCD_BITMAP
/* Set images to not to be displayed */ /* Set images to not to be displayed */
struct skin_token_list *imglist = SKINOFFSETTOPTR(skin_buffer, gwps->data->images); struct skin_token_list *imglist = SKINOFFSETTOPTR(skin_buffer, gwps->data->images);
@ -779,7 +776,6 @@ void skin_render(struct gui_wps *gwps, unsigned refresh_mode)
int old_refresh_mode = refresh_mode; int old_refresh_mode = refresh_mode;
skin_buffer = get_skin_buffer(gwps->data); skin_buffer = get_skin_buffer(gwps->data);
skinparser_set_buffer(skin_buffer);
#ifdef HAVE_LCD_CHARCELLS #ifdef HAVE_LCD_CHARCELLS
int i; int i;