(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
This commit is contained in:
Jonathan Gordon 2012-05-16 22:28:59 +10:00
parent 027ebaf463
commit 7909bf039f
2 changed files with 18 additions and 31 deletions

View file

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

View file

@ -84,8 +84,6 @@ static void skin_render_playlistviewer(struct playlistviewer* viewer,
#endif
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*
get_child(OFFSETTYPE(struct skin_element**) children, int child)
@ -720,7 +718,6 @@ void skin_render_viewport(struct skin_element* viewport, struct gui_wps *gwps,
struct align_pos * align = &info.align;
bool needs_update;
skin_buffer = get_skin_buffer(gwps->data);
skinparser_set_buffer(skin_buffer);
#ifdef HAVE_LCD_BITMAP
/* Set images to not to be displayed */
struct skin_token_list *imglist = SKINOFFSETTOPTR(skin_buffer, gwps->data->images);
@ -805,7 +802,6 @@ void skin_render(struct gui_wps *gwps, unsigned refresh_mode)
int old_refresh_mode = refresh_mode;
skin_buffer = get_skin_buffer(gwps->data);
skinparser_set_buffer(skin_buffer);
#ifdef HAVE_LCD_CHARCELLS
int i;